diff --git a/pom.xml b/pom.xml index ccd35a1ba..3faadd738 100644 --- a/pom.xml +++ b/pom.xml @@ -75,7 +75,7 @@ -LOCAL - 3.9.0 + 3.9.1 bentobox-world https://sonarcloud.io ${project.basedir}/lib diff --git a/src/main/java/world/bentobox/bentobox/listeners/flags/protection/BlockInteractionListener.java b/src/main/java/world/bentobox/bentobox/listeners/flags/protection/BlockInteractionListener.java index 0b01ce79a..56b723191 100644 --- a/src/main/java/world/bentobox/bentobox/listeners/flags/protection/BlockInteractionListener.java +++ b/src/main/java/world/bentobox/bentobox/listeners/flags/protection/BlockInteractionListener.java @@ -22,6 +22,7 @@ import world.bentobox.bentobox.api.flags.FlagListener; import world.bentobox.bentobox.database.objects.Island; import world.bentobox.bentobox.lists.Flags; +import world.bentobox.bentobox.util.Util; /** * Handle interaction with blocks @@ -246,18 +247,20 @@ private boolean checkSpecialCases(Event e, Player player, Block block) { this.checkIsland(e, player, loc, Flags.FLOWER_POT); return true; } - // Prevent animation of copper golems. Use break blocks for now. This could potentiall have it's own flag in the future. - if (Tag.COPPER_GOLEM_STATUES.isTagged(type)) { - this.checkIsland(e, player, loc, Flags.BREAK_BLOCKS); - return true; + if (Util.isVersionAtLeast("1.21.10")) { + // Prevent animation of copper golems. Use break blocks for now. This could potentiall have it's own flag in the future. + if (Tag.COPPER_GOLEM_STATUES.isTagged(type)) { + this.checkIsland(e, player, loc, Flags.BREAK_BLOCKS); + return true; + } + + // There are various types of copper chests + if (Tag.COPPER_CHESTS.isTagged(type)) { + this.checkIsland(e, player, loc, Flags.CHEST); + return true; + } } - // There are various types of copper chests - if (Tag.COPPER_CHESTS.isTagged(type)) { - this.checkIsland(e, player, loc, Flags.CHEST); - return true; - } - if (block.getState() instanceof BrushableBlock && BlockInteractionListener.holds(player, Material.BRUSH)) { // Protect this using break blocks flag for now. Maybe in the future it can have its own flag. this.checkIsland(e, player, loc, Flags.BREAK_BLOCKS); diff --git a/src/main/java/world/bentobox/bentobox/listeners/flags/protection/PlaceBlocksListener.java b/src/main/java/world/bentobox/bentobox/listeners/flags/protection/PlaceBlocksListener.java index 5bd393f80..8fd00650b 100644 --- a/src/main/java/world/bentobox/bentobox/listeners/flags/protection/PlaceBlocksListener.java +++ b/src/main/java/world/bentobox/bentobox/listeners/flags/protection/PlaceBlocksListener.java @@ -16,6 +16,8 @@ import org.bukkit.event.player.PlayerInteractEntityEvent; import org.bukkit.event.player.PlayerInteractEvent; +import com.google.common.base.Enums; + import world.bentobox.bentobox.api.flags.FlagListener; import world.bentobox.bentobox.lists.Flags; @@ -131,7 +133,7 @@ public void onPlayerInteract(final PlayerInteractEvent e) e.getMaterial() == Material.ITEM_FRAME || e.getMaterial() == Material.GLOW_ITEM_FRAME || e.getMaterial() == Material.CHEST || - e.getMaterial() == Material.COPPER_CHEST || + e.getMaterial() == Enums.getIfPresent(Material.class, "COPPER_CHEST").or(Material.CHEST) || e.getMaterial() == Material.TRAPPED_CHEST) { this.checkIsland(e, e.getPlayer(), e.getPlayer().getLocation(), Flags.PLACE_BLOCKS); diff --git a/src/main/java/world/bentobox/bentobox/listeners/flags/worldsettings/ChestDamageListener.java b/src/main/java/world/bentobox/bentobox/listeners/flags/worldsettings/ChestDamageListener.java index 1615695bb..59b67421c 100644 --- a/src/main/java/world/bentobox/bentobox/listeners/flags/worldsettings/ChestDamageListener.java +++ b/src/main/java/world/bentobox/bentobox/listeners/flags/worldsettings/ChestDamageListener.java @@ -8,6 +8,7 @@ import world.bentobox.bentobox.api.flags.FlagListener; import world.bentobox.bentobox.lists.Flags; +import world.bentobox.bentobox.util.Util; /** * @author tastybento @@ -24,10 +25,17 @@ public void onExplosion(final EntityExplodeEvent e) if (getIWM().inWorld(e.getLocation()) && !Flags.CHEST_DAMAGE.isSetForWorld(e.getLocation().getWorld())) { e.blockList().removeIf(b -> b.getType().equals(Material.CHEST) || - Tag.COPPER_CHESTS.isTagged(b.getType()) || - b.getType().equals(Material.TRAPPED_CHEST) || - Tag.SHULKER_BOXES.isTagged(b.getType())); - + isCopperChest(b.getType()) || + b.getType().equals(Material.TRAPPED_CHEST) || + Tag.SHULKER_BOXES.isTagged(b.getType())); + + } + } + + private boolean isCopperChest(Material m) { + if (Util.isVersionAtLeast("1.21.10")) { + return Tag.COPPER_CHESTS.isTagged(m); } + return false; } } diff --git a/src/main/java/world/bentobox/bentobox/util/Util.java b/src/main/java/world/bentobox/bentobox/util/Util.java index d55c813f8..9a3e45c16 100644 --- a/src/main/java/world/bentobox/bentobox/util/Util.java +++ b/src/main/java/world/bentobox/bentobox/util/Util.java @@ -73,6 +73,8 @@ public class Util { private static final String NETHER = "_nether"; private static final String THE_END = "_the_end"; + + private static final String SERVER_VERSION = Bukkit.getMinecraftVersion(); private static String serverVersion = null; private static BentoBox plugin = BentoBox.getInstance(); private static PasteHandler pasteHandler = null; @@ -363,10 +365,15 @@ public static boolean isPassiveEntity(Entity entity) { // Fishes, Dolphin and Squid extends WaterMob | Excludes PufferFish // Bat extends Mob // Most of passive mobs extends Animals - + boolean copperGolem = false; + try { + copperGolem = entity instanceof CopperGolem; + } catch (Exception ex) { + copperGolem = false; + } return entity instanceof Animals || entity instanceof IronGolem || entity instanceof Snowman || entity instanceof WaterMob && !(entity instanceof PufferFish) || entity instanceof Bat || - entity instanceof Allay || entity instanceof CopperGolem; + entity instanceof Allay || copperGolem; } public static boolean isTamableEntity(Entity entity) { @@ -744,7 +751,7 @@ public static void resetHealth(Player player) { public static void setRegenerator(WorldRegenerator regenerator) { Util.regenerator = regenerator; } - + private static Pair getPrefix() { // Bukkit method that was added in 2011 // Example value: 1.20.4-R0.1-SNAPSHOT @@ -752,7 +759,7 @@ private static Pair getPrefix() { final String pluginPackageName = plugin.getClass().getPackage().getName(); return new Pair(pluginPackageName + ".nms." + bukkitVersion, bukkitVersion); } - + /** * Generic method to get NMS handlers with fallback options * @param The type of handler to get @@ -771,7 +778,7 @@ private static T getNMSHandler(Class handlerClass, if (existingHandler != null) { return existingHandler; } - + T handler; try { Class clazz = Class.forName(getPrefix().x() + "." + implName); @@ -786,7 +793,7 @@ private static T getNMSHandler(Class handlerClass, } return handler; } - + /** * Get metadata decoder * @return an accelerated metadata class for this server @@ -909,5 +916,30 @@ public static boolean inTest() { public static String stripColor(String input) { return input.replaceAll("(?i)ยง[0-9A-FK-ORX]", ""); // Use regex because it's fast and reliable } - + + /** + * Simple utility method to check if the server version is at least the target version. + */ + public static boolean isVersionAtLeast(String targetVersion) { + // Simple string comparison may be sufficient for minor versions, + // but a proper numeric check is safer for major releases. + try { + // Get major, minor, patch versions + String[] currentParts = SERVER_VERSION.split("\\."); + String[] targetParts = targetVersion.split("\\."); + + for (int i = 0; i < targetParts.length; i++) { + int current = (i < currentParts.length) ? Integer.parseInt(currentParts[i]) : 0; + int target = Integer.parseInt(targetParts[i]); + + if (current > target) return true; + if (current < target) return false; + } + // All parts checked are equal (e.g., 1.21.9 vs 1.21.9) + return true; + } catch (NumberFormatException e) { + // Fallback for non-standard version strings + return SERVER_VERSION.startsWith(targetVersion); + } + } } diff --git a/src/test/java/world/bentobox/bentobox/AbstractCommonSetup.java b/src/test/java/world/bentobox/bentobox/AbstractCommonSetup.java index 1e970d6ee..13f36e5f8 100644 --- a/src/test/java/world/bentobox/bentobox/AbstractCommonSetup.java +++ b/src/test/java/world/bentobox/bentobox/AbstractCommonSetup.java @@ -116,6 +116,8 @@ public void setUp() throws Exception { server = ServerMocks.newServer(); // Bukkit PowerMockito.mockStatic(Bukkit.class, Mockito.RETURNS_MOCKS); + // Version + when(Bukkit.getMinecraftVersion()).thenReturn("1.21.10"); // Set up plugin Whitebox.setInternalState(BentoBox.class, "instance", plugin); diff --git a/src/test/java/world/bentobox/bentobox/listeners/PanelListenerManagerTest.java b/src/test/java/world/bentobox/bentobox/listeners/PanelListenerManagerTest.java index 6da0b43d9..6d9036664 100644 --- a/src/test/java/world/bentobox/bentobox/listeners/PanelListenerManagerTest.java +++ b/src/test/java/world/bentobox/bentobox/listeners/PanelListenerManagerTest.java @@ -37,6 +37,7 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.Mockito; +import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; import org.powermock.reflect.Whitebox; @@ -85,6 +86,8 @@ public class PanelListenerManagerTest { @SuppressWarnings("deprecation") @Before public void setUp() throws Exception { + PowerMockito.mockStatic(Bukkit.class, Mockito.RETURNS_MOCKS); + when(Bukkit.getMinecraftVersion()).thenReturn("1.21.10"); // Set up plugin BentoBox plugin = mock(BentoBox.class); Whitebox.setInternalState(BentoBox.class, "instance", plugin);