diff --git a/locales/en-US.yml b/locales/en-US.yml index 1729cf49a..24f2ddbd2 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -316,7 +316,12 @@ protection: DOOR: "Use doors" ELYTRA: "Use elytras" ENCHANTING: "Use enchanting table" - ENTER_EXIT_MESSAGES: "Display entry and exit messages" + ENTER_EXIT_MESSAGES: + name: "Enter/Exit messages" + description: "Display entry and exit messages" + now-leaving: "Now leaving [name]" + now-entering: "Now entering [name]" + island: "[name]'s island" FIRE: "FIRE" FIRE_EXTINGUISH: "FIRE_EXTINGUISH" FIRE_SPREAD: "FIRE_SPREAD" @@ -360,6 +365,12 @@ protection: allowed_rank: "&3- &a" blocked_rank: "&3- &c" minimal_rank: "&3- &2" + setting-layout: |+ + &a[description] + + &7Current setting: [setting] + setting-active: "&aActive" + setting-disabled: "&cDisabled" language: panel-title: "Select your language" diff --git a/src/main/java/us/tastybento/bskyblock/Settings.java b/src/main/java/us/tastybento/bskyblock/Settings.java index 5eab98614..53d1ed344 100644 --- a/src/main/java/us/tastybento/bskyblock/Settings.java +++ b/src/main/java/us/tastybento/bskyblock/Settings.java @@ -1306,5 +1306,4 @@ public class Settings implements ISettings, WorldSettings { return "bskyblock"; } - } \ No newline at end of file diff --git a/src/main/java/us/tastybento/bskyblock/api/commands/CompositeCommand.java b/src/main/java/us/tastybento/bskyblock/api/commands/CompositeCommand.java index e1ee5f991..561becacc 100644 --- a/src/main/java/us/tastybento/bskyblock/api/commands/CompositeCommand.java +++ b/src/main/java/us/tastybento/bskyblock/api/commands/CompositeCommand.java @@ -544,6 +544,7 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi } /** + * The the world that this command applies to. * @return the world */ public World getWorld() { diff --git a/src/main/java/us/tastybento/bskyblock/api/flags/Flag.java b/src/main/java/us/tastybento/bskyblock/api/flags/Flag.java index b88e486de..e01d352c8 100644 --- a/src/main/java/us/tastybento/bskyblock/api/flags/Flag.java +++ b/src/main/java/us/tastybento/bskyblock/api/flags/Flag.java @@ -1,8 +1,11 @@ package us.tastybento.bskyblock.api.flags; +import java.util.HashMap; +import java.util.Map; import java.util.Optional; import org.bukkit.Material; +import org.bukkit.World; import org.bukkit.event.Listener; import org.bukkit.inventory.ItemStack; @@ -13,6 +16,7 @@ import us.tastybento.bskyblock.api.panels.builders.PanelItemBuilder; import us.tastybento.bskyblock.api.user.User; import us.tastybento.bskyblock.database.objects.Island; import us.tastybento.bskyblock.managers.RanksManager; +import us.tastybento.bskyblock.util.Util; public class Flag implements Comparable { @@ -25,7 +29,8 @@ public class Flag implements Comparable { private final Material icon; private final Listener listener; private final Type type; - private boolean defaultSetting; + private Map worldSettings = new HashMap<>(); + private boolean setting; private final int defaultRank; private final PanelItem.ClickHandler clickHandler; @@ -33,7 +38,7 @@ public class Flag implements Comparable { this.id = id; this.icon = icon; this.listener = listener; - this.defaultSetting = defaultSetting; + this.setting = defaultSetting; this.type = type; this.defaultRank = defaultRank; this.clickHandler = clickListener; @@ -52,10 +57,21 @@ public class Flag implements Comparable { } /** - * @return - true means it is allowed. false means it is not allowed + * Check if a setting is set in this world + * @param world - world + * @return world setting, or default system setting if a specific world setting is not set */ - public boolean isDefaultSetting() { - return defaultSetting; + public boolean isSet(World world) { + return worldSettings.getOrDefault(Util.getWorld(world), setting); + } + + /** + * Set the default or global setting for this world + * @param world - world + * @param setting - true or false + */ + public void setSetting(World world, boolean setting) { + worldSettings.put(Util.getWorld(world), setting); } /** @@ -63,7 +79,7 @@ public class Flag implements Comparable { * @param defaultSetting - true means it is allowed. false means it is not allowed */ public void setDefaultSetting(boolean defaultSetting) { - this.defaultSetting = defaultSetting; + this.setting = defaultSetting; } /** @@ -130,6 +146,16 @@ public class Flag implements Comparable { .icon(new ItemStack(icon)) .name(user.getTranslation("protection.panel.flag-item.name-layout", TextVariables.NAME, user.getTranslation("protection.flags." + id + ".name"))) .clickHandler(clickHandler); + + // Check if this is a setting + if (this.getType().equals(Type.SETTING)) { + String setting = this.isSet(user.getWorld()) ? user.getTranslation("protection.panel.flag-item.setting-active") + : user.getTranslation("protection.panel.flag-item.setting-disabled"); + pib.description(user.getTranslation("protection.panel.flag-item.setting-layout", "[description]", user.getTranslation("protection.flags." + id + ".description") + , "[setting]", setting)); + return pib.build(); + } + // Protection flag pib.description(user.getTranslation("protection.panel.flag-item.description-layout", "[description]", user.getTranslation("protection.flags." + id + ".description"))); // Get the island this user is on or their own @@ -157,7 +183,7 @@ public class Flag implements Comparable { @Override public String toString() { return "Flag [id=" + id + ", icon=" + icon + ", listener=" + listener + ", type=" + type + ", defaultSetting=" - + defaultSetting + ", defaultRank=" + defaultRank + ", clickHandler=" + clickHandler + "]"; + + setting + ", defaultRank=" + defaultRank + ", clickHandler=" + clickHandler + "]"; } @Override diff --git a/src/main/java/us/tastybento/bskyblock/api/flags/FlagBuilder.java b/src/main/java/us/tastybento/bskyblock/api/flags/FlagBuilder.java index 9a56371ca..d0f7db45d 100644 --- a/src/main/java/us/tastybento/bskyblock/api/flags/FlagBuilder.java +++ b/src/main/java/us/tastybento/bskyblock/api/flags/FlagBuilder.java @@ -13,7 +13,7 @@ public class FlagBuilder { private String id; private Material icon; private Listener listener; - private boolean defaultSetting; + private boolean setting; private Type type = Type.PROTECTION; private int defaultRank = RanksManager.MEMBER_RANK; private PanelItem.ClickHandler onClick; @@ -25,18 +25,25 @@ public class FlagBuilder { return this; } + /** + * The material that will become the icon for this flag + * @param icon + */ public FlagBuilder icon(Material icon) { this.icon = icon; return this; } + /** + * @param listener - the Bukkit listener that will be registered to handle this flag + */ public FlagBuilder listener(Listener listener) { this.listener = listener; return this; } public Flag build() { - return new Flag(id, icon, listener, defaultSetting, type, defaultRank, onClick); + return new Flag(id, icon, listener, setting, type, defaultRank, onClick); } /** @@ -45,7 +52,7 @@ public class FlagBuilder { * @return FlagBuilder */ public FlagBuilder allowedByDefault(boolean setting) { - defaultSetting = setting; + this.setting = setting; return this; } @@ -89,4 +96,5 @@ public class FlagBuilder { this.onClick = onClickListener; return this; } + } diff --git a/src/main/java/us/tastybento/bskyblock/commands/island/IslandResetCommand.java b/src/main/java/us/tastybento/bskyblock/commands/island/IslandResetCommand.java index 485cdc942..b35c0e0dd 100644 --- a/src/main/java/us/tastybento/bskyblock/commands/island/IslandResetCommand.java +++ b/src/main/java/us/tastybento/bskyblock/commands/island/IslandResetCommand.java @@ -19,7 +19,6 @@ import us.tastybento.bskyblock.managers.island.NewIsland; public class IslandResetCommand extends CompositeCommand { private Map cooldown; - private Map confirm; public IslandResetCommand(CompositeCommand islandCommand) { super(islandCommand, "reset", "restart"); @@ -28,7 +27,6 @@ public class IslandResetCommand extends CompositeCommand { @Override public void setup() { cooldown = new HashMap<>(); - confirm = new HashMap<>(); setPermission("island.create"); setOnlyPlayer(true); setDescription("commands.island.reset.description"); @@ -73,8 +71,6 @@ public class IslandResetCommand extends CompositeCommand { } private boolean resetIsland(User user) { - // Remove the confirmation - confirm.remove(user.getUniqueId()); // Reset the island Player player = user.getPlayer(); player.setGameMode(GameMode.SPECTATOR); diff --git a/src/main/java/us/tastybento/bskyblock/commands/island/IslandSetnameCommand.java b/src/main/java/us/tastybento/bskyblock/commands/island/IslandSetnameCommand.java index 779b4600b..03a9f0bd9 100644 --- a/src/main/java/us/tastybento/bskyblock/commands/island/IslandSetnameCommand.java +++ b/src/main/java/us/tastybento/bskyblock/commands/island/IslandSetnameCommand.java @@ -5,7 +5,6 @@ import java.util.UUID; import java.util.stream.Collectors; import org.bukkit.ChatColor; -import org.bukkit.entity.Player; import us.tastybento.bskyblock.api.commands.CompositeCommand; import us.tastybento.bskyblock.api.localization.TextVariables; @@ -34,8 +33,7 @@ public class IslandSetnameCommand extends CompositeCommand { */ @Override public boolean execute(User user, List args) { - Player player = user.getPlayer(); - UUID playerUUID = player.getUniqueId(); + UUID playerUUID = user.getUniqueId(); if (!getIslands().hasIsland(getWorld(), playerUUID)) { user.sendMessage("general.errors.no-island"); @@ -66,8 +64,8 @@ public class IslandSetnameCommand extends CompositeCommand { } // Set the name - if (!player.hasPermission("island.name.format")) { - getIslands().getIsland(getWorld(), player.getUniqueId()).setName(ChatColor.translateAlternateColorCodes('&', name)); + if (user.isOp() || user.hasPermission(this.getPermissionPrefix() + ".island.name.format")) { + getIslands().getIsland(getWorld(), playerUUID).setName(ChatColor.translateAlternateColorCodes('&', name)); } else { getIslands().getIsland(getWorld(), playerUUID).setName(name); } diff --git a/src/main/java/us/tastybento/bskyblock/commands/island/IslandSettingsCommand.java b/src/main/java/us/tastybento/bskyblock/commands/island/IslandSettingsCommand.java index 374ad1cd2..7453991e9 100644 --- a/src/main/java/us/tastybento/bskyblock/commands/island/IslandSettingsCommand.java +++ b/src/main/java/us/tastybento/bskyblock/commands/island/IslandSettingsCommand.java @@ -5,6 +5,7 @@ import java.util.List; import us.tastybento.bskyblock.api.commands.CompositeCommand; import us.tastybento.bskyblock.api.user.User; import us.tastybento.bskyblock.panels.SettingsPanel; +import us.tastybento.bskyblock.util.Util; /** * @author Poslovitch @@ -30,7 +31,13 @@ public class IslandSettingsCommand extends CompositeCommand { */ @Override public boolean execute(User user, List args) { - SettingsPanel.openPanel(getPlugin(), user); - return true; + // Settings are only shown if you are in the right world + if (Util.getWorld(user.getWorld()).equals(getWorld())) { + SettingsPanel.openPanel(getPlugin(), user); + return true; + } else { + user.sendMessage("general.errors.wrong-world"); + return false; + } } } diff --git a/src/main/java/us/tastybento/bskyblock/island/builders/Clipboard.java b/src/main/java/us/tastybento/bskyblock/island/builders/Clipboard.java index 87b647710..5d5ee011e 100644 --- a/src/main/java/us/tastybento/bskyblock/island/builders/Clipboard.java +++ b/src/main/java/us/tastybento/bskyblock/island/builders/Clipboard.java @@ -387,7 +387,6 @@ public class Clipboard { /** * Load a file to clipboard - * @param file * @throws IOException * @throws InvalidConfigurationException */ diff --git a/src/main/java/us/tastybento/bskyblock/listeners/flags/AbstractFlagListener.java b/src/main/java/us/tastybento/bskyblock/listeners/flags/AbstractFlagListener.java index a2236fe11..e210e1c65 100644 --- a/src/main/java/us/tastybento/bskyblock/listeners/flags/AbstractFlagListener.java +++ b/src/main/java/us/tastybento/bskyblock/listeners/flags/AbstractFlagListener.java @@ -102,20 +102,21 @@ public abstract class AbstractFlagListener implements Listener { } /** - * Generic flag checker + * Check if flag is allowed at location * @param e - event * @param loc - location - * @param breakBlocks - * @return true if the check is okay, false if it was disallowed + * @param flag - flag {@link us.tastybento.bskyblock.lists.Flags} + * @return true if allowed, false if not */ - public boolean checkIsland(Event e, Location loc, Flag breakBlocks) { - return checkIsland(e, loc, breakBlocks, false); + public boolean checkIsland(Event e, Location loc, Flag flag) { + return checkIsland(e, loc, flag, false); } /** - * Check if flag is allowed + * Check if flag is allowed at location * @param e - event * @param loc - location + * @param flag - flag {@link us.tastybento.bskyblock.lists.Flags} * @param silent - if true, no attempt is made to tell the user * @return true if the check is okay, false if it was disallowed */ @@ -129,7 +130,7 @@ public abstract class AbstractFlagListener implements Listener { // Handle Settings Flag if (flag.getType().equals(Type.SETTING)) { // If the island exists, return the setting, otherwise return the default setting for this flag - return island.map(x -> x.isAllowed(flag)).orElse(flag.isDefaultSetting()); + return island.map(x -> x.isAllowed(flag)).orElse(flag.isSet(loc.getWorld())); } // Protection flag @@ -157,7 +158,7 @@ public abstract class AbstractFlagListener implements Listener { } } // The player is in the world, but not on an island, so general world settings apply - if (!flag.isDefaultSetting()) { + if (!flag.isSet(loc.getWorld())) { noGo(e, silent); user = null; return false; diff --git a/src/main/java/us/tastybento/bskyblock/listeners/flags/BreakBlocksListener.java b/src/main/java/us/tastybento/bskyblock/listeners/flags/BreakBlocksListener.java index b7086f425..862b52cce 100644 --- a/src/main/java/us/tastybento/bskyblock/listeners/flags/BreakBlocksListener.java +++ b/src/main/java/us/tastybento/bskyblock/listeners/flags/BreakBlocksListener.java @@ -104,7 +104,7 @@ public class BreakBlocksListener extends AbstractFlagListener { }); // The player is in the world, but not on an island, so general world settings apply - if (!Flags.BREAK_BLOCKS.isDefaultSetting()) { + if (!Flags.BREAK_BLOCKS.isSet(e.getVehicle().getWorld())) { e.setCancelled(true); user.sendMessage("protection.protected"); } diff --git a/src/main/java/us/tastybento/bskyblock/listeners/flags/EnterExitListener.java b/src/main/java/us/tastybento/bskyblock/listeners/flags/EnterExitListener.java new file mode 100644 index 000000000..e584812b4 --- /dev/null +++ b/src/main/java/us/tastybento/bskyblock/listeners/flags/EnterExitListener.java @@ -0,0 +1,55 @@ +/** + * + */ +package us.tastybento.bskyblock.listeners.flags; + +import java.util.Optional; + +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.player.PlayerMoveEvent; +import org.bukkit.util.Vector; + +import us.tastybento.bskyblock.api.user.User; +import us.tastybento.bskyblock.database.objects.Island; +import us.tastybento.bskyblock.lists.Flags; + +/** + * The Enter/Exit messages flag is a global flag and applies everywhere + * @author tastybento + * + */ +public class EnterExitListener extends AbstractFlagListener { + + private static final Vector XZ = new Vector(1,0,1); + + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void onMove(PlayerMoveEvent e) { + // Only process if Enter Exit flags are active, we are in the right world and there is a change in X or Z coords + if (!Flags.ENTER_EXIT_MESSAGES.isSet(e.getFrom().getWorld()) + || e.getFrom().toVector().multiply(XZ).equals(e.getTo().toVector().multiply(XZ)) + || !getIslandWorldManager().inWorld(e.getFrom())) { + return; + } + Optional from = this.getIslands().getProtectedIslandAt(e.getFrom()); + Optional to = this.getIslands().getProtectedIslandAt(e.getTo()); + + /* + * Options: + * + * from = empty, to = island - entering + * from = island1, to = island2 - leaving 1, entering 2 + * from = island, to = empty - leaving + * from = empty, to = empty + * from = island, to = island + */ + if (from.equals(to)) { + return; + } + User user = User.getInstance(e.getPlayer()); + from.ifPresent(i -> user.sendMessage("protection.flags.ENTER_EXIT_MESSAGES.now-leaving", "[name]", !i.getName().isEmpty() ? i.getName() : + user.getTranslation("protection.flags.ENTER_EXIT_MESSAGES.island", "[name]", getPlugin().getPlayers().getName(i.getOwner())))); + to.ifPresent(i -> user.sendMessage("protection.flags.ENTER_EXIT_MESSAGES.now-entering", "[name]", !i.getName().isEmpty() ? i.getName() : + user.getTranslation("protection.flags.ENTER_EXIT_MESSAGES.island", "[name]", getPlugin().getPlayers().getName(i.getOwner())))); + } +} diff --git a/src/main/java/us/tastybento/bskyblock/listeners/flags/FireListener.java b/src/main/java/us/tastybento/bskyblock/listeners/flags/FireListener.java index 168babd9b..285d8d21b 100644 --- a/src/main/java/us/tastybento/bskyblock/listeners/flags/FireListener.java +++ b/src/main/java/us/tastybento/bskyblock/listeners/flags/FireListener.java @@ -40,8 +40,7 @@ public class FireListener extends AbstractFlagListener { return false; } // Check if the island exists and if fire is allowed - boolean cancel = getIslands().getIslandAt(l).map(i -> !i.isAllowed(flag)).orElse(!flag.isDefaultSetting()); - + boolean cancel = getIslands().getIslandAt(l).map(i -> !i.isAllowed(flag)).orElse(!flag.isSet(l.getWorld())); e.setCancelled(cancel); return cancel; } diff --git a/src/main/java/us/tastybento/bskyblock/listeners/flags/MobSpawnListener.java b/src/main/java/us/tastybento/bskyblock/listeners/flags/MobSpawnListener.java index 874ef31f9..b20b69056 100644 --- a/src/main/java/us/tastybento/bskyblock/listeners/flags/MobSpawnListener.java +++ b/src/main/java/us/tastybento/bskyblock/listeners/flags/MobSpawnListener.java @@ -43,11 +43,11 @@ public class MobSpawnListener extends AbstractFlagListener { Optional island = getIslands().getIslandAt(e.getLocation()); // Cancel the event if these are true if ((e.getEntity() instanceof Monster || e.getEntity() instanceof Slime)) { - boolean cancel = island.map(i -> !i.isAllowed(Flags.MONSTER_SPAWN)).orElse(!Flags.MONSTER_SPAWN.isDefaultSetting()); + boolean cancel = island.map(i -> !i.isAllowed(Flags.MONSTER_SPAWN)).orElse(!Flags.MONSTER_SPAWN.isSet(e.getEntity().getWorld())); e.setCancelled(cancel); return cancel; } else if (e.getEntity() instanceof Animals) { - boolean cancel = island.map(i -> !i.isAllowed(Flags.ANIMAL_SPAWN)).orElse(!Flags.ANIMAL_SPAWN.isDefaultSetting()); + boolean cancel = island.map(i -> !i.isAllowed(Flags.ANIMAL_SPAWN)).orElse(!Flags.ANIMAL_SPAWN.isSet(e.getEntity().getWorld())); e.setCancelled(cancel); return cancel; } diff --git a/src/main/java/us/tastybento/bskyblock/listeners/flags/SettingsToggleClickListener.java b/src/main/java/us/tastybento/bskyblock/listeners/flags/SettingsToggleClickListener.java new file mode 100644 index 000000000..08836c03d --- /dev/null +++ b/src/main/java/us/tastybento/bskyblock/listeners/flags/SettingsToggleClickListener.java @@ -0,0 +1,59 @@ +/** + * + */ +package us.tastybento.bskyblock.listeners.flags; + +import org.bukkit.Sound; +import org.bukkit.event.inventory.ClickType; + +import us.tastybento.bskyblock.BSkyBlock; +import us.tastybento.bskyblock.api.flags.Flag; +import us.tastybento.bskyblock.api.panels.Panel; +import us.tastybento.bskyblock.api.panels.PanelItem.ClickHandler; +import us.tastybento.bskyblock.api.user.User; +import us.tastybento.bskyblock.util.Util; + +/** + * @author tastybento + * + */ +public class SettingsToggleClickListener implements ClickHandler { + + private BSkyBlock plugin = BSkyBlock.getInstance(); + private String id; + + /** + * @param id + */ + public SettingsToggleClickListener(String id) { + this.id = id; + } + + + /* (non-Javadoc) + * @see us.tastybento.bskyblock.api.panels.PanelItem.ClickHandler#onClick(us.tastybento.bskyblock.api.panels.Panel, us.tastybento.bskyblock.api.user.User, org.bukkit.event.inventory.ClickType, int) + */ + @Override + public boolean onClick(Panel panel, User user, ClickType clickType, int slot) { + // Get the world + if (!plugin.getIWM().inWorld(user.getLocation())) { + user.sendMessage("general.errors.wrong-world"); + return true; + } + String reqPerm = plugin.getIWM().getPermissionPrefix(Util.getWorld(user.getWorld())) + ".settings." + id; + if (!user.hasPermission(reqPerm)) { + user.sendMessage("general.errors.no-permission"); + user.sendMessage("general.errors.you-need", "[permission]", reqPerm); + return true; + } + // Get flag + Flag flag = plugin.getFlagsManager().getFlagByID(id); + // Toggle flag + flag.setSetting(user.getWorld(), !flag.isSet(user.getWorld())); + user.getWorld().playSound(user.getLocation(), Sound.BLOCK_STONE_BUTTON_CLICK_ON, 1F, 1F); + // Apply change to panel + panel.getInventory().setItem(slot, flag.toPanelItem(plugin, user).getItem()); + return true; + } + +} diff --git a/src/main/java/us/tastybento/bskyblock/lists/Flags.java b/src/main/java/us/tastybento/bskyblock/lists/Flags.java index 163df3427..ba1415daf 100644 --- a/src/main/java/us/tastybento/bskyblock/lists/Flags.java +++ b/src/main/java/us/tastybento/bskyblock/lists/Flags.java @@ -15,6 +15,7 @@ import us.tastybento.bskyblock.listeners.flags.BreakBlocksListener; import us.tastybento.bskyblock.listeners.flags.BreedingListener; import us.tastybento.bskyblock.listeners.flags.BucketListener; import us.tastybento.bskyblock.listeners.flags.EggListener; +import us.tastybento.bskyblock.listeners.flags.EnterExitListener; import us.tastybento.bskyblock.listeners.flags.EntityInteractListener; import us.tastybento.bskyblock.listeners.flags.FireListener; import us.tastybento.bskyblock.listeners.flags.HurtingListener; @@ -26,6 +27,7 @@ import us.tastybento.bskyblock.listeners.flags.PVPListener; import us.tastybento.bskyblock.listeners.flags.PhysicalInteractionListener; import us.tastybento.bskyblock.listeners.flags.PlaceBlocksListener; import us.tastybento.bskyblock.listeners.flags.PortalListener; +import us.tastybento.bskyblock.listeners.flags.SettingsToggleClickListener; import us.tastybento.bskyblock.listeners.flags.ShearingListener; import us.tastybento.bskyblock.listeners.flags.TeleportationListener; import us.tastybento.bskyblock.managers.RanksManager; @@ -132,7 +134,10 @@ public class Flags { public static final Flag PVP_NETHER = new FlagBuilder().id("PVP_NETHER").icon(Material.IRON_AXE).type(Type.SETTING).build(); public static final Flag PVP_END = new FlagBuilder().id("PVP_END").icon(Material.END_CRYSTAL).type(Type.SETTING).build(); // Others - public static final Flag ENTER_EXIT_MESSAGES = new FlagBuilder().id("ENTER_EXIT_MESSAGES").icon(Material.DIRT).allowedByDefault(true).type(Type.SETTING).build(); + public static final Flag ENTER_EXIT_MESSAGES = new FlagBuilder().id("ENTER_EXIT_MESSAGES").icon(Material.DIRT).allowedByDefault(true).type(Type.SETTING) + .listener(new EnterExitListener()) + .onClick(new SettingsToggleClickListener("ENTER_EXIT_MESSAGES")) + .build(); public static final Flag ANIMAL_SPAWN = new FlagBuilder().id("ANIMAL_SPAWN").icon(Material.APPLE).allowedByDefault(true).type(Type.SETTING).build(); public static final Flag MONSTER_SPAWN = new FlagBuilder().id("MONSTER_SPAWN").icon(Material.MOB_SPAWNER).allowedByDefault(true).type(Type.SETTING).build(); public static final Flag FIRE_SPREAD = new FlagBuilder().id("FIRE_SPREAD").icon(Material.FIREWORK_CHARGE).type(Type.SETTING).build(); diff --git a/src/main/java/us/tastybento/bskyblock/managers/IslandWorldManager.java b/src/main/java/us/tastybento/bskyblock/managers/IslandWorldManager.java index 70a613d70..3132599c7 100644 --- a/src/main/java/us/tastybento/bskyblock/managers/IslandWorldManager.java +++ b/src/main/java/us/tastybento/bskyblock/managers/IslandWorldManager.java @@ -454,4 +454,5 @@ public class IslandWorldManager { return worldSettings.get(Util.getWorld(world)).getPermissionPrefix(); } + } diff --git a/src/main/java/us/tastybento/bskyblock/managers/RanksManager.java b/src/main/java/us/tastybento/bskyblock/managers/RanksManager.java index 5f4bcf837..2328c9adf 100644 --- a/src/main/java/us/tastybento/bskyblock/managers/RanksManager.java +++ b/src/main/java/us/tastybento/bskyblock/managers/RanksManager.java @@ -118,7 +118,7 @@ public class RanksManager { /** - * Gets the next rank value above the current rank. Highest is {@link RanksManager.OWNER_RANK} + * Gets the next rank value above the current rank. Highest is {@link RanksManager#OWNER_RANK} * @param currentRank * @return Optional rank value */ @@ -132,7 +132,7 @@ public class RanksManager { } /** - * Gets the previous rank value below the current rank. Lowest is {@link RanksManager.VISITOR_RANK} + * Gets the previous rank value below the current rank. Lowest is {@link RanksManager#VISITOR_RANK} * @param currentRank * @return Optional rank value */ diff --git a/src/test/java/us/tastybento/bskyblock/api/flags/FlagTest.java b/src/test/java/us/tastybento/bskyblock/api/flags/FlagTest.java index d69fbc428..f60d1b97f 100644 --- a/src/test/java/us/tastybento/bskyblock/api/flags/FlagTest.java +++ b/src/test/java/us/tastybento/bskyblock/api/flags/FlagTest.java @@ -13,6 +13,7 @@ import java.util.UUID; import org.bukkit.Location; import org.bukkit.Material; +import org.bukkit.World; import org.bukkit.event.Listener; import org.bukkit.inventory.ItemStack; import org.junit.Before; @@ -31,9 +32,10 @@ import us.tastybento.bskyblock.api.user.User; import us.tastybento.bskyblock.database.objects.Island; import us.tastybento.bskyblock.managers.IslandsManager; import us.tastybento.bskyblock.managers.RanksManager; +import us.tastybento.bskyblock.util.Util; @RunWith(PowerMockRunner.class) -@PrepareForTest({ Flag.class }) +@PrepareForTest({ Flag.class, Util.class }) public class FlagTest { @BeforeClass @@ -42,6 +44,8 @@ public class FlagTest { @Before public void setUp() throws Exception { + PowerMockito.mockStatic(Util.class); + when(Util.getWorld(Mockito.any())).thenReturn(mock(World.class)); } @Test @@ -81,19 +85,19 @@ public class FlagTest { @Test public void testIsDefaultSetting() { Flag id = new Flag("id", Material.ACACIA_DOOR, null, false, null, 0, null); - assertFalse(id.isDefaultSetting()); + assertFalse(id.isSet(mock(World.class))); id = new Flag("id", Material.ACACIA_DOOR, null, true, null, 0, null); - assertTrue(id.isDefaultSetting()); + assertTrue(id.isSet(mock(World.class))); } @Test public void testSetDefaultSetting() { Flag id = new Flag("id", Material.ACACIA_DOOR, null, false, null, 0, null); - assertFalse(id.isDefaultSetting()); + assertFalse(id.isSet(mock(World.class))); id.setDefaultSetting(true); - assertTrue(id.isDefaultSetting()); + assertTrue(id.isSet(mock(World.class))); id.setDefaultSetting(false); - assertFalse(id.isDefaultSetting()); + assertFalse(id.isSet(mock(World.class))); } diff --git a/src/test/java/us/tastybento/bskyblock/listeners/flags/EnterExitListenerTest.java b/src/test/java/us/tastybento/bskyblock/listeners/flags/EnterExitListenerTest.java new file mode 100644 index 000000000..3fa0205e3 --- /dev/null +++ b/src/test/java/us/tastybento/bskyblock/listeners/flags/EnterExitListenerTest.java @@ -0,0 +1,240 @@ +/** + * + */ +package us.tastybento.bskyblock.listeners.flags; + +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.Optional; +import java.util.UUID; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.entity.Player; +import org.bukkit.event.player.PlayerMoveEvent; +import org.bukkit.util.Vector; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; +import org.powermock.reflect.Whitebox; + +import us.tastybento.bskyblock.BSkyBlock; +import us.tastybento.bskyblock.Settings; +import us.tastybento.bskyblock.api.user.Notifier; +import us.tastybento.bskyblock.api.user.User; +import us.tastybento.bskyblock.database.objects.Island; +import us.tastybento.bskyblock.managers.IslandWorldManager; +import us.tastybento.bskyblock.managers.IslandsManager; +import us.tastybento.bskyblock.managers.LocalesManager; +import us.tastybento.bskyblock.managers.PlayersManager; +import us.tastybento.bskyblock.util.Util; + +/** + * @author tastybento + * + */ +@RunWith(PowerMockRunner.class) +@PrepareForTest({Bukkit.class, BSkyBlock.class, Util.class }) +public class EnterExitListenerTest { + + private static final Integer PROTECTION_RANGE = 200; + private static final Integer X = 600; + private static final Integer Y = 120; + private static final Integer Z = 10000; + private UUID uuid; + private User user; + private IslandsManager im; + private Island island; + private World world; + private Location outside; + private Location inside; + private Notifier notifier; + private Location inside2; + private EnterExitListener listener; + private LocalesManager lm; + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() throws Exception { + + // Set up plugin + BSkyBlock plugin = mock(BSkyBlock.class); + Whitebox.setInternalState(BSkyBlock.class, "instance", plugin); + + // World + world = mock(World.class); + + // Settings + Settings s = mock(Settings.class); + when(plugin.getSettings()).thenReturn(s); + + // Player + Player p = mock(Player.class); + // Sometimes use Mockito.withSettings().verboseLogging() + user = mock(User.class); + User.setPlugin(plugin); + when(user.isOp()).thenReturn(false); + uuid = UUID.randomUUID(); + when(user.getUniqueId()).thenReturn(uuid); + when(user.getPlayer()).thenReturn(p); + when(user.getName()).thenReturn("tastybento"); + + // No island for player to begin with (set it later in the tests) + im = mock(IslandsManager.class); + when(plugin.getIslands()).thenReturn(im); + + // Locales + lm = mock(LocalesManager.class); + when(plugin.getLocalesManager()).thenReturn(lm); + when(lm.get(any(), any())).thenReturn("mock translation"); + + // Notifier + notifier = mock(Notifier.class); + when(plugin.getNotifier()).thenReturn(notifier); + + // Island Banned list initialization + island = mock(Island.class); + Location loc = mock(Location.class); + when(loc.getWorld()).thenReturn(world); + when(loc.getBlockX()).thenReturn(X); + when(loc.getBlockY()).thenReturn(Y); + when(loc.getBlockZ()).thenReturn(Z); + when(island.getCenter()).thenReturn(loc); + when(island.getProtectionRange()).thenReturn(PROTECTION_RANGE); + when(island.getOwner()).thenReturn(uuid); + + when(im.getIsland(Mockito.any(), Mockito.any(UUID.class))).thenReturn(island); + + // Common from to's + outside = mock(Location.class); + when(outside.getWorld()).thenReturn(world); + when(outside.getBlockX()).thenReturn(X + PROTECTION_RANGE + 1); + when(outside.getBlockY()).thenReturn(Y); + when(outside.getBlockZ()).thenReturn(Z); + when(outside.toVector()).thenReturn(new Vector(X + PROTECTION_RANGE + 1, Y, Z)); + + inside = mock(Location.class); + when(inside.getWorld()).thenReturn(world); + when(inside.getBlockX()).thenReturn(X + PROTECTION_RANGE - 1); + when(inside.getBlockY()).thenReturn(Y); + when(inside.getBlockZ()).thenReturn(Z); + when(inside.toVector()).thenReturn(new Vector(X + PROTECTION_RANGE - 1, Y, Z)); + + inside2 = mock(Location.class); + when(inside.getWorld()).thenReturn(world); + when(inside.getBlockX()).thenReturn(X + PROTECTION_RANGE - 2); + when(inside.getBlockY()).thenReturn(Y); + when(inside.getBlockZ()).thenReturn(Z); + when(inside.toVector()).thenReturn(new Vector(X + PROTECTION_RANGE -2, Y, Z)); + + Optional opIsland = Optional.ofNullable(island); + when(im.getProtectedIslandAt(Mockito.eq(inside))).thenReturn(opIsland); + when(im.getProtectedIslandAt(Mockito.eq(inside2))).thenReturn(opIsland); + when(im.getProtectedIslandAt(Mockito.eq(outside))).thenReturn(Optional.empty()); + + // Island World Manager + IslandWorldManager iwm = mock(IslandWorldManager.class); + when(iwm.inWorld(Mockito.any())).thenReturn(true); + when(plugin.getIWM()).thenReturn(iwm); + + // Player's manager + PlayersManager pm = mock(PlayersManager.class); + when(pm.getName(Mockito.any())).thenReturn("tastybento"); + when(plugin.getPlayers()).thenReturn(pm); + + // Listener + listener = new EnterExitListener(); + + PowerMockito.mockStatic(Util.class); + when(Util.getWorld(Mockito.any())).thenReturn(world); + } + + /** + * Test method for {@link us.tastybento.bskyblock.listeners.flags.EnterExitListener#onMove(org.bukkit.event.player.PlayerMoveEvent)}. + */ + @Test + public void testOnMoveInsideIsland() { + PlayerMoveEvent e = new PlayerMoveEvent(user.getPlayer(), inside, inside); + listener.onMove(e); + // Moving in the island should result in no messages to the user + Mockito.verify(user, Mockito.never()).sendMessage(Mockito.anyVararg()); + } + + /** + * Test method for {@link us.tastybento.bskyblock.listeners.flags.EnterExitListener#onMove(org.bukkit.event.player.PlayerMoveEvent)}. + */ + @Test + public void testOnMoveOutsideIsland() { + PlayerMoveEvent e = new PlayerMoveEvent(user.getPlayer(), outside, outside); + listener.onMove(e); + // Moving outside the island should result in no messages to the user + Mockito.verify(user, Mockito.never()).sendMessage(Mockito.anyVararg()); + } + + /** + * Test method for {@link us.tastybento.bskyblock.listeners.flags.EnterExitListener#onMove(org.bukkit.event.player.PlayerMoveEvent)}. + */ + @Test + public void testOnGoingIntoIslandEmptyIslandName() { + when(island.getName()).thenReturn(""); + PlayerMoveEvent e = new PlayerMoveEvent(user.getPlayer(), outside, inside); + listener.onMove(e); + // Moving into the island should show a message + Mockito.verify(lm).get(Mockito.any(), Mockito.eq("protection.flags.ENTER_EXIT_MESSAGES.now-entering")); + // The island owner needs to be checked + Mockito.verify(island).getOwner(); + } + + /** + * Test method for {@link us.tastybento.bskyblock.listeners.flags.EnterExitListener#onMove(org.bukkit.event.player.PlayerMoveEvent)}. + */ + @Test + public void testOnGoingIntoIslandWithIslandName() { + when(island.getName()).thenReturn("fancy name"); + PlayerMoveEvent e = new PlayerMoveEvent(user.getPlayer(), outside, inside); + listener.onMove(e); + // Moving into the island should show a message + Mockito.verify(lm).get(Mockito.any(), Mockito.eq("protection.flags.ENTER_EXIT_MESSAGES.now-entering")); + // No owner check + Mockito.verify(island, Mockito.never()).getOwner(); + Mockito.verify(island, Mockito.times(2)).getName(); + } + + /** + * Test method for {@link us.tastybento.bskyblock.listeners.flags.EnterExitListener#onMove(org.bukkit.event.player.PlayerMoveEvent)}. + */ + @Test + public void testExitingIslandEmptyIslandName() { + when(island.getName()).thenReturn(""); + PlayerMoveEvent e = new PlayerMoveEvent(user.getPlayer(), inside, outside); + listener.onMove(e); + // Moving into the island should show a message + Mockito.verify(lm).get(Mockito.any(), Mockito.eq("protection.flags.ENTER_EXIT_MESSAGES.now-leaving")); + // The island owner needs to be checked + Mockito.verify(island).getOwner(); + } + + /** + * Test method for {@link us.tastybento.bskyblock.listeners.flags.EnterExitListener#onMove(org.bukkit.event.player.PlayerMoveEvent)}. + */ + @Test + public void testExitingIslandWithIslandName() { + when(island.getName()).thenReturn("fancy name"); + PlayerMoveEvent e = new PlayerMoveEvent(user.getPlayer(), inside, outside); + listener.onMove(e); + // Moving into the island should show a message + Mockito.verify(lm).get(Mockito.any(), Mockito.eq("protection.flags.ENTER_EXIT_MESSAGES.now-leaving")); + // No owner check + Mockito.verify(island, Mockito.never()).getOwner(); + Mockito.verify(island, Mockito.times(2)).getName(); + } + +} diff --git a/src/test/java/us/tastybento/bskyblock/listeners/flags/FireListenerTest.java b/src/test/java/us/tastybento/bskyblock/listeners/flags/FireListenerTest.java index c189fe914..de64cf8f8 100644 --- a/src/test/java/us/tastybento/bskyblock/listeners/flags/FireListenerTest.java +++ b/src/test/java/us/tastybento/bskyblock/listeners/flags/FireListenerTest.java @@ -29,6 +29,7 @@ import org.bukkit.event.entity.EntityChangeBlockEvent; import org.bukkit.inventory.ItemFactory; import org.bukkit.inventory.meta.SkullMeta; import org.bukkit.plugin.PluginManager; +import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; @@ -61,7 +62,7 @@ public class FireListenerTest { private static IslandWorldManager iwm; @BeforeClass - public static void setUp() { + public static void setUpClass() { // Set up plugin plugin = mock(BSkyBlock.class); Whitebox.setInternalState(BSkyBlock.class, "instance", plugin); @@ -103,10 +104,7 @@ public class FireListenerTest { when(iwm.getEndWorld()).thenReturn(world); when(iwm.inWorld(any())).thenReturn(true); when(plugin.getIWM()).thenReturn(iwm); - - PowerMockito.mockStatic(Util.class); - when(Util.getWorld(Mockito.any())).thenReturn(world); - + // Monsters and animals Zombie zombie = mock(Zombie.class); when(zombie.getLocation()).thenReturn(location); @@ -137,6 +135,12 @@ public class FireListenerTest { when(pm.getName(Mockito.any())).thenReturn("tastybento"); when(plugin.getPlayers()).thenReturn(pm); } + + @Before + public void setUp() { + PowerMockito.mockStatic(Util.class); + when(Util.getWorld(Mockito.any())).thenReturn(mock(World.class)); + } @Test public void testCheckFire() { diff --git a/src/test/java/us/tastybento/bskyblock/listeners/flags/MobSpawnListenerTest.java b/src/test/java/us/tastybento/bskyblock/listeners/flags/MobSpawnListenerTest.java index 0a30237fb..dae711736 100644 --- a/src/test/java/us/tastybento/bskyblock/listeners/flags/MobSpawnListenerTest.java +++ b/src/test/java/us/tastybento/bskyblock/listeners/flags/MobSpawnListenerTest.java @@ -39,9 +39,10 @@ import us.tastybento.bskyblock.lists.Flags; import us.tastybento.bskyblock.managers.FlagsManager; import us.tastybento.bskyblock.managers.IslandWorldManager; import us.tastybento.bskyblock.managers.IslandsManager; +import us.tastybento.bskyblock.util.Util; @RunWith(PowerMockRunner.class) -@PrepareForTest( {BSkyBlock.class, Flags.class }) +@PrepareForTest( {BSkyBlock.class, Flags.class, Util.class }) public class MobSpawnListenerTest { private static Location location; @@ -96,7 +97,7 @@ public class MobSpawnListenerTest { when(slime.getLocation()).thenReturn(location); cow = mock(Cow.class); when(cow.getLocation()).thenReturn(location); - + } @Before @@ -109,6 +110,10 @@ public class MobSpawnListenerTest { when(iwm.getEndWorld()).thenReturn(world); when(iwm.inWorld(any(Location.class))).thenReturn(true); when(plugin.getIWM()).thenReturn(iwm); + + PowerMockito.mockStatic(Util.class); + when(Util.getWorld(Mockito.any())).thenReturn(mock(World.class)); + } diff --git a/src/test/java/us/tastybento/bskyblock/listeners/flags/SettingsToggleClickListenerTest.java b/src/test/java/us/tastybento/bskyblock/listeners/flags/SettingsToggleClickListenerTest.java new file mode 100644 index 000000000..986ae272a --- /dev/null +++ b/src/test/java/us/tastybento/bskyblock/listeners/flags/SettingsToggleClickListenerTest.java @@ -0,0 +1,100 @@ +package us.tastybento.bskyblock.listeners.flags; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; +import org.powermock.reflect.Whitebox; + +import us.tastybento.bskyblock.BSkyBlock; +import us.tastybento.bskyblock.api.flags.Flag; +import us.tastybento.bskyblock.api.panels.Panel; +import us.tastybento.bskyblock.api.panels.PanelItem; +import us.tastybento.bskyblock.api.user.User; +import us.tastybento.bskyblock.managers.FlagsManager; +import us.tastybento.bskyblock.managers.IslandWorldManager; +import us.tastybento.bskyblock.util.Util; + +@RunWith(PowerMockRunner.class) +@PrepareForTest({BSkyBlock.class, Util.class }) +public class SettingsToggleClickListenerTest { + + private IslandWorldManager iwm; + private SettingsToggleClickListener listener; + private Panel panel; + private User user; + private Flag flag; + + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() throws Exception { + + // Set up plugin + BSkyBlock plugin = mock(BSkyBlock.class); + Whitebox.setInternalState(BSkyBlock.class, "instance", plugin); + // Island World Manager + iwm = mock(IslandWorldManager.class); + when(iwm.inWorld(Mockito.any())).thenReturn(true); + when(iwm.getPermissionPrefix(Mockito.any())).thenReturn("bskyblock"); + when(plugin.getIWM()).thenReturn(iwm); + + + listener = new SettingsToggleClickListener("test"); + + panel = mock(Panel.class); + when(panel.getInventory()).thenReturn(mock(Inventory.class)); + // Sometimes use Mockito.withSettings().verboseLogging() + user = mock(User.class); + when(user.getWorld()).thenReturn(mock(World.class)); + when(user.getLocation()).thenReturn(mock(Location.class)); + PowerMockito.mockStatic(Util.class); + when(Util.getWorld(Mockito.any())).thenReturn(mock(World.class)); + + FlagsManager fm = mock(FlagsManager.class); + flag = mock(Flag.class); + when(flag.isSet(Mockito.any())).thenReturn(false); + PanelItem item = mock(PanelItem.class); + when(item.getItem()).thenReturn(mock(ItemStack.class)); + when(flag.toPanelItem(Mockito.any(), Mockito.eq(user))).thenReturn(item); + when(fm.getFlagByID(Mockito.anyString())).thenReturn(flag); + when(plugin.getFlagsManager()).thenReturn(fm); + + } + + @Test + public void testOnClickWrongWorld() { + when(iwm.inWorld(Mockito.any())).thenReturn(false); + listener.onClick(panel, user, ClickType.LEFT, 0); + Mockito.verify(user).sendMessage("general.errors.wrong-world"); + } + + @Test + public void testOnClickNoPermission() { + when(user.hasPermission(Mockito.anyString())).thenReturn(false); + listener.onClick(panel, user, ClickType.LEFT, 0); + Mockito.verify(user).sendMessage("general.errors.no-permission"); + Mockito.verify(user).sendMessage("general.errors.you-need", "[permission]", "bskyblock.settings.test"); + } + + @Test + public void testOnClick() { + when(user.hasPermission(Mockito.anyString())).thenReturn(true); + listener.onClick(panel, user, ClickType.LEFT, 0); + Mockito.verify(flag).setSetting(Mockito.any(), Mockito.eq(true)); + Mockito.verify(panel).getInventory(); + } + +}