From 62d8249468d37b99275d95101cf742cca3311870 Mon Sep 17 00:00:00 2001 From: tastybento Date: Tue, 8 May 2018 22:56:24 -0400 Subject: [PATCH] Added admin Make Leader command and test. Unit test passes. Not tested in-game because I'm 9930m above Chicago, it's 2858km to San Francisco, it's dark, I'm wearing sunglasses, and I have no Wi-Fi! --- locales/en-US.yml | 4 + .../bskyblock/commands/AdminCommand.java | 2 + .../teams/AdminTeamMakeLeaderCommand.java | 53 ++++- .../admin/teams/AdminTeamPromoteCommand.java | 4 - .../teams/AbstractIslandTeamCommand.java | 4 - .../teams/IslandTeamSetownerCommand.java | 27 +-- .../bskyblock/managers/IslandsManager.java | 36 +++- .../teams/AdminTeamMakeLeaderCommandTest.java | 195 ++++++++++++++++++ 8 files changed, 288 insertions(+), 37 deletions(-) delete mode 100644 src/main/java/us/tastybento/bskyblock/commands/admin/teams/AdminTeamPromoteCommand.java create mode 100644 src/test/java/us/tastybento/bskyblock/commands/admin/teams/AdminTeamMakeLeaderCommandTest.java diff --git a/locales/en-US.yml b/locales/en-US.yml index 8433e9e03..9f09181fa 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -66,6 +66,10 @@ commands: description: "kick a player from a team" cannot-kick-leader: "&cYou cannot kick the team leader. Kick members first" admin-kicked: "&cThe admin kicked you from the team." + makeleader: + parameters: "[player]" + description: "make player the team's leader" + already-leader: "&cPlayer is already the leader!" info: parameters: "" description: "get info on where you are or player's island" diff --git a/src/main/java/us/tastybento/bskyblock/commands/AdminCommand.java b/src/main/java/us/tastybento/bskyblock/commands/AdminCommand.java index 4fd21b85a..b2580e5fa 100755 --- a/src/main/java/us/tastybento/bskyblock/commands/AdminCommand.java +++ b/src/main/java/us/tastybento/bskyblock/commands/AdminCommand.java @@ -14,6 +14,7 @@ import us.tastybento.bskyblock.commands.admin.AdminVersionCommand; import us.tastybento.bskyblock.commands.admin.teams.AdminTeamAddCommand; import us.tastybento.bskyblock.commands.admin.teams.AdminTeamDisbandCommand; import us.tastybento.bskyblock.commands.admin.teams.AdminTeamKickCommand; +import us.tastybento.bskyblock.commands.admin.teams.AdminTeamMakeLeaderCommand; public class AdminCommand extends CompositeCommand { @@ -39,6 +40,7 @@ public class AdminCommand extends CompositeCommand { new AdminTeamAddCommand(this); new AdminTeamKickCommand(this); new AdminTeamDisbandCommand(this); + new AdminTeamMakeLeaderCommand(this); } @Override diff --git a/src/main/java/us/tastybento/bskyblock/commands/admin/teams/AdminTeamMakeLeaderCommand.java b/src/main/java/us/tastybento/bskyblock/commands/admin/teams/AdminTeamMakeLeaderCommand.java index a02d58bf1..0a98a247d 100644 --- a/src/main/java/us/tastybento/bskyblock/commands/admin/teams/AdminTeamMakeLeaderCommand.java +++ b/src/main/java/us/tastybento/bskyblock/commands/admin/teams/AdminTeamMakeLeaderCommand.java @@ -1,4 +1,53 @@ package us.tastybento.bskyblock.commands.admin.teams; -public class AdminTeamMakeLeaderCommand { -} +import java.util.List; +import java.util.UUID; + +import us.tastybento.bskyblock.Constants; +import us.tastybento.bskyblock.api.commands.CompositeCommand; +import us.tastybento.bskyblock.api.user.User; + +public class AdminTeamMakeLeaderCommand extends CompositeCommand { + + public AdminTeamMakeLeaderCommand(CompositeCommand parent) { + super(parent, "makeleader"); + } + + @Override + public void setup() { + setPermission(Constants.PERMPREFIX + "admin.team"); + setParameters("commands.admin.team.makeleader.parameters"); + setDescription("commands.admin.team.makeleader.description"); + } + + @Override + public boolean execute(User user, List args) { + // If args are not right, show help + if (args.size() != 1) { + showHelp(this, user); + return false; + } + // Get target + UUID targetUUID = getPlayers().getUUID(args.get(0)); + if (targetUUID == null) { + user.sendMessage("general.errors.unknown-player"); + return false; + } + if (!getIslands().hasIsland(targetUUID)) { + user.sendMessage("general.errors.no-island"); + return false; + } + if (!getIslands().inTeam(targetUUID)) { + user.sendMessage("general.errors.not-in-team"); + return false; + } + if (getIslands().getTeamLeader(targetUUID).equals(targetUUID)) { + user.sendMessage("commands.admin.team.makeleader.already-leader"); + return false; + } + // Make new leader + getIslands().makeLeader(user, targetUUID); + user.sendMessage("general.success"); + return true; + } +} \ No newline at end of file diff --git a/src/main/java/us/tastybento/bskyblock/commands/admin/teams/AdminTeamPromoteCommand.java b/src/main/java/us/tastybento/bskyblock/commands/admin/teams/AdminTeamPromoteCommand.java deleted file mode 100644 index 7a6a8ff04..000000000 --- a/src/main/java/us/tastybento/bskyblock/commands/admin/teams/AdminTeamPromoteCommand.java +++ /dev/null @@ -1,4 +0,0 @@ -package us.tastybento.bskyblock.commands.admin.teams; - -public class AdminTeamPromoteCommand { -} diff --git a/src/main/java/us/tastybento/bskyblock/commands/island/teams/AbstractIslandTeamCommand.java b/src/main/java/us/tastybento/bskyblock/commands/island/teams/AbstractIslandTeamCommand.java index 6d12c6492..ba7fb0ec5 100644 --- a/src/main/java/us/tastybento/bskyblock/commands/island/teams/AbstractIslandTeamCommand.java +++ b/src/main/java/us/tastybento/bskyblock/commands/island/teams/AbstractIslandTeamCommand.java @@ -45,8 +45,4 @@ public abstract class AbstractIslandTeamCommand extends CompositeCommand { protected int getMaxTeamSize(User user) { return Util.getPermValue(user.getPlayer(), "team.maxsize.", getSettings().getMaxTeamSize()); } - - protected int getMaxRangeSize(User user) { - return Util.getPermValue(user.getPlayer(), "island.range.", getSettings().getIslandProtectionRange()); - } } diff --git a/src/main/java/us/tastybento/bskyblock/commands/island/teams/IslandTeamSetownerCommand.java b/src/main/java/us/tastybento/bskyblock/commands/island/teams/IslandTeamSetownerCommand.java index 4a770c0b5..96ea8a3ce 100644 --- a/src/main/java/us/tastybento/bskyblock/commands/island/teams/IslandTeamSetownerCommand.java +++ b/src/main/java/us/tastybento/bskyblock/commands/island/teams/IslandTeamSetownerCommand.java @@ -11,7 +11,6 @@ import us.tastybento.bskyblock.api.commands.CompositeCommand; import us.tastybento.bskyblock.api.events.IslandBaseEvent; import us.tastybento.bskyblock.api.events.team.TeamEvent; import us.tastybento.bskyblock.api.user.User; -import us.tastybento.bskyblock.database.objects.Island; import us.tastybento.bskyblock.util.Util; public class IslandTeamSetownerCommand extends AbstractIslandTeamCommand { @@ -71,35 +70,11 @@ public class IslandTeamSetownerCommand extends AbstractIslandTeamCommand { if (event.isCancelled()) { return false; } - makeLeader(user, targetUUID); - + getIslands().makeLeader(user, targetUUID); getIslands().save(true); return true; } - private void makeLeader(User user, UUID targetUUID) { - // target is the new leader - Island island = getIslands().getIsland(user.getUniqueId()); - island.setOwner(targetUUID); - user.sendMessage("commands.island.team.setowner.name-is-the-owner", "[name]", getPlayers().getName(targetUUID)); - - // Check if online - User target = User.getInstance(targetUUID); - target.sendMessage("commands.island.team.setowner.you-are-the-owner"); - if (target.isOnline()) { - // Check if new leader has a lower range permission than the island size - int range = getMaxRangeSize(user); - // Range can go up or down - if (range != island.getProtectionRange()) { - user.sendMessage("commands.admin.setrange.range-updated", "[number]", String.valueOf(range)); - target.sendMessage("commands.admin.setrange.range-updated", "[number]", String.valueOf(range)); - getPlugin().log("Makeleader: Island protection range changed from " + island.getProtectionRange() + " to " - + range + " for " + user.getName() + " due to permission."); - } - island.setProtectionRange(range); - - } - } @Override public Optional> tabComplete(final User user, final String alias, final LinkedList args) { diff --git a/src/main/java/us/tastybento/bskyblock/managers/IslandsManager.java b/src/main/java/us/tastybento/bskyblock/managers/IslandsManager.java index 8c2f44d6c..eed74dc16 100644 --- a/src/main/java/us/tastybento/bskyblock/managers/IslandsManager.java +++ b/src/main/java/us/tastybento/bskyblock/managers/IslandsManager.java @@ -66,7 +66,7 @@ public class IslandsManager { if (space1.isLiquid() && space2.isLiquid()) { return false; } - + // Portals are not "safe" if (space1.getType() == Material.PORTAL || ground.getType() == Material.PORTAL || space2.getType() == Material.PORTAL || space1.getType() == Material.ENDER_PORTAL || ground.getType() == Material.ENDER_PORTAL || space2.getType() == Material.ENDER_PORTAL) { @@ -817,4 +817,38 @@ public class IslandsManager { public boolean inTeam(UUID playerUUID) { return getMembers(playerUUID).size() > 1; } + + /** + * Makes a new leader for an island + * @param user - the user who is issuing the command + * @param targetUUID - the current island member who is going to become the leader + */ + public void makeLeader(User user, UUID targetUUID) { + // target is the new leader + Island island = getIsland(user.getUniqueId()); + island.setOwner(targetUUID); + user.sendMessage("commands.island.team.setowner.name-is-the-owner", "[name]", plugin.getPlayers().getName(targetUUID)); + + // Check if online + User target = User.getInstance(targetUUID); + target.sendMessage("commands.island.team.setowner.you-are-the-owner"); + if (target.isOnline()) { + // Check if new leader has a different range permission than the island size + int range = getMaxRangeSize(target); + // Range can go up or down + if (range != island.getProtectionRange()) { + user.sendMessage("commands.admin.setrange.range-updated", "[number]", String.valueOf(range)); + target.sendMessage("commands.admin.setrange.range-updated", "[number]", String.valueOf(range)); + plugin.log("Makeleader: Island protection range changed from " + island.getProtectionRange() + " to " + + range + " for " + user.getName() + " due to permission."); + } + island.setProtectionRange(range); + + } + } + + private int getMaxRangeSize(User user) { + return Util.getPermValue(user.getPlayer(), "island.range.", plugin.getSettings().getIslandProtectionRange()); + } + } diff --git a/src/test/java/us/tastybento/bskyblock/commands/admin/teams/AdminTeamMakeLeaderCommandTest.java b/src/test/java/us/tastybento/bskyblock/commands/admin/teams/AdminTeamMakeLeaderCommandTest.java new file mode 100644 index 000000000..f3b9551cf --- /dev/null +++ b/src/test/java/us/tastybento/bskyblock/commands/admin/teams/AdminTeamMakeLeaderCommandTest.java @@ -0,0 +1,195 @@ +package us.tastybento.bskyblock.commands.admin.teams; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; + +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +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.user.User; +import us.tastybento.bskyblock.commands.AdminCommand; +import us.tastybento.bskyblock.database.objects.Island; +import us.tastybento.bskyblock.managers.CommandsManager; +import us.tastybento.bskyblock.managers.IslandsManager; +import us.tastybento.bskyblock.managers.LocalesManager; +import us.tastybento.bskyblock.managers.PlayersManager; + +/** + * @author tastybento + * + */ +@RunWith(PowerMockRunner.class) +@PrepareForTest({Bukkit.class, BSkyBlock.class, User.class }) +public class AdminTeamMakeLeaderCommandTest { + + private BSkyBlock plugin; + private AdminCommand ac; + private UUID uuid; + private User user; + private Settings s; + private IslandsManager im; + private PlayersManager pm; + private UUID notUUID; + + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() throws Exception { + // Set up plugin + plugin = mock(BSkyBlock.class); + Whitebox.setInternalState(BSkyBlock.class, "instance", plugin); + + // Command manager + CommandsManager cm = mock(CommandsManager.class); + when(plugin.getCommandsManager()).thenReturn(cm); + + // 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); + when(user.isOp()).thenReturn(false); + uuid = UUID.randomUUID(); + notUUID = UUID.randomUUID(); + while(notUUID.equals(uuid)) { + notUUID = UUID.randomUUID(); + } + when(user.getUniqueId()).thenReturn(uuid); + when(user.getPlayer()).thenReturn(p); + when(user.getName()).thenReturn("tastybento"); + User.setPlugin(plugin); + + // Parent command has no aliases + ac = mock(AdminCommand.class); + when(ac.getSubCommandAliases()).thenReturn(new HashMap<>()); + + // Player has island to begin with + im = mock(IslandsManager.class); + when(im.hasIsland(Mockito.any())).thenReturn(true); + when(im.isOwner(Mockito.any())).thenReturn(true); + when(im.getTeamLeader(Mockito.any())).thenReturn(uuid); + when(plugin.getIslands()).thenReturn(im); + + // Has team + pm = mock(PlayersManager.class); + when(im.inTeam(Mockito.eq(uuid))).thenReturn(true); + + when(plugin.getPlayers()).thenReturn(pm); + + // Server & Scheduler + BukkitScheduler sch = mock(BukkitScheduler.class); + PowerMockito.mockStatic(Bukkit.class); + when(Bukkit.getScheduler()).thenReturn(sch); + + // Locales + LocalesManager lm = mock(LocalesManager.class); + when(lm.get(Mockito.any(), Mockito.any())).thenReturn("mock translation"); + when(plugin.getLocalesManager()).thenReturn(lm); + } + + + /** + * Test method for {@link us.tastybento.bskyblock.commands.admin.teams.AdminTeamMakeLeaderCommand#execute(us.tastybento.bskyblock.api.user.User, java.util.List)}. + */ + @Test + public void testExecuteNoTarget() { + AdminTeamMakeLeaderCommand itl = new AdminTeamMakeLeaderCommand(ac); + assertFalse(itl.execute(user, new ArrayList<>())); + // Show help + } + + /** + * Test method for {@link us.tastybento.bskyblock.commands.admin.teams.AdminTeamMakeLeaderCommand#execute(us.tastybento.bskyblock.api.user.User, java.util.List)}. + */ + @Test + public void testExecuteUnknownPlayer() { + AdminTeamMakeLeaderCommand itl = new AdminTeamMakeLeaderCommand(ac); + String[] name = {"tastybento"}; + when(pm.getUUID(Mockito.any())).thenReturn(null); + assertFalse(itl.execute(user, Arrays.asList(name))); + Mockito.verify(user).sendMessage(Mockito.eq("general.errors.unknown-player")); + } + + /** + * Test method for {@link us.tastybento.bskyblock.commands.admin.teams.AdminTeamMakeLeaderCommand#execute(us.tastybento.bskyblock.api.user.User, java.util.List)}. + */ + @Test + public void testExecutePlayerNotInTeam() { + AdminTeamMakeLeaderCommand itl = new AdminTeamMakeLeaderCommand(ac); + String[] name = {"tastybento"}; + when(pm.getUUID(Mockito.any())).thenReturn(notUUID); + when(im.getMembers(Mockito.any())).thenReturn(new HashSet<>()); + assertFalse(itl.execute(user, Arrays.asList(name))); + Mockito.verify(user).sendMessage(Mockito.eq("general.errors.not-in-team")); + } + + /** + * Test method for {@link us.tastybento.bskyblock.commands.admin.teams.AdminTeamMakeLeaderCommand#execute(us.tastybento.bskyblock.api.user.User, java.util.List)}. + */ + @Test + public void testExecuteMakeLeaderAlreadyLeader() { + when(im.inTeam(Mockito.any())).thenReturn(true); + Island is = mock(Island.class); + when(im.getIsland(Mockito.any())).thenReturn(is); + String[] name = {"tastybento"}; + when(pm.getUUID(Mockito.any())).thenReturn(notUUID); + + when(im.getTeamLeader(notUUID)).thenReturn(notUUID); + + AdminTeamMakeLeaderCommand itl = new AdminTeamMakeLeaderCommand(ac); + assertFalse(itl.execute(user, Arrays.asList(name))); + Mockito.verify(user).sendMessage("commands.admin.team.makeleader.already-leader"); + } + + /** + * Test method for {@link us.us.tastybento.bskyblock.commands.admin.teams.AdminTeamMakeLeaderCommand#execute(us.tastybento.bskyblock.api.user.User, java.util.List)}. + */ + @Test + public void testExecuteSuccess() { + when(im.inTeam(Mockito.any())).thenReturn(true); + Island is = mock(Island.class); + when(im.getIsland(Mockito.any())).thenReturn(is); + String[] name = {"tastybento"}; + when(pm.getUUID(Mockito.any())).thenReturn(notUUID); + // Leader + when(im.getTeamLeader(notUUID)).thenReturn(uuid); + when(pm.getName(Mockito.eq(uuid))).thenReturn("leader"); + // Members + Set members = new HashSet<>(); + members.add(uuid); + members.add(notUUID); + when(im.getMembers(Mockito.any())).thenReturn(members); + + AdminTeamMakeLeaderCommand itl = new AdminTeamMakeLeaderCommand(ac); + assertTrue(itl.execute(user, Arrays.asList(name))); + // Add other verifications + Mockito.verify(im).makeLeader(user, notUUID); + Mockito.verify(user).sendMessage(Mockito.eq("general.success")); + } + +}