From 5953df9dbb280987466b5502356591a1ae28d7ee Mon Sep 17 00:00:00 2001 From: tastybento Date: Sat, 8 Jul 2023 08:33:24 -0700 Subject: [PATCH 01/30] Version 1.24.1 --- pom.xml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index d7c1a3747..477d211b5 100644 --- a/pom.xml +++ b/pom.xml @@ -67,7 +67,7 @@ 2.0.9 - 3.12.8 + 3.12.12 3.0.5 8.0.27 42.2.18 @@ -88,7 +88,7 @@ -LOCAL - 1.24.0 + 1.24.1 bentobox-world https://sonarcloud.io ${project.basedir}/lib @@ -127,6 +127,7 @@ origin/master + ${build.version} @@ -369,6 +370,7 @@ org.apache.maven.plugins maven-surefire-plugin 3.0.0-M5 + ${argLine} From 74a2e9d3c81664f486dda5c4342eaf37333669ea Mon Sep 17 00:00:00 2001 From: tastybento Date: Sat, 8 Jul 2023 08:33:51 -0700 Subject: [PATCH 02/30] Change OP to op --- src/main/resources/plugin.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 4dff30944..ac15aa754 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -62,4 +62,4 @@ permissions: default: op bentobox.perms: description: Allow use of '/bentobox perms' command - default: OP + default: op From 54139b60f0acb4b3aaae11e18739150f1f5c0ebf Mon Sep 17 00:00:00 2001 From: tastybento Date: Sat, 8 Jul 2023 08:35:22 -0700 Subject: [PATCH 03/30] Remove unneeded return --- .../bentobox/listeners/flags/protection/SculkSensorListener.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/world/bentobox/bentobox/listeners/flags/protection/SculkSensorListener.java b/src/main/java/world/bentobox/bentobox/listeners/flags/protection/SculkSensorListener.java index 8bef10902..349636bd1 100644 --- a/src/main/java/world/bentobox/bentobox/listeners/flags/protection/SculkSensorListener.java +++ b/src/main/java/world/bentobox/bentobox/listeners/flags/protection/SculkSensorListener.java @@ -42,6 +42,5 @@ public class SculkSensorListener extends FlagListener { this.checkIsland(event, player, event.getBlock().getLocation(), Flags.SCULK_SENSOR, true); } - return; } } From df6fb7d7160d88a022fb977db9afb1ddbac5adaa Mon Sep 17 00:00:00 2001 From: tastybento Date: Sat, 8 Jul 2023 08:35:31 -0700 Subject: [PATCH 04/30] Fix JavaDoc --- .../java/world/bentobox/bentobox/util/DefaultPasteUtil.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/java/world/bentobox/bentobox/util/DefaultPasteUtil.java b/src/main/java/world/bentobox/bentobox/util/DefaultPasteUtil.java index 8231ffd8b..85f7c78c1 100644 --- a/src/main/java/world/bentobox/bentobox/util/DefaultPasteUtil.java +++ b/src/main/java/world/bentobox/bentobox/util/DefaultPasteUtil.java @@ -202,9 +202,8 @@ public class DefaultPasteUtil { * * @param island - island * @param block - block - * @param lines - lines - * @param glow - is sign glowing? - * @param side - the side being writted + * @param bpSign - BlueprintBlock that is the sign + * @param side - the side being written */ public static void writeSign(Island island, final Block block, BlueprintBlock bpSign, Side side) { List lines = bpSign.getSignLines(side); From df45fca5622932cf28f7a92e100b9dcb3b930e87 Mon Sep 17 00:00:00 2001 From: tastybento Date: Sat, 8 Jul 2023 08:36:29 -0700 Subject: [PATCH 05/30] Refactor - merge List creation and addAll into one --- .../world/bentobox/bentobox/api/commands/CompositeCommand.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/world/bentobox/bentobox/api/commands/CompositeCommand.java b/src/main/java/world/bentobox/bentobox/api/commands/CompositeCommand.java index 93700da36..9533dbd5e 100644 --- a/src/main/java/world/bentobox/bentobox/api/commands/CompositeCommand.java +++ b/src/main/java/world/bentobox/bentobox/api/commands/CompositeCommand.java @@ -663,9 +663,8 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi if (command.getPermission() != null && !command.getPermission().isEmpty() && !sender.hasPermission(command.getPermission()) && !sender.isOp()) { return List.of(); } - List options = new ArrayList<>(); // Add any tab completion from the subcommand - options.addAll(command.tabComplete(User.getInstance(sender), alias, new LinkedList<>(Arrays.asList(args))).orElseGet(ArrayList::new)); + List options = new ArrayList<>(command.tabComplete(User.getInstance(sender), alias, new LinkedList<>(Arrays.asList(args))).orElseGet(ArrayList::new)); if (command.hasSubCommands()) { options.addAll(getSubCommandLabels(sender, command)); } From 2c8db2a797654a4cd42d1faba4a93b86ee54df83 Mon Sep 17 00:00:00 2001 From: tastybento Date: Sat, 8 Jul 2023 08:37:10 -0700 Subject: [PATCH 06/30] Use any() which now is a varArg tester. Remove deprecation --- .../bentobox/api/commands/island/IslandCreateCommandTest.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/test/java/world/bentobox/bentobox/api/commands/island/IslandCreateCommandTest.java b/src/test/java/world/bentobox/bentobox/api/commands/island/IslandCreateCommandTest.java index 066b7c774..3ded14952 100644 --- a/src/test/java/world/bentobox/bentobox/api/commands/island/IslandCreateCommandTest.java +++ b/src/test/java/world/bentobox/bentobox/api/commands/island/IslandCreateCommandTest.java @@ -78,7 +78,6 @@ public class IslandCreateCommandTest { /** */ - @SuppressWarnings("deprecation") @Before public void setUp() throws Exception { // Set up plugin @@ -99,7 +98,7 @@ public class IslandCreateCommandTest { when(user.getUniqueId()).thenReturn(uuid); when(user.getPlayer()).thenReturn(player); when(user.hasPermission(Mockito.anyString())).thenReturn(true); - when(user.getTranslation(Mockito.anyVararg())).thenAnswer((Answer) invocation -> invocation.getArgument(0, String.class)); + when(user.getTranslation(Mockito.any())).thenAnswer((Answer) invocation -> invocation.getArgument(0, String.class)); User.setPlugin(plugin); // Set up user already User.getInstance(player); From 30d29c6ff99fbb66179c9e99227fd94b17da1664 Mon Sep 17 00:00:00 2001 From: tastybento Date: Sat, 8 Jul 2023 08:38:20 -0700 Subject: [PATCH 07/30] Refactor: Merge switch values --- .../listeners/flags/protection/BreakBlocksListener.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/java/world/bentobox/bentobox/listeners/flags/protection/BreakBlocksListener.java b/src/main/java/world/bentobox/bentobox/listeners/flags/protection/BreakBlocksListener.java index a720ed67c..78f47e497 100644 --- a/src/main/java/world/bentobox/bentobox/listeners/flags/protection/BreakBlocksListener.java +++ b/src/main/java/world/bentobox/bentobox/listeners/flags/protection/BreakBlocksListener.java @@ -37,9 +37,8 @@ public class BreakBlocksListener extends FlagListener { Material m = e.getBlock().getType(); switch (m) { - case MELON -> this.checkIsland(e, p, l, Flags.HARVEST); - case PUMPKIN -> this.checkIsland(e, p, l, Flags.HARVEST); - default -> { + case MELON, PUMPKIN -> this.checkIsland(e, p, l, Flags.HARVEST); + default -> { // Crops if (Tag.CROPS.isTagged(m) && !m.equals(Material.MELON_STEM) From 325c9c23516ba82a7a6b178fe4e3798591a1aa0c Mon Sep 17 00:00:00 2001 From: tastybento Date: Sat, 8 Jul 2023 08:38:30 -0700 Subject: [PATCH 08/30] JavaDoc fix --- .../world/bentobox/bentobox/commands/BentoBoxPermsCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/world/bentobox/bentobox/commands/BentoBoxPermsCommand.java b/src/main/java/world/bentobox/bentobox/commands/BentoBoxPermsCommand.java index fc20c211f..f1a6d76ef 100644 --- a/src/main/java/world/bentobox/bentobox/commands/BentoBoxPermsCommand.java +++ b/src/main/java/world/bentobox/bentobox/commands/BentoBoxPermsCommand.java @@ -68,7 +68,7 @@ public class BentoBoxPermsCommand extends CompositeCommand { * Iterates over sub-commands * @param user user * @param parent parent command - * @param label + * @param label label */ private void printSubCommandData(User user, CompositeCommand parent, String label) { for (CompositeCommand cc : parent.getSubCommands().values()) { From 39a6fc500671813f48dd0fea6856f6074f021cc9 Mon Sep 17 00:00:00 2001 From: tastybento Date: Sat, 8 Jul 2023 08:39:00 -0700 Subject: [PATCH 09/30] Refactor, use if statements instead of switches --- .../dataobjects/BlueprintBlock.java | 33 ++++++++----------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/src/main/java/world/bentobox/bentobox/blueprints/dataobjects/BlueprintBlock.java b/src/main/java/world/bentobox/bentobox/blueprints/dataobjects/BlueprintBlock.java index f7b9e5a4e..52661a8e5 100644 --- a/src/main/java/world/bentobox/bentobox/blueprints/dataobjects/BlueprintBlock.java +++ b/src/main/java/world/bentobox/bentobox/blueprints/dataobjects/BlueprintBlock.java @@ -164,10 +164,11 @@ public class BlueprintBlock { * @since 1.24.0 */ public void setGlowingText(Side side, boolean glowingText) { - switch (side) { - case FRONT -> this.glowingText = glowingText; - default -> this.glowingText2 = glowingText; - }; + if (side == Side.FRONT) { + this.glowingText = glowingText; + } else { + this.glowingText2 = glowingText; + } } @@ -177,10 +178,8 @@ public class BlueprintBlock { * @since 1.24.0 */ public boolean isGlowingText(Side side) { - return switch (side) { - case FRONT -> glowingText; - default -> glowingText2; - }; + if (side == Side.FRONT) return glowingText; + return glowingText2; } /** @@ -189,10 +188,8 @@ public class BlueprintBlock { * @since 1.24.0 */ public List getSignLines(Side side) { - return switch (side) { - case FRONT -> signLines; - default -> signLines2; - }; + if (side == Side.FRONT) return signLines; + return signLines2; } /** @@ -201,12 +198,10 @@ public class BlueprintBlock { * @since 1.24.0 */ public void setSignLines(Side side, List signLines) { - switch (side) { - case FRONT -> this.signLines = signLines; - default -> this.signLines2 = signLines; - }; + if (side == Side.FRONT) { + this.signLines = signLines; + } else { + this.signLines2 = signLines; + } } - - - } From 9a464ab795274bdc301280d1879a4003aadc2b6c Mon Sep 17 00:00:00 2001 From: tastybento Date: Sat, 8 Jul 2023 08:39:56 -0700 Subject: [PATCH 10/30] Minor refactor - use containsKey method. --- .../java/world/bentobox/bentobox/managers/AddonsManager.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/world/bentobox/bentobox/managers/AddonsManager.java b/src/main/java/world/bentobox/bentobox/managers/AddonsManager.java index 8ccc1bc88..153141d8d 100644 --- a/src/main/java/world/bentobox/bentobox/managers/AddonsManager.java +++ b/src/main/java/world/bentobox/bentobox/managers/AddonsManager.java @@ -188,7 +188,7 @@ public class AddonsManager { } private PladdonData loadPladdon(YamlConfiguration data, @NonNull File f) throws InvalidAddonInheritException, MalformedURLException, InvalidAddonDescriptionException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException, InvalidDescriptionException { - Addon addon = null; + Addon addon; try { Plugin pladdon = Bukkit.getPluginManager().loadPlugin(f); if (pladdon instanceof Pladdon pl) { @@ -451,7 +451,7 @@ public class AddonsManager { if (!getEnabledAddons().isEmpty()) { plugin.log("Disabling addons..."); // Disable addons - pladdons are disabled by the server - getEnabledAddons().stream().filter(addon -> !pladdons.keySet().contains(addon)).forEach(this::disable); + getEnabledAddons().stream().filter(addon -> !pladdons.containsKey(addon)).forEach(this::disable); plugin.log("Addons successfully disabled."); } // Unregister all commands From 4ef974fbde55aaa450d4e0d092d2e165eae3b70f Mon Sep 17 00:00:00 2001 From: tastybento Date: Sat, 8 Jul 2023 08:52:20 -0700 Subject: [PATCH 11/30] Better error for unknown icon material, and test class --- .../bentobox/api/addons/AddonClassLoader.java | 6 ++++- .../api/addons/AddonClassLoaderTest.java | 22 +++++++++++++++++-- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/main/java/world/bentobox/bentobox/api/addons/AddonClassLoader.java b/src/main/java/world/bentobox/bentobox/api/addons/AddonClassLoader.java index 2efa293f6..1e765ceb8 100644 --- a/src/main/java/world/bentobox/bentobox/api/addons/AddonClassLoader.java +++ b/src/main/java/world/bentobox/bentobox/api/addons/AddonClassLoader.java @@ -125,7 +125,11 @@ public class AddonClassLoader extends URLClassLoader { if (softDepend != null) { builder.softDependencies(Arrays.asList(softDepend.split("\\s*,\\s*"))); } - builder.icon(Objects.requireNonNull(Material.getMaterial(data.getString("icon", "PAPER").toUpperCase(Locale.ENGLISH)))); + Material icon = Material.getMaterial(data.getString("icon", "PAPER").toUpperCase(Locale.ENGLISH)); + if (icon == null) { + throw new InvalidAddonDescriptionException("'icon' tag refers to an unknown Material: " + data.getString("icon")); + } + builder.icon(Objects.requireNonNull(icon)); String apiVersion = data.getString("api-version"); if (apiVersion != null) { diff --git a/src/test/java/world/bentobox/bentobox/api/addons/AddonClassLoaderTest.java b/src/test/java/world/bentobox/bentobox/api/addons/AddonClassLoaderTest.java index 3664f7e46..16eb982b1 100644 --- a/src/test/java/world/bentobox/bentobox/api/addons/AddonClassLoaderTest.java +++ b/src/test/java/world/bentobox/bentobox/api/addons/AddonClassLoaderTest.java @@ -53,7 +53,8 @@ public class AddonClassLoaderTest { MAIN, NAME, VERSION, - AUTHORS + AUTHORS, + ICON } /** * Used for file writing etc. @@ -129,7 +130,11 @@ public class AddonClassLoaderTest { r.set("repository", "repo"); r.set("depend", "Level, Warps"); r.set("softdepend", "Boxed, AcidIsland"); - r.set("icon", "IRON_INGOT"); + if (!missingTags.contains(mandatoryTags.ICON)) { + r.set("icon", "IRON_INGOT"); + } else { + r.set("icon", "unkOwnMateriaL"); + } r.set("api-version", "1.21-SNAPSHOT"); return r; } @@ -278,6 +283,19 @@ public class AddonClassLoaderTest { } } + /** + * Test method for {@link world.bentobox.bentobox.api.addons.AddonClassLoader#asDescription(org.bukkit.configuration.file.YamlConfiguration)}. + */ + @Test + public void testAsDescriptionUnknownIconMaterial() { + YamlConfiguration yml = this.getYaml(List.of(mandatoryTags.ICON)); + try { + AddonClassLoader.asDescription(yml); + } catch (InvalidAddonDescriptionException e) { + assertEquals("AddonException : 'icon' tag refers to an unknown Material: unkOwnMateriaL", e.getMessage()); + } + } + /** * Test method for {@link world.bentobox.bentobox.api.addons.AddonClassLoader#findClass(java.lang.String)}. */ From 211d636bfbf874545b94af1e6665ada125dd563b Mon Sep 17 00:00:00 2001 From: tastybento Date: Sat, 8 Jul 2023 15:02:50 -0700 Subject: [PATCH 12/30] Remove dependency on apache util --- src/main/java/world/bentobox/bentobox/util/Util.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/java/world/bentobox/bentobox/util/Util.java b/src/main/java/world/bentobox/bentobox/util/Util.java index b804d5d73..574fea82f 100644 --- a/src/main/java/world/bentobox/bentobox/util/Util.java +++ b/src/main/java/world/bentobox/bentobox/util/Util.java @@ -13,7 +13,6 @@ import java.util.jar.JarFile; import java.util.regex.Matcher; import java.util.regex.Pattern; -import org.apache.commons.lang.Validate; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.Chunk; @@ -578,7 +577,7 @@ public class Util { */ @NonNull public static String stripSpaceAfterColorCodes(@NonNull String textToStrip) { - Validate.notNull(textToStrip, "Cannot strip null text"); + if (textToStrip == null) return ""; textToStrip = textToStrip.replaceAll("(" + ChatColor.COLOR_CHAR + ".)[\\s]", "$1"); return textToStrip; } @@ -738,7 +737,7 @@ public class Util { } return regenerator; } - + /** * Checks what version the server is running and picks the appropriate NMS handler, or fallback * @return PasteHandler From 170c31fcecf09dacd93da56e250e46d6bb4ee669 Mon Sep 17 00:00:00 2001 From: tastybento Date: Sun, 9 Jul 2023 15:07:37 -0700 Subject: [PATCH 13/30] Judge location of damage by location of entity not user --- .../flags/protection/HurtingListener.java | 4 +-- .../flags/protection/HurtingListenerTest.java | 25 +++++++++---------- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/src/main/java/world/bentobox/bentobox/listeners/flags/protection/HurtingListener.java b/src/main/java/world/bentobox/bentobox/listeners/flags/protection/HurtingListener.java index 1ffc2e704..942cb7edb 100644 --- a/src/main/java/world/bentobox/bentobox/listeners/flags/protection/HurtingListener.java +++ b/src/main/java/world/bentobox/bentobox/listeners/flags/protection/HurtingListener.java @@ -75,9 +75,9 @@ public class HurtingListener extends FlagListener { private void respond(EntityDamageByEntityEvent e, Entity damager, Flag flag) { // Get the attacker if (damager instanceof Player player) { - checkIsland(e, player, player.getLocation(), flag); + checkIsland(e, player, e.getEntity().getLocation(), flag); } else if (damager instanceof Projectile p && // Find out who fired the projectile - p.getShooter() instanceof Player player && !checkIsland(e, player, player.getLocation(), flag)) { + p.getShooter() instanceof Player player && !checkIsland(e, player, e.getEntity().getLocation(), flag)) { e.getEntity().setFireTicks(0); } } diff --git a/src/test/java/world/bentobox/bentobox/listeners/flags/protection/HurtingListenerTest.java b/src/test/java/world/bentobox/bentobox/listeners/flags/protection/HurtingListenerTest.java index 596fba8ca..1cb33d1bf 100644 --- a/src/test/java/world/bentobox/bentobox/listeners/flags/protection/HurtingListenerTest.java +++ b/src/test/java/world/bentobox/bentobox/listeners/flags/protection/HurtingListenerTest.java @@ -3,7 +3,6 @@ package world.bentobox.bentobox.listeners.flags.protection; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; @@ -93,7 +92,7 @@ public class HurtingListenerTest extends AbstractCommonSetup { HurtingListener hl = new HurtingListener(); hl.onEntityDamage(e); assertTrue(e.isCancelled()); - verify(notifier).notify(eq(user), eq("protection.protected")); + verify(notifier).notify(user, "protection.protected"); } /** @@ -106,7 +105,7 @@ public class HurtingListenerTest extends AbstractCommonSetup { HurtingListener hl = new HurtingListener(); hl.onEntityDamage(e); assertFalse(e.isCancelled()); - verify(notifier, never()).notify(eq(user), eq("protection.protected")); + verify(notifier, never()).notify(user, "protection.protected"); } /** @@ -121,7 +120,7 @@ public class HurtingListenerTest extends AbstractCommonSetup { HurtingListener hl = new HurtingListener(); hl.onFishing(e); // Verify - verify(notifier).notify(eq(user), eq("protection.protected")); + verify(notifier).notify(user, "protection.protected"); } /** @@ -138,7 +137,7 @@ public class HurtingListenerTest extends AbstractCommonSetup { when(island.isAllowed(any(), any())).thenReturn(true); hl.onFishing(e); // Verify - verify(notifier, never()).notify(eq(user), eq("protection.protected")); + verify(notifier, never()).notify(user, "protection.protected"); } /** @@ -153,7 +152,7 @@ public class HurtingListenerTest extends AbstractCommonSetup { HurtingListener hl = new HurtingListener(); hl.onFishing(e); // Verify - verify(notifier).notify(eq(user), eq("protection.protected")); + verify(notifier).notify(user, "protection.protected"); } /** @@ -170,7 +169,7 @@ public class HurtingListenerTest extends AbstractCommonSetup { when(island.isAllowed(any(), any())).thenReturn(true); hl.onFishing(e); // Verify - verify(notifier, never()).notify(eq(user), eq("protection.protected")); + verify(notifier, never()).notify(user, "protection.protected"); } /** @@ -185,7 +184,7 @@ public class HurtingListenerTest extends AbstractCommonSetup { HurtingListener hl = new HurtingListener(); hl.onFishing(e); // Verify - verify(notifier).notify(eq(user), eq("protection.protected")); + verify(notifier).notify(user, "protection.protected"); } /** @@ -202,7 +201,7 @@ public class HurtingListenerTest extends AbstractCommonSetup { when(island.isAllowed(any(), any())).thenReturn(true); hl.onFishing(e); // Verify - verify(notifier, never()).notify(eq(user), eq("protection.protected")); + verify(notifier, never()).notify(user, "protection.protected"); } /** @@ -218,7 +217,7 @@ public class HurtingListenerTest extends AbstractCommonSetup { HurtingListener hl = new HurtingListener(); hl.onFishing(e); // Verify - verify(notifier).notify(eq(user), eq("protection.protected")); + verify(notifier).notify(user, "protection.protected"); } /** @@ -234,7 +233,7 @@ public class HurtingListenerTest extends AbstractCommonSetup { HurtingListener hl = new HurtingListener(); hl.onFishing(e); // Verify - verify(notifier).notify(eq(user), eq("protection.protected")); + verify(notifier).notify(user, "protection.protected"); } @@ -253,7 +252,7 @@ public class HurtingListenerTest extends AbstractCommonSetup { when(island.isAllowed(any(), any())).thenReturn(true); hl.onFishing(e); // Verify - verify(notifier, never()).notify(eq(user), eq("protection.protected")); + verify(notifier, never()).notify(user, "protection.protected"); } /** @@ -271,7 +270,7 @@ public class HurtingListenerTest extends AbstractCommonSetup { when(island.isAllowed(any(), any())).thenReturn(true); hl.onFishing(e); // Verify - verify(notifier, never()).notify(eq(user), eq("protection.protected")); + verify(notifier, never()).notify(user, "protection.protected"); } /** From 988ace83291363386ae47c5d8b20c2d6e59ade0e Mon Sep 17 00:00:00 2001 From: tastybento Date: Mon, 10 Jul 2023 21:18:58 -0700 Subject: [PATCH 14/30] Update to latest Jacoco --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 477d211b5..a579060e4 100644 --- a/pom.xml +++ b/pom.xml @@ -507,7 +507,7 @@ org.jacoco jacoco-maven-plugin - 0.8.7 + 0.8.10 true From c5baa1d0ebb8daac7f13b184b31ef6bc7801fc62 Mon Sep 17 00:00:00 2001 From: tastybento Date: Mon, 10 Jul 2023 22:08:02 -0700 Subject: [PATCH 15/30] Refactor to reduce complexity --- .../commands/admin/AdminSettingsCommand.java | 81 +++++++++++-------- 1 file changed, 48 insertions(+), 33 deletions(-) diff --git a/src/main/java/world/bentobox/bentobox/api/commands/admin/AdminSettingsCommand.java b/src/main/java/world/bentobox/bentobox/api/commands/admin/AdminSettingsCommand.java index 7e34456b6..b7e450a36 100644 --- a/src/main/java/world/bentobox/bentobox/api/commands/admin/AdminSettingsCommand.java +++ b/src/main/java/world/bentobox/bentobox/api/commands/admin/AdminSettingsCommand.java @@ -107,51 +107,66 @@ public class AdminSettingsCommand extends CompositeCommand { /** * Check that this command is correct to set a setting + * * @param user - user * @param args - args * @return true if the syntax is correct */ private boolean checkSyntax(User user, List args) { - // Update the flag lists this.makeLists(); - if (args.size() == 2) { - // Should be a world setting - // If world settings, then active/disabled, otherwise player flags - if (worldSettingFlagNames.contains(args.get(0).toUpperCase(Locale.ENGLISH))) { - if (checkActiveDisabled(user, args.get(1))) { - flag = getPlugin().getFlagsManager().getFlag(args.get(0).toUpperCase(Locale.ENGLISH)); - return true; - } - } else { - this.showHelp(this, user); - return false; - } - } else if (args.size() > 2) { - // Get island - if (!getIsland(user, args)) { - return false; - } - if (!settingFlagNames.contains(args.get(1).toUpperCase(Locale.ENGLISH)) - && !protectionFlagNames.contains(args.get(1).toUpperCase(Locale.ENGLISH))) { - user.sendMessage("commands.admin.settings.unknown-flag", TextVariables.NAME, args.get(2)); - return false; - } - // Set flag - flag = getPlugin().getFlagsManager().getFlag(args.get(1).toUpperCase(Locale.ENGLISH)); - // Check settings - if (flag.isPresent()) { - if (flag.get().getType().equals(Type.SETTING)) { - return checkActiveDisabled(user, args.get(2)); - } else { - // Protection flag - return checkRank(user, String.join(" ", args.subList(2, args.size()))); - } + int argSize = args.size(); + + if (argSize == 2) { + return checkWorldSetting(user, args); + } else if (argSize > 2) { + return checkIslandSetting(user, args); + } + + return false; + } + + private boolean checkWorldSetting(User user, List args) { + String arg0 = args.get(0).toUpperCase(Locale.ENGLISH); + + if (worldSettingFlagNames.contains(arg0)) { + if (checkActiveDisabled(user, args.get(1))) { + flag = getPlugin().getFlagsManager().getFlag(args.get(0).toUpperCase(Locale.ENGLISH)); + return true; } + } else { + this.showHelp(this, user); + return false; } return false; } + private boolean checkIslandSetting(User user, List args) { + // Get island + if (!getIsland(user, args)) { + return false; + } + + String arg1 = args.get(1).toUpperCase(Locale.ENGLISH); + + if (!settingFlagNames.contains(arg1) && !protectionFlagNames.contains(arg1)) { + user.sendMessage("commands.admin.settings.unknown-flag", TextVariables.NAME, args.get(2)); + return false; + } + // Set flag + flag = getPlugin().getFlagsManager().getFlag(arg1); + // Check settings + if (flag.isPresent()) { + if (flag.get().getType().equals(Type.SETTING)) { + return checkActiveDisabled(user, args.get(2)); + } else { + // Protection flag + return checkRank(user, String.join(" ", args.subList(2, args.size()))); + } + } + + return false; + } /** * Check the rank given. From a6bb78c80f3d4177bd9743083f39690679a4ee53 Mon Sep 17 00:00:00 2001 From: tastybento Date: Mon, 10 Jul 2023 22:25:30 -0700 Subject: [PATCH 16/30] Refactor to reduce complexity --- .../island/team/IslandTeamInviteCommand.java | 119 ++++++++++++------ .../team/IslandTeamInviteCommandTest.java | 27 ++-- 2 files changed, 98 insertions(+), 48 deletions(-) diff --git a/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamInviteCommand.java b/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamInviteCommand.java index 5eb674a4c..3335075b9 100644 --- a/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamInviteCommand.java +++ b/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamInviteCommand.java @@ -15,6 +15,8 @@ import world.bentobox.bentobox.api.events.team.TeamEvent; import world.bentobox.bentobox.api.localization.TextVariables; import world.bentobox.bentobox.api.user.User; import world.bentobox.bentobox.database.objects.Island; +import world.bentobox.bentobox.managers.IslandsManager; +import world.bentobox.bentobox.managers.PlayersManager; import world.bentobox.bentobox.managers.RanksManager; import world.bentobox.bentobox.util.Util; @@ -39,74 +41,121 @@ public class IslandTeamInviteCommand extends CompositeCommand { @Override public boolean canExecute(User user, String label, List args) { + UUID playerUUID = user.getUniqueId(); + IslandsManager islandsManager = getIslands(); + // Player issuing the command must have an island or be in a team - if (!getIslands().inTeam(getWorld(), user.getUniqueId()) && !getIslands().hasIsland(getWorld(), user.getUniqueId())) { + if (!islandsManager.inTeam(getWorld(), playerUUID) && !islandsManager.hasIsland(getWorld(), playerUUID)) { user.sendMessage("general.errors.no-island"); return false; } - UUID playerUUID = user.getUniqueId(); + if (args.size() != 1) { - // Invite label with no name, i.e., /island invite - tells the player who has invited them so far and why - if (itc.isInvited(playerUUID)) { - Invite invite = itc.getInvite(playerUUID); - String name = getPlayers().getName(playerUUID); - switch (invite.getType()) { - case COOP -> user.sendMessage("commands.island.team.invite.name-has-invited-you.coop", TextVariables.NAME, name); - case TRUST -> user.sendMessage("commands.island.team.invite.name-has-invited-you.trust", TextVariables.NAME, name); - default -> user.sendMessage("commands.island.team.invite.name-has-invited-you", TextVariables.NAME, name); - } - return true; - } - // Show help - showHelp(this, user); - return false; + return handleCommandWithNoArgs(user); } - // Check rank to use command - Island island = getIslands().getIsland(getWorld(), user); + + Island island = islandsManager.getIsland(getWorld(), user); int rank = Objects.requireNonNull(island).getRank(user); - if (rank < island.getRankCommand(getUsage())) { - user.sendMessage("general.errors.insufficient-rank", TextVariables.RANK, user.getTranslation(getPlugin().getRanksManager().getRank(rank))); + + return checkRankAndInvitePlayer(user, island, rank, args.get(0)); + } + + private boolean handleCommandWithNoArgs(User user) { + UUID playerUUID = user.getUniqueId(); + Type inviteType = getInviteType(playerUUID); + + if (inviteType != null) { + String name = getPlayers().getName(playerUUID); + switch (inviteType) { + case COOP -> user.sendMessage("commands.island.team.invite.name-has-invited-you.coop", TextVariables.NAME, name); + case TRUST -> user.sendMessage("commands.island.team.invite.name-has-invited-you.trust", TextVariables.NAME, name); + default -> user.sendMessage("commands.island.team.invite.name-has-invited-you", TextVariables.NAME, name); + } + return true; + } + + showHelp(this, user); + return false; + } + + private boolean checkRankAndInvitePlayer(User user, Island island, int rank, String playerName) { + RanksManager ranksManager = getPlugin().getRanksManager(); + PlayersManager playersManager = getPlayers(); + UUID playerUUID = user.getUniqueId(); + + // Check rank to use command + int requiredRank = island.getRankCommand(getUsage()); + if (rank < requiredRank) { + user.sendMessage("general.errors.insufficient-rank", TextVariables.RANK, user.getTranslation(ranksManager.getRank(rank))); return false; } + // Check for space on team - if (island.getMemberSet().size() >= getIslands().getMaxMembers(island, RanksManager.MEMBER_RANK)) { + int maxMembers = getIslands().getMaxMembers(island, RanksManager.MEMBER_RANK); + if (island.getMemberSet().size() >= maxMembers) { user.sendMessage("commands.island.team.invite.errors.island-is-full"); return false; } - UUID invitedPlayerUUID = getPlayers().getUUID(args.get(0)); + UUID invitedPlayerUUID = playersManager.getUUID(playerName); if (invitedPlayerUUID == null) { - user.sendMessage("general.errors.unknown-player", TextVariables.NAME, args.get(0)); + user.sendMessage("general.errors.unknown-player", TextVariables.NAME, playerName); return false; } - // Only online players can be invited + // Write to field as this is used by execute method invitedPlayer = User.getInstance(invitedPlayerUUID); - if (!invitedPlayer.isOnline() || !user.getPlayer().canSee(invitedPlayer.getPlayer())) { - user.sendMessage("general.errors.offline-player"); + if (!canInvitePlayer(user, invitedPlayer)) { return false; } - // Player cannot invite themselves - if (playerUUID.equals(invitedPlayerUUID)) { - user.sendMessage("commands.island.team.invite.errors.cannot-invite-self"); - return false; - } - // Check cool down - if (getSettings().getInviteCooldown() > 0 && checkCooldown(user, getIslands().getIsland(getWorld(), user).getUniqueId(), invitedPlayerUUID.toString())) { + + // Check cooldown + if (this.getSettings().getInviteCooldown() > 0 && checkCooldown(user, island.getUniqueId(), invitedPlayerUUID.toString())) { return false; } + // Player cannot invite someone already on a team if (getIslands().inTeam(getWorld(), invitedPlayerUUID)) { user.sendMessage("commands.island.team.invite.errors.already-on-team"); return false; } - if (itc.isInvited(invitedPlayerUUID) && itc.getInviter(invitedPlayerUUID).equals(user.getUniqueId()) && itc.getInvite(invitedPlayerUUID).getType().equals(Type.TEAM)) { - // Prevent spam + + if (isInvitedByUser(invitedPlayerUUID, playerUUID) && isInviteTypeTeam(invitedPlayerUUID)) { user.sendMessage("commands.island.team.invite.errors.you-have-already-invited"); return false; } + return true; } + private Type getInviteType(UUID playerUUID) { + if (itc.isInvited(playerUUID)) { + Invite invite = itc.getInvite(playerUUID); + return invite.getType(); + } + return null; + } + + private boolean canInvitePlayer(User user, User invitedPlayer) { + UUID playerUUID = user.getUniqueId(); + if (!invitedPlayer.isOnline() || !user.getPlayer().canSee(invitedPlayer.getPlayer())) { + user.sendMessage("general.errors.offline-player"); + return false; + } + if (playerUUID.equals(invitedPlayer.getUniqueId())) { + user.sendMessage("commands.island.team.invite.errors.cannot-invite-self"); + return false; + } + return true; + } + + private boolean isInvitedByUser(UUID invitedPlayerUUID, UUID inviterUUID) { + return itc.isInvited(invitedPlayerUUID) && itc.getInviter(invitedPlayerUUID).equals(inviterUUID); + } + + private boolean isInviteTypeTeam(UUID invitedPlayerUUID) { + return itc.getInvite(invitedPlayerUUID).getType().equals(Type.TEAM); + } + @Override public boolean execute(User user, String label, List args) { // Rare case when invited player is null. Could be a race condition. diff --git a/src/test/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamInviteCommandTest.java b/src/test/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamInviteCommandTest.java index de0b1da13..38ae1ba94 100644 --- a/src/test/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamInviteCommandTest.java +++ b/src/test/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamInviteCommandTest.java @@ -13,6 +13,7 @@ import static org.mockito.Mockito.when; import java.util.Collections; import java.util.HashMap; +import java.util.List; import java.util.UUID; import org.bukkit.Bukkit; @@ -182,7 +183,7 @@ public class IslandTeamInviteCommandTest { // 10 minutes = 600 seconds when(s.getInviteCooldown()).thenReturn(10); itl.setCooldown(islandUUID, notUUID, 100); - assertFalse(itl.canExecute(user, itl.getLabel(), Collections.singletonList("target"))); + assertFalse(itl.canExecute(user, itl.getLabel(), List.of("target"))); verify(user).sendMessage(eq("general.errors.you-must-wait"), eq(TextVariables.NUMBER), anyString()); } @@ -192,7 +193,7 @@ public class IslandTeamInviteCommandTest { @Test public void testCanExecuteDifferentPlayerInTeam() { when(im.inTeam(any(), any())).thenReturn(true); - assertFalse(itl.canExecute(user, itl.getLabel(), Collections.singletonList("target"))); + assertFalse(itl.canExecute(user, itl.getLabel(), List.of("target"))); verify(user).sendMessage(eq("commands.island.team.invite.errors.already-on-team")); } @@ -203,7 +204,7 @@ public class IslandTeamInviteCommandTest { public void testCanExecuteLowRank() { when(island.getRank(any(User.class))).thenReturn(RanksManager.MEMBER_RANK); when(island.getRankCommand(anyString())).thenReturn(RanksManager.OWNER_RANK); - assertFalse(itl.canExecute(user, itl.getLabel(), Collections.singletonList("target"))); + assertFalse(itl.canExecute(user, itl.getLabel(), List.of("target"))); verify(user).sendMessage(eq("general.errors.insufficient-rank"), eq(TextVariables.RANK), eq("ranks.member")); } @@ -214,7 +215,7 @@ public class IslandTeamInviteCommandTest { public void testCanExecuteNoIsland() { when(im.hasIsland(any(), any(UUID.class))).thenReturn(false); when(im.inTeam(any(), any(UUID.class))).thenReturn(false); - assertFalse(itl.canExecute(user, itl.getLabel(), Collections.singletonList("target"))); + assertFalse(itl.canExecute(user, itl.getLabel(), List.of("target"))); verify(user).sendMessage(eq("general.errors.no-island")); } @@ -235,7 +236,7 @@ public class IslandTeamInviteCommandTest { @Test public void testCanExecuteOfflinePlayer() { when(target.isOnline()).thenReturn(false); - assertFalse(itl.canExecute(user, itl.getLabel(), Collections.singletonList("target"))); + assertFalse(itl.canExecute(user, itl.getLabel(), List.of("target"))); verify(user).sendMessage(eq("general.errors.offline-player")); } @@ -245,7 +246,7 @@ public class IslandTeamInviteCommandTest { @Test public void testCanExecuteVanishedPlayer() { when(p.canSee(any())).thenReturn(false); - assertFalse(itl.canExecute(user, itl.getLabel(), Collections.singletonList("target"))); + assertFalse(itl.canExecute(user, itl.getLabel(), List.of("target"))); verify(user).sendMessage(eq("general.errors.offline-player")); } @@ -255,7 +256,7 @@ public class IslandTeamInviteCommandTest { */ @Test public void testCanExecuteSamePlayer() { - assertFalse(itl.canExecute(user, itl.getLabel(), Collections.singletonList("tastybento"))); + assertFalse(itl.canExecute(user, itl.getLabel(), List.of("tastybento"))); verify(user).sendMessage(eq("commands.island.team.invite.errors.cannot-invite-self")); } @@ -264,7 +265,7 @@ public class IslandTeamInviteCommandTest { */ @Test public void testCanExecuteSuccess() { - assertTrue(itl.canExecute(user, itl.getLabel(), Collections.singletonList("target"))); + assertTrue(itl.canExecute(user, itl.getLabel(), List.of("target"))); } /** @@ -273,7 +274,7 @@ public class IslandTeamInviteCommandTest { @Test public void testCanExecuteUnknownPlayer() { when(pm.getUUID(eq("target"))).thenReturn(null); - assertFalse(itl.canExecute(user, itl.getLabel(), Collections.singletonList("target"))); + assertFalse(itl.canExecute(user, itl.getLabel(), List.of("target"))); verify(user).sendMessage(eq("general.errors.unknown-player"), eq(TextVariables.NAME), eq("target")); } @@ -284,7 +285,7 @@ public class IslandTeamInviteCommandTest { @Test public void testCanExecuteFullIsland() { when(im.getMaxMembers(eq(island), anyInt())).thenReturn(0); - assertFalse(itl.canExecute(user, itl.getLabel(), Collections.singletonList("target"))); + assertFalse(itl.canExecute(user, itl.getLabel(), List.of("target"))); verify(user).sendMessage(eq("commands.island.team.invite.errors.island-is-full")); } @@ -295,7 +296,7 @@ public class IslandTeamInviteCommandTest { public void testExecuteSuccessTargetHasIsland() { when(im.hasIsland(any(), eq(notUUID))).thenReturn(true); testCanExecuteSuccess(); - assertTrue(itl.execute(user, itl.getLabel(), Collections.singletonList("target"))); + assertTrue(itl.execute(user, itl.getLabel(), List.of("target"))); verify(pim).callEvent(any(IslandBaseEvent.class)); verify(user, never()).sendMessage(eq("commands.island.team.invite.removing-invite")); verify(ic).addInvite(eq(Invite.Type.TEAM), eq(uuid), eq(notUUID)); @@ -312,7 +313,7 @@ public class IslandTeamInviteCommandTest { @Test public void testExecuteSuccessTargetHasNoIsland() { testCanExecuteSuccess(); - assertTrue(itl.execute(user, itl.getLabel(), Collections.singletonList("target"))); + assertTrue(itl.execute(user, itl.getLabel(), List.of("target"))); verify(pim).callEvent(any(IslandBaseEvent.class)); verify(user, never()).sendMessage("commands.island.team.invite.removing-invite"); verify(ic).addInvite(Invite.Type.TEAM, uuid, notUUID); @@ -336,7 +337,7 @@ public class IslandTeamInviteCommandTest { Invite invite = mock(Invite.class); when(invite.getType()).thenReturn(Type.TEAM); when(ic.getInvite(notUUID)).thenReturn(invite); - assertTrue(itl.execute(user, itl.getLabel(), Collections.singletonList("target"))); + assertTrue(itl.execute(user, itl.getLabel(), List.of("target"))); verify(pim).callEvent(any(IslandBaseEvent.class)); verify(ic).removeInvite(notUUID); verify(user).sendMessage("commands.island.team.invite.removing-invite"); From 585f720f6f4a7e9480af5065469c92e23e5a987e Mon Sep 17 00:00:00 2001 From: tastybento Date: Mon, 10 Jul 2023 22:48:33 -0700 Subject: [PATCH 17/30] Reduce complexity --- .../bentobox/api/panels/TemplatedPanel.java | 168 +++++++----------- 1 file changed, 66 insertions(+), 102 deletions(-) diff --git a/src/main/java/world/bentobox/bentobox/api/panels/TemplatedPanel.java b/src/main/java/world/bentobox/bentobox/api/panels/TemplatedPanel.java index 0968e6630..438735754 100644 --- a/src/main/java/world/bentobox/bentobox/api/panels/TemplatedPanel.java +++ b/src/main/java/world/bentobox/bentobox/api/panels/TemplatedPanel.java @@ -65,153 +65,117 @@ public class TemplatedPanel extends Panel private void generatePanel() { Map items = switch (this.panelTemplate.type()) - { + { case INVENTORY -> this.populateInventoryPanel(); case HOPPER -> this.populateHopperPanel(); case DROPPER -> this.populateDropperPanel(); - }; + }; - super.makePanel(this.user.getTranslation(this.panelTemplate.title(), this.parameters), - items, - items.keySet().stream().max(Comparator.naturalOrder()).orElse(9), - this.user, - this.getListener().orElse(null), - this.panelTemplate.type()); + super.makePanel(this.user.getTranslation(this.panelTemplate.title(), this.parameters), + items, + items.keySet().stream().max(Comparator.naturalOrder()).orElse(9), + this.user, + this.getListener().orElse(null), + this.panelTemplate.type()); } - /** * This method creates map with item indexes and their icons that will be added into * Inventory Panel. * @return Map that contains indexes linked to the correct panel item. */ @NonNull - private Map populateInventoryPanel() - { - // Init item array with the max available size. + private Map populateInventoryPanel() { PanelItem[][] itemArray = new PanelItem[6][9]; + processItemData(itemArray); + removeEmptyLines(itemArray); + fillBorder(itemArray); + fillBackground(itemArray); + return createItemMap(itemArray); + } + private void processItemData(PanelItem[][] itemArray) { // Analyze the GUI button layout a bit. - for (int i = 0; i < this.panelTemplate.content().length; i++) - { - for (int k = 0; k < this.panelTemplate.content()[i].length; k++) - { - ItemTemplateRecord rec = this.panelTemplate.content()[i][k]; - - if (rec != null && rec.dataMap().containsKey("type")) - { + for (int i = 0; i < panelTemplate.content().length; i++) { + for (int k = 0; k < panelTemplate.content()[i].length; k++) { + ItemTemplateRecord rec = panelTemplate.content()[i][k]; + if (rec != null && rec.dataMap().containsKey("type")) { String type = String.valueOf(rec.dataMap().get("type")); - - int counter = this.typeSlotMap.computeIfAbsent(type, key -> 0); - this.typeSlotMap.put(type, counter + 1); + int counter = typeSlotMap.computeIfAbsent(type, key -> 0); + typeSlotMap.put(type, counter + 1); } + // Make buttons for the GUI + itemArray[i][k] = makeButton(panelTemplate.content()[i][k]); } } + } - // Make buttons for the GUI - for (int i = 0; i < this.panelTemplate.content().length; i++) - { - for (int k = 0; k < this.panelTemplate.content()[i].length; k++) - { - itemArray[i][k] = this.makeButton(this.panelTemplate.content()[i][k]); - } - } - - // After items are created, remove empty lines. - boolean[] showLine = this.panelTemplate.forcedRows(); - - for (int i = 0; i < this.panelTemplate.content().length; i++) - { + private void removeEmptyLines(PanelItem[][] itemArray) { + boolean[] showLine = panelTemplate.forcedRows(); + for (int i = 0; i < panelTemplate.content().length; i++) { boolean emptyLine = true; - - for (int k = 0; emptyLine && k < this.panelTemplate.content()[i].length; k++) - { + for (int k = 0; emptyLine && k < panelTemplate.content()[i].length; k++) { emptyLine = itemArray[i][k] == null; } - - // Do not generate fallback for "empty" lines. showLine[i] = showLine[i] || !emptyLine; } + } - // Now fill the border. - if (this.panelTemplate.border() != null) - { - PanelItem template = this.makeTemplate(this.panelTemplate.border()); - - // Hard codded 6 - for (int i = 0; i < 6; i++) - { - if (i == 0 || i == 5) - { + private void fillBorder(PanelItem[][] itemArray) { + if (panelTemplate.border() != null) { + PanelItem template = makeTemplate(panelTemplate.border()); + // Hard coded 6 + for (int i = 0; i < 6; i++) { + if (i == 0 || i == 5) { // Fill first and last row completely with border. - for (int k = 0; k < 9; k++) - { - if (itemArray[i][k] == null) - { + for (int k = 0; k < 9; k++) { + if (itemArray[i][k] == null) { itemArray[i][k] = template; } } - } - else - { + } else { // Fill first and last element in row with border. - if (itemArray[i][0] == null) - { + if (itemArray[i][0] == null) { itemArray[i][0] = template; } - - if (itemArray[i][8] == null) - { + if (itemArray[i][8] == null) { itemArray[i][8] = template; } } } - - showLine[0] = true; - showLine[5] = true; + panelTemplate.forcedRows()[0] = true; + panelTemplate.forcedRows()[5] = true; } + } - // Now fill the background. - if (this.panelTemplate.background() != null) - { - PanelItem template = this.makeTemplate(this.panelTemplate.background()); - - for (int i = 0; i < 6; i++) - { - for (int k = 0; k < 9; k++) - { - if (itemArray[i][k] == null) - { + private void fillBackground(PanelItem[][] itemArray) { + if (panelTemplate.background() != null) { + PanelItem template = makeTemplate(panelTemplate.background()); + for (int i = 0; i < 6; i++) { + for (int k = 0; k < 9; k++) { + if (itemArray[i][k] == null) { itemArray[i][k] = template; } } } } + } - // Now place all panel items with their indexes into item map. + private Map createItemMap(PanelItem[][] itemArray) { Map itemMap = new HashMap<>(6 * 9); - int correctIndex = 0; - - for (int i = 0; i < itemArray.length; i++) - { - final boolean iterate = showLine[i]; - - for (int k = 0; iterate && k < itemArray[i].length; k++) - { - if (itemArray[i][k] != null) - { + for (int i = 0; i < itemArray.length; i++) { + final boolean iterate = panelTemplate.forcedRows()[i]; + for (int k = 0; iterate && k < itemArray[i].length; k++) { + if (itemArray[i][k] != null) { itemMap.put(correctIndex, itemArray[i][k]); } - correctIndex++; } } - return itemMap; } - /** * This method creates map with item indexes and their icons that will be added into * hopper Panel. @@ -394,8 +358,8 @@ public class TemplatedPanel extends Panel // If there are generic click handlers that could be added, then this is a place // where to process them. - // Click Handlers are managed by custom addon buttons. - return itemBuilder.build(); + // Click Handlers are managed by custom addon buttons. + return itemBuilder.build(); } } @@ -421,8 +385,8 @@ public class TemplatedPanel extends Panel // Get next slot index. ItemSlot itemSlot = this.typeIndex.containsKey(type) ? - this.typeIndex.get(type) : - new ItemSlot(0, this.typeSlotMap); + this.typeIndex.get(type) : + new ItemSlot(0, this.typeSlotMap); this.typeIndex.put(type, itemSlot.nextItemSlot()); // Try to get next object. @@ -475,9 +439,9 @@ public class TemplatedPanel extends Panel } -// --------------------------------------------------------------------- -// Section: Classes -// --------------------------------------------------------------------- + // --------------------------------------------------------------------- + // Section: Classes + // --------------------------------------------------------------------- /** @@ -500,9 +464,9 @@ public class TemplatedPanel extends Panel } -// --------------------------------------------------------------------- -// Section: Variables -// --------------------------------------------------------------------- + // --------------------------------------------------------------------- + // Section: Variables + // --------------------------------------------------------------------- /** From a0b349ec27f2df4ba8b774fd9f549ea3aeb26bda Mon Sep 17 00:00:00 2001 From: tastybento Date: Sat, 15 Jul 2023 16:27:31 -0700 Subject: [PATCH 18/30] Complexity reduction --- .../island/team/IslandTeamInviteCommand.java | 2 +- .../bentobox/api/panels/TemplatedPanel.java | 43 ++++++++++--------- 2 files changed, 24 insertions(+), 21 deletions(-) diff --git a/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamInviteCommand.java b/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamInviteCommand.java index 3335075b9..15c2aaa84 100644 --- a/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamInviteCommand.java +++ b/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamInviteCommand.java @@ -153,7 +153,7 @@ public class IslandTeamInviteCommand extends CompositeCommand { } private boolean isInviteTypeTeam(UUID invitedPlayerUUID) { - return itc.getInvite(invitedPlayerUUID).getType().equals(Type.TEAM); + return Objects.requireNonNull(itc.getInvite(invitedPlayerUUID)).getType().equals(Type.TEAM); } @Override diff --git a/src/main/java/world/bentobox/bentobox/api/panels/TemplatedPanel.java b/src/main/java/world/bentobox/bentobox/api/panels/TemplatedPanel.java index 438735754..aeda7561f 100644 --- a/src/main/java/world/bentobox/bentobox/api/panels/TemplatedPanel.java +++ b/src/main/java/world/bentobox/bentobox/api/panels/TemplatedPanel.java @@ -122,30 +122,33 @@ public class TemplatedPanel extends Panel } private void fillBorder(PanelItem[][] itemArray) { - if (panelTemplate.border() != null) { - PanelItem template = makeTemplate(panelTemplate.border()); - // Hard coded 6 - for (int i = 0; i < 6; i++) { - if (i == 0 || i == 5) { - // Fill first and last row completely with border. - for (int k = 0; k < 9; k++) { - if (itemArray[i][k] == null) { - itemArray[i][k] = template; - } - } - } else { - // Fill first and last element in row with border. - if (itemArray[i][0] == null) { - itemArray[i][0] = template; - } - if (itemArray[i][8] == null) { - itemArray[i][8] = template; + if (panelTemplate.border() == null) { + return; + } + PanelItem template = makeTemplate(panelTemplate.border()); + int numRows = itemArray.length; + int numCols = itemArray[0].length; + + for (int i = 0; i < numRows; i++) { + if (i == 0 || i == numRows - 1) { + // Fill first and last row completely with border. + for (int k = 0; k < numCols; k++) { + if (itemArray[i][k] == null) { + itemArray[i][k] = template; } } + } else { + // Fill first and last element in row with border. + if (itemArray[i][0] == null) { + itemArray[i][0] = template; + } + if (itemArray[i][numCols - 1] == null) { + itemArray[i][numCols - 1] = template; + } } - panelTemplate.forcedRows()[0] = true; - panelTemplate.forcedRows()[5] = true; } + panelTemplate.forcedRows()[0] = true; + panelTemplate.forcedRows()[numRows - 1] = true; } private void fillBackground(PanelItem[][] itemArray) { From 357a8fdc5f5a3e5b70a7650711b7727ca936b5f5 Mon Sep 17 00:00:00 2001 From: tastybento Date: Sat, 15 Jul 2023 16:45:51 -0700 Subject: [PATCH 19/30] Added test class for BlueprintEntity --- .../dataobjects/BlueprintEntityTest.java | 211 ++++++++++++++++++ 1 file changed, 211 insertions(+) create mode 100644 src/test/java/world/bentobox/bentobox/blueprints/dataobjects/BlueprintEntityTest.java diff --git a/src/test/java/world/bentobox/bentobox/blueprints/dataobjects/BlueprintEntityTest.java b/src/test/java/world/bentobox/bentobox/blueprints/dataobjects/BlueprintEntityTest.java new file mode 100644 index 000000000..bb5dec831 --- /dev/null +++ b/src/test/java/world/bentobox/bentobox/blueprints/dataobjects/BlueprintEntityTest.java @@ -0,0 +1,211 @@ +package world.bentobox.bentobox.blueprints.dataobjects; + +import static org.mockito.Mockito.when; + +import java.util.HashMap; +import java.util.Map; + +import org.bukkit.DyeColor; +import org.bukkit.Material; +import org.bukkit.entity.ChestedHorse; +import org.bukkit.entity.Cow; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Horse; +import org.bukkit.entity.Horse.Style; +import org.bukkit.entity.Sheep; +import org.bukkit.entity.Villager; +import org.bukkit.entity.Villager.Profession; +import org.bukkit.entity.Wolf; +import org.bukkit.inventory.ItemStack; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.powermock.modules.junit4.PowerMockRunner; + +/** + * @author tastybento + * + */ +@RunWith(PowerMockRunner.class) +public class BlueprintEntityTest { + + @Mock + private Villager villager; + @Mock + private Sheep sheep; + @Mock + private Wolf wolf; + @Mock + private ChestedHorse chestedHorse; + @Mock + private Cow cow; + @Mock + private Horse horse; + + + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() throws Exception { + when(villager.getProfession()).thenReturn(Profession.LIBRARIAN); + when(villager.getVillagerExperience()).thenReturn(100); + when(villager.getVillagerLevel()).thenReturn(2); + when(villager.getVillagerType()).thenReturn(Villager.Type.PLAINS); + when(sheep.getColor()).thenReturn(DyeColor.BLUE); + when(wolf.isTamed()).thenReturn(true); + when(chestedHorse.isCarryingChest()).thenReturn(true); + when(horse.getDomestication()).thenReturn(50); + when(horse.getStyle()).thenReturn(Horse.Style.WHITE_DOTS); + + } + + /** + * @throws java.lang.Exception + */ + @After + public void tearDown() throws Exception { + Mockito.framework().clearInlineMocks(); + } + + + @Test + public void testConfigureEntityWithVillager() { + BlueprintEntity blueprint = new BlueprintEntity(); + + blueprint.setType(EntityType.VILLAGER); + blueprint.setProfession(Profession.LIBRARIAN); + blueprint.setExperience(100); + blueprint.setVillagerType(Villager.Type.PLAINS); + + blueprint.configureEntity(villager); + + Assert.assertEquals(Profession.LIBRARIAN, villager.getProfession()); + Assert.assertEquals(100, villager.getVillagerExperience()); + Assert.assertEquals(2, villager.getVillagerLevel()); + Assert.assertEquals(Villager.Type.PLAINS, villager.getVillagerType()); + } + + @Test + public void testConfigureEntityWithColorable() { + BlueprintEntity blueprint = new BlueprintEntity(); + + blueprint.setType(EntityType.SHEEP); + blueprint.setColor(DyeColor.BLUE); + + blueprint.configureEntity(sheep); + + Assert.assertEquals(DyeColor.BLUE, sheep.getColor()); + } + + @Test + public void testConfigureEntityWithTameable() { + BlueprintEntity blueprint = new BlueprintEntity(); + + blueprint.setType(EntityType.WOLF); + blueprint.setTamed(true); + + blueprint.configureEntity(wolf); + + Assert.assertTrue(wolf.isTamed()); + } + + @Test + public void testConfigureEntityWithChestedHorse() { + BlueprintEntity blueprint = new BlueprintEntity(); + + blueprint.setType(EntityType.HORSE); + blueprint.setChest(true); + + blueprint.configureEntity(chestedHorse); + + Assert.assertTrue(chestedHorse.isCarryingChest()); + } + + @Test + public void testConfigureEntityWithAgeable() { + BlueprintEntity blueprint = new BlueprintEntity(); + + blueprint.setType(EntityType.COW); + blueprint.setAdult(false); + + blueprint.configureEntity(cow); + + Assert.assertFalse(cow.isAdult()); + } + + @Test + public void testConfigureEntityWithAbstractHorse() { + BlueprintEntity blueprint = new BlueprintEntity(); + + blueprint.setType(EntityType.HORSE); + blueprint.setDomestication(50); + + blueprint.configureEntity(horse); + + Assert.assertEquals(50, horse.getDomestication()); + } + + @Test + public void testConfigureEntityWithHorse() { + BlueprintEntity blueprint = new BlueprintEntity(); + + blueprint.setType(EntityType.HORSE); + blueprint.setStyle(Style.WHITE_DOTS); + + blueprint.configureEntity(horse); + + Assert.assertEquals(Style.WHITE_DOTS, horse.getStyle()); + } + + @Test + public void testGettersAndSetters() { + BlueprintEntity blueprint = new BlueprintEntity(); + + blueprint.setColor(DyeColor.RED); + Assert.assertEquals(DyeColor.RED, blueprint.getColor()); + + blueprint.setType(EntityType.CREEPER); + Assert.assertEquals(EntityType.CREEPER, blueprint.getType()); + + blueprint.setCustomName("My Entity"); + Assert.assertEquals("My Entity", blueprint.getCustomName()); + + blueprint.setTamed(true); + Assert.assertTrue(blueprint.getTamed()); + + blueprint.setChest(true); + Assert.assertTrue(blueprint.getChest()); + + blueprint.setAdult(false); + Assert.assertFalse(blueprint.getAdult()); + + blueprint.setDomestication(75); + Assert.assertEquals(75, blueprint.getDomestication().intValue()); + + Map inventory = new HashMap<>(); + inventory.put(1, new ItemStack(Material.DIAMOND)); + blueprint.setInventory(inventory); + Assert.assertEquals(inventory, blueprint.getInventory()); + + blueprint.setStyle(Style.WHITE); + Assert.assertEquals(Style.WHITE, blueprint.getStyle()); + + blueprint.setLevel(5); + Assert.assertEquals(5, blueprint.getLevel().intValue()); + + blueprint.setProfession(Profession.FARMER); + Assert.assertEquals(Profession.FARMER, blueprint.getProfession()); + + blueprint.setExperience(500); + Assert.assertEquals(500, blueprint.getExperience().intValue()); + + blueprint.setVillagerType(Villager.Type.TAIGA); + Assert.assertEquals(Villager.Type.TAIGA, blueprint.getVillagerType()); + } + +} From 2dfd13659141aaf716e5e64bd37376184c9eed1e Mon Sep 17 00:00:00 2001 From: tastybento Date: Sat, 15 Jul 2023 16:55:59 -0700 Subject: [PATCH 20/30] Added test class --- .../DatabaseConnectionSettingsImplTest.java | 125 ++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 src/test/java/world/bentobox/bentobox/database/DatabaseConnectionSettingsImplTest.java diff --git a/src/test/java/world/bentobox/bentobox/database/DatabaseConnectionSettingsImplTest.java b/src/test/java/world/bentobox/bentobox/database/DatabaseConnectionSettingsImplTest.java new file mode 100644 index 000000000..2c9ecd357 --- /dev/null +++ b/src/test/java/world/bentobox/bentobox/database/DatabaseConnectionSettingsImplTest.java @@ -0,0 +1,125 @@ +package world.bentobox.bentobox.database; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import org.junit.Test; + +import world.bentobox.bentobox.database.DatabaseConnectionSettingsImpl.DatabaseSettings; + +/** + * @author tastybento + * + */ +public class DatabaseConnectionSettingsImplTest { + + private DatabaseSettings setting = new DatabaseSettings( + "localhost", + 3306, + "mydb", + "myuser", + "mypassword", + true, + 10, + Collections.singletonMap("key", "value") + ); + + @Test + public void testConstructorWithDatabaseSettings() { + DatabaseConnectionSettingsImpl.DatabaseSettings settings = new DatabaseConnectionSettingsImpl.DatabaseSettings( + "localhost", + 3306, + "mydb", + "myuser", + "mypassword", + true, + 10, + Collections.singletonMap("key", "value") + ); + + DatabaseConnectionSettingsImpl connectionSettings = new DatabaseConnectionSettingsImpl(settings); + + assertEquals("localhost", connectionSettings.getHost()); + assertEquals(3306, connectionSettings.getPort()); + assertEquals("mydb", connectionSettings.getDatabaseName()); + assertEquals("myuser", connectionSettings.getUsername()); + assertEquals("mypassword", connectionSettings.getPassword()); + assertTrue(connectionSettings.isUseSSL()); + assertEquals(10, connectionSettings.getMaxConnections()); + assertEquals(Collections.singletonMap("key", "value"), connectionSettings.getExtraProperties()); + } + + @Test + public void testConstructorWithAllParameters() { + DatabaseConnectionSettingsImpl connectionSettings = new DatabaseConnectionSettingsImpl(setting); + + assertEquals("localhost", connectionSettings.getHost()); + assertEquals(3306, connectionSettings.getPort()); + assertEquals("mydb", connectionSettings.getDatabaseName()); + assertEquals("myuser", connectionSettings.getUsername()); + assertEquals("mypassword", connectionSettings.getPassword()); + assertTrue(connectionSettings.isUseSSL()); + assertEquals(10, connectionSettings.getMaxConnections()); + assertEquals(Collections.singletonMap("key", "value"), connectionSettings.getExtraProperties()); + } + + @Test + public void testConstructorWithoutExtraProperties() { + DatabaseConnectionSettingsImpl connectionSettings = new DatabaseConnectionSettingsImpl( + "localhost", + 3306, + "mydb", + "myuser", + "mypassword", + true, + 10 + ); + + assertEquals("localhost", connectionSettings.getHost()); + assertEquals(3306, connectionSettings.getPort()); + assertEquals("mydb", connectionSettings.getDatabaseName()); + assertEquals("myuser", connectionSettings.getUsername()); + assertEquals("mypassword", connectionSettings.getPassword()); + assertTrue(connectionSettings.isUseSSL()); + assertEquals(10, connectionSettings.getMaxConnections()); + assertNotNull(connectionSettings.getExtraProperties()); + assertTrue(connectionSettings.getExtraProperties().isEmpty()); + } + + @Test + public void testGettersAndSetters() { + DatabaseConnectionSettingsImpl connectionSettings = new DatabaseConnectionSettingsImpl(setting); + + connectionSettings.setHost("localhost"); + assertEquals("localhost", connectionSettings.getHost()); + + connectionSettings.setPort(3306); + assertEquals(3306, connectionSettings.getPort()); + + connectionSettings.setDatabaseName("mydb"); + assertEquals("mydb", connectionSettings.getDatabaseName()); + + connectionSettings.setUsername("myuser"); + assertEquals("myuser", connectionSettings.getUsername()); + + connectionSettings.setPassword("mypassword"); + assertEquals("mypassword", connectionSettings.getPassword()); + + connectionSettings.setUseSSL(true); + assertTrue(connectionSettings.isUseSSL()); + + connectionSettings.setMaxConnections(10); + assertEquals(10, connectionSettings.getMaxConnections()); + + Map extraProperties = new HashMap<>(); + extraProperties.put("key", "value"); + connectionSettings.setExtraProperties(extraProperties); + assertEquals(extraProperties, connectionSettings.getExtraProperties()); + } +} + From 8ce78c8fe0bd53c7181253fcc3ee9cd3dc57a83e Mon Sep 17 00:00:00 2001 From: tastybento Date: Sat, 15 Jul 2023 17:55:48 -0700 Subject: [PATCH 21/30] Added DefaultPasteUtil test class --- .../bentobox/util/DefaultPasteUtilTest.java | 191 ++++++++++++++++++ 1 file changed, 191 insertions(+) create mode 100644 src/test/java/world/bentobox/bentobox/util/DefaultPasteUtilTest.java diff --git a/src/test/java/world/bentobox/bentobox/util/DefaultPasteUtilTest.java b/src/test/java/world/bentobox/bentobox/util/DefaultPasteUtilTest.java new file mode 100644 index 000000000..f383c7f7d --- /dev/null +++ b/src/test/java/world/bentobox/bentobox/util/DefaultPasteUtilTest.java @@ -0,0 +1,191 @@ +package world.bentobox.bentobox.util; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.block.BlockState; +import org.bukkit.block.Sign; +import org.bukkit.block.data.BlockData; +import org.bukkit.block.data.type.WallSign; +import org.bukkit.block.sign.Side; +import org.bukkit.block.sign.SignSide; +import org.bukkit.entity.Player; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.powermock.modules.junit4.PowerMockRunner; +import org.powermock.reflect.Whitebox; + +import world.bentobox.bentobox.BentoBox; +import world.bentobox.bentobox.api.addons.AddonDescription; +import world.bentobox.bentobox.api.addons.GameModeAddon; +import world.bentobox.bentobox.api.localization.TextVariables; +import world.bentobox.bentobox.api.user.User; +import world.bentobox.bentobox.blueprints.dataobjects.BlueprintBlock; +import world.bentobox.bentobox.database.objects.Island; +import world.bentobox.bentobox.managers.IslandWorldManager; +import world.bentobox.bentobox.managers.LocalesManager; +import world.bentobox.bentobox.managers.PlayersManager; + +/** + * @author tastybento + * + */ +@RunWith(PowerMockRunner.class) +public class DefaultPasteUtilTest { + + @Mock + private BentoBox plugin; + @Mock + private Block block; + @Mock + private Island island; + @Mock + private BlueprintBlock bpSign; + private Side side; + @Mock + private User user; + @Mock + private Player player; + @Mock + private IslandWorldManager iwm; + @Mock + private GameModeAddon addon; + @Mock(extraInterfaces = {WallSign.class}) + BlockData wallSignData; + @Mock(extraInterfaces = {org.bukkit.block.data.type.Sign.class}) + BlockData signData; + @Mock(extraInterfaces = {org.bukkit.block.Sign.class}) + BlockState sign; + + @Mock + private World world; + @Mock + private PlayersManager pm; + + + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() throws Exception { + // Set up plugin + Whitebox.setInternalState(BentoBox.class, "instance", plugin); + AddonDescription desc = new AddonDescription.Builder("", "", "").build(); + when(addon.getDescription()).thenReturn(desc); + when(plugin.getIWM()).thenReturn(iwm); + when(iwm.getAddon(any())).thenReturn(Optional.of(addon)); + side = Side.FRONT; + UUID uuid = UUID.randomUUID(); + when(player.getName()).thenReturn("username"); + when(player.getUniqueId()).thenReturn(uuid); + when(island.getOwner()).thenReturn(uuid); + User.getInstance(player); + when(((WallSign)wallSignData).getFacing()).thenReturn(BlockFace.NORTH); + when(((org.bukkit.block.data.type.Sign)signData).getRotation()).thenReturn(BlockFace.NORTH); + + when(pm.getName(any())).thenReturn("tastybento"); + LocalesManager localesManager = mock(LocalesManager.class); + when(plugin.getLocalesManager()).thenReturn(localesManager); + when(localesManager.getOrDefault(any(), anyString(), anyString())).thenReturn("translated"); + + when(plugin.getPlayers()).thenReturn(pm); + } + + /** + * @throws java.lang.Exception + */ + @After + public void tearDown() throws Exception { + User.clearUsers(); + } + + @Test + public void testWriteSignWithSpawnHere() { + List lines = Collections.singletonList(TextVariables.SPAWN_HERE); + Mockito.when(bpSign.getSignLines(side)).thenReturn(lines); + + when(block.getBlockData()).thenReturn(wallSignData); + when(block.getType()).thenReturn(Material.BAMBOO_WALL_SIGN); + when(block.getWorld()).thenReturn(world); + + DefaultPasteUtil.writeSign(island, block, bpSign, side); + + verify(block).setType(Material.AIR); + + ArgumentCaptor spawnPointCaptor = ArgumentCaptor.forClass(Location.class); + verify(island).setSpawnPoint(any(), spawnPointCaptor.capture()); + Location spawnPoint = spawnPointCaptor.getValue(); + + Assert.assertEquals(block.getWorld(), spawnPoint.getWorld()); + Assert.assertEquals(block.getX() + 0.5D, spawnPoint.getX(), 0.001); + Assert.assertEquals(block.getY(), spawnPoint.getY(), 0.001); + Assert.assertEquals(block.getZ() + 0.5D, spawnPoint.getZ(), 0.001); + Assert.assertEquals(Util.blockFaceToFloat(BlockFace.SOUTH), spawnPoint.getYaw(), 0.001); + Assert.assertEquals(30F, spawnPoint.getPitch(), 0.001); + } + + @Test + public void testWriteSignWithStartText() { + List lines = Collections.singletonList(TextVariables.START_TEXT); + when(bpSign.getSignLines(side)).thenReturn(lines); + when(block.getState()).thenReturn(sign); + when(((Sign) sign).getSide(side)).thenReturn(mock(SignSide.class)); + when(block.getType()).thenReturn(Material.BAMBOO_SIGN); + when(block.getBlockData()).thenReturn(signData); + + DefaultPasteUtil.writeSign(island, block, bpSign, side); + + //verify(((Sign) sign), times(4)).setLine(anyInt(), anyString()); + verify(((Sign) sign).getSide(side), times(4)).setLine(anyInt(), anyString()); + + ArgumentCaptor lineCaptor = ArgumentCaptor.forClass(String.class); + verify(((Sign) sign).getSide(side), times(4)).setLine(anyInt(), lineCaptor.capture()); + + List capturedLines = lineCaptor.getAllValues(); + Assert.assertEquals(Arrays.asList("translated", "translated", "translated", "translated"), capturedLines); + } + + @Test + public void testWriteSignWithoutSpecialText() { + List lines = Arrays.asList(TextVariables.START_TEXT, "Line 2", "Line 3", "Line 4"); + List linesTranslated = Arrays.asList("translated", "translated", "translated", "translated"); + when(bpSign.getSignLines(side)).thenReturn(lines); + + when(block.getBlockData()).thenReturn(signData); + when(block.getState()).thenReturn(sign); + when(((Sign) sign).getSide(side)).thenReturn(mock(SignSide.class)); + when(block.getType()).thenReturn(Material.BAMBOO_SIGN); + + DefaultPasteUtil.writeSign(island, block, bpSign, side); + + verify(((Sign) sign).getSide(side), times(4)).setLine(anyInt(), anyString()); + + ArgumentCaptor lineCaptor = ArgumentCaptor.forClass(String.class); + verify(((Sign) sign).getSide(side), times(4)).setLine(anyInt(), lineCaptor.capture()); + + List capturedLines = lineCaptor.getAllValues(); + Assert.assertEquals(linesTranslated, capturedLines); + } +} From 850939f3a8342d633f626a6719b51328047bef5c Mon Sep 17 00:00:00 2001 From: tastybento Date: Thu, 20 Jul 2023 00:27:27 -0700 Subject: [PATCH 22/30] Fix issue were glow was not removed. If glow was applied to a panel item, but then the glow setting was set to false, the glow was not removed from the panel item. Relates to https://github.com/BentoBoxWorld/AOneBlock/issues/326 --- .../java/world/bentobox/bentobox/api/panels/PanelItem.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/world/bentobox/bentobox/api/panels/PanelItem.java b/src/main/java/world/bentobox/bentobox/api/panels/PanelItem.java index 6354bae6a..64e093508 100644 --- a/src/main/java/world/bentobox/bentobox/api/panels/PanelItem.java +++ b/src/main/java/world/bentobox/bentobox/api/panels/PanelItem.java @@ -130,8 +130,13 @@ public class PanelItem { public void setGlow(boolean glow) { this.glow = glow; if (meta != null) { - meta.addEnchant(Enchantment.ARROW_DAMAGE, 0, glow); + if (glow) { + meta.addEnchant(Enchantment.ARROW_DAMAGE, 0, glow); + } else { + meta.removeEnchant(Enchantment.ARROW_DAMAGE); + } icon.setItemMeta(meta); + } } From 2512a892fd80d59a8171d04f268cc3cff65c91c4 Mon Sep 17 00:00:00 2001 From: tastybento Date: Thu, 20 Jul 2023 00:38:58 -0700 Subject: [PATCH 23/30] Added clearInline Mocks just in case. --- .../bentobox/bentobox/util/teleport/SafeSpotTeleportTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/java/world/bentobox/bentobox/util/teleport/SafeSpotTeleportTest.java b/src/test/java/world/bentobox/bentobox/util/teleport/SafeSpotTeleportTest.java index c20357d38..d69972d8e 100644 --- a/src/test/java/world/bentobox/bentobox/util/teleport/SafeSpotTeleportTest.java +++ b/src/test/java/world/bentobox/bentobox/util/teleport/SafeSpotTeleportTest.java @@ -139,6 +139,7 @@ public class SafeSpotTeleportTest { */ @After public void tearDown() throws Exception { + Mockito.framework().clearInlineMocks(); } /** From 1a0a314ece4a05765441e31c71e40017a1b2f519 Mon Sep 17 00:00:00 2001 From: tastybento Date: Thu, 20 Jul 2023 15:09:14 -0700 Subject: [PATCH 24/30] Added ClosestSafeSpotTeleport class Removed code from the main class that was not being used. e.g., failureRunnable. --- .../teleport/ClosestSafeSpotTeleport.java | 175 +++------- .../teleport/ClosestSafeSpotTeleportTest.java | 307 ++++++++++++++++++ 2 files changed, 359 insertions(+), 123 deletions(-) create mode 100644 src/test/java/world/bentobox/bentobox/util/teleport/ClosestSafeSpotTeleportTest.java diff --git a/src/main/java/world/bentobox/bentobox/util/teleport/ClosestSafeSpotTeleport.java b/src/main/java/world/bentobox/bentobox/util/teleport/ClosestSafeSpotTeleport.java index d25bd0ac0..e124e63ed 100644 --- a/src/main/java/world/bentobox/bentobox/util/teleport/ClosestSafeSpotTeleport.java +++ b/src/main/java/world/bentobox/bentobox/util/teleport/ClosestSafeSpotTeleport.java @@ -54,9 +54,6 @@ public class ClosestSafeSpotTeleport this.portal = builder.isPortal(); this.successRunnable = builder.getSuccessRunnable(); - this.failRunnable = builder.getFailRunnable(); - - this.failureMessage = builder.getFailureMessage(); this.result = builder.getResult(); this.world = Objects.requireNonNull(this.location.getWorld()); @@ -72,7 +69,7 @@ public class ClosestSafeSpotTeleport * This is main method that triggers safe spot search. * It starts with the given location and afterwards checks all blocks in required area. */ - private void checkLocation() + void checkLocation() { if (!this.portal && this.plugin.getIslandsManager().isSafeLocation(this.location)) { @@ -115,7 +112,7 @@ public class ClosestSafeSpotTeleport /** * This method loads all chunks in async and populates blockQueue with all blocks. */ - private void gatherChunks() + void gatherChunks() { // Set a flag so this is only run if it's not already in progress if (this.checking.get()) @@ -165,7 +162,7 @@ public class ClosestSafeSpotTeleport * * @return - list of chunk coordinates to be scanned */ - private List> getChunksToScan() + List> getChunksToScan() { List> chunksToScan = new ArrayList<>(); @@ -210,7 +207,7 @@ public class ClosestSafeSpotTeleport * @param blockCoord Block coordinates that must be in island. * @param chunkCoord Chunk coordinate. */ - private void addChunk(List> chunksToScan, + void addChunk(List> chunksToScan, Pair blockCoord, Pair chunkCoord) { @@ -228,7 +225,7 @@ public class ClosestSafeSpotTeleport * Add only positions that are inside BoundingBox and is safe for teleportation. * @param chunkSnapshot Spigot Chunk Snapshot with blocks. */ - private void scanAndPopulateBlockQueue(ChunkSnapshot chunkSnapshot) + void scanAndPopulateBlockQueue(ChunkSnapshot chunkSnapshot) { int startY = this.location.getBlockY(); int minY = this.world.getMinHeight(); @@ -238,15 +235,14 @@ public class ClosestSafeSpotTeleport int chunkX = chunkSnapshot.getX() << 4; int chunkZ = chunkSnapshot.getZ() << 4; - for (int x = 0; x < 16; x++) { for (int z = 0; z < 16; z++) { + for (int y = Math.max(minY, startY - this.range); y < Math.min(maxY, startY + this.range); y++) { Vector positionVector = new Vector(chunkX + x, y, chunkZ + z); - if (this.boundingBox.contains(positionVector)) { // Process positions that are inside bounding box of search area. @@ -279,7 +275,7 @@ public class ClosestSafeSpotTeleport *

