From bd48e33aceebc29b3cb4db7a5eb39a9e606e2709 Mon Sep 17 00:00:00 2001 From: Dylan Garvis Date: Sat, 8 Aug 2026 14:52:01 -0400 Subject: [PATCH] fix(stats): skip registry entries without keys --- design/log.md | 1 + design/user-stories/us-004-capture-player-snapshots.md | 1 + .../games/dmg/spigotevents/stats/BukkitRegistryKeys.java | 6 +++++- .../dmg/spigotevents/stats/BukkitRegistryKeysTest.java | 9 +++++++++ 4 files changed, 16 insertions(+), 1 deletion(-) diff --git a/design/log.md b/design/log.md index 8b042c7..c43b830 100644 --- a/design/log.md +++ b/design/log.md @@ -10,3 +10,4 @@ description: Chronological record of material changes to the design knowledge bu - Established the OKF v0.1 design bundle. - Documented the existing configuration, event production, activity capture, snapshots, durable delivery, and release workflows as user stories. +- Made snapshot collection skip Bukkit registry entries whose keys are unavailable. diff --git a/design/user-stories/us-004-capture-player-snapshots.md b/design/user-stories/us-004-capture-player-snapshots.md index 22d05e9..89cd2c6 100644 --- a/design/user-stories/us-004-capture-player-snapshots.md +++ b/design/user-stories/us-004-capture-player-snapshots.md @@ -13,6 +13,7 @@ As a **server analyst**, I want periodic player location and statistic snapshots - [x] Each configured interval captures every online player's world identity, coordinates, orientation, game mode, and biome. - [x] Registry-backed snapshot values use Bukkit's stable `Keyed` contract so collection remains compatible with the supported Purpur runtime. +- [x] Unkeyed registry entries such as `EntityType.UNKNOWN` are skipped without throwing or interrupting snapshot collection. - [x] Every Bukkit untyped, block, item, and entity statistic combination accepted by Bukkit is captured, including zero values. - [x] Invalid statistic subtype combinations are skipped without stopping the snapshot. - [x] Statistic reads are spread across ticks according to a configurable operation budget and run through Bukkit scheduling. diff --git a/src/main/java/games/dmg/spigotevents/stats/BukkitRegistryKeys.java b/src/main/java/games/dmg/spigotevents/stats/BukkitRegistryKeys.java index 9d15aac..f1e7481 100644 --- a/src/main/java/games/dmg/spigotevents/stats/BukkitRegistryKeys.java +++ b/src/main/java/games/dmg/spigotevents/stats/BukkitRegistryKeys.java @@ -7,7 +7,11 @@ final class BukkitRegistryKeys { private BukkitRegistryKeys() {} static NamespacedKey get(Keyed value) { - return value.getKey(); + try { + return value.getKey(); + } catch (IllegalArgumentException ignored) { + return null; + } } static String format(Keyed value, String fallback) { diff --git a/src/test/java/games/dmg/spigotevents/stats/BukkitRegistryKeysTest.java b/src/test/java/games/dmg/spigotevents/stats/BukkitRegistryKeysTest.java index cdc5f2e..c833ca7 100644 --- a/src/test/java/games/dmg/spigotevents/stats/BukkitRegistryKeysTest.java +++ b/src/test/java/games/dmg/spigotevents/stats/BukkitRegistryKeysTest.java @@ -21,4 +21,13 @@ class BukkitRegistryKeysTest { assertNull(BukkitRegistryKeys.get(keyed)); } + + @Test + void reportsAKeyThatBukkitRejectsAsUnavailable() { + Keyed keyed = () -> { + throw new IllegalArgumentException("Registry entry does not have a key"); + }; + + assertNull(BukkitRegistryKeys.get(keyed)); + } }