From 7f4e0749dfd0662db2372f43c051d4138b8a43d7 Mon Sep 17 00:00:00 2001 From: XxFran10xX <318299142+XxFran10xX@users.noreply.github.com> Date: Thu, 22 Oct 2026 23:54:00 +0200 Subject: [PATCH 1/2] perf: read grave tags without copying the chest on hopper moves GraveManager.getAt runs for both inventories of every InventoryMoveItemEvent. It used block.getState(), which snapshots the block entity and deep-copies the whole chest inventory just to read the grave id tag. A spark profile on Main showed this at ~3 s of server-thread time per minute. Read the live block entity with getState(false) instead. The lookup only reads the persistent data container on the server thread and never keeps the state, so the result is identical. Co-Authored-By: Claude Opus 5.5 --- .../tfminecraft/rpcharacters/grave/GraveManager.java | 4 +++- .../rpcharacters/grave/GraveManagerTest.java | 10 ++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/tfminecraft/rpcharacters/grave/GraveManager.java b/src/main/java/net/tfminecraft/rpcharacters/grave/GraveManager.java index bce4119..75bba98 100644 --- a/src/main/java/net/tfminecraft/rpcharacters/grave/GraveManager.java +++ b/src/main/java/net/tfminecraft/rpcharacters/grave/GraveManager.java @@ -56,7 +56,9 @@ public Grave getAt(Block block) { if (block == null) { return null; } - if (block.getState() instanceof TileState tile) { + // Hopper moves call this for every transfer. A snapshot copies the whole chest + // inventory just to read one tag, so read the live block entity instead. + if (block.getState(false) instanceof TileState tile) { String raw = tile.getPersistentDataContainer().get(GraveKeys.graveId(), GraveKeys.GRAVE_ID_TYPE); if (raw != null && !raw.isBlank()) { try { diff --git a/src/test/java/net/tfminecraft/rpcharacters/grave/GraveManagerTest.java b/src/test/java/net/tfminecraft/rpcharacters/grave/GraveManagerTest.java index e9154fd..ddb06ac 100644 --- a/src/test/java/net/tfminecraft/rpcharacters/grave/GraveManagerTest.java +++ b/src/test/java/net/tfminecraft/rpcharacters/grave/GraveManagerTest.java @@ -104,6 +104,16 @@ ItemStack namedItem() { assertSame(grave, manager.getAt(grave.getBlockLocation().getBlock())); } + @Test void taggedLookupReadsTheLiveBlockEntityWithoutCopyingTheChest() { + Grave grave = grave(3, 64, 3); manager.register(grave); + Block block = mock(Block.class); TileState live = mock(TileState.class, RETURNS_DEEP_STUBS); + when(block.getWorld()).thenReturn(world); when(block.getX()).thenReturn(3); when(block.getY()).thenReturn(64); when(block.getZ()).thenReturn(3); + when(block.getState(false)).thenReturn(live); + when(live.getPersistentDataContainer().get(GraveKeys.graveId(), GraveKeys.GRAVE_ID_TYPE)).thenReturn(grave.getId().toString()); + assertSame(grave, manager.getAt(block)); assertTrue(manager.isGrave(block)); + verify(block, never()).getState(); + } + @Test void staleBlockTagsCannotExposeLootFromAMovedGrave() { Grave grave = grave(1, 64, 1); Block previous = grave.getBlockLocation().getBlock(); previous.setType(Material.CHEST); manager.save(grave); grave.setBlockLocation(new Location(world, 9, 64, 9)); manager.register(grave); From 3699fad6e712831944e1ac8db2ff2f14ff162638 Mon Sep 17 00:00:00 2001 From: XxFran10xX <318299142+XxFran10xX@users.noreply.github.com> Date: Fri, 23 Oct 2026 02:15:51 +0200 Subject: [PATCH 2/2] test: check the grave tag itself is read from the live block entity Co-Authored-By: Claude Opus 5.5 --- .../net/tfminecraft/rpcharacters/grave/GraveManagerTest.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/test/java/net/tfminecraft/rpcharacters/grave/GraveManagerTest.java b/src/test/java/net/tfminecraft/rpcharacters/grave/GraveManagerTest.java index ddb06ac..b29416c 100644 --- a/src/test/java/net/tfminecraft/rpcharacters/grave/GraveManagerTest.java +++ b/src/test/java/net/tfminecraft/rpcharacters/grave/GraveManagerTest.java @@ -111,6 +111,9 @@ ItemStack namedItem() { when(block.getState(false)).thenReturn(live); when(live.getPersistentDataContainer().get(GraveKeys.graveId(), GraveKeys.GRAVE_ID_TYPE)).thenReturn(grave.getId().toString()); assertSame(grave, manager.getAt(block)); assertTrue(manager.isGrave(block)); + // The grave is also indexed at these coordinates, so check the tag itself was read. + verify(block, times(2)).getState(false); + verify(live.getPersistentDataContainer(), times(2)).get(GraveKeys.graveId(), GraveKeys.GRAVE_ID_TYPE); verify(block, never()).getState(); }