diff --git a/locales/en-US.yml b/locales/en-US.yml index 8d3ae390f..65fbdc99f 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -35,6 +35,7 @@ general: warp-not-safe: "&cThat warp is not safe right now!" wrong-world: "&cYou are not in the right world to do that!" you-must-wait: "&cYou must wait [seconds]s before you can do that command again" + you-need: "&cYou need [permission]" tips: changing-obsidian-to-lava: "Changing obsidian back into lava. Be careful!" @@ -163,9 +164,13 @@ commands: cannot-ban: "&cThat player cannot be banned." cannot-ban-member: "&cKick the team member first, then ban." player-already-banned: "&cPlayer is already banned" + you-are-banned: "&b[owner]&c banned you from their island!" unban: description: "unban a player from your island" parameters: "" + cannot-unban-yourself: "&cYou cannot unban yourself!" + player-not-banned: "&cPlayer is not banned" + you-are-unbanned: "&b[owner]&a unbanned you from their island!" banlist: description: "list banned players" lock: diff --git a/src/main/java/us/tastybento/bskyblock/api/commands/CompositeCommand.java b/src/main/java/us/tastybento/bskyblock/api/commands/CompositeCommand.java index 1e918da33..97e5855ff 100644 --- a/src/main/java/us/tastybento/bskyblock/api/commands/CompositeCommand.java +++ b/src/main/java/us/tastybento/bskyblock/api/commands/CompositeCommand.java @@ -154,7 +154,7 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi // Check perms, but only if this isn't the console if ((sender instanceof Player) && !sender.isOp() && !cmd.getPermission().isEmpty() && !sender.hasPermission(cmd.getPermission())) { user.sendMessage("general.errors.no-permission"); - user.sendRawMessage("You need " + cmd.getPermission()); + user.sendMessage("general.errors.you-need", "[permission]", cmd.getPermission()); return true; } // Fire an event to see if this command should be cancelled diff --git a/src/main/java/us/tastybento/bskyblock/api/user/User.java b/src/main/java/us/tastybento/bskyblock/api/user/User.java index 8fe44d1b7..97ab1b4b9 100644 --- a/src/main/java/us/tastybento/bskyblock/api/user/User.java +++ b/src/main/java/us/tastybento/bskyblock/api/user/User.java @@ -105,7 +105,7 @@ public class User { private User(UUID playerUUID) { player = Bukkit.getPlayer(playerUUID); this.playerUUID = playerUUID; - sender = null; + sender = player; } /** diff --git a/src/main/java/us/tastybento/bskyblock/commands/IslandCommand.java b/src/main/java/us/tastybento/bskyblock/commands/IslandCommand.java index e3f3a0d55..af550e67f 100755 --- a/src/main/java/us/tastybento/bskyblock/commands/IslandCommand.java +++ b/src/main/java/us/tastybento/bskyblock/commands/IslandCommand.java @@ -7,6 +7,7 @@ import us.tastybento.bskyblock.Constants; import us.tastybento.bskyblock.api.commands.CompositeCommand; import us.tastybento.bskyblock.api.user.User; import us.tastybento.bskyblock.commands.island.IslandAboutCommand; +import us.tastybento.bskyblock.commands.island.IslandBanCommand; import us.tastybento.bskyblock.commands.island.IslandCreateCommand; import us.tastybento.bskyblock.commands.island.IslandGoCommand; import us.tastybento.bskyblock.commands.island.IslandLanguageCommand; @@ -15,6 +16,7 @@ import us.tastybento.bskyblock.commands.island.IslandResetnameCommand; import us.tastybento.bskyblock.commands.island.IslandSethomeCommand; import us.tastybento.bskyblock.commands.island.IslandSetnameCommand; import us.tastybento.bskyblock.commands.island.IslandSettingsCommand; +import us.tastybento.bskyblock.commands.island.IslandUnbanCommand; import us.tastybento.bskyblock.commands.island.teams.IslandTeamCommand; public class IslandCommand extends CompositeCommand { @@ -42,6 +44,8 @@ public class IslandCommand extends CompositeCommand { new IslandSethomeCommand(this); new IslandSettingsCommand(this); new IslandLanguageCommand(this); + new IslandBanCommand(this); + new IslandUnbanCommand(this); // Team commands new IslandTeamCommand(this); } diff --git a/src/main/java/us/tastybento/bskyblock/commands/island/IslandBanCommand.java b/src/main/java/us/tastybento/bskyblock/commands/island/IslandBanCommand.java index 0bf53951b..ffb9248ff 100644 --- a/src/main/java/us/tastybento/bskyblock/commands/island/IslandBanCommand.java +++ b/src/main/java/us/tastybento/bskyblock/commands/island/IslandBanCommand.java @@ -1,11 +1,19 @@ package us.tastybento.bskyblock.commands.island; +import java.util.LinkedList; import java.util.List; +import java.util.Optional; import java.util.UUID; +import java.util.stream.Collectors; + +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; import us.tastybento.bskyblock.Constants; import us.tastybento.bskyblock.api.commands.CompositeCommand; import us.tastybento.bskyblock.api.user.User; +import us.tastybento.bskyblock.database.objects.Island; +import us.tastybento.bskyblock.util.Util; public class IslandBanCommand extends CompositeCommand { @@ -17,16 +25,17 @@ public class IslandBanCommand extends CompositeCommand { public void setup() { setPermission(Constants.PERMPREFIX + "island.ban"); setOnlyPlayer(true); - setParameters("command.island.ban.parameters"); + setParameters("commands.island.ban.parameters"); setDescription("commands.island.ban.description"); } @Override public boolean execute(User user, List args) { if (args.size() != 1) { + // Show help showHelp(this, user); return false; - } + } UUID playerUUID = user.getUniqueId(); // Player issuing the command must have an island if (!getIslands().hasIsland(playerUUID)) { @@ -37,54 +46,61 @@ public class IslandBanCommand extends CompositeCommand { user.sendMessage("general.errors.not-leader"); return false; } - if (args.isEmpty() || args.size() > 1) { - // Show help - showHelp(this, user); + // Get target player + UUID targetUUID = getPlayers().getUUID(args.get(0)); + if (targetUUID == null) { + user.sendMessage("general.errors.unknown-player"); return false; - } else { - // Get target player - UUID targetUUID = getPlayers().getUUID(args.get(0)); - if (targetUUID == null) { - user.sendMessage("general.errors.unknown-player"); - return false; - } - // Player cannot ban themselves - if (playerUUID.equals(targetUUID)) { - user.sendMessage("commands.island.ban.cannot-ban-yourself"); - return false; - } - if (getIslands().getMembers(user.getUniqueId()).contains(targetUUID)) { - user.sendMessage("commands.island.ban.cannot-ban-member"); - return false; - } - if (getIslands().getIsland(playerUUID).isBanned(targetUUID)) { - user.sendMessage("commands.island.ban.player-already-banned"); - return false; - } - User target = User.getInstance(targetUUID); - // Cannot ban ops - if (!target.isPlayer() || target.isOp()) { - user.sendMessage("commands.island.ban.cannot-ban"); - return false; - } - - User targetUser = User.getInstance(targetUUID); - // Finished error checking - start the banning - if (getIslands().getIsland(playerUUID).addToBanList(targetUUID)) { - user.sendMessage("general.success"); - targetUser.sendMessage("commands.island.ban.you-are-banned", "[owner]", user.getName()); - if (target.isOnline()) { - // Remove from island - if (getPlayers().hasIsland(targetUUID)) { - getIslands().homeTeleport(target.getPlayer()); - } - // TODO else if there is a spawn, send them there - } - return true; - } - // Banning was blocked, maybe due to an event cancellation. Fail silently. } + // Player cannot ban themselves + if (playerUUID.equals(targetUUID)) { + user.sendMessage("commands.island.ban.cannot-ban-yourself"); + return false; + } + if (getIslands().getMembers(user.getUniqueId()).contains(targetUUID)) { + user.sendMessage("commands.island.ban.cannot-ban-member"); + return false; + } + if (getIslands().getIsland(playerUUID).isBanned(targetUUID)) { + user.sendMessage("commands.island.ban.player-already-banned"); + return false; + } + User target = User.getInstance(targetUUID); + // Cannot ban ops + if (!target.isPlayer() || target.isOp()) { + user.sendMessage("commands.island.ban.cannot-ban"); + return false; + } + // Finished error checking - start the banning + return ban(user, target); + } + + private boolean ban(User user, User targetUser) { + if (getIslands().getIsland(user.getUniqueId()).addToBanList(targetUser.getUniqueId())) { + user.sendMessage("general.success"); + targetUser.sendMessage("commands.island.ban.you-are-banned", "[owner]", user.getName()); + if (targetUser.isOnline() && getPlayers().hasIsland(targetUser.getUniqueId())) { + getIslands().homeTeleport(targetUser.getPlayer()); + } + return true; + } + // Banning was blocked, maybe due to an event cancellation. Fail silently. return false; } + @Override + public Optional> tabComplete(final User user, final String alias, final LinkedList args) { + if (args.isEmpty()) { + // Don't show every player on the server. Require at least the first letter + return Optional.empty(); + } + Island island = getIslands().getIsland(user.getUniqueId()); + List options = Bukkit.getOnlinePlayers().stream() + .filter(p -> !p.getUniqueId().equals(user.getUniqueId())) + .filter(p -> !island.isBanned(p.getUniqueId())) + .filter(p -> user.getPlayer().canSee(p)) + .map(Player::getName).collect(Collectors.toList()); + String lastArg = (!args.isEmpty() ? args.getLast() : ""); + return Optional.of(Util.tabLimit(options, lastArg)); + } } diff --git a/src/main/java/us/tastybento/bskyblock/commands/island/IslandResetCommand.java b/src/main/java/us/tastybento/bskyblock/commands/island/IslandResetCommand.java index 350029771..669301269 100644 --- a/src/main/java/us/tastybento/bskyblock/commands/island/IslandResetCommand.java +++ b/src/main/java/us/tastybento/bskyblock/commands/island/IslandResetCommand.java @@ -64,60 +64,70 @@ public class IslandResetCommand extends CompositeCommand { } } // Check for non-confirm command - if (args.size() > 0 && !(confirm.containsKey(user.getUniqueId()) && args.get(0).equalsIgnoreCase("confirm"))) { + if (!args.isEmpty() && !(confirm.containsKey(user.getUniqueId()) && args.get(0).equalsIgnoreCase("confirm"))) { showHelp(this, user); return false; } // Check confirmation or reset immediately if no confirmation required if (!getSettings().isResetConfirmation() || (confirm.containsKey(user.getUniqueId()) && args.size() == 1 && args.get(0).equalsIgnoreCase("confirm"))) { - // Remove the confirmation - confirm.remove(user.getUniqueId()); - // Reset the island - Player player = user.getPlayer(); - player.setGameMode(GameMode.SPECTATOR); - // Get the player's old island - Island oldIsland = getIslands().getIsland(player.getUniqueId()); - // Remove them from this island (it still exists and will be deleted later) - getIslands().removePlayer(player.getUniqueId()); - // Create new island and then delete the old one - try { - NewIsland.builder() - .player(player) - .reason(Reason.RESET) - .oldIsland(oldIsland) - .build(); - } catch (IOException e) { - getPlugin().logError("Could not create island for player. " + e.getMessage()); - user.sendMessage("commands.island.create.unable-create-island"); - } - setCooldown(user); - return true; + return resetIsland(user); } // Confirmation required if (!confirm.containsKey(user.getUniqueId())) { - user.sendMessage("commands.island.reset.confirm", "[label]", Constants.ISLANDCOMMAND, "[seconds]", String.valueOf(getSettings().getConfirmationTime())); - // Require confirmation - confirm.put(user.getUniqueId(), System.currentTimeMillis() + getSettings().getConfirmationTime() * 1000L); - Bukkit.getScheduler().runTaskLater(getPlugin(), () -> { - if (confirm.containsKey(user.getUniqueId())) { - user.sendMessage("commands.island.reset.cancelled"); - confirm.remove(user.getUniqueId()); - } - }, getSettings().getConfirmationTime() * 20L); + requestConfirmation(user); } else { + // Show how many seconds left to confirm int time = (int)((confirm.get(user.getUniqueId()) - System.currentTimeMillis()) / 1000D); user.sendMessage("commands.island.reset.confirm", "[label]", Constants.ISLANDCOMMAND, "[seconds]", String.valueOf(time)); } return true; } + private void requestConfirmation(User user) { + user.sendMessage("commands.island.reset.confirm", "[label]", Constants.ISLANDCOMMAND, "[seconds]", String.valueOf(getSettings().getConfirmationTime())); + // Require confirmation + confirm.put(user.getUniqueId(), System.currentTimeMillis() + getSettings().getConfirmationTime() * 1000L); + Bukkit.getScheduler().runTaskLater(getPlugin(), () -> { + if (confirm.containsKey(user.getUniqueId())) { + user.sendMessage("commands.island.reset.cancelled"); + confirm.remove(user.getUniqueId()); + } + }, getSettings().getConfirmationTime() * 20L); + } + + private boolean resetIsland(User user) { + // Remove the confirmation + confirm.remove(user.getUniqueId()); + // Reset the island + Player player = user.getPlayer(); + player.setGameMode(GameMode.SPECTATOR); + // Get the player's old island + Island oldIsland = getIslands().getIsland(player.getUniqueId()); + // Remove them from this island (it still exists and will be deleted later) + getIslands().removePlayer(player.getUniqueId()); + // Create new island and then delete the old one + try { + NewIsland.builder() + .player(player) + .reason(Reason.RESET) + .oldIsland(oldIsland) + .build(); + } catch (IOException e) { + getPlugin().logError("Could not create island for player. " + e.getMessage()); + user.sendMessage("commands.island.create.unable-create-island"); + return false; + } + setCooldown(user); + return true; + } + private int onRestartWaitTime(User user) { if (!cooldown.containsKey(user.getUniqueId())) { return 0; } - return (int) ((System.currentTimeMillis() - cooldown.get(user.getUniqueId()) / 1000)); + return (int) (System.currentTimeMillis() - cooldown.get(user.getUniqueId()) / 1000); } private void setCooldown(User user) { diff --git a/src/main/java/us/tastybento/bskyblock/commands/island/IslandUnbanCommand.java b/src/main/java/us/tastybento/bskyblock/commands/island/IslandUnbanCommand.java index 5b37ea01f..f3103920b 100644 --- a/src/main/java/us/tastybento/bskyblock/commands/island/IslandUnbanCommand.java +++ b/src/main/java/us/tastybento/bskyblock/commands/island/IslandUnbanCommand.java @@ -1,4 +1,83 @@ package us.tastybento.bskyblock.commands.island; -public class IslandUnbanCommand { +import java.util.LinkedList; +import java.util.List; +import java.util.Optional; +import java.util.UUID; +import java.util.stream.Collectors; + +import us.tastybento.bskyblock.Constants; +import us.tastybento.bskyblock.api.commands.CompositeCommand; +import us.tastybento.bskyblock.api.user.User; +import us.tastybento.bskyblock.database.objects.Island; +import us.tastybento.bskyblock.util.Util; + +public class IslandUnbanCommand extends CompositeCommand { + + public IslandUnbanCommand(CompositeCommand islandCommand) { + super(islandCommand, "unban"); + } + + @Override + public void setup() { + setPermission(Constants.PERMPREFIX + "island.ban"); + setOnlyPlayer(true); + setParameters("commands.island.unban.parameters"); + setDescription("commands.island.unban.description"); + } + + @Override + public boolean execute(User user, List args) { + if (args.size() != 1) { + // Show help + showHelp(this, user); + return false; + } + UUID playerUUID = user.getUniqueId(); + // Player issuing the command must have an island + if (!getIslands().hasIsland(playerUUID)) { + user.sendMessage("general.errors.no-island"); + return false; + } + if (!getIslands().isOwner(playerUUID)) { + user.sendMessage("general.errors.not-leader"); + return false; + } + // Get target player + UUID targetUUID = getPlayers().getUUID(args.get(0)); + if (targetUUID == null) { + user.sendMessage("general.errors.unknown-player"); + return false; + } + // Player cannot unban themselves + if (playerUUID.equals(targetUUID)) { + user.sendMessage("commands.island.unban.cannot-unban-yourself"); + return false; + } + if (!getIslands().getIsland(playerUUID).isBanned(targetUUID)) { + user.sendMessage("commands.island.unban.player-not-banned"); + return false; + } + // Finished error checking - start the unbanning + User targetUser = User.getInstance(targetUUID); + return unban(user, targetUser); + } + + private boolean unban(User user, User targetUser) { + if (getIslands().getIsland(user.getUniqueId()).removeFromBanList(targetUser.getUniqueId())) { + user.sendMessage("general.success"); + targetUser.sendMessage("commands.island.unban.you-are-unbanned", "[owner]", user.getName()); + return true; + } + // Unbanning was blocked, maybe due to an event cancellation. Fail silently. + return false; + } + + @Override + public Optional> tabComplete(final User user, final String alias, final LinkedList args) { + Island island = getIslands().getIsland(user.getUniqueId()); + List options = island.getBanned().stream().map(getPlayers()::getName).collect(Collectors.toList()); + String lastArg = (!args.isEmpty() ? args.getLast() : ""); + return Optional.of(Util.tabLimit(options, lastArg)); + } } diff --git a/src/main/java/us/tastybento/bskyblock/managers/island/NewIsland.java b/src/main/java/us/tastybento/bskyblock/managers/island/NewIsland.java index 6cea68e01..4b1310c44 100644 --- a/src/main/java/us/tastybento/bskyblock/managers/island/NewIsland.java +++ b/src/main/java/us/tastybento/bskyblock/managers/island/NewIsland.java @@ -168,8 +168,6 @@ public class NewIsland { while (plugin.getIslands().isIsland(next)) { next = nextGridLocation(next); } - // Make the last next, last - last = next.clone(); return next; } diff --git a/src/test/java/us/tastybento/bskyblock/commands/island/IslandBanCommandTest.java b/src/test/java/us/tastybento/bskyblock/commands/island/IslandBanCommandTest.java index 91d2d8e07..689761c05 100644 --- a/src/test/java/us/tastybento/bskyblock/commands/island/IslandBanCommandTest.java +++ b/src/test/java/us/tastybento/bskyblock/commands/island/IslandBanCommandTest.java @@ -12,8 +12,13 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Optional; import java.util.Set; import java.util.UUID; +import java.util.stream.Collectors; import org.bukkit.Bukkit; import org.bukkit.entity.Player; @@ -22,6 +27,8 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mockito; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; @@ -122,14 +129,11 @@ public class IslandBanCommandTest { // Ban self // Ban team mate // Ban someone you have already banned - // Unban someone not banned // Ban an Op // *** Working conditions *** // Ban offline user // Ban online user - // Unban offline user - // Unban online user @Test public void testNoArgs() { @@ -279,4 +283,105 @@ public class IslandBanCommandTest { Mockito.verify(targetUser, Mockito.never()).sendMessage("commands.island.ban.you-are-banned", "[owner]", user.getName()); } + @Test + public void testTabComplete() { + + String[] names = {"adam", "ben", "cara", "dave", "ed", "frank", "freddy", "george", "harry", "ian", "joe"}; + Map online = new HashMap<>(); + + Set banned = new HashSet<>(); + Set onlinePlayers = new HashSet<>(); + for (int j = 0; j < names.length; j++) { + Player p = mock(Player.class); + UUID uuid = UUID.randomUUID(); + when(p.getUniqueId()).thenReturn(uuid); + when(p.getName()).thenReturn(names[j]); + online.put(uuid, names[j]); + // Ban the first 3 players + if (j < 3) { + banned.add(uuid); + } + onlinePlayers.add(p); + } + + when(island.isBanned(Mockito.any(UUID.class))).thenAnswer(new Answer() { + + @Override + public Boolean answer(InvocationOnMock invocation) throws Throwable { + return banned.contains(invocation.getArgumentAt(0, UUID.class)); + } + + }); + // Create the names + when(pm.getName(Mockito.any(UUID.class))).then(new Answer() { + + @Override + public String answer(InvocationOnMock invocation) throws Throwable { + return online.getOrDefault(invocation.getArgumentAt(0, UUID.class), "tastybento"); + } + + }); + + // Return a set of online players + PowerMockito.mockStatic(Bukkit.class); + when(Bukkit.getOnlinePlayers()).then(new Answer>() { + + @Override + public Set answer(InvocationOnMock invocation) throws Throwable { + return onlinePlayers; + } + + }); + + IslandBanCommand ibc = new IslandBanCommand(ic); + // Set up the user + User user = mock(User.class); + when(user.getUniqueId()).thenReturn(UUID.randomUUID()); + Player player = mock(Player.class); + // Player can see every other player except Ian + when(player.canSee(Mockito.any(Player.class))).thenAnswer(new Answer() { + + @Override + public Boolean answer(InvocationOnMock invocation) throws Throwable { + Player p = invocation.getArgumentAt(0, Player.class); + return p.getName().equals("ian") ? false : true; + } + + }); + when(user.getPlayer()).thenReturn(player); + + // Get the tab-complete list with no argument + Optional> result = ibc.tabComplete(user, "", new LinkedList<>()); + assertFalse(result.isPresent()); + + // Get the tab-complete list with one argument + LinkedList args = new LinkedList<>(); + args.add(""); + result = ibc.tabComplete(user, "", args); + assertTrue(result.isPresent()); + List r = result.get().stream().sorted().collect(Collectors.toList()); + // Compare the expected with the actual + String[] expectedNames = {"dave", "ed", "frank", "freddy", "george", "harry", "joe"}; + assertTrue(Arrays.equals(expectedNames, r.toArray())); + + // Get the tab-complete list with one letter argument + args = new LinkedList<>(); + args.add("d"); + result = ibc.tabComplete(user, "", args); + assertTrue(result.isPresent()); + r = result.get().stream().sorted().collect(Collectors.toList()); + // Compare the expected with the actual + String[] expectedName = {"dave"}; + assertTrue(Arrays.equals(expectedName, r.toArray())); + + // Get the tab-complete list with one letter argument + args = new LinkedList<>(); + args.add("fr"); + result = ibc.tabComplete(user, "", args); + assertTrue(result.isPresent()); + r = result.get().stream().sorted().collect(Collectors.toList()); + // Compare the expected with the actual + String[] expected = {"frank", "freddy"}; + assertTrue(Arrays.equals(expected, r.toArray())); + } } diff --git a/src/test/java/us/tastybento/bskyblock/commands/island/IslandResetCommandTest.java b/src/test/java/us/tastybento/bskyblock/commands/island/IslandResetCommandTest.java index c167d4e96..a03a8f75c 100644 --- a/src/test/java/us/tastybento/bskyblock/commands/island/IslandResetCommandTest.java +++ b/src/test/java/us/tastybento/bskyblock/commands/island/IslandResetCommandTest.java @@ -279,4 +279,41 @@ public class IslandResetCommandTest { Mockito.verify(builder).build(); } + + @Test + public void testNewIslandError() throws IOException { + IslandResetCommand irc = new IslandResetCommand(ic); + // Now has island, but is not the leader + when(im.hasIsland(Mockito.eq(uuid))).thenReturn(true); + // Now is owner, but still has team + when(im.isOwner(Mockito.eq(uuid))).thenReturn(true); + // Now has no team + when(pm.inTeam(Mockito.eq(uuid))).thenReturn(false); + // Give the user some resets + when(pm.getResetsLeft(Mockito.eq(uuid))).thenReturn(1); + // Set so no confirmation required + when(s.isResetConfirmation()).thenReturn(false); + + // Old island mock + Island oldIsland = mock(Island.class); + when(im.getIsland(Mockito.eq(uuid))).thenReturn(oldIsland); + + // Mock up NewIsland builder + NewIsland.Builder builder = mock(NewIsland.Builder.class); + when(builder.player(Mockito.any())).thenReturn(builder); + when(builder.oldIsland(Mockito.any())).thenReturn(builder); + when(builder.reason(Mockito.any())).thenReturn(builder); + when(builder.build()).thenThrow(new IOException()); + PowerMockito.mockStatic(NewIsland.class); + when(NewIsland.builder()).thenReturn(builder); + + // Require no confirmation + when(s.isResetConfirmation()).thenReturn(false); + + // Reset + assertFalse(irc.execute(user, new ArrayList<>())); + Mockito.verify(user).sendMessage("commands.island.create.unable-create-island"); + + + } } diff --git a/src/test/java/us/tastybento/bskyblock/commands/island/IslandUnbanCommandTest.java b/src/test/java/us/tastybento/bskyblock/commands/island/IslandUnbanCommandTest.java new file mode 100644 index 000000000..82cd28962 --- /dev/null +++ b/src/test/java/us/tastybento/bskyblock/commands/island/IslandUnbanCommandTest.java @@ -0,0 +1,249 @@ +/** + * + */ +package us.tastybento.bskyblock.commands.island; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +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.LinkedList; +import java.util.List; +import java.util.Optional; +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.IslandCommand; +import us.tastybento.bskyblock.database.objects.Island; +import us.tastybento.bskyblock.managers.CommandsManager; +import us.tastybento.bskyblock.managers.IslandsManager; +import us.tastybento.bskyblock.managers.PlayersManager; + +/** + * @author tastybento + * + */ +@RunWith(PowerMockRunner.class) +@PrepareForTest({Bukkit.class, BSkyBlock.class, User.class }) +public class IslandUnbanCommandTest { + + private BSkyBlock plugin; + private IslandCommand ic; + private UUID uuid; + private User user; + private Settings s; + private IslandsManager im; + private PlayersManager pm; + private Island island; + + /** + * @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(); + when(user.getUniqueId()).thenReturn(uuid); + when(user.getPlayer()).thenReturn(p); + when(user.getName()).thenReturn("tastybento"); + + // Parent command has no aliases + ic = mock(IslandCommand.class); + when(ic.getSubCommandAliases()).thenReturn(new HashMap<>()); + + // 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 + BukkitScheduler sch = mock(BukkitScheduler.class); + PowerMockito.mockStatic(Bukkit.class); + when(Bukkit.getScheduler()).thenReturn(sch); + + // Island Banned list initialization + island = mock(Island.class); + when(island.getBanned()).thenReturn(new HashSet<>()); + when(island.isBanned(Mockito.any())).thenReturn(false); + when(im.getIsland(Mockito.any(UUID.class))).thenReturn(island); + + } + + /** + * Test method for {@link us.tastybento.bskyblock.commands.island.IslandUnbanCommand#execute(us.tastybento.bskyblock.api.user.User, java.util.List)}. + */ + // Island ban command by itself + + // *** Error conditions *** + // Unban without an island + // Unban as not a team leader + // Unban unknown user + // Unban self + // Unban someone not banned + + // *** Working conditions *** + // Unban user + + @Test + public void testNoArgs() { + IslandUnbanCommand iubc = new IslandUnbanCommand(ic); + assertFalse(iubc.execute(user, new ArrayList<>())); + } + + @Test + public void testNoIsland() { + IslandUnbanCommand iubc = new IslandUnbanCommand(ic); + assertFalse(iubc.execute(user, Arrays.asList("bill"))); + Mockito.verify(user).sendMessage("general.errors.no-island"); + } + + @Test + public void testNotOwner() { + IslandUnbanCommand iubc = new IslandUnbanCommand(ic); + when(im.hasIsland(Mockito.eq(uuid))).thenReturn(true); + assertFalse(iubc.execute(user, Arrays.asList("bill"))); + Mockito.verify(user).sendMessage("general.errors.not-leader"); + } + + @Test + public void testUnknownUser() { + IslandUnbanCommand iubc = new IslandUnbanCommand(ic); + when(im.hasIsland(Mockito.eq(uuid))).thenReturn(true); + when(im.isOwner(Mockito.eq(uuid))).thenReturn(true); + when(pm.getUUID(Mockito.anyString())).thenReturn(null); + assertFalse(iubc.execute(user, Arrays.asList("bill"))); + Mockito.verify(user).sendMessage("general.errors.unknown-player"); + } + + @Test + public void testBanSelf() { + IslandUnbanCommand iubc = new IslandUnbanCommand(ic); + when(im.hasIsland(Mockito.eq(uuid))).thenReturn(true); + when(im.isOwner(Mockito.eq(uuid))).thenReturn(true); + when(pm.getUUID(Mockito.anyString())).thenReturn(uuid); + assertFalse(iubc.execute(user, Arrays.asList("bill"))); + Mockito.verify(user).sendMessage("commands.island.unban.cannot-unban-yourself"); + } + + @Test + public void testBanNotBanned() { + IslandUnbanCommand iubc = new IslandUnbanCommand(ic); + when(im.hasIsland(Mockito.eq(uuid))).thenReturn(true); + when(im.isOwner(Mockito.eq(uuid))).thenReturn(true); + UUID bannedUser = UUID.randomUUID(); + when(pm.getUUID(Mockito.anyString())).thenReturn(bannedUser); + when(island.isBanned(Mockito.eq(bannedUser))).thenReturn(false); + assertFalse(iubc.execute(user, Arrays.asList("bill"))); + Mockito.verify(user).sendMessage("commands.island.unban.player-not-banned"); + } + + @Test + public void testUnbanUser() { + IslandUnbanCommand iubc = new IslandUnbanCommand(ic); + when(im.hasIsland(Mockito.eq(uuid))).thenReturn(true); + when(im.isOwner(Mockito.eq(uuid))).thenReturn(true); + UUID targetUUID = UUID.randomUUID(); + when(pm.getUUID(Mockito.anyString())).thenReturn(targetUUID); + PowerMockito.mockStatic(User.class); + User targetUser = mock(User.class); + when(targetUser.isOp()).thenReturn(false); + when(targetUser.isPlayer()).thenReturn(true); + when(targetUser.isOnline()).thenReturn(false); + when(User.getInstance(Mockito.any(UUID.class))).thenReturn(targetUser); + // Mark as banned + when(island.isBanned(Mockito.eq(targetUUID))).thenReturn(true); + + // Allow removing from ban list + when(island.removeFromBanList(Mockito.any())).thenReturn(true); + + assertTrue(iubc.execute(user, Arrays.asList("bill"))); + Mockito.verify(user).sendMessage("general.success"); + Mockito.verify(targetUser).sendMessage("commands.island.unban.you-are-unbanned", "[owner]", user.getName()); + } + + @Test + public void testCancelledUnban() { + IslandUnbanCommand iubc = new IslandUnbanCommand(ic); + when(im.hasIsland(Mockito.eq(uuid))).thenReturn(true); + when(im.isOwner(Mockito.eq(uuid))).thenReturn(true); + UUID targetUUID = UUID.randomUUID(); + when(pm.getUUID(Mockito.anyString())).thenReturn(targetUUID); + PowerMockito.mockStatic(User.class); + User targetUser = mock(User.class); + when(targetUser.isOp()).thenReturn(false); + when(targetUser.isPlayer()).thenReturn(true); + when(targetUser.isOnline()).thenReturn(false); + when(User.getInstance(Mockito.any(UUID.class))).thenReturn(targetUser); + // Mark as banned + when(island.isBanned(Mockito.eq(targetUUID))).thenReturn(true); + + // Allow removing from ban list + when(island.removeFromBanList(Mockito.any())).thenReturn(false); + + assertFalse(iubc.execute(user, Arrays.asList("bill"))); + Mockito.verify(user, Mockito.never()).sendMessage("general.success"); + Mockito.verify(targetUser, Mockito.never()).sendMessage("commands.island.unban.you-are-unbanned", "[owner]", user.getName()); + } + + @Test + public void testTabComplete() { + Set banned = new HashSet<>(); + // Add ten people to the banned list + for (int i = 0; i < 10; i++) { + banned.add(UUID.randomUUID()); + } + when(island.getBanned()).thenReturn(banned); + when(pm.getName(Mockito.any())).thenReturn("a", "b", "c", "d", "e", "f", "g", "h", "i", "j"); + IslandUnbanCommand iubc = new IslandUnbanCommand(ic); + User user = mock(User.class); + when(user.getUniqueId()).thenReturn(UUID.randomUUID()); + Optional> result = iubc.tabComplete(user, "", new LinkedList<>()); + assertTrue(result.isPresent()); + String[] names = {"a", "b", "c", "d", "e", "f", "g", "h", "i", "j"}; + assertTrue(Arrays.equals(names, result.get().toArray())); + } +} diff --git a/src/test/java/us/tastybento/bskyblock/database/mysql/MySQLDatabaseHandlerTest.java b/src/test/java/us/tastybento/bskyblock/database/mysql/MySQLDatabaseHandlerTest.java index ec61fdec6..10f4a0275 100644 --- a/src/test/java/us/tastybento/bskyblock/database/mysql/MySQLDatabaseHandlerTest.java +++ b/src/test/java/us/tastybento/bskyblock/database/mysql/MySQLDatabaseHandlerTest.java @@ -131,7 +131,7 @@ public class MySQLDatabaseHandlerTest { island.setLevelHandicap(10); island.setLocked(true); Map members = new HashMap<>(); - for (int i = 0; i < 100; i++) { + for (int i = 0; i < 10; i++) { members.put(UUID.randomUUID(), i); } island.setMembers(members);