From 9a666e29ca9f99f635ede71206dfec0cafd2bf30 Mon Sep 17 00:00:00 2001 From: tastybento Date: Fri, 8 Jun 2018 08:20:16 -0700 Subject: [PATCH] Added specific WORLD_SETTING flag. This flag is separate from island SETTING flags. The settings are done in a different way and rather than try and work out which type is which, it is better to specify them at the start. Also added a SUB_MENU settings type. --- locales/en-US.yml | 21 ++++++-- .../us/tastybento/bskyblock/Settings.java | 2 + .../api/configuration/WorldSettings.java | 6 +++ .../tastybento/bskyblock/api/flags/Flag.java | 48 ++++++++++------- .../bskyblock/api/flags/FlagBuilder.java | 4 +- .../bskyblock/database/objects/Island.java | 42 +++++++++++---- .../listeners/flags/AbstractFlagListener.java | 4 +- .../listeners/flags/BreakBlocksListener.java | 2 +- .../listeners/flags/EnterExitListener.java | 10 ++-- .../listeners/flags/FireListener.java | 2 +- .../flags/InvincibleVisitorsListener.java | 35 ++++++++++++- .../listeners/flags/MobSpawnListener.java | 4 +- .../listeners/flags/PVPListener.java | 42 +++++++++++++-- .../listeners/flags/PistonPushListener.java | 2 +- .../{ => clicklisteners}/CycleClick.java | 2 +- .../IslandToggleClickListener.java | 52 +++++++++++++++++++ .../WorldToggleClickListener.java} | 9 ++-- .../us/tastybento/bskyblock/lists/Flags.java | 22 ++++---- .../managers/IslandWorldManager.java | 10 ++++ .../bskyblock/managers/IslandsManager.java | 7 +-- .../bskyblock/managers/PlayersManager.java | 4 +- .../bskyblock/api/flags/FlagTest.java | 10 ++-- .../listeners/flags/CycleClickTest.java | 1 + .../SettingsToggleClickListenerTest.java | 7 +-- 24 files changed, 271 insertions(+), 77 deletions(-) rename src/main/java/us/tastybento/bskyblock/listeners/flags/{ => clicklisteners}/CycleClick.java (97%) create mode 100644 src/main/java/us/tastybento/bskyblock/listeners/flags/clicklisteners/IslandToggleClickListener.java rename src/main/java/us/tastybento/bskyblock/listeners/flags/{SettingsToggleClickListener.java => clicklisteners/WorldToggleClickListener.java} (85%) diff --git a/locales/en-US.yml b/locales/en-US.yml index 9a54c2c48..bdbe5d46f 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -334,6 +334,9 @@ protection: ITEM_PICKUP: "ITEM_PICKUP" INVINCIBLE_VISITORS: name: "Invincible Visitors" + description: | + Configure invincible visitor + settings. LEASH: "LEASH" LOCK: name: "Lock island" @@ -353,9 +356,21 @@ protection: PLACE_BLOCKS: "PLACE_BLOCKS" PORTAL: "PORTAL" PRESSURE_PLATE: "PRESSURE_PLATE" - PVP_OVERWORLD: "PVP_OVERWORLD" - PVP_NETHER: "PVP_NETHER" - PVP_END: "PVP_END" + PVP_OVERWORLD: + name: "Overworld PVP" + description: | + Enable/Disable PVP + on island. + PVP_NETHER: + name: "Nether PVP" + description: | + Enable/Disable PVP + in nether. + PVP_END: + name: "End PVP" + description: | + Enable/Disable PVP + in the End. REDSTONE: "REDSTONE" SPAWN_EGGS: "SPAWN_EGGS" SHEARING: "SHEARING" diff --git a/src/main/java/us/tastybento/bskyblock/Settings.java b/src/main/java/us/tastybento/bskyblock/Settings.java index ebca3a34f..71163c940 100644 --- a/src/main/java/us/tastybento/bskyblock/Settings.java +++ b/src/main/java/us/tastybento/bskyblock/Settings.java @@ -1494,8 +1494,10 @@ public class Settings implements DataObject, WorldSettings { } /** + * Invincible visitor settings * @return the ivSettings */ + @Override public List getIvSettings() { return ivSettings; } diff --git a/src/main/java/us/tastybento/bskyblock/api/configuration/WorldSettings.java b/src/main/java/us/tastybento/bskyblock/api/configuration/WorldSettings.java index c4237ab74..e0becd29f 100644 --- a/src/main/java/us/tastybento/bskyblock/api/configuration/WorldSettings.java +++ b/src/main/java/us/tastybento/bskyblock/api/configuration/WorldSettings.java @@ -1,5 +1,6 @@ package us.tastybento.bskyblock.api.configuration; +import java.util.List; import java.util.Map; import org.bukkit.entity.EntityType; @@ -125,5 +126,10 @@ public interface WorldSettings { * @return the permission prefix */ String getPermissionPrefix(); + + /** + * @return Invincible Visitor setting list + */ + List getIvSettings(); } 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 e01d352c8..42eba2c94 100644 --- a/src/main/java/us/tastybento/bskyblock/api/flags/Flag.java +++ b/src/main/java/us/tastybento/bskyblock/api/flags/Flag.java @@ -22,7 +22,9 @@ public class Flag implements Comparable { public enum Type { PROTECTION, - SETTING + SETTING, + SUB_MENU, + WORLD_SETTING } private final String id; @@ -61,10 +63,10 @@ public class Flag implements Comparable { * @param world - world * @return world setting, or default system setting if a specific world setting is not set */ - public boolean isSet(World world) { + public boolean isSetForWorld(World world) { return worldSettings.getOrDefault(Util.getWorld(world), setting); } - + /** * Set the default or global setting for this world * @param world - world @@ -146,32 +148,40 @@ 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") + // Check if this is a setting or world setting + if (this.getType().equals(Type.WORLD_SETTING)) { + String setting = this.isSetForWorld(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 Island island = plugin.getIslands().getIslandAt(user.getLocation()).orElse(plugin.getIslands().getIsland(user.getWorld(), user.getUniqueId())); if (island != null) { + if (this.getType().equals(Type.SETTING)) { + String setting = island.isAllowed(this) ? 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(); + } // TODO: Get the world settings - the player has no island and is not in an island location // Dynamic rank list - plugin.getRanksManager().getRanks().forEach((reference, score) -> { - if (score > RanksManager.BANNED_RANK && score < island.getFlag(this)) { - pib.description(user.getTranslation("protection.panel.flag-item.blocked_rank") + user.getTranslation(reference)); - } else if (score <= RanksManager.OWNER_RANK && score > island.getFlag(this)) { - pib.description(user.getTranslation("protection.panel.flag-item.allowed_rank") + user.getTranslation(reference)); - } else if (score == island.getFlag(this)) { - pib.description(user.getTranslation("protection.panel.flag-item.minimal_rank") + user.getTranslation(reference)); - } - }); + if (this.getType().equals(Type.PROTECTION)) { + // Protection flag + pib.description(user.getTranslation("protection.panel.flag-item.description-layout", "[description]", user.getTranslation("protection.flags." + id + ".description"))); + plugin.getRanksManager().getRanks().forEach((reference, score) -> { + if (score > RanksManager.BANNED_RANK && score < island.getFlag(this)) { + pib.description(user.getTranslation("protection.panel.flag-item.blocked_rank") + user.getTranslation(reference)); + } else if (score <= RanksManager.OWNER_RANK && score > island.getFlag(this)) { + pib.description(user.getTranslation("protection.panel.flag-item.allowed_rank") + user.getTranslation(reference)); + } else if (score == island.getFlag(this)) { + pib.description(user.getTranslation("protection.panel.flag-item.minimal_rank") + user.getTranslation(reference)); + } + }); + } } return pib.build(); } 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 d0f7db45d..df2e16eff 100644 --- a/src/main/java/us/tastybento/bskyblock/api/flags/FlagBuilder.java +++ b/src/main/java/us/tastybento/bskyblock/api/flags/FlagBuilder.java @@ -5,7 +5,7 @@ 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.CycleClick; +import us.tastybento.bskyblock.listeners.flags.clicklisteners.CycleClick; import us.tastybento.bskyblock.managers.RanksManager; public class FlagBuilder { @@ -88,7 +88,7 @@ public class FlagBuilder { /** * Adds a listener for clicks on this flag when it is a panel item. Default is - * {@link us.tastybento.bskyblock.listeners.flags.CycleClick} + * {@link us.tastybento.bskyblock.listeners.flags.clicklisteners.CycleClick} * @param onClickListener - the listener for clicks. Must use the ClickOn interface * @return FlagBuilder */ diff --git a/src/main/java/us/tastybento/bskyblock/database/objects/Island.java b/src/main/java/us/tastybento/bskyblock/database/objects/Island.java index d3276f9af..a3926c4bf 100755 --- a/src/main/java/us/tastybento/bskyblock/database/objects/Island.java +++ b/src/main/java/us/tastybento/bskyblock/database/objects/Island.java @@ -167,17 +167,15 @@ public class Island implements DataObject { return createdDate; } /** - * Gets the rank needed to bypass this Island Guard flag + * Gets the Island Guard flag's setting. If this is a protection flag, the this will be the + * rank needed to bypass this flag. If it is a Settings flag, any non-zero value means the + * setting is allowed. * @param flag - * @return the rank needed to bypass this flag. Players must have at least this rank to bypass this flag. + * @return flag value */ - public int getFlag(Flag flag){ - if(flags.containsKey(flag)) { - return flags.get(flag); - } else { - flags.put(flag, flag.getDefaultRank()); - return flag.getDefaultRank(); - } + public int getFlag(Flag flag) { + flags.putIfAbsent(flag, flag.getDefaultRank()); + return flags.get(flag); } /** @@ -396,11 +394,12 @@ public class Island implements DataObject { /** * Check if the flag is allowed or not - * For flags that are for the island in general and not related to rank + * For flags that are for the island in general and not related to rank. * @param flag * @return true if allowed, false if not */ public boolean isAllowed(Flag flag) { + // A negative value means not allowed return getFlag(flag) >= 0; } @@ -701,4 +700,27 @@ public class Island implements DataObject { } + + /** + * Toggles a settings flag + * @param flag + */ + public void toggleFlag(Flag flag) { + if (flag.getType().equals(Flag.Type.SETTING) || flag.getType().equals(Flag.Type.WORLD_SETTING)) { + setSettingsFlag(flag, !isAllowed(flag)); + } + } + + /** + * Sets the state of a settings flag + * @param flag + * @param state + */ + public void setSettingsFlag(Flag flag, boolean state) { + if (flag.getType().equals(Flag.Type.SETTING) || flag.getType().equals(Flag.Type.WORLD_SETTING)) { + flags.put(flag, state ? 1 : -1); + } + } + + } \ No newline at end of file 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 e210e1c65..782661e27 100644 --- a/src/main/java/us/tastybento/bskyblock/listeners/flags/AbstractFlagListener.java +++ b/src/main/java/us/tastybento/bskyblock/listeners/flags/AbstractFlagListener.java @@ -130,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.isSet(loc.getWorld())); + return island.map(x -> x.isAllowed(flag)).orElse(flag.isSetForWorld(loc.getWorld())); } // Protection flag @@ -158,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.isSet(loc.getWorld())) { + if (!flag.isSetForWorld(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 862b52cce..8e5cd0b9b 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.isSet(e.getVehicle().getWorld())) { + if (!Flags.BREAK_BLOCKS.isSetForWorld(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 index e584812b4..fa351ca4e 100644 --- a/src/main/java/us/tastybento/bskyblock/listeners/flags/EnterExitListener.java +++ b/src/main/java/us/tastybento/bskyblock/listeners/flags/EnterExitListener.java @@ -26,7 +26,7 @@ public class EnterExitListener extends AbstractFlagListener { @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()) + if (!Flags.ENTER_EXIT_MESSAGES.isSetForWorld(e.getFrom().getWorld()) || e.getFrom().toVector().multiply(XZ).equals(e.getTo().toVector().multiply(XZ)) || !getIslandWorldManager().inWorld(e.getFrom())) { return; @@ -47,9 +47,13 @@ public class EnterExitListener extends AbstractFlagListener { 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() : + // Send message if island is owned by someone + from.filter(i -> i.getOwner() != null).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() : + to.filter(i -> i.getOwner() != null).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())))); + // Send message if island is unowned, but has a name + from.filter(i -> i.getOwner() == null && !i.getName().isEmpty()).ifPresent(i -> user.sendMessage("protection.flags.ENTER_EXIT_MESSAGES.now-leaving", "[name]", i.getName())); + to.filter(i -> i.getOwner() == null && !i.getName().isEmpty()).ifPresent(i -> user.sendMessage("protection.flags.ENTER_EXIT_MESSAGES.now-entering", "[name]", i.getName())); } } 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 285d8d21b..1734db4f8 100644 --- a/src/main/java/us/tastybento/bskyblock/listeners/flags/FireListener.java +++ b/src/main/java/us/tastybento/bskyblock/listeners/flags/FireListener.java @@ -40,7 +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.isSet(l.getWorld())); + boolean cancel = getIslands().getIslandAt(l).map(i -> !i.isAllowed(flag)).orElse(!flag.isSetForWorld(l.getWorld())); e.setCancelled(cancel); return cancel; } diff --git a/src/main/java/us/tastybento/bskyblock/listeners/flags/InvincibleVisitorsListener.java b/src/main/java/us/tastybento/bskyblock/listeners/flags/InvincibleVisitorsListener.java index 82e71b3c2..f32f49fa5 100644 --- a/src/main/java/us/tastybento/bskyblock/listeners/flags/InvincibleVisitorsListener.java +++ b/src/main/java/us/tastybento/bskyblock/listeners/flags/InvincibleVisitorsListener.java @@ -5,7 +5,12 @@ package us.tastybento.bskyblock.listeners.flags; import java.util.Arrays; +import org.bukkit.GameMode; import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; import org.bukkit.event.entity.EntityDamageEvent; import org.bukkit.event.entity.EntityDamageEvent.DamageCause; import org.bukkit.event.inventory.ClickType; @@ -16,6 +21,7 @@ import us.tastybento.bskyblock.api.panels.builders.PanelBuilder; import us.tastybento.bskyblock.api.panels.builders.PanelItemBuilder; import us.tastybento.bskyblock.api.user.User; import us.tastybento.bskyblock.util.Util; +import us.tastybento.bskyblock.util.teleport.SafeTeleportBuilder; /** * @author tastybento @@ -62,7 +68,34 @@ public class InvincibleVisitorsListener extends AbstractFlagListener implements pb.item(pib.build()); }); pb.build(); - + + } + + /** + * Prevents visitors from getting damage if a particular damage type is listed in the config + * @param e - event + */ + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onVisitorGetDamage(EntityDamageEvent e) { + World world = e.getEntity().getWorld(); + if (!getPlugin().getIWM().getIvSettings(world).contains(e.getCause().name()) + || !(e.getEntity() instanceof Player) + || e.getCause().equals(DamageCause.ENTITY_ATTACK) + || !getPlugin().getIWM().inWorld(e.getEntity().getLocation()) + || getIslands().userIsOnIsland(world, User.getInstance(e.getEntity()))) { + return; + } + // Player is a visitor and should be protected from damage + e.setCancelled(true); + Player p = (Player) e.getEntity(); + // Handle the void - teleport player back to island in a safe spot + if(e.getCause().equals(DamageCause.VOID)) { + // Will be set back after the teleport + p.setGameMode(GameMode.SPECTATOR); + getIslands().getIslandAt(p.getLocation()).ifPresent(i -> { + new SafeTeleportBuilder(getPlugin()).entity(p).island(i).build(); + }); + } } 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 b20b69056..8f4e22d70 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.isSet(e.getEntity().getWorld())); + boolean cancel = island.map(i -> !i.isAllowed(Flags.MONSTER_SPAWN)).orElse(!Flags.MONSTER_SPAWN.isSetForWorld(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.isSet(e.getEntity().getWorld())); + boolean cancel = island.map(i -> !i.isAllowed(Flags.ANIMAL_SPAWN)).orElse(!Flags.ANIMAL_SPAWN.isSetForWorld(e.getEntity().getWorld())); e.setCancelled(cancel); return cancel; } diff --git a/src/main/java/us/tastybento/bskyblock/listeners/flags/PVPListener.java b/src/main/java/us/tastybento/bskyblock/listeners/flags/PVPListener.java index 185e6e26f..d333f351c 100644 --- a/src/main/java/us/tastybento/bskyblock/listeners/flags/PVPListener.java +++ b/src/main/java/us/tastybento/bskyblock/listeners/flags/PVPListener.java @@ -39,26 +39,40 @@ public class PVPListener extends AbstractFlagListener { */ @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) public void onEntityDamage(final EntityDamageByEntityEvent e) { + // Check PVP if (e.getEntity() instanceof Player) { + // Protect visitors + if (e.getCause().equals(DamageCause.ENTITY_ATTACK) + && getPlugin().getIWM().getIvSettings(e.getEntity().getWorld()).contains(DamageCause.ENTITY_ATTACK.name()) + && !getIslands().userIsOnIsland(e.getEntity().getWorld(), User.getInstance(e.getEntity()))) { + e.setCancelled(true); + return; + } Flag flag = Flags.PVP_OVERWORLD; - if (e.getEntity().getWorld().equals(getPlugin().getIWM().getNetherWorld())) { + if (e.getEntity().getWorld().equals(getPlugin().getIWM().getNetherWorld(e.getEntity().getWorld()))) { flag = Flags.PVP_NETHER; - } else if (e.getEntity().getWorld().equals(getPlugin().getIWM().getEndWorld())) { + } else if (e.getEntity().getWorld().equals(getPlugin().getIWM().getEndWorld(e.getEntity().getWorld()))) { flag = Flags.PVP_END; } respond(e, e.getDamager(), flag); } } - private void respond(Event event, Entity damager, Flag flag) { + /** + * Checks how to respond to an attack + * @param e + * @param damager + * @param flag + */ + private void respond(Event e, Entity damager, Flag flag) { // Get the attacker if (damager instanceof Player) { - setUser(User.getInstance(damager)).checkIsland(event, damager.getLocation(), flag); + setUser(User.getInstance(damager)).checkIsland(e, damager.getLocation(), flag); } else if (damager instanceof Projectile) { // Find out who fired the arrow Projectile p = (Projectile) damager; if (p.getShooter() instanceof Player) { - if (!setUser(User.getInstance((Player)p.getShooter())).checkIsland(event, damager.getLocation(), flag)) { + if (!setUser(User.getInstance((Player)p.getShooter())).checkIsland(e, damager.getLocation(), flag)) { damager.setFireTicks(0); damager.remove(); } @@ -70,6 +84,12 @@ public class PVPListener extends AbstractFlagListener { @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) public void onFishing(PlayerFishEvent e) { if (e.getCaught() instanceof Player) { + // Protect visitors + if (getPlugin().getIWM().getIvSettings(e.getPlayer().getWorld()).contains(DamageCause.ENTITY_ATTACK.name()) + && !getIslands().userIsOnIsland(e.getPlayer().getWorld(), User.getInstance(e.getCaught()))) { + e.setCancelled(true); + return; + } Flag flag = Flags.PVP_OVERWORLD; if (e.getCaught().getWorld().equals(getPlugin().getIWM().getNetherWorld())) { flag = Flags.PVP_NETHER; @@ -108,6 +128,12 @@ public class PVPListener extends AbstractFlagListener { } // PVP? if (entity instanceof Player) { + // Protect visitors + if (getPlugin().getIWM().getIvSettings(entity.getWorld()).contains(DamageCause.ENTITY_ATTACK.name()) + && !getIslands().userIsOnIsland(entity.getWorld(), User.getInstance(entity))) { + e.setCancelled(true); + return; + } if (!setUser(User.getInstance(attacker)).checkIsland(e, entity.getLocation(), flag)) { for (PotionEffect effect : e.getPotion().getEffects()) { entity.removePotionEffect(effect.getType()); @@ -153,6 +179,12 @@ public class PVPListener extends AbstractFlagListener { Entity entity = e.getEntity(); // PVP? if (entity instanceof Player) { + // Protect visitors + if (getPlugin().getIWM().getIvSettings(entity.getWorld()).contains(DamageCause.ENTITY_ATTACK.name()) + && !getIslands().userIsOnIsland(entity.getWorld(), User.getInstance(entity))) { + e.setCancelled(true); + return; + } checkIsland(e, entity.getLocation(), flag); } } diff --git a/src/main/java/us/tastybento/bskyblock/listeners/flags/PistonPushListener.java b/src/main/java/us/tastybento/bskyblock/listeners/flags/PistonPushListener.java index ee5c1468a..ef606b2e4 100644 --- a/src/main/java/us/tastybento/bskyblock/listeners/flags/PistonPushListener.java +++ b/src/main/java/us/tastybento/bskyblock/listeners/flags/PistonPushListener.java @@ -19,7 +19,7 @@ public class PistonPushListener extends AbstractFlagListener { @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) public void onPistonExtend(BlockPistonExtendEvent e) { // Only process if flag is active - if (Flags.PISTON_PUSH.isSet(e.getBlock().getWorld())) { + if (Flags.PISTON_PUSH.isSetForWorld(e.getBlock().getWorld())) { getIslands().getProtectedIslandAt(e.getBlock().getLocation()).ifPresent(i -> e.setCancelled( // Run through the location of all the relative blocks and see if they are outside the island diff --git a/src/main/java/us/tastybento/bskyblock/listeners/flags/CycleClick.java b/src/main/java/us/tastybento/bskyblock/listeners/flags/clicklisteners/CycleClick.java similarity index 97% rename from src/main/java/us/tastybento/bskyblock/listeners/flags/CycleClick.java rename to src/main/java/us/tastybento/bskyblock/listeners/flags/clicklisteners/CycleClick.java index 748fe576e..922241eaa 100644 --- a/src/main/java/us/tastybento/bskyblock/listeners/flags/CycleClick.java +++ b/src/main/java/us/tastybento/bskyblock/listeners/flags/clicklisteners/CycleClick.java @@ -1,4 +1,4 @@ -package us.tastybento.bskyblock.listeners.flags; +package us.tastybento.bskyblock.listeners.flags.clicklisteners; import org.bukkit.Sound; import org.bukkit.event.inventory.ClickType; diff --git a/src/main/java/us/tastybento/bskyblock/listeners/flags/clicklisteners/IslandToggleClickListener.java b/src/main/java/us/tastybento/bskyblock/listeners/flags/clicklisteners/IslandToggleClickListener.java new file mode 100644 index 000000000..80b566c09 --- /dev/null +++ b/src/main/java/us/tastybento/bskyblock/listeners/flags/clicklisteners/IslandToggleClickListener.java @@ -0,0 +1,52 @@ +/** + * + */ +package us.tastybento.bskyblock.listeners.flags.clicklisteners; + +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.database.objects.Island; + +/** + * Toggles a island setting on/off + * @author tastybento + * + */ +public class IslandToggleClickListener implements ClickHandler { + + private BSkyBlock plugin = BSkyBlock.getInstance(); + private String id; + + /** + * @param id + */ + public IslandToggleClickListener(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 user's island + Island island = plugin.getIslands().getIsland(user.getWorld(), user.getUniqueId()); + if (island != null && island.getOwner().equals(user.getUniqueId())) { + Flag flag = plugin.getFlagsManager().getFlagByID(id); + // Toggle flag + island.toggleFlag(flag); + 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/listeners/flags/SettingsToggleClickListener.java b/src/main/java/us/tastybento/bskyblock/listeners/flags/clicklisteners/WorldToggleClickListener.java similarity index 85% rename from src/main/java/us/tastybento/bskyblock/listeners/flags/SettingsToggleClickListener.java rename to src/main/java/us/tastybento/bskyblock/listeners/flags/clicklisteners/WorldToggleClickListener.java index 08836c03d..bbb93e2dd 100644 --- a/src/main/java/us/tastybento/bskyblock/listeners/flags/SettingsToggleClickListener.java +++ b/src/main/java/us/tastybento/bskyblock/listeners/flags/clicklisteners/WorldToggleClickListener.java @@ -1,7 +1,7 @@ /** * */ -package us.tastybento.bskyblock.listeners.flags; +package us.tastybento.bskyblock.listeners.flags.clicklisteners; import org.bukkit.Sound; import org.bukkit.event.inventory.ClickType; @@ -14,10 +14,11 @@ import us.tastybento.bskyblock.api.user.User; import us.tastybento.bskyblock.util.Util; /** + * Toggles a worldwide setting on/off * @author tastybento * */ -public class SettingsToggleClickListener implements ClickHandler { +public class WorldToggleClickListener implements ClickHandler { private BSkyBlock plugin = BSkyBlock.getInstance(); private String id; @@ -25,7 +26,7 @@ public class SettingsToggleClickListener implements ClickHandler { /** * @param id */ - public SettingsToggleClickListener(String id) { + public WorldToggleClickListener(String id) { this.id = id; } @@ -49,7 +50,7 @@ public class SettingsToggleClickListener implements ClickHandler { // Get flag Flag flag = plugin.getFlagsManager().getFlagByID(id); // Toggle flag - flag.setSetting(user.getWorld(), !flag.isSet(user.getWorld())); + flag.setSetting(user.getWorld(), !flag.isSetForWorld(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()); diff --git a/src/main/java/us/tastybento/bskyblock/lists/Flags.java b/src/main/java/us/tastybento/bskyblock/lists/Flags.java index fa5a09be1..1d9ac150d 100644 --- a/src/main/java/us/tastybento/bskyblock/lists/Flags.java +++ b/src/main/java/us/tastybento/bskyblock/lists/Flags.java @@ -29,9 +29,10 @@ import us.tastybento.bskyblock.listeners.flags.PhysicalInteractionListener; import us.tastybento.bskyblock.listeners.flags.PistonPushListener; 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.listeners.flags.clicklisteners.IslandToggleClickListener; +import us.tastybento.bskyblock.listeners.flags.clicklisteners.WorldToggleClickListener; import us.tastybento.bskyblock.managers.RanksManager; public class Flags { @@ -132,24 +133,27 @@ public class Flags { * Settings flags (not protection flags) */ // PVP - public static final Flag PVP_OVERWORLD = new FlagBuilder().id("PVP_OVERWORLD").icon(Material.ARROW).type(Type.SETTING).listener(new PVPListener()).build(); - 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(); + public static final Flag PVP_OVERWORLD = new FlagBuilder().id("PVP_OVERWORLD").icon(Material.ARROW).type(Type.SETTING) + .listener(new PVPListener()).onClick(new IslandToggleClickListener("PVP_OVERWORLD")).build(); + public static final Flag PVP_NETHER = new FlagBuilder().id("PVP_NETHER").icon(Material.IRON_AXE).type(Type.SETTING) + .onClick(new IslandToggleClickListener("PVP_NETHER")).build(); + public static final Flag PVP_END = new FlagBuilder().id("PVP_END").icon(Material.END_CRYSTAL).type(Type.SETTING) + .onClick(new IslandToggleClickListener("PVP_END")).build(); // Others 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(); // Global flags (apply to every island) - public static final Flag ENTER_EXIT_MESSAGES = new FlagBuilder().id("ENTER_EXIT_MESSAGES").icon(Material.DIRT).allowedByDefault(true).type(Type.SETTING) + public static final Flag ENTER_EXIT_MESSAGES = new FlagBuilder().id("ENTER_EXIT_MESSAGES").icon(Material.DIRT).allowedByDefault(true).type(Type.WORLD_SETTING) .listener(new EnterExitListener()) - .onClick(new SettingsToggleClickListener("ENTER_EXIT_MESSAGES")) + .onClick(new WorldToggleClickListener("ENTER_EXIT_MESSAGES")) .build(); - public static final Flag PISTON_PUSH = new FlagBuilder().id("PISTON_PUSH").icon(Material.PISTON_BASE).allowedByDefault(true).type(Type.SETTING) + public static final Flag PISTON_PUSH = new FlagBuilder().id("PISTON_PUSH").icon(Material.PISTON_BASE).allowedByDefault(true).type(Type.WORLD_SETTING) .listener(new PistonPushListener()) - .onClick(new SettingsToggleClickListener("PISTON_PUSH")) + .onClick(new WorldToggleClickListener("PISTON_PUSH")) .build(); static InvincibleVisitorsListener ilv = new InvincibleVisitorsListener(); - public static final Flag INVINCIBLE_VISITORS = new FlagBuilder().id("INVINCIBLE_VISITORS").icon(Material.DIAMOND_CHESTPLATE).type(Type.SETTING) + public static final Flag INVINCIBLE_VISITORS = new FlagBuilder().id("INVINCIBLE_VISITORS").icon(Material.DIAMOND_CHESTPLATE).type(Type.SUB_MENU) .listener(ilv).onClick(ilv).build(); /** diff --git a/src/main/java/us/tastybento/bskyblock/managers/IslandWorldManager.java b/src/main/java/us/tastybento/bskyblock/managers/IslandWorldManager.java index 3132599c7..b349f9c7d 100644 --- a/src/main/java/us/tastybento/bskyblock/managers/IslandWorldManager.java +++ b/src/main/java/us/tastybento/bskyblock/managers/IslandWorldManager.java @@ -449,10 +449,20 @@ public class IslandWorldManager { /** * Get the permission prefix for this world * @param world + * @return permission prefix for this world */ public String getPermissionPrefix(World world) { return worldSettings.get(Util.getWorld(world)).getPermissionPrefix(); } + /** + * Get the invincible visitor settings for this world + * @param world + * @return invisible visitor settings + */ + public List getIvSettings(World world) { + return worldSettings.get(world).getIvSettings(); + } + } diff --git a/src/main/java/us/tastybento/bskyblock/managers/IslandsManager.java b/src/main/java/us/tastybento/bskyblock/managers/IslandsManager.java index 324cb4236..56a9b15ba 100644 --- a/src/main/java/us/tastybento/bskyblock/managers/IslandsManager.java +++ b/src/main/java/us/tastybento/bskyblock/managers/IslandsManager.java @@ -633,10 +633,11 @@ public class IslandsManager { /** * Checks if an online player is in the protected area of their island, a team island or a - * coop island + * coop island in the specific world in the arguments. Note that the user * - * @param user - the User - * @return true if on valid island, false if not + * @param world - the world to check + * @param user - the user + * @return true if on their island in world, false if not */ public boolean userIsOnIsland(World world, User user) { if (user == null) { diff --git a/src/main/java/us/tastybento/bskyblock/managers/PlayersManager.java b/src/main/java/us/tastybento/bskyblock/managers/PlayersManager.java index c6f0a7da7..9d271d94e 100644 --- a/src/main/java/us/tastybento/bskyblock/managers/PlayersManager.java +++ b/src/main/java/us/tastybento/bskyblock/managers/PlayersManager.java @@ -275,11 +275,11 @@ public class PlayersManager { * Player must have logged into the game before * * @param playerUUID - the player's UUID - * @return String - playerName + * @return String - playerName, empty string if UUID is null */ public String getName(UUID playerUUID) { if (playerUUID == null) { - return null; + return ""; } addPlayer(playerUUID); return playerCache.get(playerUUID).getPlayerName(); 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 f60d1b97f..4725fe749 100644 --- a/src/test/java/us/tastybento/bskyblock/api/flags/FlagTest.java +++ b/src/test/java/us/tastybento/bskyblock/api/flags/FlagTest.java @@ -85,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.isSet(mock(World.class))); + assertFalse(id.isSetForWorld(mock(World.class))); id = new Flag("id", Material.ACACIA_DOOR, null, true, null, 0, null); - assertTrue(id.isSet(mock(World.class))); + assertTrue(id.isSetForWorld(mock(World.class))); } @Test public void testSetDefaultSetting() { Flag id = new Flag("id", Material.ACACIA_DOOR, null, false, null, 0, null); - assertFalse(id.isSet(mock(World.class))); + assertFalse(id.isSetForWorld(mock(World.class))); id.setDefaultSetting(true); - assertTrue(id.isSet(mock(World.class))); + assertTrue(id.isSetForWorld(mock(World.class))); id.setDefaultSetting(false); - assertFalse(id.isSet(mock(World.class))); + assertFalse(id.isSetForWorld(mock(World.class))); } diff --git a/src/test/java/us/tastybento/bskyblock/listeners/flags/CycleClickTest.java b/src/test/java/us/tastybento/bskyblock/listeners/flags/CycleClickTest.java index 37bfd8e9c..9fee4b85a 100644 --- a/src/test/java/us/tastybento/bskyblock/listeners/flags/CycleClickTest.java +++ b/src/test/java/us/tastybento/bskyblock/listeners/flags/CycleClickTest.java @@ -36,6 +36,7 @@ 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.listeners.flags.clicklisteners.CycleClick; import us.tastybento.bskyblock.managers.FlagsManager; import us.tastybento.bskyblock.managers.IslandsManager; import us.tastybento.bskyblock.managers.LocalesManager; diff --git a/src/test/java/us/tastybento/bskyblock/listeners/flags/SettingsToggleClickListenerTest.java b/src/test/java/us/tastybento/bskyblock/listeners/flags/SettingsToggleClickListenerTest.java index 986ae272a..494f37aa3 100644 --- a/src/test/java/us/tastybento/bskyblock/listeners/flags/SettingsToggleClickListenerTest.java +++ b/src/test/java/us/tastybento/bskyblock/listeners/flags/SettingsToggleClickListenerTest.java @@ -22,6 +22,7 @@ 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.listeners.flags.clicklisteners.WorldToggleClickListener; import us.tastybento.bskyblock.managers.FlagsManager; import us.tastybento.bskyblock.managers.IslandWorldManager; import us.tastybento.bskyblock.util.Util; @@ -31,7 +32,7 @@ import us.tastybento.bskyblock.util.Util; public class SettingsToggleClickListenerTest { private IslandWorldManager iwm; - private SettingsToggleClickListener listener; + private WorldToggleClickListener listener; private Panel panel; private User user; private Flag flag; @@ -52,7 +53,7 @@ public class SettingsToggleClickListenerTest { when(plugin.getIWM()).thenReturn(iwm); - listener = new SettingsToggleClickListener("test"); + listener = new WorldToggleClickListener("test"); panel = mock(Panel.class); when(panel.getInventory()).thenReturn(mock(Inventory.class)); @@ -65,7 +66,7 @@ public class SettingsToggleClickListenerTest { FlagsManager fm = mock(FlagsManager.class); flag = mock(Flag.class); - when(flag.isSet(Mockito.any())).thenReturn(false); + when(flag.isSetForWorld(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);