From b3a36c75bb59a7019f27cfb203469065569a5855 Mon Sep 17 00:00:00 2001 From: DevSolaris <105156235+DevSolaris@users.noreply.github.com> Date: Thu, 19 Jan 2023 21:56:31 +0100 Subject: [PATCH] Create set warp flag (#117) --- src/main/java/world/bentobox/warps/Warp.java | 23 +++++++ .../world/bentobox/warps/config/Settings.java | 22 ++++++- .../warps/listeners/WarpSignsListener.java | 56 +++++++++++++++-- src/main/resources/config.yml | 5 ++ src/main/resources/locales/en-US.yml | 9 ++- .../listeners/WarpSignsListenerTest.java | 61 +++++++++++++++++-- 6 files changed, 164 insertions(+), 12 deletions(-) diff --git a/src/main/java/world/bentobox/warps/Warp.java b/src/main/java/world/bentobox/warps/Warp.java index fc762a8..fe3838c 100644 --- a/src/main/java/world/bentobox/warps/Warp.java +++ b/src/main/java/world/bentobox/warps/Warp.java @@ -7,10 +7,13 @@ import java.util.Set; import java.util.UUID; import org.bukkit.Bukkit; +import org.bukkit.Material; import org.bukkit.World; import world.bentobox.bentobox.api.addons.Addon; import world.bentobox.bentobox.api.configuration.Config; +import world.bentobox.bentobox.api.flags.Flag; +import world.bentobox.bentobox.managers.RanksManager; import world.bentobox.bentobox.util.Util; import world.bentobox.level.Level; import world.bentobox.warps.commands.WarpCommand; @@ -71,6 +74,11 @@ public class Warp extends Addon { */ private Config settingsConfig; + /** + * Create Warp Flag + */ + private Flag createWarpFlag; + // --------------------------------------------------------------------- // Section: Methods // --------------------------------------------------------------------- @@ -146,6 +154,14 @@ public class Warp extends Addon { logWarning("Addon did not hook into anything and is not running stand-alone"); this.setState(State.DISABLED); } + + this.createWarpFlag = new Flag.Builder("SET-WARP", Material.OAK_SIGN) + .addon(this) + .defaultRank(RanksManager.MEMBER_RANK) + .mode(Flag.Mode.EXPERT) + .build(); + + getPlugin().getFlagsManager().registerFlag(this, this.createWarpFlag); } @@ -213,6 +229,13 @@ public class Warp extends Addon { return settings; } + /** + * @return the createWarpFlag + */ + public Flag getCreateWarpFlag() { + return createWarpFlag; + } + /** * Get the island level * @param world - world diff --git a/src/main/java/world/bentobox/warps/config/Settings.java b/src/main/java/world/bentobox/warps/config/Settings.java index 5e9bfbb..883687b 100644 --- a/src/main/java/world/bentobox/warps/config/Settings.java +++ b/src/main/java/world/bentobox/warps/config/Settings.java @@ -23,6 +23,13 @@ public class Settings implements ConfigObject @ConfigEntry(path = "warplevelrestriction") private int warpLevelRestriction = 10; + @ConfigComment("") + @ConfigComment("Should warps be removed when the island protection settings") + @ConfigComment("change, and the owner of the warp does no longer have") + @ConfigComment("the correct rank") + @ConfigEntry(path = "removeExistingWarpsWhenFlagChanges") + private boolean removeExistingWarpsWhenFlagChanges = false; + @ConfigComment("") @ConfigComment("Text that player must put on sign to make it a warp sign") @ConfigComment("Not case sensitive!") @@ -55,7 +62,6 @@ public class Settings implements ConfigObject @ConfigEntry(path = "warps-command") String warpsCommand = "warps"; - // --------------------------------------------------------------------- // Section: Constructor // --------------------------------------------------------------------- @@ -198,4 +204,18 @@ public class Settings implements ConfigObject public void setWarpsCommand(String warpsCommand) { this.warpsCommand = warpsCommand; } + + /** + * @return the removeExistingWarpsWhenFlagChanges + */ + public boolean getRemoveExistingWarpsWhenFlagChanges() { + return removeExistingWarpsWhenFlagChanges; + } + + /** + * @param removeExistingWarpsWhenFlagChanges the removeExistingWarpsWhenFlagChanges to set + */ + public void setRemoveExistingWarpsWhenFlagChanges(boolean removeExistingWarpsWhenFlagChanges) { + this.removeExistingWarpsWhenFlagChanges = removeExistingWarpsWhenFlagChanges; + } } diff --git a/src/main/java/world/bentobox/warps/listeners/WarpSignsListener.java b/src/main/java/world/bentobox/warps/listeners/WarpSignsListener.java index 36d2805..0be6ef1 100644 --- a/src/main/java/world/bentobox/warps/listeners/WarpSignsListener.java +++ b/src/main/java/world/bentobox/warps/listeners/WarpSignsListener.java @@ -1,10 +1,7 @@ package world.bentobox.warps.listeners; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.Objects; -import java.util.UUID; +import java.util.*; +import java.util.stream.Collectors; import org.bukkit.Bukkit; import org.bukkit.ChatColor; @@ -25,9 +22,11 @@ import org.eclipse.jdt.annotation.Nullable; import world.bentobox.bentobox.BentoBox; import world.bentobox.bentobox.api.events.addon.AddonEvent; +import world.bentobox.bentobox.api.events.flags.FlagProtectionChangeEvent; import world.bentobox.bentobox.api.events.team.TeamKickEvent; import world.bentobox.bentobox.api.events.team.TeamLeaveEvent; import world.bentobox.bentobox.api.user.User; +import world.bentobox.bentobox.database.objects.Island; import world.bentobox.bentobox.util.Util; import world.bentobox.warps.Warp; import world.bentobox.warps.event.WarpRemoveEvent; @@ -164,6 +163,13 @@ public class WarpSignsListener implements Listener { e.setLine(0, ChatColor.RED + addon.getSettings().getWelcomeLine()); return; } + + if(!hasCorrectIslandRank(b, user)) { + e.setLine(0, ChatColor.RED + addon.getSettings().getWelcomeLine()); + user.sendMessage("warps.error.not-correct-rank"); + return; + } + // Check if the player already has a sign final Location oldSignLoc = addon.getWarpSignsManager().getWarp(b.getWorld(), user.getUniqueId()); if (oldSignLoc != null) { @@ -192,6 +198,46 @@ public class WarpSignsListener implements Listener { } + private boolean hasCorrectIslandRank(Block b, User user) { + final Optional islandOpt = plugin.getIslands().getIslandAt(b.getLocation()); + + if(islandOpt.isEmpty()) return false; + + final Island island = islandOpt.get(); + + final int userRank = island.getRank(user); + + return userRank >= island.getFlag(addon.getCreateWarpFlag()); + } + + @EventHandler + public void onFlagChange(FlagProtectionChangeEvent e) { + if(!e.getEditedFlag().equals(addon.getCreateWarpFlag())) return; + if(!addon.getSettings().getRemoveExistingWarpsWhenFlagChanges()) return; + + final Island island = e.getIsland(); + + final Map islandWarps = addon + .getWarpSignsManager() + .getWarpMap(island.getWorld()) + .entrySet() + .stream() + .filter(x -> island.inIslandSpace(x.getValue())) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + + for(Map.Entry entry : islandWarps.entrySet()) { + if(island.getRank(entry.getKey()) >= e.getSetTo()) continue; + + //The user has a lower rank than the new set value. + //We need to remove the warp. + addon.getWarpSignsManager().removeWarp(island.getWorld(), entry.getKey()); + + if(Bukkit.getPlayer(entry.getKey()) != null) { + Objects.requireNonNull(User.getInstance(entry.getKey())).sendMessage(WARPS_DEACTIVATE); + } + } + } + private boolean noLevelOrIsland(User user, World world) { // Get level if level addon is available Long level = addon.getLevel(Util.getWorld(world), user.getUniqueId()); diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index a647e5c..1975fd0 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -7,6 +7,11 @@ # Warp Restriction - needed levels to be able to create a warp # 0 or negative values will disable this restriction 10 is default warplevelrestriction: 10 +# +# Should warps be removed when the island protection settings +# change, and the owner of the warp does no longer have +# the correct rank +removeExistingWarpsWhenFlagChanges: true # # Text that player must put on sign to make it a warp sign # Not case sensitive! diff --git a/src/main/resources/locales/en-US.yml b/src/main/resources/locales/en-US.yml index 1ba6190..cd880e3 100755 --- a/src/main/resources/locales/en-US.yml +++ b/src/main/resources/locales/en-US.yml @@ -18,7 +18,8 @@ warps: not-on-island: "&c You must be on your island to do that!" not-safe: "&c That warp is not safe!" your-level-is: "&c Your island level is only [level] and must be higher than [required]. Run the level command." - help: + not-correct-rank: "&c You do not have the correct rank to set a warp!" + help: description: "open the warps panel" player-warped: "&2 [name] warped to your [gamemode] warp sign!" sign-removed: "&c Warp sign removed!" @@ -59,4 +60,8 @@ warps: # Prefix for messages that are send from server. prefix: "&l&6 [BentoBox]: &r" - +protection: + flags: + SET-WARP: + name: Set warp + description: Allow setting up warp signs diff --git a/src/test/java/world/bentobox/warps/listeners/WarpSignsListenerTest.java b/src/test/java/world/bentobox/warps/listeners/WarpSignsListenerTest.java index 9ecb1c6..f98d1be 100644 --- a/src/test/java/world/bentobox/warps/listeners/WarpSignsListenerTest.java +++ b/src/test/java/world/bentobox/warps/listeners/WarpSignsListenerTest.java @@ -8,10 +8,7 @@ import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; +import static org.mockito.Mockito.*; import java.util.HashMap; import java.util.Map; @@ -44,7 +41,10 @@ import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; import world.bentobox.bentobox.BentoBox; +import world.bentobox.bentobox.api.events.flags.FlagProtectionChangeEvent; +import world.bentobox.bentobox.api.flags.Flag; import world.bentobox.bentobox.api.user.User; +import world.bentobox.bentobox.database.objects.Island; import world.bentobox.bentobox.managers.IslandWorldManager; import world.bentobox.bentobox.managers.IslandsManager; import world.bentobox.bentobox.managers.LocalesManager; @@ -83,6 +83,8 @@ public class WarpSignsListenerTest { private IslandsManager im; @Mock private IslandWorldManager iwm; + @Mock + private Island island; @Before public void setUp() { @@ -148,6 +150,9 @@ public class WarpSignsListenerTest { when(settings.getWelcomeLine()).thenReturn("[WELCOME]"); when(addon.getSettings()).thenReturn(settings); + island = mock(Island.class); + when(im.getIslandAt(any())).thenReturn(Optional.of(island)); + // On island when(plugin.getIslands()).thenReturn(im); when(im.userIsOnIsland(any(World.class), any(User.class))).thenReturn(true); @@ -299,6 +304,54 @@ public class WarpSignsListenerTest { assertEquals(ChatColor.GREEN + "[WELCOME]", e.getLine(0)); } + @Test + public void testOnCreateWithoutCorrectRankNotAllowed() { + WarpSignsListener wsl = new WarpSignsListener(addon); + SignChangeEvent e = new SignChangeEvent(block, player, lines); + when(player.hasPermission(anyString())).thenReturn(true); + when(addon.inRegisteredWorld(any())).thenReturn(true); + when(island.getRank(player.getUniqueId())).thenReturn(0); + when(island.getFlag(any())).thenReturn(1000); + wsl.onSignWarpCreate(e); + verify(player).sendMessage("warps.error.not-correct-rank"); + } + + @Test + public void testOnFlagChangeWhenSettingIsOffNothingHappens() { + Flag flag = mock(Flag.class); + + when(addon.getCreateWarpFlag()).thenReturn(flag); + when(settings.getRemoveExistingWarpsWhenFlagChanges()).thenReturn(false); + WarpSignsListener wsl = new WarpSignsListener(addon); + + FlagProtectionChangeEvent e = new FlagProtectionChangeEvent(island, player.getUniqueId(), flag, 1000); + + wsl.onFlagChange(e); + + verifyNoInteractions(island); + } + + @Test + public void testOnFlagChangeWhenSettingIsOnWarpGetsRemoved() { + Flag flag = mock(Flag.class); + + when(addon.getCreateWarpFlag()).thenReturn(flag); + when(settings.getRemoveExistingWarpsWhenFlagChanges()).thenReturn(true); + WarpSignsListener wsl = new WarpSignsListener(addon); + + Map warps = Map.of( + player.getUniqueId(), block.getLocation() + ); + + when(wsm.getWarpMap(any())).thenReturn(warps); + when(island.inIslandSpace(any(Location.class))).thenReturn(true); + + FlagProtectionChangeEvent e = new FlagProtectionChangeEvent(island, player.getUniqueId(), flag, 1000); + + wsl.onFlagChange(e); + verify(addon.getWarpSignsManager()).removeWarp(any(), any()); + } + @Test public void testOnCreateNotGameWorldNotAllowed() { when(settings.isAllowInOtherWorlds()).thenReturn(false);