From de85f85bbe057e797b70f7baf8015a3e98195298 Mon Sep 17 00:00:00 2001 From: Tastybento Date: Tue, 1 May 2018 22:56:10 -0700 Subject: [PATCH] Enabled settings flag clicks to work. A listener can be added to a flag. This listener is the same as a panel item listener. When the settings flag is clicked, it'll call the listener. There is a default listener. Right now the default is called UpDownClick.java. This makes the rank go up when you left click and down when you right click. Another implementation may be to just have the rank loop around with left clicks. I added two more ranks - Admin and Mod. These are special ranks that have a value above owner. If a player is given this rank, they can bypass protections. This will avoid the need to use permissions and also enable islands to be set up that for example, only Admins can edit, but Mods cannot. So, it's now possible for an owner to lock out team members from the island as well as visitors. This is a bit weird and so more click classes should be created. For example, one that just toggles between Owner and Visitor. Currently, only an island owner can change settings, but this could be expanded to allow members. Also, it will need to be expanded to allow Admins. --- .../tastybento/bskyblock/api/flags/Flag.java | 33 ++- .../bskyblock/api/flags/FlagBuilder.java | 18 +- .../bskyblock/api/panels/ClickType.java | 6 - .../bskyblock/api/panels/PanelItem.java | 7 +- .../island/IslandSettingsCommand.java | 2 +- .../teams/IslandTeamPromoteCommand.java | 4 +- .../listeners/PanelListenerManager.java | 5 +- .../listeners/flags/LockAndBanListener.java | 10 +- .../listeners/flags/UpDownClick.java | 60 +++++ .../us/tastybento/bskyblock/lists/Flags.java | 5 +- .../bskyblock/managers/IslandsManager.java | 2 + .../bskyblock/managers/RanksManager.java | 28 +- .../bskyblock/panels/LanguagePanel.java | 2 +- .../bskyblock/panels/SettingsPanel.java | 14 +- .../bskyblock/api/flags/FlagTest.java | 192 ++++++++++++++ .../panels/builders/PanelItemBuilderTest.java | 7 +- .../listeners/flags/UpDownClickTest.java | 242 ++++++++++++++++++ .../bskyblock/managers/RanksManagerTest.java | 25 +- 18 files changed, 603 insertions(+), 59 deletions(-) delete mode 100644 src/main/java/us/tastybento/bskyblock/api/panels/ClickType.java create mode 100644 src/main/java/us/tastybento/bskyblock/listeners/flags/UpDownClick.java create mode 100644 src/test/java/us/tastybento/bskyblock/api/flags/FlagTest.java create mode 100644 src/test/java/us/tastybento/bskyblock/listeners/flags/UpDownClickTest.java 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 e9d19b2c5..56ff09349 100644 --- a/src/main/java/us/tastybento/bskyblock/api/flags/Flag.java +++ b/src/main/java/us/tastybento/bskyblock/api/flags/Flag.java @@ -6,9 +6,12 @@ import org.bukkit.Material; import org.bukkit.event.Listener; import org.bukkit.inventory.ItemStack; +import us.tastybento.bskyblock.BSkyBlock; import us.tastybento.bskyblock.api.panels.PanelItem; 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; public class Flag implements Comparable { @@ -23,14 +26,16 @@ public class Flag implements Comparable { private final Type type; private boolean defaultSetting; private final int defaultRank; + private final PanelItem.ClickHandler clickHandler; - Flag(String id, Material icon, Listener listener, boolean defaultSetting, Type type, int defaultRank) { + Flag(String id, Material icon, Listener listener, boolean defaultSetting, Type type, int defaultRank, PanelItem.ClickHandler clickListener) { this.id = id; this.icon = icon; this.listener = listener; this.defaultSetting = defaultSetting; this.type = type; this.defaultRank = defaultRank; + this.clickHandler = clickListener; } public String getID() { @@ -112,26 +117,38 @@ public class Flag implements Comparable { return type == other.type; } - public PanelItem toPanelItem(User user) { + /** + * Converts a flag to a panel item. The content of the flag will change depending on who the user is and where they are. + * The panel item may reflect their island settings, the island they are on, or the world in general. + * @param user - user that will see this flag + * @return - PanelItem for this flag + */ + public PanelItem toPanelItem(BSkyBlock plugin, User user) { + // Get the island this user is on or their own + Island island = plugin.getIslands().getIslandAt(user.getLocation()).orElse(plugin.getIslands().getIsland(user.getUniqueId())); + String rank = RanksManager.OWNER_RANK_REF; + if (island != null) { + // TODO: Get the world settings - the player has no island and is not in an island location + rank = plugin.getRanksManager().getRank(island.getFlag(this)); + } return new PanelItemBuilder() .icon(new ItemStack(icon)) .name(user.getTranslation("protection.panel.flag-item.name-layout", "[name]", user.getTranslation("protection.flags." + id + ".name"))) .description(user.getTranslation("protection.panel.flag-item.description-layout", "[description]", user.getTranslation("protection.flags." + id + ".description"), - "[rank]", "Owner")) - .clickHandler((clicker, click) -> { - clicker.sendRawMessage("You clicked on : " + id); - return true; - }) + "[rank]", user.getTranslation(rank))) + .clickHandler(clickHandler) .build(); } + /* (non-Javadoc) * @see java.lang.Object#toString() */ @Override public String toString() { - return "Flag [id=" + id + ", icon=" + icon + ", type=" + type + ", defaultSetting=" + defaultSetting + "]"; + return "Flag [id=" + id + ", icon=" + icon + ", listener=" + listener + ", type=" + type + ", defaultSetting=" + + defaultSetting + ", 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 1ff90ed34..8325d3462 100644 --- a/src/main/java/us/tastybento/bskyblock/api/flags/FlagBuilder.java +++ b/src/main/java/us/tastybento/bskyblock/api/flags/FlagBuilder.java @@ -4,6 +4,8 @@ import org.bukkit.Material; import org.bukkit.event.Listener; import us.tastybento.bskyblock.api.flags.Flag.Type; +import us.tastybento.bskyblock.api.panels.PanelItem; +import us.tastybento.bskyblock.listeners.flags.UpDownClick; import us.tastybento.bskyblock.managers.RanksManager; public class FlagBuilder { @@ -14,9 +16,12 @@ public class FlagBuilder { private boolean defaultSetting; private Type type = Type.PROTECTION; private int defaultRank = RanksManager.MEMBER_RANK; + private PanelItem.ClickHandler onClick; public FlagBuilder id(String string) { id = string; + // Set the default click operation to UpDownClick + onClick = new UpDownClick(id); return this; } @@ -31,7 +36,7 @@ public class FlagBuilder { } public Flag build() { - return new Flag(id, icon, listener, defaultSetting, type, defaultRank); + return new Flag(id, icon, listener, defaultSetting, type, defaultRank, onClick); } /** @@ -73,4 +78,15 @@ public class FlagBuilder { this.defaultRank = rank; return this; } + + /** + * Adds a listener for clicks on this flag when it is a panel item. Default is + * {@link us.tastybento.bskyblock.listeners.flags.UpDownClick.UpDownClick} + * @param onClickListener - the listener for clicks. Must use the ClickOn interface + * @return FlagBuilder + */ + public FlagBuilder onClick(PanelItem.ClickHandler onClickListener) { + this.onClick = onClickListener; + return this; + } } diff --git a/src/main/java/us/tastybento/bskyblock/api/panels/ClickType.java b/src/main/java/us/tastybento/bskyblock/api/panels/ClickType.java deleted file mode 100644 index a363efd17..000000000 --- a/src/main/java/us/tastybento/bskyblock/api/panels/ClickType.java +++ /dev/null @@ -1,6 +0,0 @@ -package us.tastybento.bskyblock.api.panels; - -public enum ClickType { - RIGHT, - LEFT -} diff --git a/src/main/java/us/tastybento/bskyblock/api/panels/PanelItem.java b/src/main/java/us/tastybento/bskyblock/api/panels/PanelItem.java index a79d1c11b..114d42c02 100644 --- a/src/main/java/us/tastybento/bskyblock/api/panels/PanelItem.java +++ b/src/main/java/us/tastybento/bskyblock/api/panels/PanelItem.java @@ -4,6 +4,7 @@ import java.util.List; import java.util.Optional; import org.bukkit.enchantments.Enchantment; +import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemFlag; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; @@ -102,11 +103,13 @@ public class PanelItem { public interface ClickHandler { /** * This is executed when the icon is clicked + * @param panel - the panel that is being clicked * @param user - the User - * @param click + * @param clickType - the click type + * @param slot - the slot that was clicked * @return true if the click event should be cancelled */ - boolean onClick(User user, ClickType click); + boolean onClick(Panel panel, User user, ClickType clickType, int slot); } public void setHead(ItemStack itemStack) { 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 dcf3bf5a5..690e673de 100644 --- a/src/main/java/us/tastybento/bskyblock/commands/island/IslandSettingsCommand.java +++ b/src/main/java/us/tastybento/bskyblock/commands/island/IslandSettingsCommand.java @@ -32,7 +32,7 @@ public class IslandSettingsCommand extends CompositeCommand { */ @Override public boolean execute(User user, List args) { - SettingsPanel.openPanel(user); + SettingsPanel.openPanel(getPlugin(), user); return true; } } diff --git a/src/main/java/us/tastybento/bskyblock/commands/island/teams/IslandTeamPromoteCommand.java b/src/main/java/us/tastybento/bskyblock/commands/island/teams/IslandTeamPromoteCommand.java index 9ea783667..d6fe63999 100644 --- a/src/main/java/us/tastybento/bskyblock/commands/island/teams/IslandTeamPromoteCommand.java +++ b/src/main/java/us/tastybento/bskyblock/commands/island/teams/IslandTeamPromoteCommand.java @@ -56,7 +56,7 @@ public class IslandTeamPromoteCommand extends AbstractIslandTeamCommand { private boolean change(User user, User target) { int currentRank = getIslands().getIsland(user.getUniqueId()).getRank(target); if (this.getLabel().equals("promote")) { - int nextRank = getPlugin().getRanksManager().getNextRankValue(currentRank); + int nextRank = getPlugin().getRanksManager().getRankUpValue(currentRank); if (nextRank > currentRank) { getIslands().getIsland(user.getUniqueId()).setRank(target, nextRank); String rankName = user.getTranslation(getPlugin().getRanksManager().getRank(nextRank)); @@ -68,7 +68,7 @@ public class IslandTeamPromoteCommand extends AbstractIslandTeamCommand { } } else { // Demote - int prevRank = getPlugin().getRanksManager().getPreviousRankValue(currentRank); + int prevRank = getPlugin().getRanksManager().getRankDownValue(currentRank); if (prevRank < currentRank) { getIslands().getIsland(user.getUniqueId()).setRank(target, prevRank); String rankName = user.getTranslation(getPlugin().getRanksManager().getRank(prevRank)); diff --git a/src/main/java/us/tastybento/bskyblock/listeners/PanelListenerManager.java b/src/main/java/us/tastybento/bskyblock/listeners/PanelListenerManager.java index cca0ee90a..285c6cbc6 100644 --- a/src/main/java/us/tastybento/bskyblock/listeners/PanelListenerManager.java +++ b/src/main/java/us/tastybento/bskyblock/listeners/PanelListenerManager.java @@ -12,7 +12,6 @@ import org.bukkit.event.inventory.InventoryCloseEvent; import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.inventory.Inventory; -import us.tastybento.bskyblock.api.panels.ClickType; import us.tastybento.bskyblock.api.panels.Panel; import us.tastybento.bskyblock.api.user.User; @@ -36,11 +35,9 @@ public class PanelListenerManager implements Listener { // Check that they clicked on a specific item for (int slot : panel.getItems().keySet()) { if (slot == event.getRawSlot()) { - // Check that they left clicked on it - // TODO: in the future, we may want to support right clicking panel.getItems().get(slot).getClickHandler().ifPresent(handler -> // Execute the handler's onClick method and optionally cancel the event if the handler returns true - event.setCancelled(handler.onClick(user, ClickType.LEFT)) + event.setCancelled(handler.onClick(panel, user, event.getClick(), event.getSlot())) ); } } diff --git a/src/main/java/us/tastybento/bskyblock/listeners/flags/LockAndBanListener.java b/src/main/java/us/tastybento/bskyblock/listeners/flags/LockAndBanListener.java index c9e77936c..4565ebf47 100644 --- a/src/main/java/us/tastybento/bskyblock/listeners/flags/LockAndBanListener.java +++ b/src/main/java/us/tastybento/bskyblock/listeners/flags/LockAndBanListener.java @@ -4,6 +4,7 @@ package us.tastybento.bskyblock.listeners.flags; import org.bukkit.Bukkit; +import org.bukkit.GameMode; import org.bukkit.Location; import org.bukkit.Sound; import org.bukkit.entity.Player; @@ -14,6 +15,7 @@ import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerMoveEvent; import org.bukkit.event.player.PlayerTeleportEvent; import org.bukkit.event.vehicle.VehicleMoveEvent; +import org.bukkit.util.Vector; import us.tastybento.bskyblock.BSkyBlock; import us.tastybento.bskyblock.api.user.User; @@ -57,9 +59,11 @@ public class LockAndBanListener implements Listener { if (e.getFrom().getBlockX() - e.getTo().getBlockX() == 0 && e.getFrom().getBlockZ() - e.getTo().getBlockZ() == 0) { return; } - e.setCancelled(checkAndNotify(e.getPlayer(), e.getTo()).equals(CheckResult.OPEN) ? false : true); - if (e.isCancelled()) { + if (checkAndNotify(e.getPlayer(), e.getTo()).equals(CheckResult.OPEN) ? false : true) { + e.setCancelled(true); e.getFrom().getWorld().playSound(e.getFrom(), Sound.BLOCK_ANVIL_HIT, 1F, 1F); + e.getPlayer().setVelocity(new Vector(0,0,0)); + e.getPlayer().setGliding(false); } // Check from - just in case the player is inside the island if (!check(e.getPlayer(), e.getFrom()).equals(CheckResult.OPEN)) { @@ -101,6 +105,7 @@ public class LockAndBanListener implements Listener { * @return CheckResult LOCKED, BANNED or OPEN. If an island is locked, that will take priority over banned */ private CheckResult check(Player player, Location loc) { + // See if the island is locked to non-members or player is banned return im.getProtectedIslandAt(loc) .map(is -> !is.isAllowed(User.getInstance(player), Flags.LOCK) ? CheckResult.LOCKED @@ -135,6 +140,7 @@ public class LockAndBanListener implements Listener { * @param player */ private void eject(Player player) { + player.setGameMode(GameMode.SPECTATOR); // Teleport player to their home if (im.hasIsland(player.getUniqueId())) { im.homeTeleport(player); diff --git a/src/main/java/us/tastybento/bskyblock/listeners/flags/UpDownClick.java b/src/main/java/us/tastybento/bskyblock/listeners/flags/UpDownClick.java new file mode 100644 index 000000000..235f00c0a --- /dev/null +++ b/src/main/java/us/tastybento/bskyblock/listeners/flags/UpDownClick.java @@ -0,0 +1,60 @@ +/** + * + */ +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; +import us.tastybento.bskyblock.api.user.User; +import us.tastybento.bskyblock.database.objects.Island; +import us.tastybento.bskyblock.managers.RanksManager; + +/** + * Left Clicks increase rank, right clicks lower rank + * @author tastybento + * + */ +public class UpDownClick implements PanelItem.ClickHandler { + + private BSkyBlock plugin = BSkyBlock.getInstance(); + private final String id; + + + /** + * @param id - the flag id that will be adjusted by this click + */ + public UpDownClick(String id) { + this.id = id; + } + + @Override + public boolean onClick(Panel panel, User user, ClickType click, int slot) { + // Left clicking increases the rank required + // Right clicking decreases the rank required + // Get the user's island + Island island = plugin.getIslands().getIsland(user.getUniqueId()); + if (island != null && island.getOwner().equals(user.getUniqueId())) { + RanksManager rm = plugin.getRanksManager(); + Flag flag = plugin.getFlagsManager().getFlagByID(id); + int currentRank = island.getFlag(flag); + if (click.equals(ClickType.LEFT)) { + int nextRank = rm.getRankUpValue(currentRank); + island.setFlag(flag, nextRank); + user.getWorld().playSound(user.getLocation(), Sound.BLOCK_STONE_BUTTON_CLICK_ON, 1F, 1F); + } else if (click.equals(ClickType.RIGHT)) { + int nextRank = rm.getRankDownValue(currentRank); + island.setFlag(flag, nextRank); + user.getWorld().playSound(user.getLocation(), Sound.BLOCK_STONE_BUTTON_CLICK_OFF, 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 f4a75c245..23a9547ef 100644 --- a/src/main/java/us/tastybento/bskyblock/lists/Flags.java +++ b/src/main/java/us/tastybento/bskyblock/lists/Flags.java @@ -119,7 +119,10 @@ public class Flags { public static final Flag ITEM_PICKUP = new FlagBuilder().id("ITEM_PICKUP").icon(Material.BEETROOT_SEEDS).build(); // Island lock - public static final Flag LOCK = new FlagBuilder().id("LOCK").icon(Material.TRIPWIRE_HOOK).type(Type.PROTECTION).allowedByDefault(true).defaultRank(RanksManager.VISITOR_RANK).listener(new LockAndBanListener()).build(); + public static final Flag LOCK = new FlagBuilder().id("LOCK") + .icon(Material.TRIPWIRE_HOOK).type(Type.PROTECTION).allowedByDefault(true) + .defaultRank(RanksManager.VISITOR_RANK).listener(new LockAndBanListener()) + .build(); /* * Settings flags (not protection flags) diff --git a/src/main/java/us/tastybento/bskyblock/managers/IslandsManager.java b/src/main/java/us/tastybento/bskyblock/managers/IslandsManager.java index 6710663c0..9f2c57d2b 100644 --- a/src/main/java/us/tastybento/bskyblock/managers/IslandsManager.java +++ b/src/main/java/us/tastybento/bskyblock/managers/IslandsManager.java @@ -520,6 +520,8 @@ public class IslandsManager { @SuppressWarnings("deprecation") public void homeTeleport(final Player player, int number) { Location home = getSafeHomeLocation(player.getUniqueId(), number); + // Stop any gliding + player.setGliding(false); // Check if the player is a passenger in a boat if (player.isInsideVehicle()) { Entity boat = player.getVehicle(); diff --git a/src/main/java/us/tastybento/bskyblock/managers/RanksManager.java b/src/main/java/us/tastybento/bskyblock/managers/RanksManager.java index 013323458..a53a7da8a 100644 --- a/src/main/java/us/tastybento/bskyblock/managers/RanksManager.java +++ b/src/main/java/us/tastybento/bskyblock/managers/RanksManager.java @@ -10,10 +10,14 @@ import us.tastybento.bskyblock.BSkyBlock; public class RanksManager { // Constants that define the hard coded rank values + public static final String ADMIN_RANK_REF = "ranks.admin"; + public static final String MOD_RANK_REF = "ranks.mod"; public static final String OWNER_RANK_REF = "ranks.owner"; public static final String MEMBER_RANK_REF = "ranks.member"; public static final String VISITOR_RANK_REF = "ranks.visitor"; public static final String BANNED_RANK_REF = "ranks.banned"; + public static final int ADMIN_RANK = 10000; + public static final int MOD_RANK = 5000; public static final int OWNER_RANK = 1000; public static final int MEMBER_RANK = 900; public static final int VISITOR_RANK = 0; @@ -31,6 +35,8 @@ public class RanksManager { super(); this.plugin = plugin; // Hard coded ranks + ranksPut(ADMIN_RANK_REF, ADMIN_RANK); + ranksPut(MOD_RANK_REF, MOD_RANK); ranksPut(OWNER_RANK_REF, OWNER_RANK); ranksPut(MEMBER_RANK_REF, MEMBER_RANK); ranksPut(VISITOR_RANK_REF, VISITOR_RANK); @@ -59,11 +65,13 @@ public class RanksManager { if (reference.equalsIgnoreCase(OWNER_RANK_REF) || reference.equalsIgnoreCase(MEMBER_RANK_REF) || reference.equalsIgnoreCase(VISITOR_RANK_REF) - || reference.equalsIgnoreCase(BANNED_RANK_REF)) { + || reference.equalsIgnoreCase(BANNED_RANK_REF) + || reference.equalsIgnoreCase(ADMIN_RANK_REF) + || reference.equalsIgnoreCase(MOD_RANK_REF)) { return false; } ranksPut(reference, value); - + return true; } @@ -85,7 +93,9 @@ public class RanksManager { if (reference.equalsIgnoreCase(OWNER_RANK_REF) || reference.equalsIgnoreCase(MEMBER_RANK_REF) || reference.equalsIgnoreCase(VISITOR_RANK_REF) - || reference.equalsIgnoreCase(BANNED_RANK_REF)) { + || reference.equalsIgnoreCase(BANNED_RANK_REF) + || reference.equalsIgnoreCase(ADMIN_RANK_REF) + || reference.equalsIgnoreCase(MOD_RANK_REF)) { return false; } @@ -111,11 +121,11 @@ public class RanksManager { /** - * Gets the next rank value above the current rank, excluding the owner rank + * Gets the next rank value above the current rank. Highest is {@link RanksManager.OWNER_RANK} * @param currentRank * @return Optional rank value */ - public int getNextRankValue(int currentRank) { + public int getRankUpValue(int currentRank) { return getRanks().values().stream().mapToInt(x -> { if (x > currentRank) { return x; @@ -123,18 +133,18 @@ public class RanksManager { return OWNER_RANK; }).min().orElse(currentRank); } - + /** - * Gets the previous rank value below the current rank + * Gets the previous rank value below the current rank. Lowest is {@link RanksManager.VISITOR_RANK} * @param currentRank * @return Optional rank value */ - public int getPreviousRankValue(int currentRank) { + public int getRankDownValue(int currentRank) { return getRanks().values().stream().mapToInt(x -> { if (x < currentRank) { return x; } - return BANNED_RANK; + return VISITOR_RANK; }).max().orElse(currentRank); } diff --git a/src/main/java/us/tastybento/bskyblock/panels/LanguagePanel.java b/src/main/java/us/tastybento/bskyblock/panels/LanguagePanel.java index 64b48ccac..2475726d2 100644 --- a/src/main/java/us/tastybento/bskyblock/panels/LanguagePanel.java +++ b/src/main/java/us/tastybento/bskyblock/panels/LanguagePanel.java @@ -23,7 +23,7 @@ public class LanguagePanel { for (Locale locale : BSkyBlock.getInstance().getLocalesManager().getAvailableLocales()) { PanelItemBuilder localeIcon = new PanelItemBuilder().icon(BSkyBlock.getInstance().getLocalesManager().getLanguages().get(locale).getBanner()) .name(fancyLocaleDisplayName(user, locale)) - .clickHandler((u, click) -> { + .clickHandler((panel, u, click, slot) -> { BSkyBlock.getInstance().getPlayers().setLocale(u.getUniqueId(), locale.toLanguageTag()); u.sendMessage("language.edited", "[lang]", fancyLocaleDisplayName(u, locale)); openPanel(u); diff --git a/src/main/java/us/tastybento/bskyblock/panels/SettingsPanel.java b/src/main/java/us/tastybento/bskyblock/panels/SettingsPanel.java index 96f974876..00c6be36a 100644 --- a/src/main/java/us/tastybento/bskyblock/panels/SettingsPanel.java +++ b/src/main/java/us/tastybento/bskyblock/panels/SettingsPanel.java @@ -1,7 +1,6 @@ package us.tastybento.bskyblock.panels; import us.tastybento.bskyblock.BSkyBlock; -import us.tastybento.bskyblock.api.flags.Flag; import us.tastybento.bskyblock.api.panels.PanelItem; import us.tastybento.bskyblock.api.panels.builders.PanelBuilder; import us.tastybento.bskyblock.api.panels.builders.PanelItemBuilder; @@ -16,22 +15,23 @@ public class SettingsPanel { * Dynamically creates the panel. * @param user the User to show the panel to */ - public static void openPanel(User user) { + public static void openPanel(BSkyBlock plugin, User user) { + // Make a panel for settings PanelBuilder panelBuilder = new PanelBuilder() .name(user.getTranslation("protection.panel.title")); + // Make the help item PanelItem help = new PanelItemBuilder() .name(user.getTranslation("protection.panel.help-item.name")) .icon("MHF_Question") // Question marks .build(); - + // Place it at position 8 (end of first row) panelBuilder.item(8, help); - for (Flag flag : BSkyBlock.getInstance().getFlagsManager().getFlags()) { - PanelItem flagIcon = flag.toPanelItem(user); - panelBuilder.item(flagIcon); - } + // Add flags after position 8, i.e., from second row + plugin.getFlagsManager().getFlags().forEach((f -> panelBuilder.item(f.toPanelItem(plugin, user)))); + // Make the panel panelBuilder.build().open(user); } } diff --git a/src/test/java/us/tastybento/bskyblock/api/flags/FlagTest.java b/src/test/java/us/tastybento/bskyblock/api/flags/FlagTest.java new file mode 100644 index 000000000..9004f504d --- /dev/null +++ b/src/test/java/us/tastybento/bskyblock/api/flags/FlagTest.java @@ -0,0 +1,192 @@ +package us.tastybento.bskyblock.api.flags; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.Optional; +import java.util.UUID; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.event.Listener; +import org.bukkit.inventory.ItemStack; +import org.junit.Before; +import org.junit.BeforeClass; +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 us.tastybento.bskyblock.BSkyBlock; +import us.tastybento.bskyblock.api.panels.PanelItem; +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.IslandsManager; +import us.tastybento.bskyblock.managers.RanksManager; + +@RunWith(PowerMockRunner.class) +@PrepareForTest({ Flag.class }) +public class FlagTest { + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + } + + @Before + public void setUp() throws Exception { + } + + @Test + public void testHashCode() { + Flag flag1 = new Flag(null, null, null, false, null, 0, null); + Flag flag2 = new Flag(null, null, null, false, null, 0, null); + assertTrue(flag1.hashCode() == flag2.hashCode()); + } + + @Test + public void testFlag() { + assertNotNull(new Flag(null, null, null, false, null, 0, null)); + } + + @Test + public void testGetID() { + Flag id = new Flag("id", null, null, false, null, 0, null); + assertEquals("id", id.getID()); + } + + @Test + public void testGetIcon() { + Flag id = new Flag("id", Material.ACACIA_DOOR, null, false, null, 0, null); + assertEquals(Material.ACACIA_DOOR, id.getIcon()); + } + + @Test + public void testGetListener() { + Listener l = mock(Listener.class); + Flag id = new Flag("id", Material.ACACIA_DOOR, l, false, null, 0, null); + Optional ol = Optional.ofNullable(l); + assertEquals(ol, id.getListener()); + id = new Flag("id", Material.ACACIA_DOOR, null, false, null, 0, null); + assertEquals(Optional.empty(), id.getListener()); + } + + @Test + public void testIsDefaultSetting() { + Flag id = new Flag("id", Material.ACACIA_DOOR, null, false, null, 0, null); + assertFalse(id.isDefaultSetting()); + id = new Flag("id", Material.ACACIA_DOOR, null, true, null, 0, null); + assertTrue(id.isDefaultSetting()); + } + + @Test + public void testSetDefaultSetting() { + Flag id = new Flag("id", Material.ACACIA_DOOR, null, false, null, 0, null); + assertFalse(id.isDefaultSetting()); + id.setDefaultSetting(true); + assertTrue(id.isDefaultSetting()); + id.setDefaultSetting(false); + assertFalse(id.isDefaultSetting()); + + } + + @Test + public void testGetType() { + Flag id = new Flag("id", Material.ACACIA_DOOR, null, false, Flag.Type.PROTECTION, 0, null); + assertEquals(Flag.Type.PROTECTION,id.getType()); + id = new Flag("id", Material.ACACIA_DOOR, null, false, Flag.Type.SETTING, 0, null); + assertEquals(Flag.Type.SETTING,id.getType()); + } + + @Test + public void testGetDefaultRank() { + Flag id = new Flag("id", Material.ACACIA_DOOR, null, false, Flag.Type.PROTECTION, 100, null); + assertEquals(100, id.getDefaultRank()); + } + + @Test + public void testEqualsObject() { + Flag flag1 = null; + Flag flag2 = new Flag(null, null, null, false, null, 0, null); + + assertFalse(flag2.equals(null)); + int i = 45; + assertFalse(flag2.equals(i)); + + flag1 = new Flag(null, null, null, false, null, 0, null); + flag2 = flag1; + assertTrue(flag1.equals(flag2)); + assertTrue(flag2.equals(flag1)); + + flag2 = new Flag("id", Material.ACACIA_DOOR, null, false, Flag.Type.PROTECTION, 0, null); + assertFalse(flag1.equals(flag2)); + assertFalse(flag2.equals(flag1)); + + } + + @Test + public void testToPanelItem() throws Exception { + BSkyBlock plugin = mock(BSkyBlock.class); + + IslandsManager im = mock(IslandsManager.class); + + Island island = mock(Island.class); + when(island.getFlag(Mockito.any())).thenReturn(RanksManager.VISITOR_RANK); + + User user = mock(User.class); + when(user.getUniqueId()).thenReturn(UUID.randomUUID()); + when(user.getTranslation(Mockito.anyString())).thenReturn("translation"); + when(user.getTranslation(Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString())).thenReturn("long translation"); + + when(im.getIsland(Mockito.any())).thenReturn(island); + Optional oL = Optional.ofNullable(island); + when(im.getIslandAt(Mockito.any(Location.class))).thenReturn(oL); + when(plugin.getIslands()).thenReturn(im); + + RanksManager rm = mock(RanksManager.class); + when(plugin.getRanksManager()).thenReturn(rm); + when(rm.getRank(Mockito.eq(RanksManager.VISITOR_RANK))).thenReturn("Visitor"); + when(rm.getRank(Mockito.eq(RanksManager.OWNER_RANK))).thenReturn("Owner"); + + PowerMockito.whenNew(ItemStack.class).withAnyArguments().thenReturn(mock(ItemStack.class)); + + PanelItemBuilder pib = mock(PanelItemBuilder.class); + when(pib.description(Mockito.anyString())).thenReturn(pib); + when(pib.name(Mockito.anyString())).thenReturn(pib); + when(pib.icon(Mockito.any(ItemStack.class))).thenReturn(pib); + when(pib.clickHandler(Mockito.any())).thenReturn(pib); + when(pib.build()).thenReturn(mock(PanelItem.class)); + + // Remember to prepare the calling class, not the subject class! + PowerMockito.whenNew(PanelItemBuilder.class).withAnyArguments().thenReturn(pib); + + Flag id = new Flag("id", Material.ACACIA_DOOR, null, false, Flag.Type.PROTECTION, 0, null); + + id.toPanelItem(plugin, user); + + verify(user).getTranslation(Mockito.eq("protection.flags.id.name")); + verify(user).getTranslation(Mockito.eq("protection.panel.flag-item.name-layout"), Mockito.anyVararg()); + } + + @Test + public void testToString() { + Flag id = new Flag("id", Material.ACACIA_DOOR, null, false, Flag.Type.PROTECTION, 0, null); + assertEquals("Flag [id=id, icon=ACACIA_DOOR, listener=null, type=PROTECTION, defaultSetting=false, defaultRank=0, clickHandler=null]", id.toString()); + } + + @Test + public void testCompareTo() { + Flag aaa = new Flag("AAA", Material.ACACIA_DOOR, null, false, Flag.Type.PROTECTION, 0, null); + Flag bbb = new Flag("BBB", Material.ACACIA_DOOR, null, false, Flag.Type.PROTECTION, 0, null); + assertTrue(aaa.compareTo(bbb) < bbb.compareTo(aaa)); + assertTrue(aaa.compareTo(aaa) == 0); + } + +} diff --git a/src/test/java/us/tastybento/bskyblock/api/panels/builders/PanelItemBuilderTest.java b/src/test/java/us/tastybento/bskyblock/api/panels/builders/PanelItemBuilderTest.java index f66e771af..4402cbccc 100644 --- a/src/test/java/us/tastybento/bskyblock/api/panels/builders/PanelItemBuilderTest.java +++ b/src/test/java/us/tastybento/bskyblock/api/panels/builders/PanelItemBuilderTest.java @@ -18,6 +18,7 @@ import org.bukkit.Material; import org.bukkit.OfflinePlayer; import org.bukkit.Server; import org.bukkit.World; +import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemFactory; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.SkullMeta; @@ -28,7 +29,7 @@ import org.junit.runner.RunWith; import org.mockito.Mockito; import org.powermock.modules.junit4.PowerMockRunner; -import us.tastybento.bskyblock.api.panels.ClickType; +import us.tastybento.bskyblock.api.panels.Panel; import us.tastybento.bskyblock.api.panels.PanelItem; import us.tastybento.bskyblock.api.user.User; @@ -141,7 +142,7 @@ public class PanelItemBuilderTest { item = builder.clickHandler(new Clicker()).build(); assertTrue(item.getClickHandler().isPresent()); - assertTrue(item.getClickHandler().map(x -> x.onClick(null, ClickType.LEFT)).orElse(false)); + assertTrue(item.getClickHandler().map(x -> x.onClick(null, null, ClickType.LEFT, 0)).orElse(false)); } @Test @@ -159,7 +160,7 @@ public class PanelItemBuilderTest { public class Clicker implements PanelItem.ClickHandler { @Override - public boolean onClick(User user, ClickType click) { + public boolean onClick(Panel panel, User user, ClickType click, int slot) { return true; } diff --git a/src/test/java/us/tastybento/bskyblock/listeners/flags/UpDownClickTest.java b/src/test/java/us/tastybento/bskyblock/listeners/flags/UpDownClickTest.java new file mode 100644 index 000000000..5736100b8 --- /dev/null +++ b/src/test/java/us/tastybento/bskyblock/listeners/flags/UpDownClickTest.java @@ -0,0 +1,242 @@ +package us.tastybento.bskyblock.listeners.flags; + +import static org.junit.Assert.*; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.Arrays; +import java.util.HashSet; +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.inventory.ClickType; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.scheduler.BukkitScheduler; +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.flags.Flag; +import us.tastybento.bskyblock.api.panels.Panel; +import us.tastybento.bskyblock.api.panels.PanelItem; +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.FlagsManager; +import us.tastybento.bskyblock.managers.IslandsManager; +import us.tastybento.bskyblock.managers.LocalesManager; +import us.tastybento.bskyblock.managers.PlayersManager; +import us.tastybento.bskyblock.managers.RanksManager; + +@RunWith(PowerMockRunner.class) +@PrepareForTest({Bukkit.class, BSkyBlock.class, User.class }) +public class UpDownClickTest { + + 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 BSkyBlock plugin; + private UUID uuid; + private User user; + private Settings s; + private IslandsManager im; + private PlayersManager pm; + private Island island; + private World world; + private Location loc; + private Location outside; + private Location inside; + private Notifier notifier; + private Location inside2; + private BukkitScheduler sch; + private Flag flag; + private PanelItem panelItem; + private Panel panel; + private Inventory inv; + + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() throws Exception { + + // Set up plugin + plugin = mock(BSkyBlock.class); + Whitebox.setInternalState(BSkyBlock.class, "instance", plugin); + + // World + world = mock(World.class); + + // Settings + s = mock(Settings.class); + when(s.getResetWait()).thenReturn(0L); + when(s.getResetLimit()).thenReturn(3); + 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"); + when(user.getWorld()).thenReturn(world); + + // No island for player to begin with (set it later in the tests) + im = mock(IslandsManager.class); + when(im.hasIsland(Mockito.eq(uuid))).thenReturn(false); + when(im.isOwner(Mockito.eq(uuid))).thenReturn(false); + when(plugin.getIslands()).thenReturn(im); + + // Has team + pm = mock(PlayersManager.class); + when(pm.inTeam(Mockito.eq(uuid))).thenReturn(true); + when(plugin.getPlayers()).thenReturn(pm); + + // Server & Scheduler + sch = mock(BukkitScheduler.class); + PowerMockito.mockStatic(Bukkit.class); + when(Bukkit.getScheduler()).thenReturn(sch); + + // Locales + LocalesManager 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); + when(island.getBanned()).thenReturn(new HashSet<>()); + when(island.isBanned(Mockito.any())).thenReturn(false); + 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); + // Island is not locked by default + when(island.isAllowed(Mockito.any(), Mockito.any())).thenReturn(true); + // Island owner is user by default + when(island.getOwner()).thenReturn(uuid); + + when(im.getIsland(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); + + 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); + + 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); + + 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()); + + panelItem = mock(PanelItem.class); + flag = mock(Flag.class); + when(flag.toPanelItem(Mockito.any(), Mockito.any())).thenReturn(panelItem); + when(panelItem.getItem()).thenReturn(mock(ItemStack.class)); + FlagsManager fm = mock(FlagsManager.class); + when(fm.getFlagByID(Mockito.anyString())).thenReturn(flag); + when(plugin.getFlagsManager()).thenReturn(fm); + + RanksManager rm = mock(RanksManager.class); + + when(plugin.getRanksManager()).thenReturn(rm); + + // Provide a current rank value - member + when(island.getFlag(Mockito.any())).thenReturn(RanksManager.MEMBER_RANK); + // Set up up and down ranks + when(rm.getRankUpValue(Mockito.eq(RanksManager.MEMBER_RANK))).thenReturn(RanksManager.OWNER_RANK); + when(rm.getRankDownValue(Mockito.eq(RanksManager.MEMBER_RANK))).thenReturn(RanksManager.VISITOR_RANK); + + panel = mock(Panel.class); + inv = mock(Inventory.class); + when(panel.getInventory()).thenReturn(inv); + + } + + @Test + public void testUpDownClick() { + UpDownClick udc = new UpDownClick("LOCK"); + assertNotNull(udc); + } + + @Test + public void testOnLeftClick() { + UpDownClick udc = new UpDownClick("LOCK"); + // Click left + assertTrue(udc.onClick(panel, user, ClickType.LEFT, 5)); + Mockito.verify(island).setFlag(Mockito.eq(flag), Mockito.eq(RanksManager.OWNER_RANK)); + Mockito.verify(flag).toPanelItem(Mockito.any(), Mockito.any()); + Mockito.verify(inv).setItem(Mockito.eq(5), Mockito.any()); + } + + @Test + public void testOnRightClick() { + UpDownClick udc = new UpDownClick("LOCK"); + // Right click + assertTrue(udc.onClick(panel, user, ClickType.RIGHT, 0)); + Mockito.verify(island).setFlag(Mockito.eq(flag), Mockito.eq(RanksManager.VISITOR_RANK)); + } + + @Test + public void testAllClicks() { + // Test all possible click types + UpDownClick udc = new UpDownClick("LOCK"); + Arrays.asList(ClickType.values()).forEach(c -> assertTrue(udc.onClick(panel, user, c, 0))); + } + + @Test + public void testNotOwner() { + UUID u; + do { + u = UUID.randomUUID(); + } while(u.equals(uuid)); + + when(island.getOwner()).thenReturn(u); + Mockito.verify(plugin, Mockito.never()).getRanksManager(); + + } + + @Test + public void testNullIsland() { + when(im.getIsland(Mockito.any(UUID.class))).thenReturn(null); + Mockito.verify(plugin, Mockito.never()).getRanksManager(); + } + +} diff --git a/src/test/java/us/tastybento/bskyblock/managers/RanksManagerTest.java b/src/test/java/us/tastybento/bskyblock/managers/RanksManagerTest.java index 286f14150..454120a26 100644 --- a/src/test/java/us/tastybento/bskyblock/managers/RanksManagerTest.java +++ b/src/test/java/us/tastybento/bskyblock/managers/RanksManagerTest.java @@ -83,27 +83,28 @@ public class RanksManagerTest { } /** - * Test method for {@link us.tastybento.bskyblock.managers.RanksManager#getNextRankValue(int)}. + * Test method for {@link us.tastybento.bskyblock.managers.RanksManager#getRankUpValue(int)}. */ @Test public void testGetNextRankValue() { - assertEquals(RanksManager.BANNED_RANK, ranksManager.getNextRankValue(-20)); - assertEquals(RanksManager.VISITOR_RANK, ranksManager.getNextRankValue(RanksManager.BANNED_RANK)); - assertEquals(RanksManager.MEMBER_RANK, ranksManager.getNextRankValue(RanksManager.VISITOR_RANK)); - assertEquals(RanksManager.OWNER_RANK, ranksManager.getNextRankValue(RanksManager.MEMBER_RANK)); - assertEquals(RanksManager.OWNER_RANK, ranksManager.getNextRankValue(RanksManager.OWNER_RANK)); - assertEquals(RanksManager.OWNER_RANK, ranksManager.getNextRankValue(2000)); + assertEquals(RanksManager.BANNED_RANK, ranksManager.getRankUpValue(-20)); + assertEquals(RanksManager.VISITOR_RANK, ranksManager.getRankUpValue(RanksManager.BANNED_RANK)); + assertEquals(RanksManager.MEMBER_RANK, ranksManager.getRankUpValue(RanksManager.VISITOR_RANK)); + assertEquals(RanksManager.OWNER_RANK, ranksManager.getRankUpValue(RanksManager.MEMBER_RANK)); + assertEquals(RanksManager.OWNER_RANK, ranksManager.getRankUpValue(RanksManager.OWNER_RANK)); + assertEquals(RanksManager.OWNER_RANK, ranksManager.getRankUpValue(2000)); } /** - * Test method for {@link us.tastybento.bskyblock.managers.RanksManager#getPreviousRankValue(int)}. + * Test method for {@link us.tastybento.bskyblock.managers.RanksManager#getRankDownValue(int)}. */ @Test public void testGetPreviousRankValue() { - assertEquals(RanksManager.BANNED_RANK, ranksManager.getPreviousRankValue(-20)); - assertEquals(RanksManager.BANNED_RANK, ranksManager.getPreviousRankValue(RanksManager.VISITOR_RANK)); - assertEquals(RanksManager.VISITOR_RANK, ranksManager.getPreviousRankValue(RanksManager.MEMBER_RANK)); - assertEquals(RanksManager.MEMBER_RANK, ranksManager.getPreviousRankValue(RanksManager.OWNER_RANK)); + // Lowest rank is Visitor + assertEquals(RanksManager.VISITOR_RANK, ranksManager.getRankDownValue(-20)); + assertEquals(RanksManager.VISITOR_RANK, ranksManager.getRankDownValue(RanksManager.VISITOR_RANK)); + assertEquals(RanksManager.VISITOR_RANK, ranksManager.getRankDownValue(RanksManager.MEMBER_RANK)); + assertEquals(RanksManager.MEMBER_RANK, ranksManager.getRankDownValue(RanksManager.OWNER_RANK)); } /**