From 3f5f510fc5e266bd3dbbcce48224f6b7976d3e9c Mon Sep 17 00:00:00 2001 From: nossr50 Date: Thu, 7 Nov 2024 18:55:59 -0800 Subject: [PATCH] Fixed NPE on chunk unload --- .../util/blockmeta/HashChunkManager.java | 17 ++------------- .../util/blockmeta/UserBlockTrackerTest.java | 21 +++++++++++++++++++ 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/src/main/java/com/gmail/nossr50/util/blockmeta/HashChunkManager.java b/src/main/java/com/gmail/nossr50/util/blockmeta/HashChunkManager.java index aa5d9da2f..5d860e0e3 100644 --- a/src/main/java/com/gmail/nossr50/util/blockmeta/HashChunkManager.java +++ b/src/main/java/com/gmail/nossr50/util/blockmeta/HashChunkManager.java @@ -39,9 +39,7 @@ public class HashChunkManager implements ChunkManager { } private synchronized @Nullable ChunkStore readChunkStore(@NotNull World world, int cx, int cz) throws IOException { - McMMOSimpleRegionFile rf = getReadableSimpleRegionFile(world, cx, cz); - if (rf == null) - return null; // If there is no region file, there can't be a chunk + final McMMOSimpleRegionFile rf = getWriteableSimpleRegionFile(world, cx, cz); try (DataInputStream in = rf.getInputStream(cx, cz)) { // Get input stream for chunk if (in == null) return null; // No chunk @@ -74,17 +72,6 @@ public class HashChunkManager implements ChunkManager { }); } - private synchronized @Nullable McMMOSimpleRegionFile getReadableSimpleRegionFile(@NotNull World world, int cx, int cz) { - CoordinateKey regionKey = toRegionKey(world.getUID(), cx, cz); - - return regionMap.computeIfAbsent(regionKey, k -> { - File regionFile = getRegionFile(world, regionKey); - if (!regionFile.exists()) - return null; // Don't create the file on read-only operations - return new McMMOSimpleRegionFile(regionFile, regionKey.x, regionKey.z); - }); - } - private @NotNull File getRegionFile(@NotNull World world, @NotNull CoordinateKey regionKey) { if (world.getUID() != regionKey.worldID) throw new IllegalArgumentException(); @@ -112,7 +99,7 @@ public class HashChunkManager implements ChunkManager { CoordinateKey regionKey = toRegionKey(world.getUID(), cx, cz); HashSet chunkKeys = chunkUsageMap.get(regionKey); chunkKeys.remove(chunkKey); // remove from region file in-use set - // If it was last chunk in region, close the region file and remove it from memory + // If it was last chunk in the region, close the region file and remove it from memory if (chunkKeys.isEmpty()) { chunkUsageMap.remove(regionKey); regionMap.remove(regionKey).close(); diff --git a/src/test/java/com/gmail/nossr50/util/blockmeta/UserBlockTrackerTest.java b/src/test/java/com/gmail/nossr50/util/blockmeta/UserBlockTrackerTest.java index 5bdf5e485..a522b3585 100644 --- a/src/test/java/com/gmail/nossr50/util/blockmeta/UserBlockTrackerTest.java +++ b/src/test/java/com/gmail/nossr50/util/blockmeta/UserBlockTrackerTest.java @@ -170,6 +170,27 @@ class UserBlockTrackerTest { assertTrue(chunkManager.isIneligible(mockBlockA)); } + @Test + void testUnload() { + final ChunkManager chunkManager = new HashChunkManager(); + Block mockBlockA = Mockito.mock(Block.class); + when(mockBlockA.getX()).thenReturn(15); + when(mockBlockA.getZ()).thenReturn(15); + when(mockBlockA.getY()).thenReturn(0); + when(mockBlockA.getWorld()).thenReturn(mockWorld); + Block mockBlockB = Mockito.mock(Block.class); + when(mockBlockB.getX()).thenReturn(-15); + when(mockBlockB.getZ()).thenReturn(-15); + when(mockBlockB.getY()).thenReturn(0); + when(mockBlockB.getWorld()).thenReturn(mockWorld); + + chunkManager.setIneligible(mockBlockA); + chunkManager.setEligible(mockBlockB); + assertTrue(chunkManager.isIneligible(mockBlockA)); + + chunkManager.chunkUnloaded(0, 0, mockWorld); + } + @NotNull private Block initMockBlock(int x, int y, int z) { final Block mockBlock = Mockito.mock(Block.class);