From c42ba6888ae9d7f3a0b661869f6d6a65cc92312b Mon Sep 17 00:00:00 2001 From: Dylan Garvis Date: Sat, 29 Aug 2026 14:51:56 -0400 Subject: [PATCH] fix(pocket-base): accept recovery compass metadata --- design/log.md | 5 +++++ .../us-023-craft-pocket-base-keystone.md | 1 + .../spigotbase/PocketBaseKeystoneService.java | 9 ++++++--- .../PocketBaseKeystoneServiceTest.java | 16 ++++++++++++++++ 4 files changed, 28 insertions(+), 3 deletions(-) diff --git a/design/log.md b/design/log.md index 8ee762b..ee394c5 100644 --- a/design/log.md +++ b/design/log.md @@ -165,6 +165,11 @@ description: Chronological record of material decisions affecting the Spigot Bas - Restored Back buttons from nested native dialog screens to the main Base Settings dashboard. - Verified 149 tests and the Java 25 plugin artifact with `./gradlew clean check jar`. +## 2026-08-29 — Recovery Compass metadata compatibility + +- Accepted Purpur's valid generic item metadata when creating the Pocket Base Keystone instead of requiring the legacy Compass-specific metadata subtype. +- Added regression coverage and verified 158 tests and the Java 25 plugin artifact with `./gradlew clean check jar`. + ## 2026-08-29 — Pocket Base Keystone travel - Added a reusable Recovery Compass keystone recipe with an Ender Pearl center, cardinal Netherite Ingots, and Obsidian corners. diff --git a/design/user-stories/us-023-craft-pocket-base-keystone.md b/design/user-stories/us-023-craft-pocket-base-keystone.md index 38023c4..eab24db 100644 --- a/design/user-stories/us-023-craft-pocket-base-keystone.md +++ b/design/user-stories/us-023-craft-pocket-base-keystone.md @@ -12,6 +12,7 @@ As a **Pocket Base owner**, I want to craft a reusable keystone that instantly t ## Acceptance criteria - [x] The Pocket Base Keystone is a distinct Recovery Compass identified by persistent item metadata rather than its display name alone. +- [x] Keystone creation accepts the valid generic item metadata supplied for Recovery Compasses by the supported Purpur runtime. - [x] Its shaped recipe places an Ender Pearl in the center, Netherite Ingots on the four cardinal slots, and Obsidian in the four corners. - [x] Only a player who has unlocked Pocket Base I can complete the recipe or use a keystone. - [x] Right-clicking a keystone outside a Pocket Base instantly teleports the player to their own Pocket Base arrival point. diff --git a/src/main/java/games/dmg/spigotbase/PocketBaseKeystoneService.java b/src/main/java/games/dmg/spigotbase/PocketBaseKeystoneService.java index 32768e7..c4c49c8 100644 --- a/src/main/java/games/dmg/spigotbase/PocketBaseKeystoneService.java +++ b/src/main/java/games/dmg/spigotbase/PocketBaseKeystoneService.java @@ -27,7 +27,6 @@ import org.bukkit.event.player.PlayerTeleportEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ShapedRecipe; import org.bukkit.inventory.meta.ItemMeta; -import org.bukkit.inventory.meta.CompassMeta; import org.bukkit.persistence.PersistentDataType; final class PocketBaseKeystoneService implements Listener { @@ -201,8 +200,13 @@ final class PocketBaseKeystoneService implements Listener { static ItemStack createKeystone(NamespacedKey markerKey) { ItemStack item = new ItemStack(Material.RECOVERY_COMPASS); + decorateKeystone(item, markerKey); + return item; + } + + static void decorateKeystone(ItemStack item, NamespacedKey markerKey) { ItemMeta metadata = item.getItemMeta(); - if (!(metadata instanceof CompassMeta)) { + if (metadata == null) { throw new IllegalStateException("Recovery Compass metadata is unavailable"); } metadata.displayName(Component.text( @@ -218,7 +222,6 @@ final class PocketBaseKeystoneService implements Listener { markerKey, PersistentDataType.BYTE, (byte) 1 ); item.setItemMeta(metadata); - return item; } static RecipeSpec recipeSpecification() { diff --git a/src/test/java/games/dmg/spigotbase/PocketBaseKeystoneServiceTest.java b/src/test/java/games/dmg/spigotbase/PocketBaseKeystoneServiceTest.java index 9601cb8..4b33210 100644 --- a/src/test/java/games/dmg/spigotbase/PocketBaseKeystoneServiceTest.java +++ b/src/test/java/games/dmg/spigotbase/PocketBaseKeystoneServiceTest.java @@ -34,6 +34,22 @@ import org.bukkit.persistence.PersistentDataType; import org.junit.jupiter.api.Test; final class PocketBaseKeystoneServiceTest { + @Test + void createsKeystoneWithGenericRecoveryCompassMetadata() { + NamespacedKey key = NamespacedKey.minecraft("pocket_base_keystone"); + ItemStack item = mock(ItemStack.class); + ItemMeta genericMetadata = mock(ItemMeta.class); + PersistentDataContainer data = mock(PersistentDataContainer.class); + + when(item.getItemMeta()).thenReturn(genericMetadata); + when(genericMetadata.getPersistentDataContainer()).thenReturn(data); + + PocketBaseKeystoneService.decorateKeystone(item, key); + + verify(data).set(key, PersistentDataType.BYTE, (byte) 1); + verify(item).setItemMeta(genericMetadata); + } + @Test void recipeUsesNetheriteOnCardinalsAndObsidianInCorners() { PocketBaseKeystoneService.RecipeSpec recipe =