diff --git a/src/main/java/com/gmail/nossr50/listeners/BlockListener.java b/src/main/java/com/gmail/nossr50/listeners/BlockListener.java index 479228b19..d4da8e1a0 100644 --- a/src/main/java/com/gmail/nossr50/listeners/BlockListener.java +++ b/src/main/java/com/gmail/nossr50/listeners/BlockListener.java @@ -21,7 +21,6 @@ import com.gmail.nossr50.skills.repair.Repair; import com.gmail.nossr50.skills.salvage.Salvage; import com.gmail.nossr50.skills.woodcutting.WoodcuttingManager; import com.gmail.nossr50.util.*; -import com.gmail.nossr50.util.compat.layers.world.WorldCompatibilityLayer; import com.gmail.nossr50.util.player.UserManager; import com.gmail.nossr50.util.skills.SkillUtils; import com.gmail.nossr50.util.sounds.SoundManager; @@ -131,12 +130,10 @@ public class BlockListener implements Listener { BlockFace direction = event.getDirection(); Block movedBlock; - WorldCompatibilityLayer worldCompatibilityLayer = mcMMO.getCompatibilityManager().getWorldCompatibilityLayer(); - for (Block block : event.getBlocks()) { movedBlock = block.getRelative(direction); - if(BlockUtils.isWithinWorldBounds(worldCompatibilityLayer, movedBlock)) { + if(BlockUtils.isWithinWorldBounds(movedBlock)) { mcMMO.getPlaceStore().setTrue(movedBlock); } } @@ -161,15 +158,13 @@ public class BlockListener implements Listener { BlockFace direction = event.getDirection(); Block movedBlock = event.getBlock().getRelative(direction); - WorldCompatibilityLayer worldCompatibilityLayer = mcMMO.getCompatibilityManager().getWorldCompatibilityLayer(); - //Spigot makes bad things happen in its API - if(BlockUtils.isWithinWorldBounds(worldCompatibilityLayer, movedBlock)) { + if(BlockUtils.isWithinWorldBounds(movedBlock)) { mcMMO.getPlaceStore().setTrue(movedBlock); } for (Block block : event.getBlocks()) { - if(BlockUtils.isWithinWorldBounds(worldCompatibilityLayer, block)) { + if(BlockUtils.isWithinWorldBounds(block)) { mcMMO.getPlaceStore().setTrue(block.getRelative(direction)); } } @@ -192,10 +187,9 @@ public class BlockListener implements Listener { BlockState blockState = event.getNewState(); if(ExperienceConfig.getInstance().isSnowExploitPrevented() && BlockUtils.shouldBeWatched(blockState)) { - WorldCompatibilityLayer worldCompatibilityLayer = mcMMO.getCompatibilityManager().getWorldCompatibilityLayer(); Block block = blockState.getBlock(); - if(BlockUtils.isWithinWorldBounds(worldCompatibilityLayer, block)) { + if(BlockUtils.isWithinWorldBounds(block)) { mcMMO.getPlaceStore().setTrue(block); } } @@ -215,10 +209,9 @@ public class BlockListener implements Listener { if(ExperienceConfig.getInstance().preventStoneLavaFarming()) { BlockState newState = event.getNewState(); - WorldCompatibilityLayer worldCompatibilityLayer = mcMMO.getCompatibilityManager().getWorldCompatibilityLayer(); if(newState.getType() != Material.OBSIDIAN && ExperienceConfig.getInstance().doesBlockGiveSkillXP(PrimarySkillType.MINING, newState.getBlockData())) { - if(BlockUtils.isWithinWorldBounds(worldCompatibilityLayer, newState.getBlock())) { + if(BlockUtils.isWithinWorldBounds(newState.getBlock())) { mcMMO.getPlaceStore().setTrue(newState); } } @@ -243,9 +236,7 @@ public class BlockListener implements Listener { return; } - WorldCompatibilityLayer worldCompatibilityLayer = mcMMO.getCompatibilityManager().getWorldCompatibilityLayer(); - - if(BlockUtils.isWithinWorldBounds(worldCompatibilityLayer, block)) { + if(BlockUtils.isWithinWorldBounds(block)) { //NOTE: BlockMultiPlace has its own logic so don't handle anything that would overlap if (!(event instanceof BlockMultiPlaceEvent)) { mcMMO.getPlaceStore().setTrue(blockState); @@ -283,10 +274,8 @@ public class BlockListener implements Listener { BlockState blockState = replacedBlockState.getBlock().getState(); Block block = blockState.getBlock(); - WorldCompatibilityLayer worldCompatibilityLayer = mcMMO.getCompatibilityManager().getWorldCompatibilityLayer(); - /* Check if the blocks placed should be monitored so they do not give out XP in the future */ - if(BlockUtils.isWithinWorldBounds(worldCompatibilityLayer, block)) { + if(BlockUtils.isWithinWorldBounds(block)) { //Updated: 10/5/2021 //Note: For some reason Azalea trees trigger this event but no other tree does (as of 10/5/2021) but if this changes in the future we may need to update this if(BlockUtils.isPartOfTree(event.getBlockPlaced())) { @@ -311,9 +300,7 @@ public class BlockListener implements Listener { return; // Minecraft is dumb, the events still throw when a plant "grows" higher than the max block height. Even though no new block is created - WorldCompatibilityLayer worldCompatibilityLayer = mcMMO.getCompatibilityManager().getWorldCompatibilityLayer(); - - if(BlockUtils.isWithinWorldBounds(worldCompatibilityLayer, block)) { + if(BlockUtils.isWithinWorldBounds(block)) { mcMMO.getPlaceStore().setFalse(block); } } diff --git a/src/main/java/com/gmail/nossr50/util/BlockUtils.java b/src/main/java/com/gmail/nossr50/util/BlockUtils.java index f3c1dbd25..c899fc148 100644 --- a/src/main/java/com/gmail/nossr50/util/BlockUtils.java +++ b/src/main/java/com/gmail/nossr50/util/BlockUtils.java @@ -7,7 +7,6 @@ import com.gmail.nossr50.datatypes.skills.SubSkillType; import com.gmail.nossr50.mcMMO; import com.gmail.nossr50.skills.repair.Repair; import com.gmail.nossr50.skills.salvage.Salvage; -import com.gmail.nossr50.util.compat.layers.world.WorldCompatibilityLayer; import com.gmail.nossr50.util.random.RandomChanceSkill; import com.gmail.nossr50.util.random.RandomChanceUtil; import org.bukkit.Material; @@ -302,11 +301,17 @@ public final class BlockUtils { return hasWoodcuttingXP(block.getState()) || isNonWoodPartOfTree(block.getType()); } - public static boolean isWithinWorldBounds(@NotNull WorldCompatibilityLayer worldCompatibilityLayer, @NotNull Block block) { + /** + * Checks to see if a Block is within the world bounds + * Prevent processing blocks from other plugins (or perhaps odd spigot anomalies) from sending blocks that can't exist within the world + * @param block + * @return + */ + public static boolean isWithinWorldBounds(@NotNull Block block) { World world = block.getWorld(); //World min height = inclusive | World max height = exclusive - return block.getY() >= worldCompatibilityLayer.getMinWorldHeight(world) && block.getY() < worldCompatibilityLayer.getMaxWorldHeight(world); + return block.getY() >= world.getMinHeight() && block.getY() < world.getMaxHeight(); } } diff --git a/src/main/java/com/gmail/nossr50/util/blockmeta/BitSetChunkStore.java b/src/main/java/com/gmail/nossr50/util/blockmeta/BitSetChunkStore.java index d850cec06..bdee4a3b9 100644 --- a/src/main/java/com/gmail/nossr50/util/blockmeta/BitSetChunkStore.java +++ b/src/main/java/com/gmail/nossr50/util/blockmeta/BitSetChunkStore.java @@ -1,6 +1,5 @@ package com.gmail.nossr50.util.blockmeta; -import com.gmail.nossr50.mcMMO; import org.bukkit.Bukkit; import org.bukkit.World; import org.jetbrains.annotations.NotNull; @@ -25,7 +24,7 @@ public class BitSetChunkStore implements ChunkStore { private transient boolean dirty = false; public BitSetChunkStore(@NotNull World world, int cx, int cz) { - this(world.getUID(), mcMMO.getCompatibilityManager().getWorldCompatibilityLayer().getMinWorldHeight(world), world.getMaxHeight(), cx, cz); + this(world.getUID(), world.getMinHeight(), world.getMaxHeight(), cx, cz); } private BitSetChunkStore(@NotNull UUID worldUid, int worldMin, int worldMax, int cx, int cz) { @@ -109,23 +108,23 @@ public class BitSetChunkStore implements ChunkStore { return (z * 16 + x) + (256 * (y + yOffset)); } - private static int getWorldMin(@NotNull UUID worldUid, int storedWorldMin) { + private static int getWorldMin(@NotNull UUID worldUid) { World world = Bukkit.getWorld(worldUid); // Not sure how this case could come up, but might as well handle it gracefully. Loading a chunkstore for an unloaded world? if (world == null) - return storedWorldMin; + throw new RuntimeException("Cannot grab a minimum world height for an unloaded world"); - return mcMMO.getCompatibilityManager().getWorldCompatibilityLayer().getMinWorldHeight(world); + return world.getMinHeight(); } - private static int getWorldMax(@NotNull UUID worldUid, int storedWorldMax) + private static int getWorldMax(@NotNull UUID worldUid) { World world = Bukkit.getWorld(worldUid); // Not sure how this case could come up, but might as well handle it gracefully. Loading a chunkstore for an unloaded world? if (world == null) - return storedWorldMax; + throw new RuntimeException("Cannot grab a maximum world height for an unloaded world"); return world.getMaxHeight(); } @@ -171,8 +170,8 @@ public class BitSetChunkStore implements ChunkStore { in.readFully(temp); BitSet stored = BitSet.valueOf(temp); - int currentWorldMin = getWorldMin(worldUid, worldMin); - int currentWorldMax = getWorldMax(worldUid, worldMax); + int currentWorldMin = getWorldMin(worldUid); + int currentWorldMax = getWorldMax(worldUid); // The order in which the world height update code occurs here is important, the world max truncate math only holds up if done before adjusting for min changes // Lop off extra data if world max has shrunk @@ -273,8 +272,8 @@ public class BitSetChunkStore implements ChunkStore { public @NotNull BitSetChunkStore convert() { - int currentWorldMin = getWorldMin(worldUid, 0); - int currentWorldMax = getWorldMax(worldUid, worldMax); + int currentWorldMin = getWorldMin(worldUid); + int currentWorldMax = getWorldMax(worldUid); BitSetChunkStore converted = new BitSetChunkStore(worldUid, currentWorldMin, currentWorldMax, cx, cz); diff --git a/src/main/java/com/gmail/nossr50/util/compat/CompatibilityManager.java b/src/main/java/com/gmail/nossr50/util/compat/CompatibilityManager.java index 44231f0b0..f1f0b185b 100644 --- a/src/main/java/com/gmail/nossr50/util/compat/CompatibilityManager.java +++ b/src/main/java/com/gmail/nossr50/util/compat/CompatibilityManager.java @@ -10,12 +10,9 @@ import com.gmail.nossr50.util.compat.layers.persistentdata.SpigotPersistentDataL import com.gmail.nossr50.util.compat.layers.persistentdata.SpigotPersistentDataLayer_1_14; import com.gmail.nossr50.util.compat.layers.skills.AbstractMasterAnglerCompatibility; import com.gmail.nossr50.util.compat.layers.skills.MasterAnglerCompatibilityLayer; -import com.gmail.nossr50.util.compat.layers.world.WorldCompatibilityLayer; -import com.gmail.nossr50.util.compat.layers.world.WorldCompatibilityLayer_1_16_4; import com.gmail.nossr50.util.nms.NMSVersion; import com.gmail.nossr50.util.platform.MinecraftGameVersion; import com.gmail.nossr50.util.text.StringUtils; -import org.bukkit.World; import org.bukkit.command.CommandSender; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -40,7 +37,6 @@ public class CompatibilityManager { private AbstractPersistentDataLayer persistentDataLayer; private AbstractBungeeSerializerCompatibilityLayer bungeeSerializerCompatibilityLayer; private AbstractMasterAnglerCompatibility masterAnglerCompatibility; - private WorldCompatibilityLayer worldCompatibilityLayer; public CompatibilityManager(@NotNull MinecraftGameVersion minecraftGameVersion) { mcMMO.p.getLogger().info("Loading compatibility layers..."); @@ -71,29 +67,10 @@ public class CompatibilityManager { initPersistentDataLayer(); initBungeeSerializerLayer(); initMasterAnglerLayer(); - initWorldCompatibilityLayer(); isFullyCompatibleServerSoftware = true; } - private void initWorldCompatibilityLayer() { - if(minecraftGameVersion.isAtLeast(1, 17, 0)) { - worldCompatibilityLayer = new WorldCompatibilityLayer_1_16_4(); - } else { - worldCompatibilityLayer = new WorldCompatibilityLayer() { - @Override - public int getMinWorldHeight(@NotNull World world) { - return WorldCompatibilityLayer.super.getMinWorldHeight(world); - } - - @Override - public int getMaxWorldHeight(@NotNull World world) { - return WorldCompatibilityLayer.super.getMaxWorldHeight(world); - } - }; - } - } - private void initMasterAnglerLayer() { if(minecraftGameVersion.isAtLeast(1, 16, 3)) { masterAnglerCompatibility = new MasterAnglerCompatibilityLayer(); @@ -202,10 +179,6 @@ public class CompatibilityManager { return masterAnglerCompatibility; } - public @NotNull WorldCompatibilityLayer getWorldCompatibilityLayer() { - return worldCompatibilityLayer; - } - public @Nullable MinecraftGameVersion getMinecraftGameVersion() { return minecraftGameVersion; } diff --git a/src/main/java/com/gmail/nossr50/util/compat/layers/world/WorldCompatibilityLayer.java b/src/main/java/com/gmail/nossr50/util/compat/layers/world/WorldCompatibilityLayer.java deleted file mode 100644 index 115aeb7fb..000000000 --- a/src/main/java/com/gmail/nossr50/util/compat/layers/world/WorldCompatibilityLayer.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.gmail.nossr50.util.compat.layers.world; - -import com.gmail.nossr50.util.compat.CompatibilityLayer; -import org.bukkit.World; -import org.jetbrains.annotations.NotNull; - -public interface WorldCompatibilityLayer extends CompatibilityLayer { - default int getMinWorldHeight(@NotNull World world) { return 0; } - - default int getMaxWorldHeight(@NotNull World world) { return 256; } -} diff --git a/src/main/java/com/gmail/nossr50/util/compat/layers/world/WorldCompatibilityLayer_1_16_4.java b/src/main/java/com/gmail/nossr50/util/compat/layers/world/WorldCompatibilityLayer_1_16_4.java deleted file mode 100644 index 4e67aaf5c..000000000 --- a/src/main/java/com/gmail/nossr50/util/compat/layers/world/WorldCompatibilityLayer_1_16_4.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.gmail.nossr50.util.compat.layers.world; - -import org.bukkit.World; -import org.jetbrains.annotations.NotNull; - -public class WorldCompatibilityLayer_1_16_4 implements WorldCompatibilityLayer { - @Override - public int getMinWorldHeight(@NotNull World world) { - return world.getMinHeight(); - } - - @Override - public int getMaxWorldHeight(@NotNull World world) { - return world.getMaxHeight(); - } -} diff --git a/src/test/java/com/gmail/nossr50/util/blockmeta/ChunkStoreTest.java b/src/test/java/com/gmail/nossr50/util/blockmeta/ChunkStoreTest.java index f10b77898..1e0c209fe 100644 --- a/src/test/java/com/gmail/nossr50/util/blockmeta/ChunkStoreTest.java +++ b/src/test/java/com/gmail/nossr50/util/blockmeta/ChunkStoreTest.java @@ -4,7 +4,6 @@ package com.gmail.nossr50.util.blockmeta; import com.gmail.nossr50.mcMMO; import com.gmail.nossr50.util.BlockUtils; import com.gmail.nossr50.util.compat.CompatibilityManager; -import com.gmail.nossr50.util.compat.layers.world.WorldCompatibilityLayer; import com.gmail.nossr50.util.platform.PlatformManager; import com.google.common.io.Files; import org.bukkit.Bukkit; @@ -39,10 +38,7 @@ class ChunkStoreTest { } private World mockWorld; - private CompatibilityManager compatibilityManager; - private WorldCompatibilityLayer worldCompatibilityLayer; - private PlatformManager platformManager; - + private MockedStatic bukkitMock; private MockedStatic mcMMOMock; @@ -57,24 +53,10 @@ class ChunkStoreTest { bukkitMock = Mockito.mockStatic(Bukkit.class); bukkitMock.when(() -> Bukkit.getWorld(worldUUID)).thenReturn(mockWorld); - platformManager = Mockito.mock(PlatformManager.class); - compatibilityManager = Mockito.mock(CompatibilityManager.class); - worldCompatibilityLayer = Mockito.mock(WorldCompatibilityLayer.class); - mcMMOMock = Mockito.mockStatic(mcMMO.class); - mcMMOMock.when(() -> mcMMO.getPlatformManager()).thenReturn(platformManager); - Assertions.assertNotNull(mcMMO.getPlatformManager()); - - mcMMOMock.when(() -> mcMMO.getCompatibilityManager()).thenReturn(compatibilityManager); - Assertions.assertNotNull(mcMMO.getCompatibilityManager()); - - Mockito.when(platformManager.getCompatibilityManager()).thenReturn(compatibilityManager); - Mockito.when(platformManager.getCompatibilityManager().getWorldCompatibilityLayer()).thenReturn(worldCompatibilityLayer); - Assertions.assertNotNull(mcMMO.getCompatibilityManager().getWorldCompatibilityLayer()); - Mockito.when(worldCompatibilityLayer.getMinWorldHeight(mockWorld)).thenReturn(LEGACY_WORLD_HEIGHT_MIN); - Mockito.when(worldCompatibilityLayer.getMaxWorldHeight(mockWorld)).thenReturn(LEGACY_WORLD_HEIGHT_MAX); - + Mockito.when(mockWorld.getMinHeight()).thenReturn(LEGACY_WORLD_HEIGHT_MIN); + Mockito.when(mockWorld.getMaxHeight()).thenReturn(LEGACY_WORLD_HEIGHT_MAX); } @AfterEach @@ -85,7 +67,7 @@ class ChunkStoreTest { @Test void testIndexOutOfBounds() { - Mockito.when(mcMMO.getCompatibilityManager().getWorldCompatibilityLayer().getMinWorldHeight(mockWorld)).thenReturn(-64); + Mockito.when(mockWorld.getMinHeight()).thenReturn(-64); HashChunkManager hashChunkManager = new HashChunkManager(); // Top Block @@ -96,7 +78,7 @@ class ChunkStoreTest { @Test void testSetTrue() { - Mockito.when(mcMMO.getCompatibilityManager().getWorldCompatibilityLayer().getMinWorldHeight(mockWorld)).thenReturn(-64); + Mockito.when(mockWorld.getMinHeight()).thenReturn(-64); HashChunkManager hashChunkManager = new HashChunkManager(); int radius = 2; // Could be anything but drastically changes test time @@ -117,7 +99,7 @@ class ChunkStoreTest { Block bottomBlock = initMockBlock(1337, 0, -1337); Assertions.assertFalse(hashChunkManager.isTrue(bottomBlock)); - Assertions.assertTrue(BlockUtils.isWithinWorldBounds(worldCompatibilityLayer, bottomBlock)); + Assertions.assertTrue(BlockUtils.isWithinWorldBounds(bottomBlock)); hashChunkManager.setTrue(bottomBlock); Assertions.assertTrue(hashChunkManager.isTrue(bottomBlock)); @@ -125,7 +107,7 @@ class ChunkStoreTest { Block topBlock = initMockBlock(1337, 255, -1337); Assertions.assertFalse(hashChunkManager.isTrue(topBlock)); - Assertions.assertTrue(BlockUtils.isWithinWorldBounds(worldCompatibilityLayer, topBlock)); + Assertions.assertTrue(BlockUtils.isWithinWorldBounds(topBlock)); hashChunkManager.setTrue(topBlock); Assertions.assertTrue(hashChunkManager.isTrue(topBlock)); } @@ -161,7 +143,7 @@ class ChunkStoreTest { @Test void testNegativeWorldMin() throws IOException { - Mockito.when(mcMMO.getCompatibilityManager().getWorldCompatibilityLayer().getMinWorldHeight(mockWorld)).thenReturn(-64); + Mockito.when(mockWorld.getMinHeight()).thenReturn(-64); BitSetChunkStore original = new BitSetChunkStore(mockWorld, 1, 2); original.setTrue(14, -32, 12); @@ -180,8 +162,9 @@ class ChunkStoreTest { original.setTrue(13, 3, 12); byte[] serializedBytes = serializeChunkstore(original); - Mockito.when(mcMMO.getCompatibilityManager().getWorldCompatibilityLayer().getMinWorldHeight(mockWorld)).thenReturn(-64); + Mockito.when(mockWorld.getMinHeight()).thenReturn(-64); ChunkStore deserialized = BitSetChunkStore.Serialization.readChunkStore(new DataInputStream(new ByteArrayInputStream(serializedBytes))); + assert deserialized != null; assertEqualIgnoreMinMax(original, deserialized); } @@ -202,6 +185,7 @@ class ChunkStoreTest { original.setTrue(13, 89, 12); byte[] serializedBytes = serializeChunkstore(original); ChunkStore deserialized = BitSetChunkStore.Serialization.readChunkStore(new DataInputStream(new ByteArrayInputStream(serializedBytes))); + assert deserialized != null; assertEqual(original, deserialized); } @@ -221,6 +205,7 @@ class ChunkStoreTest { try (DataInputStream is = region.getInputStream(original.getChunkX(), original.getChunkZ())) { Assertions.assertNotNull(is); ChunkStore deserialized = BitSetChunkStore.Serialization.readChunkStore(is); + assert deserialized != null; assertEqual(original, deserialized); } region.close(); @@ -299,7 +284,6 @@ class ChunkStoreTest { } public static class LegacyChunkStore implements ChunkStore, Serializable { - private static final long serialVersionUID = -1L; transient private boolean dirty = false; public boolean[][][] store;