* This method stops position finding task and process teleporation. */ - private void finishTask() + void finishTask() { // Still Async! // Nothing left to check and still not canceled @@ -297,64 +293,41 @@ public class ClosestSafeSpotTeleport else if (this.entity instanceof Player player) { // Return to main thread and teleport the player - Bukkit.getScheduler().runTask(this.plugin, () -> - { - // Failed, no safe spot - if (!this.failureMessage.isEmpty()) - { - User.getInstance(this.entity).notify(this.failureMessage); - } - - // Check highest block - Block highestBlock = this.world.getHighestBlockAt(this.location); - - if (highestBlock.getType().isSolid() && - this.plugin.getIslandsManager().isSafeLocation(highestBlock.getLocation())) - { - // Try to teleport player to the highest block. - this.asyncTeleport(highestBlock.getLocation().add(new Vector(0.5D, 0D, 0.5D))); - return; - } - else if (!this.plugin.getIWM().inWorld(this.entity.getLocation())) - { - // Last resort - player.performCommand("spawn"); - } - else if (!this.cancelIfFail) - { - // Create a spot for the player to be - if (this.world.getEnvironment().equals(World.Environment.NETHER)) - { - this.makeAndTeleport(Material.NETHERRACK); - } - else if (this.world.getEnvironment().equals(World.Environment.THE_END)) - { - this.makeAndTeleport(Material.END_STONE); - } - else - { - this.makeAndTeleport(Material.COBBLESTONE); - } - } - - if (this.failRunnable != null) - { - Bukkit.getScheduler().runTask(this.plugin, this.failRunnable); - } - - this.result.complete(false); - }); + Bukkit.getScheduler().runTask(this.plugin, () -> returnAndTeleport(player)); } - else + // We do not teleport entities if position failed. + // Fail the completion + this.result.complete(false); + + } + + void returnAndTeleport(Player player) { + // Notify player + User.getInstance(this.entity).notify("general.errors.no-safe-location-found"); + + // Check highest block + Block highestBlock = this.world.getHighestBlockAt(this.location); + + if (highestBlock.getType().isSolid() && + this.plugin.getIslandsManager().isSafeLocation(highestBlock.getLocation())) { - // We do not teleport entities if position failed. - - if (this.failRunnable != null) - { - Bukkit.getScheduler().runTask(this.plugin, this.failRunnable); + // Try to teleport player to the highest block. + this.asyncTeleport(highestBlock.getLocation().add(new Vector(0.5D, 0D, 0.5D))); + return; + } + else if (!this.plugin.getIWM().inWorld(this.entity.getLocation())) + { + // Last resort + player.performCommand("spawn"); + } + else if (!this.cancelIfFail) + { + // Create a spot for the player to be + switch(world.getEnvironment()) { + case NETHER -> this.makeAndTeleport(Material.NETHERRACK); + case THE_END -> this.makeAndTeleport(Material.END_STONE); + default -> this.makeAndTeleport(Material.COBBLESTONE); } - - this.result.complete(false); } } @@ -364,7 +337,7 @@ public class ClosestSafeSpotTeleport * above location and fills the space between them with air. * @param baseMaterial Material that will be for top and bottom block. */ - private void makeAndTeleport(Material baseMaterial) + void makeAndTeleport(Material baseMaterial) { this.location.getBlock().getRelative(BlockFace.DOWN).setType(baseMaterial, false); this.location.getBlock().setType(Material.AIR, false); @@ -380,7 +353,7 @@ public class ClosestSafeSpotTeleport * This method scans all populated positions and returns true if position is found, or false, if not. * @return {@code true} if safe position is found, otherwise false. */ - private boolean scanBlockQueue() + boolean scanBlockQueue() { boolean blockFound = false; @@ -396,7 +369,7 @@ public class ClosestSafeSpotTeleport /** * This method triggers a task that will teleport entity in a main thread. */ - private void teleportEntity(final Location location) + void teleportEntity(final Location location) { // Return to main thread and teleport the player Bukkit.getScheduler().runTask(this.plugin, () -> this.asyncTeleport(location)); @@ -407,7 +380,7 @@ public class ClosestSafeSpotTeleport * This method performs async teleportation and runs end tasks for spot-finder. * @param location Location where player should be teleported. */ - private void asyncTeleport(final Location location) + void asyncTeleport(final Location location) { Util.teleportAsync(this.entity, location).thenRun(() -> { @@ -429,7 +402,7 @@ public class ClosestSafeSpotTeleport * @param positionData Position data that must be checked. * @return {@code true} if position is found and no extra processing required, {@code false} otherwise. */ - private boolean checkPosition(PositionData positionData) + boolean checkPosition(PositionData positionData) { if (this.portal) { @@ -477,12 +450,12 @@ public class ClosestSafeSpotTeleport /** * PositionData record holds information about position where player will be teleported. * @param vector Vector of the position. + * @param block Block material on which player will be placed. + * @param spaceOne Material one block above block. + * @param spaceTwo Material two blocks above block. * @param distance Distance till the position. - * @param block Block on which player will be placed. - * @param spaceOne One block above block. - * @param spaceTwo Two blocks above block. */ - private record PositionData(Vector vector, Material block, Material spaceOne, Material spaceTwo, double distance) {} + record PositionData(Vector vector, Material block, Material spaceOne, Material spaceTwo, double distance) {} public static Builder builder(BentoBox plugin) @@ -496,6 +469,10 @@ public class ClosestSafeSpotTeleport // --------------------------------------------------------------------- + /** + * Builder for ClosestSafeSpotTeleport + * + */ public static class Builder { private Builder(BentoBox plugin) @@ -590,11 +567,6 @@ public class ClosestSafeSpotTeleport return null; } - if (this.failureMessage.isEmpty() && this.entity instanceof Player) - { - this.failureMessage = "general.errors.no-safe-location-found"; - } - return new ClosestSafeSpotTeleport(this); } @@ -669,29 +641,6 @@ public class ClosestSafeSpotTeleport return this.successRunnable; } - - /** - * Gets fail runnable. - * - * @return the fail runnable - */ - public Runnable getFailRunnable() - { - return this.failRunnable; - } - - - /** - * Gets failure message. - * - * @return the failure message - */ - public String getFailureMessage() - { - return this.failureMessage; - } - - /** * Is portal boolean. * @@ -749,16 +698,6 @@ public class ClosestSafeSpotTeleport */ private Runnable successRunnable; - /** - * Runnable that will be triggered after failing teleportation. - */ - private Runnable failRunnable; - - /** - * Stores the failure message that is sent to a player. - */ - private String failureMessage = ""; - /** * Boolean that indicates if teleportation should search for portal. */ @@ -827,16 +766,6 @@ public class ClosestSafeSpotTeleport */ private final Runnable successRunnable; - /** - * Runnable that will be triggered after failing teleportation. - */ - private final Runnable failRunnable; - - /** - * Stores the failure message that is sent to a player. - */ - private final String failureMessage; - /** * CompletableFuture that is triggered upon finishing position searching. */ diff --git a/src/test/java/world/bentobox/bentobox/util/teleport/ClosestSafeSpotTeleportTest.java b/src/test/java/world/bentobox/bentobox/util/teleport/ClosestSafeSpotTeleportTest.java new file mode 100644 index 000000000..9724d82fe --- /dev/null +++ b/src/test/java/world/bentobox/bentobox/util/teleport/ClosestSafeSpotTeleportTest.java @@ -0,0 +1,307 @@ +package world.bentobox.bentobox.util.teleport; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; + +import org.bukkit.Bukkit; +import org.bukkit.Chunk; +import org.bukkit.ChunkSnapshot; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitScheduler; +import org.bukkit.scheduler.BukkitTask; +import org.bukkit.util.Vector; +import org.eclipse.jdt.annotation.NonNull; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.internal.verification.VerificationModeFactory; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; +import org.powermock.reflect.Whitebox; + +import world.bentobox.bentobox.BentoBox; +import world.bentobox.bentobox.Settings; +import world.bentobox.bentobox.database.objects.Island; +import world.bentobox.bentobox.managers.IslandWorldManager; +import world.bentobox.bentobox.managers.IslandsManager; +import world.bentobox.bentobox.util.Pair; +import world.bentobox.bentobox.util.Util; +import world.bentobox.bentobox.util.teleport.ClosestSafeSpotTeleport.Builder; +import world.bentobox.bentobox.util.teleport.ClosestSafeSpotTeleport.PositionData; + +/** + * @author tastybento + * + */ +@RunWith(PowerMockRunner.class) +@PrepareForTest({Util.class, Bukkit.class}) +public class ClosestSafeSpotTeleportTest { + + // Class under test + private ClosestSafeSpotTeleport csst; + + @Mock + private BentoBox plugin; + @Mock + private Location location; + @Mock + private World world; + @Mock + private Player entity; + + @Mock + private Runnable runnable; + @Mock + private Runnable failRunnable; + @Mock + private CompletableFuture result; + @Mock + private @NonNull CompletableFuture cfChunk; + @Mock + private IslandsManager im; + @Mock + private BukkitScheduler scheduler; + + private Island island; + @Mock + private IslandWorldManager iwm; + + @Mock + private BukkitTask task; + @Mock + private ChunkSnapshot chunkSnapshot; + @Mock + private Block block; + + private Builder builder; + /** + */ + @Before + public void setUp() throws Exception { + // Setup instance + Whitebox.setInternalState(BentoBox.class, "instance", plugin); + // IWM + when(iwm.getIslandProtectionRange(any())).thenReturn(100); + when(iwm.getIslandDistance(any())).thenReturn(400); + when(plugin.getIWM()).thenReturn(iwm); + when(plugin.getIslandsManager()).thenReturn(im); + Settings settings = new Settings(); + when(plugin.getSettings()).thenReturn(settings); + + // Mock static Util + PowerMockito.mockStatic(Util.class, Mockito.RETURNS_MOCKS); + when(Util.getChunkAtAsync(any(Location.class))).thenReturn(cfChunk); + // Same world + when(Util.sameWorld(any(), any())).thenReturn(true); + // Set up builder + // Set the default world + when(location.getWorld()).thenReturn(world); + when(location.getBlock()).thenReturn(block); + when(location.clone()).thenReturn(location); + when(location.add(any(Vector.class))).thenReturn(location); + + // World + when(world.getMinHeight()).thenReturn(0); + when(world.getMaxHeight()).thenReturn(1); + + // Island + island = new Island(location, UUID.randomUUID(), 50); + + // Plugin Island Manager + // Default that locations are safe + when(im.isSafeLocation(any(Location.class))).thenReturn(true); + when(im.checkIfSafe(any(),any(),any(),any())).thenReturn(true); + // Provide an island + when(im.getIslandAt(any(Location.class))).thenReturn(Optional.of(island)); + + // Block + when(block.getRelative(any())).thenReturn(block); + when(plugin.getIslands()).thenReturn(im); + + // Bukkit scheduler + when(scheduler.runTaskTimer(eq(plugin), any(Runnable.class), anyLong(), anyLong())).thenReturn(task); + PowerMockito.mockStatic(Bukkit.class, Mockito.RETURNS_MOCKS); + when(Bukkit.getScheduler()).thenReturn(scheduler); + + // DUT + builder = ClosestSafeSpotTeleport.builder(plugin).entity(entity).portal() + .location(location) + .successRunnable(failRunnable); + csst = builder.build(); + + } + + /** + */ + @After + public void tearDown() throws Exception { + Mockito.framework().clearInlineMocks(); + } + /** + * Test method for {@link world.bentobox.bentobox.util.teleport.ClosestSafeSpotTeleport#ClosestSafeSpotTeleport(world.bentobox.bentobox.util.teleport.ClosestSafeSpotTeleport.Builder)}. + */ + @Test + public void testClosestSafeSpotTeleport() { + assertNotNull(csst); + } + + /** + * Test method for {@link world.bentobox.bentobox.util.teleport.ClosestSafeSpotTeleport#checkLocation()}. + */ + @Test + public void testCheckLocation() { + csst.checkLocation(); + PowerMockito.verifyStatic(Bukkit.class, VerificationModeFactory.times(1)); + Bukkit.getScheduler(); + verify(im, times(17)).getIslandAt(location); + } + + /** + * Test method for {@link world.bentobox.bentobox.util.teleport.ClosestSafeSpotTeleport#checkLocation()}. + */ + @Test + public void testCheckLocationSafeSpotImmediately() { + // No portal + csst = ClosestSafeSpotTeleport.builder(plugin).entity(entity).location(location).successRunnable(failRunnable).build(); + when(im.isSafeLocation(this.location)).thenReturn(true); + csst.checkLocation(); + PowerMockito.verifyStatic(Bukkit.class, VerificationModeFactory.times(1)); + Bukkit.getScheduler(); + verify(im, never()).getIslandAt(location); + verify(im).isSafeLocation(location); + } + + /** + * Test method for {@link world.bentobox.bentobox.util.teleport.ClosestSafeSpotTeleport#gatherChunks()}. + */ + @Test + public void testGatherChunks() { + csst.checkLocation(); + csst.gatherChunks(); + PowerMockito.verifyStatic(Util.class, VerificationModeFactory.times(1)); + Util.getChunkAtAsync(eq(world), anyInt(), anyInt()); + } + + /** + * Test method for {@link world.bentobox.bentobox.util.teleport.ClosestSafeSpotTeleport#getChunksToScan()}. + */ + @Test + public void testGetChunksToScan() { + List> list = csst.getChunksToScan(); + assertEquals(16, list.size()); + } + + /** + * Test method for {@link world.bentobox.bentobox.util.teleport.ClosestSafeSpotTeleport#addChunk(java.util.List, world.bentobox.bentobox.util.Pair, world.bentobox.bentobox.util.Pair)}. + */ + @Test + public void testAddChunk() { + Pair chunkCoord = new Pair<>(0,0); + Pair chunksToScan = new Pair<>(0,0); + List> list = new ArrayList<>(); + csst.addChunk(list, chunksToScan, chunkCoord); + assertEquals(1, list.size()); + } + + /** + * Test method for {@link world.bentobox.bentobox.util.teleport.ClosestSafeSpotTeleport#scanAndPopulateBlockQueue(org.bukkit.ChunkSnapshot)}. + */ + @Test + public void testScanAndPopulateBlockQueue() { + csst.checkLocation(); + csst.scanAndPopulateBlockQueue(chunkSnapshot); + assertFalse(csst.scanBlockQueue()); + } + + /** + * Test method for {@link world.bentobox.bentobox.util.teleport.ClosestSafeSpotTeleport#finishTask()}. + * @throws ExecutionException + * @throws InterruptedException + */ + @Test + public void testFinishTask() throws InterruptedException, ExecutionException { + csst.checkLocation(); + csst.finishTask(); + assertFalse(builder.getResult().get()); + } + + /** + * Test method for {@link world.bentobox.bentobox.util.teleport.ClosestSafeSpotTeleport#makeAndTeleport(org.bukkit.Material)}. + */ + @Test + public void testMakeAndTeleport() { + csst.checkLocation(); + csst.makeAndTeleport(Material.STONE); + verify(location, times(4)).getBlock(); + PowerMockito.verifyStatic(Util.class, VerificationModeFactory.times(1)); + Util.teleportAsync(entity, location); + } + + /** + * Test method for {@link world.bentobox.bentobox.util.teleport.ClosestSafeSpotTeleport#scanBlockQueue()}. + */ + @Test + public void testScanBlockQueue() { + csst.checkLocation(); + assertFalse(csst.scanBlockQueue()); + } + + /** + * Test method for {@link world.bentobox.bentobox.util.teleport.ClosestSafeSpotTeleport#teleportEntity(org.bukkit.Location)}. + */ + @Test + public void testTeleportEntity() { + csst.checkLocation(); + csst.teleportEntity(location); + verify(scheduler).runTask(eq(plugin), any(Runnable.class)); + } + + /** + * Test method for {@link world.bentobox.bentobox.util.teleport.ClosestSafeSpotTeleport#asyncTeleport(org.bukkit.Location)}. + */ + @Test + public void testAsyncTeleport() { + csst.checkLocation(); + csst.asyncTeleport(location); + PowerMockito.verifyStatic(Util.class, VerificationModeFactory.times(1)); + Util.teleportAsync(entity, location); + } + + /** + * Test method for {@link world.bentobox.bentobox.util.teleport.ClosestSafeSpotTeleport#checkPosition(world.bentobox.bentobox.util.teleport.ClosestSafeSpotTeleport.PositionData)}. + */ + @Test + public void testCheckPosition() { + Vector vector = new Vector(1,2,3); + Material block = Material.STONE; + Material space1 = Material.AIR; + Material space2 = Material.AIR; + PositionData positionData = new PositionData(vector, block, space1, space2, 3); + assertFalse(csst.checkPosition(positionData)); + } + +} From 62a3a8d6fae88b1643627c2e766803f1afd89832 Mon Sep 17 00:00:00 2001 From: tastybento Date: Sat, 22 Jul 2023 12:00:10 -0700 Subject: [PATCH 25/30] Fixed NPE when getting UUID for unknown name. Added test methods for PlayersManager --- .../bentobox/managers/PlayersManager.java | 3 +- .../bentobox/managers/PlayersManagerTest.java | 564 ++++++++++++------ 2 files changed, 397 insertions(+), 170 deletions(-) diff --git a/src/main/java/world/bentobox/bentobox/managers/PlayersManager.java b/src/main/java/world/bentobox/bentobox/managers/PlayersManager.java index cad7a15de..f15318ceb 100644 --- a/src/main/java/world/bentobox/bentobox/managers/PlayersManager.java +++ b/src/main/java/world/bentobox/bentobox/managers/PlayersManager.java @@ -479,7 +479,8 @@ public class PlayersManager { * @return user - user or null if unknown */ public User getUser(String name) { - return getUser(getUUID(name)); + UUID uuid = getUUID(name); + return uuid == null ? null : getUser(uuid); } /** diff --git a/src/test/java/world/bentobox/bentobox/managers/PlayersManagerTest.java b/src/test/java/world/bentobox/bentobox/managers/PlayersManagerTest.java index 9943e3a62..451c5e25a 100644 --- a/src/test/java/world/bentobox/bentobox/managers/PlayersManagerTest.java +++ b/src/test/java/world/bentobox/bentobox/managers/PlayersManagerTest.java @@ -1,10 +1,6 @@ package world.bentobox.bentobox.managers; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; +import static org.junit.Assert.*; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; @@ -53,6 +49,7 @@ import org.powermock.reflect.Whitebox; import world.bentobox.bentobox.BentoBox; import world.bentobox.bentobox.Settings; +import world.bentobox.bentobox.api.flags.Flag.Mode; import world.bentobox.bentobox.api.user.User; import world.bentobox.bentobox.database.AbstractDatabaseHandler; import world.bentobox.bentobox.database.Database; @@ -71,35 +68,36 @@ import world.bentobox.bentobox.util.Util; @PrepareForTest({Bukkit.class, BentoBox.class, User.class, Util.class, Logger.class, DatabaseSetup.class,}) public class PlayersManagerTest { + private static AbstractDatabaseHandler h; + private Database db; @Mock - private BentoBox plugin; + private World end; @Mock - private World world; + private Inventory inv; + @Mock + private Island island; @Mock private IslandWorldManager iwm; @Mock private World nether; - @Mock - private World end; - private UUID uuid; - private User user; private UUID notUUID; - private Database db; - private PlayersManager pm; - @Mock - private Tameable tamed; @Mock private Player p; @Mock - private Inventory inv; - @Mock - private VaultHook vault; - @Mock private PlayerInventory playerInv; @Mock - private Island island; - - private static AbstractDatabaseHandler h; + private BentoBox plugin; + private PlayersManager pm; + @Mock + private Tameable tamed; + private User user; + private UUID uuid; + + @Mock + private VaultHook vault; + + @Mock + private World world; @SuppressWarnings("unchecked") @BeforeClass @@ -114,6 +112,16 @@ public class PlayersManagerTest { when(h.saveObject(any())).thenReturn(CompletableFuture.completedFuture(true)); } + private void deleteAll(File file) throws IOException { + if (file.exists()) { + Files.walk(file.toPath()) + .sorted(Comparator.reverseOrder()) + .map(Path::toFile) + .forEach(File::delete); + } + + } + /** */ @SuppressWarnings("unchecked") @@ -156,7 +164,7 @@ public class PlayersManagerTest { while(notUUID.equals(uuid)) { notUUID = UUID.randomUUID(); } - + // Island when(island.getOwner()).thenReturn(uuid); @@ -167,6 +175,8 @@ public class PlayersManagerTest { AttributeInstance at = mock(AttributeInstance.class); when(at.getValue()).thenReturn(20D); when(p.getAttribute(Attribute.GENERIC_MAX_HEALTH)).thenReturn(at); + when(p.getName()).thenReturn("tastybento"); + User.getInstance(p); // Sometimes use Mockito.withSettings().verboseLogging() user = mock(User.class); @@ -213,6 +223,8 @@ public class PlayersManagerTest { // Leave commands when(iwm.getOnLeaveCommands(any())).thenReturn(Collections.emptyList()); + // Deaths + when(iwm.getDeathsMax(world)).thenReturn(100); // Leave settings when(iwm.isOnLeaveResetEnderChest(any())).thenReturn(true); @@ -244,56 +256,14 @@ public class PlayersManagerTest { deleteAll(new File("database_backup")); } - private void deleteAll(File file) throws IOException { - if (file.exists()) { - Files.walk(file.toPath()) - .sorted(Comparator.reverseOrder()) - .map(Path::toFile) - .forEach(File::delete); - } - - } /** - * Test method for {@link world.bentobox.bentobox.managers.PlayersManager#PlayersManager(world.bentobox.bentobox.BentoBox)}. + * Test method for {@link world.bentobox.bentobox.managers.PlayersManager#addDeath(org.bukkit.World, java.util.UUID)}. */ @Test - public void testPlayersManager() { - assertNotNull(pm); - } - - /** - * Test method for {@link world.bentobox.bentobox.managers.PlayersManager#load()}. - */ - @Test - public void testLoad() { - pm.setHandler(db); - pm.load(); - } - - /** - * Test method for {@link world.bentobox.bentobox.managers.PlayersManager#saveAll()}. - */ - @Test - public void testSaveBoolean() { - pm.saveAll(); - } - - /** - * Test method for {@link world.bentobox.bentobox.managers.PlayersManager#shutdown()}. - */ - @Test - public void testShutdown() { - pm.shutdown(); - } - - /** - * Test method for {@link world.bentobox.bentobox.managers.PlayersManager#getPlayer(java.util.UUID)}. - */ - @Test - public void testGetPlayer() { - Players player = pm.getPlayer(uuid); - assertEquals("tastybento", player.getPlayerName()); - assertEquals(uuid.toString(), player.getUniqueId()); + public void testAddDeath() { + int deaths = pm.getDeaths(world, uuid); + pm.addDeath(world, uuid); + assertEquals(deaths + 1, pm.getDeaths(world, uuid)); } /** @@ -311,107 +281,13 @@ public class PlayersManagerTest { } /** - * Test method for {@link world.bentobox.bentobox.managers.PlayersManager#isKnown(java.util.UUID)}. + * Test method for {@link world.bentobox.bentobox.managers.PlayersManager#addReset(org.bukkit.World, java.util.UUID)}. */ @Test - public void testIsKnown() { - - pm.addPlayer(uuid); - pm.addPlayer(notUUID); - - assertFalse(pm.isKnown(null)); - assertTrue(pm.isKnown(uuid)); - assertTrue(pm.isKnown(notUUID)); - } - - /** - * Test method for {@link world.bentobox.bentobox.managers.PlayersManager#getUUID(java.lang.String)}. - */ - @Test - public void testGetUUIDwithUUID() { - assertEquals(uuid,pm.getUUID(uuid.toString())); - } - - /** - * Test method for {@link world.bentobox.bentobox.managers.PlayersManager#getUUID(java.lang.String)}. - */ - @Test - public void testGetUUIDOfflinePlayer() { - pm.setHandler(db); - // Add a player to the cache - pm.addPlayer(uuid); - UUID uuidResult = pm.getUUID("tastybento"); - assertEquals(uuid, uuidResult); - } - - /** - * Test method for {@link world.bentobox.bentobox.managers.PlayersManager#setPlayerName(world.bentobox.bentobox.api.user.User)}. - */ - @Test - public void testSetandGetPlayerName() { - pm.setHandler(db); - // Add a player - pm.addPlayer(uuid); - assertEquals("tastybento", pm.getName(user.getUniqueId())); - pm.setPlayerName(user); - assertEquals(user.getName(), pm.getName(user.getUniqueId())); - } - - /** - * Test method for {@link world.bentobox.bentobox.managers.PlayersManager#getUUID(java.lang.String)}. - */ - @Test - public void testGetUUIDUnknownPlayer() { - pm.setHandler(db); - // Add a player to the cache - pm.addPlayer(uuid); - // Unknown player should return null - assertNull(pm.getUUID("tastybento123")); - } - - /** - * Test method for {@link world.bentobox.bentobox.managers.PlayersManager#setResets(World, UUID, int)}. - */ - @Test - public void testGetSetResetsLeft() { - // Add a player - pm.addPlayer(uuid); - assertEquals(0, pm.getResets(world, uuid)); - pm.setResets(world, uuid, 20); - assertEquals(20, pm.getResets(world, uuid)); - } - - /** - * Test method for {@link world.bentobox.bentobox.managers.PlayersManager#save(java.util.UUID)}. - */ - @Test - public void testSaveUUID() { - // Add a player - pm.addPlayer(uuid); - //pm.save(uuid); - } - - /** - * Test method for {@link world.bentobox.bentobox.managers.PlayersManager#cleanLeavingPlayer(World, User, boolean)}. - */ - @Test - public void testCleanLeavingPlayerLeave() { - pm.cleanLeavingPlayer(world, user, false, island); - // Tamed animals - verify(tamed).setOwner(eq(null)); - // Economy - verify(vault).withdraw(eq(user), eq(0D), eq(world)); - // Enderchest - verify(inv).clear(); - // Player inventory - verify(playerInv).clear(); - // Health - PowerMockito.verifyStatic(Util.class); - Util.resetHealth(eq(p)); - // Food - verify(p).setFoodLevel(eq(20)); - // XP - verify(p).setTotalExperience(eq(0)); + public void testAddReset() { + int resets = pm.getResets(world, uuid); + pm.addReset(world, uuid); + assertEquals(resets + 1, pm.getResets(world, uuid)); } /** @@ -462,4 +338,354 @@ public class PlayersManagerTest { // XP verify(p).setTotalExperience(eq(0)); } + + /** + * Test method for {@link world.bentobox.bentobox.managers.PlayersManager#cleanLeavingPlayer(World, User, boolean)}. + */ + @Test + public void testCleanLeavingPlayerLeave() { + pm.cleanLeavingPlayer(world, user, false, island); + // Tamed animals + verify(tamed).setOwner(eq(null)); + // Economy + verify(vault).withdraw(eq(user), eq(0D), eq(world)); + // Enderchest + verify(inv).clear(); + // Player inventory + verify(playerInv).clear(); + // Health + PowerMockito.verifyStatic(Util.class); + Util.resetHealth(eq(p)); + // Food + verify(p).setFoodLevel(eq(20)); + // XP + verify(p).setTotalExperience(eq(0)); + } + + /** + * Test method for {@link world.bentobox.bentobox.managers.PlayersManager#getDeaths(org.bukkit.World, java.util.UUID)}. + */ + @Test + public void testGetDeaths() { + assertEquals(0, pm.getDeaths(world, uuid)); + } + + /** + * Test method for {@link world.bentobox.bentobox.managers.PlayersManager#getFlagsDisplayMode(java.util.UUID)}. + */ + @Test + public void testGetFlagsDisplayMode() { + assertEquals(Mode.BASIC, pm.getFlagsDisplayMode(uuid)); + } + + /** + * Test method for {@link world.bentobox.bentobox.managers.PlayersManager#getLocale(java.util.UUID)}. + */ + @Test + public void testGetLocale() { + assertTrue(pm.getLocale(uuid).isEmpty()); + } + + /** + * Test method for {@link world.bentobox.bentobox.managers.PlayersManager#getName(java.util.UUID)}. + */ + @Test + public void testGetName() { + assertTrue(pm.getName(null).isEmpty()); + String name = pm.getName(uuid); + assertEquals("tastybento", name); + } + + /** + * Test method for {@link world.bentobox.bentobox.managers.PlayersManager#getPlayer(java.util.UUID)}. + */ + @Test + public void testGetPlayer() { + Players player = pm.getPlayer(uuid); + assertEquals("tastybento", player.getPlayerName()); + assertEquals(uuid.toString(), player.getUniqueId()); + } + + /** + * Test method for {@link world.bentobox.bentobox.managers.PlayersManager#getPlayers()}. + */ + @Test + public void testGetPlayers() { + assertTrue(pm.getPlayers().isEmpty()); + } + + /** + * Test method for {@link world.bentobox.bentobox.managers.PlayersManager#getResets(org.bukkit.World, java.util.UUID)}. + */ + @Test + public void testGetResets() { + assertEquals(0, pm.getResets(world, uuid)); + } + + /** + * Test method for {@link world.bentobox.bentobox.managers.PlayersManager#getResetsLeft(org.bukkit.World, java.util.UUID)}. + */ + @Test + public void testGetResetsLeft() { + assertEquals(0, pm.getResetsLeft(world, uuid)); + } + + /** + * Test method for {@link world.bentobox.bentobox.managers.PlayersManager#setResets(World, UUID, int)}. + */ + @Test + public void testGetSetResetsLeft() { + // Add a player + pm.addPlayer(uuid); + assertEquals(0, pm.getResets(world, uuid)); + pm.setResets(world, uuid, 20); + assertEquals(20, pm.getResets(world, uuid)); + } + + /** + * Test method for {@link world.bentobox.bentobox.managers.PlayersManager#getUser(java.lang.String)}. + */ + @Test + public void testGetUserString() { + User user = pm.getUser("random"); + assertNull(user); + pm.addPlayer(uuid); + user = pm.getUser("tastybento"); + assertEquals("tastybento", user.getName()); + } + + /** + * Test method for {@link world.bentobox.bentobox.managers.PlayersManager#getUser(java.util.UUID)}. + */ + @Test + public void testGetUserUUID() { + UUID uuid = pm.getUUID("unknown"); + assertNull(uuid); + } + + /** + * Test method for {@link world.bentobox.bentobox.managers.PlayersManager#getUUID(java.lang.String)}. + */ + @Test + public void testGetUUID() { + pm.addPlayer(uuid); + assertEquals(uuid, pm.getUUID("tastybento")); + assertNull(pm.getUUID("unknown")); + } + + /** + * Test method for {@link world.bentobox.bentobox.managers.PlayersManager#getUUID(java.lang.String)}. + */ + @Test + public void testGetUUIDOfflinePlayer() { + pm.setHandler(db); + // Add a player to the cache + pm.addPlayer(uuid); + UUID uuidResult = pm.getUUID("tastybento"); + assertEquals(uuid, uuidResult); + } + + /** + * Test method for {@link world.bentobox.bentobox.managers.PlayersManager#getUUID(java.lang.String)}. + */ + @Test + public void testGetUUIDUnknownPlayer() { + pm.setHandler(db); + // Add a player to the cache + pm.addPlayer(uuid); + // Unknown player should return null + assertNull(pm.getUUID("tastybento123")); + } + + /** + * Test method for {@link world.bentobox.bentobox.managers.PlayersManager#getUUID(java.lang.String)}. + */ + @Test + public void testGetUUIDwithUUID() { + assertEquals(uuid,pm.getUUID(uuid.toString())); + } + + /** + * Test method for {@link world.bentobox.bentobox.managers.PlayersManager#isInTeleport(java.util.UUID)}. + */ + @Test + public void testIsInTeleport() { + assertFalse(pm.isInTeleport(uuid)); + } + + /** + * Test method for {@link world.bentobox.bentobox.managers.PlayersManager#isKnown(java.util.UUID)}. + */ + @Test + public void testIsKnown() { + + pm.addPlayer(uuid); + pm.addPlayer(notUUID); + + assertFalse(pm.isKnown(null)); + assertTrue(pm.isKnown(uuid)); + assertTrue(pm.isKnown(notUUID)); + } + + /** + * Test method for {@link world.bentobox.bentobox.managers.PlayersManager#isSaveTaskRunning()}. + */ + @Test + public void testIsSaveTaskRunning() { + assertFalse(pm.isSaveTaskRunning()); + } + + /** + * Test method for {@link world.bentobox.bentobox.managers.PlayersManager#load()}. + */ + @Test + public void testLoad() { + pm.setHandler(db); + pm.load(); + } + + /** + * Test method for {@link world.bentobox.bentobox.managers.PlayersManager#PlayersManager(world.bentobox.bentobox.BentoBox)}. + */ + @Test + public void testPlayersManager() { + assertNotNull(pm); + } + + /** + * Test method for {@link world.bentobox.bentobox.managers.PlayersManager#removeInTeleport(java.util.UUID)}. + */ + @Test + public void testRemoveInTeleport() { + pm.setInTeleport(uuid); + assertTrue(pm.isInTeleport(uuid)); + pm.removeInTeleport(uuid); + assertFalse(pm.isInTeleport(uuid)); + } + + /** + * Test method for {@link world.bentobox.bentobox.managers.PlayersManager#removePlayer(org.bukkit.entity.Player)}. + */ + @Test + public void testRemovePlayer() { + this.testGetUUID(); + pm.removePlayer(p); + assertNull(pm.getUUID("tastybeto")); + } + + /** + * Test method for {@link world.bentobox.bentobox.managers.PlayersManager#saveAll()}. + */ + @Test + public void testSaveAll() { + pm.setHandler(db); + pm.addPlayer(uuid); + pm.saveAll(); + verify(db).saveObjectAsync(any()); + } + + /** + * Test method for {@link world.bentobox.bentobox.managers.PlayersManager#saveAll(boolean)}. + */ + @Test + public void testSaveAllBoolean() { + pm.setHandler(db); + pm.addPlayer(uuid); + pm.saveAll(true); + assertTrue(pm.isSaveTaskRunning()); + } + + /** + * Test method for {@link world.bentobox.bentobox.managers.PlayersManager#save(java.util.UUID)}. + */ + @Test + public void testSave() { + pm.setHandler(db); + // Add a player + pm.addPlayer(uuid); + pm.save(uuid); + verify(db).saveObjectAsync(any()); + } + + /** + * Test method for {@link world.bentobox.bentobox.managers.PlayersManager#setPlayerName(world.bentobox.bentobox.api.user.User)}. + */ + @Test + public void testSetandGetPlayerName() { + pm.setHandler(db); + // Add a player + pm.addPlayer(uuid); + assertEquals("tastybento", pm.getName(user.getUniqueId())); + pm.setPlayerName(user); + assertEquals(user.getName(), pm.getName(user.getUniqueId())); + } + + /** + * Test method for {@link world.bentobox.bentobox.managers.PlayersManager#setDeaths(org.bukkit.World, java.util.UUID, int)}. + */ + @Test + public void testSetDeaths() { + pm.setDeaths(world, uuid, 50); + assertEquals(50, pm.getDeaths(world, uuid)); + + } + + /** + * Test method for {@link world.bentobox.bentobox.managers.PlayersManager#setFlagsDisplayMode(java.util.UUID, world.bentobox.bentobox.api.flags.Flag.Mode)}. + */ + @Test + public void testSetFlagsDisplayMode() { + pm.setFlagsDisplayMode(uuid, Mode.ADVANCED); + assertEquals(Mode.ADVANCED, pm.getFlagsDisplayMode(uuid)); + } + + /** + * Test method for {@link world.bentobox.bentobox.managers.PlayersManager#setInTeleport(java.util.UUID)}. + */ + @Test + public void testSetInTeleport() { + assertFalse(pm.isInTeleport(uuid)); + pm.setInTeleport(uuid); + assertTrue(pm.isInTeleport(uuid)); + } + + /** + * Test method for {@link world.bentobox.bentobox.managers.PlayersManager#setLocale(java.util.UUID, java.lang.String)}. + */ + @Test + public void testSetLocale() { + pm.setLocale(uuid, "en-UK"); + assertEquals("en-UK", pm.getLocale(uuid)); + } + + /** + * Test method for {@link world.bentobox.bentobox.managers.PlayersManager#setPlayerName(world.bentobox.bentobox.api.user.User)}. + */ + @Test + public void testSetPlayerName() { + pm.setPlayerName(user); + assertEquals("tastybento", pm.getName(uuid)); + when(user.getName()).thenReturn("newName"); + assertEquals("tastybento", pm.getName(uuid)); + pm.setPlayerName(user); + assertEquals("newName", pm.getName(uuid)); + } + + /** + * Test method for {@link world.bentobox.bentobox.managers.PlayersManager#setResets(org.bukkit.World, java.util.UUID, int)}. + */ + @Test + public void testSetResets() { + pm.setResets(world, uuid, 33); + assertEquals(33, pm.getResets(world, uuid)); + } + + /** + * Test method for {@link world.bentobox.bentobox.managers.PlayersManager#shutdown()}. + */ + @Test + public void testShutdown() { + pm.shutdown(); // Clears cache + } + } From 7a21aba3a84f562c33fc38de31eeb4fe127d886f Mon Sep 17 00:00:00 2001 From: tastybento Date: Sat, 22 Jul 2023 12:00:43 -0700 Subject: [PATCH 26/30] Added more JavaDoc to ConfirmableCommand --- .../bentobox/bentobox/api/commands/ConfirmableCommand.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/world/bentobox/bentobox/api/commands/ConfirmableCommand.java b/src/main/java/world/bentobox/bentobox/api/commands/ConfirmableCommand.java index ca1e326a1..be9175229 100644 --- a/src/main/java/world/bentobox/bentobox/api/commands/ConfirmableCommand.java +++ b/src/main/java/world/bentobox/bentobox/api/commands/ConfirmableCommand.java @@ -11,7 +11,8 @@ import world.bentobox.bentobox.api.user.User; /** * BentoBox Confirmable Command - * Adds ability to confirm a command before execution + * Adds ability to confirm a command before execution. + * See {@link #askConfirmation(User, Runnable)}, {@link #askConfirmation(User, String, Runnable)} * @author tastybento * @author Poslovitch */ @@ -88,7 +89,8 @@ public abstract class ConfirmableCommand extends CompositeCommand { } /** - * Tells user to confirm command by retyping it. + * Tells user to confirm command by retyping it. Uses the default message to retype it.

+ * If you need a custom message, use {@link #askConfirmation(User, String, Runnable)} * @param user User to ask confirmation to. * @param confirmed Runnable to be executed if successfully confirmed. */ From fec43adc35a863783e98b6026d76f523c1528b8e Mon Sep 17 00:00:00 2001 From: tastybento Date: Sat, 22 Jul 2023 15:52:15 -0700 Subject: [PATCH 27/30] Refactor YamlDatabaseHandler to reduce continue statements in a loop to just one. --- .../database/yaml/YamlDatabaseHandler.java | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/src/main/java/world/bentobox/bentobox/database/yaml/YamlDatabaseHandler.java b/src/main/java/world/bentobox/bentobox/database/yaml/YamlDatabaseHandler.java index 7de79cb79..c4b5ba763 100644 --- a/src/main/java/world/bentobox/bentobox/database/yaml/YamlDatabaseHandler.java +++ b/src/main/java/world/bentobox/bentobox/database/yaml/YamlDatabaseHandler.java @@ -358,11 +358,11 @@ public class YamlDatabaseHandler extends AbstractDatabaseHandler { // See if there are any top-level comments handleComments(instance.getClass(), config, yamlComments, ""); - // Run through all the fields in the class that is being stored. EVERY field must have a get and set method for (Field field : dataObject.getDeclaredFields()) { if (field.isSynthetic()) { continue; } + // Get the property descriptor for this field PropertyDescriptor propertyDescriptor = new PropertyDescriptor(field.getName(), dataObject); // Get the read method @@ -376,12 +376,7 @@ public class YamlDatabaseHandler extends AbstractDatabaseHandler { ConfigEntry configEntry = field.getAnnotation(ConfigEntry.class); // If there is a config path annotation or adapter then deal with them - if (configEntry != null && !configEntry.path().isEmpty()) { - if (configEntry.hidden()) { - // If the annotation tells us to not print the config entry, then we won't. - continue; - } - + if (configEntry != null && !configEntry.path().isEmpty() && !configEntry.hidden()) { // Get the storage location storageLocation = configEntry.path(); @@ -392,9 +387,7 @@ public class YamlDatabaseHandler extends AbstractDatabaseHandler { } handleComments(field, config, yamlComments, parent); handleConfigEntryComments(configEntry, config, yamlComments, parent); - } - - if (!checkAdapter(field, config, storageLocation, value)) { + } else if (!checkAdapter(field, config, storageLocation, value)) { // Set the filename if it has not be set already if (filename.isEmpty() && method.getName().equals("getUniqueId")) { // Save the name for when the file is saved @@ -411,6 +404,7 @@ public class YamlDatabaseHandler extends AbstractDatabaseHandler { } } } + // If the filename has not been set by now then we have a problem if (filename.isEmpty()) { throw new IllegalArgumentException("No uniqueId in class"); From 3e1dc81592f90aa33788f08e3911810f95d962d3 Mon Sep 17 00:00:00 2001 From: tastybento Date: Sat, 22 Jul 2023 16:03:55 -0700 Subject: [PATCH 28/30] Minor code smell reduction --- .../protection/BlockInteractionListener.java | 2 +- .../flags/protection/BreakBlocksListener.java | 16 +++-- .../listeners/flags/settings/PVPListener.java | 2 +- .../bentobox/bentobox/util/ItemParser.java | 12 ++-- .../teleport/ClosestSafeSpotTeleport.java | 1 - .../admin/AdminTeleportCommandTest.java | 59 +++++++++---------- 6 files changed, 44 insertions(+), 48 deletions(-) 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 8f082e66c..b1a713850 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 @@ -100,7 +100,7 @@ public class BlockInteractionListener extends FlagListener return; } - if (block.getState() instanceof BrushableBlock bb && BlockInteractionListener.holds(player, Material.BRUSH)) { + 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); return; diff --git a/src/main/java/world/bentobox/bentobox/listeners/flags/protection/BreakBlocksListener.java b/src/main/java/world/bentobox/bentobox/listeners/flags/protection/BreakBlocksListener.java index 78f47e497..6f494e32a 100644 --- a/src/main/java/world/bentobox/bentobox/listeners/flags/protection/BreakBlocksListener.java +++ b/src/main/java/world/bentobox/bentobox/listeners/flags/protection/BreakBlocksListener.java @@ -35,22 +35,20 @@ public class BreakBlocksListener extends FlagListener { Player p = e.getPlayer(); Location l = e.getBlock().getLocation(); Material m = e.getBlock().getType(); - switch (m) - { - case MELON, PUMPKIN -> this.checkIsland(e, p, l, Flags.HARVEST); - default -> { + if (m.equals(Material.MELON) || m.equals(Material.PUMPKIN)) { + this.checkIsland(e, p, l, Flags.HARVEST); + } else { // Crops - if (Tag.CROPS.isTagged(m) - && !m.equals(Material.MELON_STEM) - && !m.equals(Material.PUMPKIN_STEM) - && !m.equals(Material.ATTACHED_MELON_STEM) + if (Tag.CROPS.isTagged(m) + && !m.equals(Material.MELON_STEM) + && !m.equals(Material.PUMPKIN_STEM) + && !m.equals(Material.ATTACHED_MELON_STEM) && !m.equals(Material.ATTACHED_PUMPKIN_STEM)) { this.checkIsland(e, p, l, Flags.HARVEST); } else { checkIsland(e, p, l, Flags.BREAK_BLOCKS); } } - } } /** diff --git a/src/main/java/world/bentobox/bentobox/listeners/flags/settings/PVPListener.java b/src/main/java/world/bentobox/bentobox/listeners/flags/settings/PVPListener.java index 54779a707..2b6689165 100644 --- a/src/main/java/world/bentobox/bentobox/listeners/flags/settings/PVPListener.java +++ b/src/main/java/world/bentobox/bentobox/listeners/flags/settings/PVPListener.java @@ -90,7 +90,7 @@ public class PVPListener extends FlagListener { user.notify(getFlag(player.getWorld()).getHintReference()); e.setCancelled(true); } - } else if (damager instanceof Projectile && ((Projectile)damager).getShooter() instanceof Player shooter) { + } else if (damager instanceof Projectile projectile && projectile.getShooter() instanceof Player shooter) { // Find out who fired the arrow processDamage(e, damager, shooter, hurtEntity, flag); } else if (damager instanceof Firework && firedFireworks.containsKey(damager)) { diff --git a/src/main/java/world/bentobox/bentobox/util/ItemParser.java b/src/main/java/world/bentobox/bentobox/util/ItemParser.java index 49335b69e..41a8a6c98 100644 --- a/src/main/java/world/bentobox/bentobox/util/ItemParser.java +++ b/src/main/java/world/bentobox/bentobox/util/ItemParser.java @@ -66,7 +66,7 @@ public class ItemParser { try { // Because I am lazy, and do not want to rewrite every parser, I will just add custom data as // parameter and remove that array part form input data. - Optional first = Arrays.stream(part).filter(field -> field.matches("(CMD-[0-9]*)")).findFirst(); + Optional first = Arrays.stream(part).filter(field -> field.matches("(CMD-\\d*)")).findFirst(); Integer customModelData = null; if (first.isPresent()) { @@ -75,7 +75,7 @@ public class ItemParser { int j = 0; for (String field : part) { - if (!field.matches("(CMD-[0-9]*)")) { + if (!field.matches("(CMD-\\d*)")) { copyParts[j++] = field; } } @@ -182,11 +182,11 @@ public class ItemParser { /** * This method parses array of 6 items into an item stack. * Format: - *

{@code 
+     * 
{@code
      *      POTION:NAME::::QTY
      * }
* Example: - *
{@code 
+     * 
{@code
      *      POTION:STRENGTH:1:EXTENDED:SPLASH:1
      * }
* @param part String array that contains 6 elements. @@ -261,13 +261,13 @@ public class ItemParser { /** * This method parses array of 2 to 3 elements that represents player head. * Format: - *
{@code 
+     * 
{@code
      *    PLAYER_HEAD::QTY
      *    PLAYER_HEAD:
      *    PLAYER_HEAD:QTY
      * }
* Example: - *
{@code 
+     * 
{@code
      *    PLAYER_HEAD:1
      *    PLAYER_HEAD:BONNe1704
      *    PLAYER_HEAD:eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYWY1ZjE1OTg4NmNjNTMxZmZlYTBkOGFhNWY5MmVkNGU1ZGE2NWY3MjRjMDU3MGFmODZhOTBiZjAwYzY3YzQyZSJ9fX0:1
diff --git a/src/main/java/world/bentobox/bentobox/util/teleport/ClosestSafeSpotTeleport.java b/src/main/java/world/bentobox/bentobox/util/teleport/ClosestSafeSpotTeleport.java
index e124e63ed..61ea184c8 100644
--- a/src/main/java/world/bentobox/bentobox/util/teleport/ClosestSafeSpotTeleport.java
+++ b/src/main/java/world/bentobox/bentobox/util/teleport/ClosestSafeSpotTeleport.java
@@ -313,7 +313,6 @@ public class ClosestSafeSpotTeleport
         {
             // Try to teleport player to the highest block.
             this.asyncTeleport(highestBlock.getLocation().add(new Vector(0.5D, 0D, 0.5D)));
-            return;
         }
         else if (!this.plugin.getIWM().inWorld(this.entity.getLocation()))
         {
diff --git a/src/test/java/world/bentobox/bentobox/api/commands/admin/AdminTeleportCommandTest.java b/src/test/java/world/bentobox/bentobox/api/commands/admin/AdminTeleportCommandTest.java
index bb4b800fe..2346edade 100644
--- a/src/test/java/world/bentobox/bentobox/api/commands/admin/AdminTeleportCommandTest.java
+++ b/src/test/java/world/bentobox/bentobox/api/commands/admin/AdminTeleportCommandTest.java
@@ -11,7 +11,6 @@ import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Optional;
@@ -103,7 +102,7 @@ public class AdminTeleportCommandTest {
         when(p.getUniqueId()).thenReturn(uuid);
         when(p.hasPermission("admin.tp")).thenReturn(true);
         when(p.hasPermission("admin")).thenReturn(false);
-        
+
         when(user.getUniqueId()).thenReturn(uuid);
         when(user.getPlayer()).thenReturn(p);
         when(user.getName()).thenReturn("tastybento");
@@ -153,7 +152,7 @@ public class AdminTeleportCommandTest {
         when(lm.get(any(), any())).thenAnswer((Answer) invocation -> invocation.getArgument(1, String.class));
         when(plugin.getLocalesManager()).thenReturn(lm);
 
-        when(user.getTranslation(Mockito.anyString(),Mockito.anyString(), Mockito.anyString())).thenAnswer((Answer) invocation -> invocation.getArgument(0, String.class));
+        when(user.getTranslation(anyString(),anyString(), anyString())).thenAnswer((Answer) invocation -> invocation.getArgument(0, String.class));
 
         // Island location
         Location location = mock(Location.class);
@@ -178,7 +177,7 @@ public class AdminTeleportCommandTest {
         // Util
         PowerMockito.mockStatic(Util.class, Mockito.RETURNS_MOCKS);
         when(Util.getUUID(anyString())).thenCallRealMethod();
-        
+
         // Placeholder manager
         when(plugin.getPlaceholdersManager()).thenReturn(phm);
     }
@@ -215,16 +214,16 @@ public class AdminTeleportCommandTest {
     @Test
     public void testExecuteUserStringListOfStringUnknownTarget() {
         AdminTeleportCommand atc = new AdminTeleportCommand(ac,"tp");
-        assertFalse(atc.canExecute(user, "tp", Collections.singletonList("tastybento")));
+        assertFalse(atc.canExecute(user, "tp", List.of("tastybento")));
         verify(user).sendMessage(eq("general.errors.unknown-player"), eq(TextVariables.NAME), eq("tastybento"));
     }
 
     @Test
     public void testExecuteUserStringListOfStringKnownTargetNoIsland() {
-        when(pm.getUUID(eq("tastybento"))).thenReturn(notUUID);
+        when(pm.getUUID("tastybento")).thenReturn(notUUID);
         when(im.hasIsland(any(), any(UUID.class))).thenReturn(false);
         AdminTeleportCommand atc = new AdminTeleportCommand(ac,"tp");
-        assertFalse(atc.canExecute(user, "tp", Collections.singletonList("tastybento")));
+        assertFalse(atc.canExecute(user, "tp", List.of("tastybento")));
         verify(user).sendMessage(eq("general.errors.player-has-no-island"));
     }
 
@@ -233,12 +232,12 @@ public class AdminTeleportCommandTest {
      */
     @Test
     public void testExecuteUserStringListOfStringKnownTargetHasIsland() {
-        when(pm.getUUID(eq("tastybento"))).thenReturn(notUUID);
+        when(pm.getUUID("tastybento")).thenReturn(notUUID);
         when(im.hasIsland(any(), any(UUID.class))).thenReturn(true);
         AdminTeleportCommand atc = new AdminTeleportCommand(ac,"tp");
-        assertTrue(atc.canExecute(user, "tp", Collections.singletonList("tastybento")));
-        assertTrue(atc.execute(user, "tp", Collections.singletonList("tastybento")));
-        verify(user).getTranslation(eq("commands.admin.tp.manual"), eq("[location]"), eq("0 0 0"));
+        assertTrue(atc.canExecute(user, "tp", List.of("tastybento")));
+        assertTrue(atc.execute(user, "tp", List.of("tastybento")));
+        verify(user).getTranslation("commands.admin.tp.manual", "[location]", "0 0 0");
     }
 
     /**
@@ -247,56 +246,56 @@ public class AdminTeleportCommandTest {
     @Test
     public void testExecuteUserStringListOfStringKnownTargetHasIslandSpawnPoint() {
         when(island.getSpawnPoint(any())).thenReturn(spawnPoint);
-        when(pm.getUUID(eq("tastybento"))).thenReturn(notUUID);
+        when(pm.getUUID("tastybento")).thenReturn(notUUID);
         when(im.hasIsland(any(), any(UUID.class))).thenReturn(true);
         AdminTeleportCommand atc = new AdminTeleportCommand(ac,"tp");
-        assertTrue(atc.canExecute(user, "tp", Collections.singletonList("tastybento")));
-        assertTrue(atc.execute(user, "tp", Collections.singletonList("tastybento")));
-        verify(user).getTranslation(eq("commands.admin.tp.manual"), eq("[location]"), eq("0 0 0"));
+        assertTrue(atc.canExecute(user, "tp", List.of("tastybento")));
+        assertTrue(atc.execute(user, "tp", List.of("tastybento")));
+        verify(user).getTranslation("commands.admin.tp.manual", "[location]", "0 0 0");
     }
 
     @Test
     public void testExecuteUserStringListOfStringKnownTargetIsTeamMember() {
-        when(pm.getUUID(eq("tastybento"))).thenReturn(notUUID);
+        when(pm.getUUID("tastybento")).thenReturn(notUUID);
         when(im.hasIsland(any(), any(UUID.class))).thenReturn(false);
         when(im.inTeam(any(), any(UUID.class))).thenReturn(true);
         AdminTeleportCommand atc = new AdminTeleportCommand(ac,"tp");
-        assertTrue(atc.canExecute(user, "tp", Collections.singletonList("tastybento")));
-        assertTrue(atc.execute(user, "tp", Collections.singletonList("tastybento")));
+        assertTrue(atc.canExecute(user, "tp", List.of("tastybento")));
+        assertTrue(atc.execute(user, "tp", List.of("tastybento")));
         verify(iwm, Mockito.never()).getNetherWorld(any());
         verify(iwm, Mockito.never()).getEndWorld(any());
-        verify(user).getTranslation(eq("commands.admin.tp.manual"), eq("[location]"), eq("0 0 0"));
+        verify(user).getTranslation("commands.admin.tp.manual", "[location]", "0 0 0");
     }
 
     @Test
     public void testExecuteUserStringListOfStringKnownTargetHasIslandNether() {
-        when(pm.getUUID(eq("tastybento"))).thenReturn(notUUID);
+        when(pm.getUUID("tastybento")).thenReturn(notUUID);
         when(im.hasIsland(any(), any(UUID.class))).thenReturn(true);
         AdminTeleportCommand atc = new AdminTeleportCommand(ac,"tpnether");
-        assertTrue(atc.canExecute(user, "tpnether", Collections.singletonList("tastybento")));
-        assertTrue(atc.execute(user, "tpnether", Collections.singletonList("tastybento")));
+        assertTrue(atc.canExecute(user, "tpnether", List.of("tastybento")));
+        assertTrue(atc.execute(user, "tpnether", List.of("tastybento")));
         verify(iwm).getNetherWorld(any());
         verify(iwm, Mockito.never()).getEndWorld(any());
-        verify(user).getTranslation(eq("commands.admin.tp.manual"), eq("[location]"), eq("0 0 0"));
+        verify(user).getTranslation("commands.admin.tp.manual", "[location]", "0 0 0");
     }
 
     @Test
     public void testExecuteUserStringListOfStringKnownTargetHasIslandEnd() {
-        when(pm.getUUID(eq("tastybento"))).thenReturn(notUUID);
+        when(pm.getUUID("tastybento")).thenReturn(notUUID);
         when(im.hasIsland(any(), any(UUID.class))).thenReturn(true);
         AdminTeleportCommand atc = new AdminTeleportCommand(ac,"tpend");
-        assertTrue(atc.canExecute(user, "tpend", Collections.singletonList("tastybento")));
-        assertTrue(atc.execute(user, "tpend", Collections.singletonList("tastybento")));
+        assertTrue(atc.canExecute(user, "tpend", List.of("tastybento")));
+        assertTrue(atc.execute(user, "tpend", List.of("tastybento")));
         verify(iwm, Mockito.never()).getNetherWorld(any());
         verify(iwm).getEndWorld(any());
-        verify(user).getTranslation(eq("commands.admin.tp.manual"), eq("[location]"), eq("0 0 0"));
+        verify(user).getTranslation("commands.admin.tp.manual", "[location]", "0 0 0");
     }
 
     @Test
     public void testPermissionsNoRootPermission() {
         when(p.hasPermission("admin.tp")).thenReturn(true);
         when(p.hasPermission("admin")).thenReturn(false);
-        when(pm.getUUID(eq("tastybento"))).thenReturn(notUUID);
+        when(pm.getUUID("tastybento")).thenReturn(notUUID);
         when(im.hasIsland(any(), any(UUID.class))).thenReturn(true);
         AdminTeleportCommand atc = new AdminTeleportCommand(ac,"tpend");
         assertTrue(atc.canExecute(user, "tpend", List.of("tastybento")));
@@ -306,12 +305,12 @@ public class AdminTeleportCommandTest {
         // Should fail
         assertFalse(atc.execute(p, "tpend", list));
     }
-    
+
     @Test
     public void testPermissionsHasRootPermission() {
         when(p.hasPermission("admin.tp")).thenReturn(true);
         when(p.hasPermission("admin")).thenReturn(true);
-        when(pm.getUUID(eq("tastybento"))).thenReturn(notUUID);
+        when(pm.getUUID("tastybento")).thenReturn(notUUID);
         when(im.hasIsland(any(), any(UUID.class))).thenReturn(true);
         AdminTeleportCommand atc = new AdminTeleportCommand(ac,"tpend");
         assertTrue(atc.canExecute(user, "tpend", List.of("tastybento")));

From 2ad77965820390250f2641fdfb760901fe8b8bf1 Mon Sep 17 00:00:00 2001
From: tastybento 
Date: Sat, 22 Jul 2023 16:20:21 -0700
Subject: [PATCH 29/30] Refactor to reduce complexity

---
 .../protection/BlockInteractionListener.java  | 148 ++++++++++--------
 1 file changed, 84 insertions(+), 64 deletions(-)

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 b1a713850..cd5693782 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
@@ -91,72 +91,11 @@ public class BlockInteractionListener extends FlagListener
      */
     private void checkClickedBlock(Event e, Player player, Block block)
     {
+        if (checkSpecialCases(e, player, block) || checkTags(e, player, block)) {
+            return;
+        }
         Material type = block.getType();
         Location loc = block.getLocation();
-        // Handle pots
-        if (type.name().startsWith("POTTED"))
-        {
-            this.checkIsland(e, player, loc, Flags.FLOWER_POT);
-            return;
-        }
-
-        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);
-            return;
-        }
-
-        if (Tag.ANVIL.isTagged(type))
-        {
-            this.checkIsland(e, player, loc, Flags.ANVIL);
-            return;
-        }
-
-        if (Tag.BUTTONS.isTagged(type))
-        {
-            this.checkIsland(e, player, loc, Flags.BUTTON);
-            return;
-        }
-
-        if (Tag.BEDS.isTagged(type))
-        {
-            this.checkIsland(e, player, loc, Flags.BED);
-            return;
-        }
-
-        if (Tag.DOORS.isTagged(type))
-        {
-            this.checkIsland(e, player, loc, Flags.DOOR);
-            return;
-        }
-
-        if (Tag.SHULKER_BOXES.isTagged(type))
-        {
-            this.checkIsland(e, player, loc, Flags.SHULKER_BOX);
-            return;
-        }
-
-        if (Tag.TRAPDOORS.isTagged(type))
-        {
-            this.checkIsland(e, player, loc, Flags.TRAPDOOR);
-            return;
-        }
-
-        if (Tag.SIGNS.isTagged(type) && block.getState() instanceof Sign sign && !sign.isWaxed()) {
-            // If waxed, then sign cannot be edited otherwise check
-            this.checkIsland(e, player, loc, Flags.SIGN_EDITING);
-            return;
-        }
-
-        if (Tag.FENCE_GATES.isTagged(type))
-        {
-            this.checkIsland(e, player, loc, Flags.GATE);
-        }
-
-        if (Tag.ITEMS_CHEST_BOATS.isTagged(type))
-        {
-            this.checkIsland(e, player, loc, Flags.CHEST);
-        }
 
         switch (type)
         {
@@ -231,6 +170,87 @@ public class BlockInteractionListener extends FlagListener
     }
 
 
+    private boolean checkTags(Event e, Player player, Block block) {
+        Material type = block.getType();
+        Location loc = block.getLocation();
+
+        if (Tag.ANVIL.isTagged(type))
+        {
+            this.checkIsland(e, player, loc, Flags.ANVIL);
+            return true;
+        }
+
+        if (Tag.BUTTONS.isTagged(type))
+        {
+            this.checkIsland(e, player, loc, Flags.BUTTON);
+            return true;
+        }
+
+        if (Tag.BEDS.isTagged(type))
+        {
+            this.checkIsland(e, player, loc, Flags.BED);
+            return true;
+        }
+
+        if (Tag.DOORS.isTagged(type))
+        {
+            this.checkIsland(e, player, loc, Flags.DOOR);
+            return true;
+        }
+
+        if (Tag.SHULKER_BOXES.isTagged(type))
+        {
+            this.checkIsland(e, player, loc, Flags.SHULKER_BOX);
+            return true;
+        }
+
+        if (Tag.TRAPDOORS.isTagged(type))
+        {
+            this.checkIsland(e, player, loc, Flags.TRAPDOOR);
+            return true;
+        }
+
+        if (Tag.SIGNS.isTagged(type) && block.getState() instanceof Sign sign && !sign.isWaxed()) {
+            // If waxed, then sign cannot be edited otherwise check
+            this.checkIsland(e, player, loc, Flags.SIGN_EDITING);
+            return true;
+        }
+
+        if (Tag.FENCE_GATES.isTagged(type))
+        {
+            this.checkIsland(e, player, loc, Flags.GATE);
+            return true;
+        }
+
+        if (Tag.ITEMS_CHEST_BOATS.isTagged(type))
+        {
+            this.checkIsland(e, player, loc, Flags.CHEST);
+            return true;
+        }
+        return false;
+    }
+
+
+    private boolean checkSpecialCases(Event e, Player player, Block block) {
+        Material type = block.getType();
+        Location loc = block.getLocation();
+
+        // Handle pots
+        if (type.name().startsWith("POTTED"))
+        {
+            this.checkIsland(e, player, loc, Flags.FLOWER_POT);
+            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);
+            return true;
+        }
+        return false;
+    }
+
+
     /**
      * When breaking blocks is allowed, this protects specific blocks from being broken, which would bypass the
      * protection. For example, player enables break blocks, but chests are still protected Fires after the BreakBlocks

From 475e67c44704ae0335ace2a0fbc9162094c41a8c Mon Sep 17 00:00:00 2001
From: tastybento 
Date: Mon, 24 Jul 2023 18:27:06 -0700
Subject: [PATCH 30/30] Revert "Refactor YamlDatabaseHandler to reduce continue
 statements"

This reverts commit fec43adc35a863783e98b6026d76f523c1528b8e.
---
 .../database/yaml/YamlDatabaseHandler.java         | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/src/main/java/world/bentobox/bentobox/database/yaml/YamlDatabaseHandler.java b/src/main/java/world/bentobox/bentobox/database/yaml/YamlDatabaseHandler.java
index c4b5ba763..7de79cb79 100644
--- a/src/main/java/world/bentobox/bentobox/database/yaml/YamlDatabaseHandler.java
+++ b/src/main/java/world/bentobox/bentobox/database/yaml/YamlDatabaseHandler.java
@@ -358,11 +358,11 @@ public class YamlDatabaseHandler extends AbstractDatabaseHandler {
         // See if there are any top-level comments
         handleComments(instance.getClass(), config, yamlComments, "");
 
+        // Run through all the fields in the class that is being stored. EVERY field must have a get and set method
         for (Field field : dataObject.getDeclaredFields()) {
             if (field.isSynthetic()) {
                 continue;
             }
-
             // Get the property descriptor for this field
             PropertyDescriptor propertyDescriptor = new PropertyDescriptor(field.getName(), dataObject);
             // Get the read method
@@ -376,7 +376,12 @@ public class YamlDatabaseHandler extends AbstractDatabaseHandler {
             ConfigEntry configEntry = field.getAnnotation(ConfigEntry.class);
 
             // If there is a config path annotation or adapter then deal with them
-            if (configEntry != null && !configEntry.path().isEmpty() && !configEntry.hidden()) {
+            if (configEntry != null && !configEntry.path().isEmpty()) {
+                if (configEntry.hidden()) {
+                    // If the annotation tells us to not print the config entry, then we won't.
+                    continue;
+                }
+
                 // Get the storage location
                 storageLocation = configEntry.path();
 
@@ -387,7 +392,9 @@ public class YamlDatabaseHandler extends AbstractDatabaseHandler {
                 }
                 handleComments(field, config, yamlComments, parent);
                 handleConfigEntryComments(configEntry, config, yamlComments, parent);
-            } else if (!checkAdapter(field, config, storageLocation, value)) {
+            }
+
+            if (!checkAdapter(field, config, storageLocation, value)) {
                 // Set the filename if it has not be set already
                 if (filename.isEmpty() && method.getName().equals("getUniqueId")) {
                     // Save the name for when the file is saved
@@ -404,7 +411,6 @@ public class YamlDatabaseHandler extends AbstractDatabaseHandler {
                 }
             }
         }
-
         // If the filename has not been set by now then we have a problem
         if (filename.isEmpty()) {
             throw new IllegalArgumentException("No uniqueId in class");