diff --git a/src/main/java/world/bentobox/bentobox/api/commands/CompositeCommand.java b/src/main/java/world/bentobox/bentobox/api/commands/CompositeCommand.java index 1d2fb7e21..23c27162c 100644 --- a/src/main/java/world/bentobox/bentobox/api/commands/CompositeCommand.java +++ b/src/main/java/world/bentobox/bentobox/api/commands/CompositeCommand.java @@ -107,7 +107,7 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi /** * Cool down tracker */ - private Map> cooldowns = new HashMap<>(); + private Map> cooldowns = new HashMap<>(); /** * Top level command @@ -670,32 +670,76 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi /** * Set a cool down - can be set by other commands on this one - * @param uniqueId - the caller + * @param uniqueId - the unique ID that is having the cooldown * @param targetUUID - the target (if any) * @param timeInSeconds - time in seconds to cool down + * @since 1.5.0 */ - public void setCooldown(UUID uniqueId, UUID targetUUID, int timeInSeconds) { + public void setCooldown(String uniqueId, String targetUUID, int timeInSeconds) { cooldowns.putIfAbsent(uniqueId, new HashMap<>()); cooldowns.get(uniqueId).put(targetUUID, System.currentTimeMillis() + timeInSeconds * 1000); } /** - * Check if cool down is in progress + * Set a cool down - can be set by other commands on this one + * @param uniqueId - the UUID that is having the cooldown + * @param targetUUID - the target UUID (if any) + * @param timeInSeconds - time in seconds to cool down + */ + public void setCooldown(UUID uniqueId, UUID targetUUID, int timeInSeconds) { + cooldowns.putIfAbsent(uniqueId.toString(), new HashMap<>()); + cooldowns.get(uniqueId.toString()).put(targetUUID == null ? null : targetUUID.toString(), System.currentTimeMillis() + timeInSeconds * 1000); + } + + /** + * Set a cool down for a user - can be set by other commands on this one + * @param uniqueId - the UUID that is having the cooldown + * @param timeInSeconds - time in seconds to cool down + * @since 1.5.0 + */ + public void setCooldown(UUID uniqueId, int timeInSeconds) { + setCooldown(uniqueId, null, timeInSeconds); + } + + /** + * Check if cool down is in progress for user * @param user - the caller of the command * @param targetUUID - the target (if any) * @return true if cool down in place, false if not */ protected boolean checkCooldown(User user, UUID targetUUID) { - if (!cooldowns.containsKey(user.getUniqueId()) || user.isOp() || user.hasPermission(getPermissionPrefix() + "mod.bypasscooldowns")) { + return checkCooldown(user, user.getUniqueId().toString(), targetUUID == null ? null : targetUUID.toString()); + } + + /** + * Check if cool down is in progress for user + * @param user - the user to check + * @return true if cool down in place, false if not + * @since 1.5.0 + */ + protected boolean checkCooldown(User user) { + return checkCooldown(user, user.getUniqueId().toString(), null); + } + + /** + * Check if cool down is in progress + * @param user - the caller of the command + * @param uniqueId - the id that needs to be checked + * @param targetUUID - the target (if any) + * @return true if cool down in place, false if not + * @since 1.5.0 + */ + protected boolean checkCooldown(User user, String uniqueId, String targetUUID) { + if (!cooldowns.containsKey(uniqueId) || user.isOp() || user.hasPermission(getPermissionPrefix() + "mod.bypasscooldowns")) { return false; } - cooldowns.putIfAbsent(user.getUniqueId(), new HashMap<>()); - if (cooldowns.get(user.getUniqueId()).getOrDefault(targetUUID, 0L) - System.currentTimeMillis() <= 0) { + cooldowns.putIfAbsent(uniqueId, new HashMap<>()); + if (cooldowns.get(uniqueId).getOrDefault(targetUUID, 0L) - System.currentTimeMillis() <= 0) { // Cool down is done - cooldowns.get(user.getUniqueId()).remove(targetUUID); + cooldowns.get(uniqueId).remove(targetUUID); return false; } - int timeToGo = (int) ((cooldowns.get(user.getUniqueId()).getOrDefault(targetUUID, 0L) - System.currentTimeMillis()) / 1000); + int timeToGo = (int) ((cooldowns.get(uniqueId).getOrDefault(targetUUID, 0L) - System.currentTimeMillis()) / 1000); user.sendMessage("general.errors.you-must-wait", TextVariables.NUMBER, String.valueOf(timeToGo)); return true; } diff --git a/src/main/java/world/bentobox/bentobox/api/commands/island/IslandBanCommand.java b/src/main/java/world/bentobox/bentobox/api/commands/island/IslandBanCommand.java index 452a81ca1..86549e1fc 100644 --- a/src/main/java/world/bentobox/bentobox/api/commands/island/IslandBanCommand.java +++ b/src/main/java/world/bentobox/bentobox/api/commands/island/IslandBanCommand.java @@ -46,7 +46,8 @@ public class IslandBanCommand extends CompositeCommand { return false; } // Check rank to use command - if (getIslands().getIsland(getWorld(), user).getRank(user) < getPlugin().getSettings().getRankCommand(getUsage())) { + Island island = getIslands().getIsland(getWorld(), user); + if (island.getRank(user) < getPlugin().getSettings().getRankCommand(getUsage())) { user.sendMessage("general.errors.no-permission"); return false; } @@ -69,7 +70,7 @@ public class IslandBanCommand extends CompositeCommand { user.sendMessage("commands.island.ban.player-already-banned"); return false; } - if (getSettings().getBanCooldown() > 0 && checkCooldown(user, targetUUID)) { + if (getSettings().getBanCooldown() > 0 && checkCooldown(user, island.getUniqueId(), targetUUID.toString())) { return false; } User target = User.getInstance(targetUUID); diff --git a/src/main/java/world/bentobox/bentobox/api/commands/island/IslandCreateCommand.java b/src/main/java/world/bentobox/bentobox/api/commands/island/IslandCreateCommand.java index 111fda006..b85841ec5 100644 --- a/src/main/java/world/bentobox/bentobox/api/commands/island/IslandCreateCommand.java +++ b/src/main/java/world/bentobox/bentobox/api/commands/island/IslandCreateCommand.java @@ -86,7 +86,7 @@ public class IslandCreateCommand extends CompositeCommand { return false; } if (getSettings().isResetCooldownOnCreate()) { - getParent().getSubCommand("reset").ifPresent(resetCommand -> resetCommand.setCooldown(user.getUniqueId(), null, getSettings().getResetCooldown())); + getParent().getSubCommand("reset").ifPresent(resetCommand -> resetCommand.setCooldown(user.getUniqueId(), getSettings().getResetCooldown())); } return true; } diff --git a/src/main/java/world/bentobox/bentobox/api/commands/island/IslandResetCommand.java b/src/main/java/world/bentobox/bentobox/api/commands/island/IslandResetCommand.java index 47898c877..11401ac4d 100644 --- a/src/main/java/world/bentobox/bentobox/api/commands/island/IslandResetCommand.java +++ b/src/main/java/world/bentobox/bentobox/api/commands/island/IslandResetCommand.java @@ -35,7 +35,7 @@ public class IslandResetCommand extends ConfirmableCommand { @Override public boolean canExecute(User user, String label, List args) { // Check cooldown - if (getSettings().getResetCooldown() > 0 && checkCooldown(user, null)) { + if (getSettings().getResetCooldown() > 0 && checkCooldown(user)) { return false; } @@ -128,7 +128,7 @@ public class IslandResetCommand extends ConfirmableCommand { user.sendMessage("commands.island.create.unable-create-island"); return false; } - setCooldown(user.getUniqueId(), null, getSettings().getResetCooldown()); + setCooldown(user.getUniqueId(), getSettings().getResetCooldown()); return true; } } diff --git a/src/main/java/world/bentobox/bentobox/api/commands/island/IslandUnbanCommand.java b/src/main/java/world/bentobox/bentobox/api/commands/island/IslandUnbanCommand.java index 72ff1f86f..6e764dc2a 100644 --- a/src/main/java/world/bentobox/bentobox/api/commands/island/IslandUnbanCommand.java +++ b/src/main/java/world/bentobox/bentobox/api/commands/island/IslandUnbanCommand.java @@ -84,7 +84,7 @@ public class IslandUnbanCommand extends CompositeCommand { // Set cooldown if (getSettings().getBanCooldown() > 0 && getParent() != null) { getParent().getSubCommand("ban").ifPresent(subCommand -> - subCommand.setCooldown(issuer.getUniqueId(), target.getUniqueId(), getSettings().getBanCooldown() * 60)); + subCommand.setCooldown(island.getUniqueId(), target.getUniqueId().toString(), getSettings().getBanCooldown() * 60)); } return true; } diff --git a/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamCoopCommand.java b/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamCoopCommand.java index e45620236..3db356d8e 100644 --- a/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamCoopCommand.java +++ b/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamCoopCommand.java @@ -48,7 +48,8 @@ public class IslandTeamCoopCommand extends CompositeCommand { return false; } // Check rank to use command - if (getIslands().getIsland(getWorld(), user).getRank(user) < getPlugin().getSettings().getRankCommand(getUsage())) { + Island island = getIslands().getIsland(getWorld(), user); + if (island.getRank(user) < getPlugin().getSettings().getRankCommand(getUsage())) { user.sendMessage("general.errors.no-permission"); return false; } @@ -59,7 +60,7 @@ public class IslandTeamCoopCommand extends CompositeCommand { return false; } // Check cooldown - if (getSettings().getCoopCooldown() > 0 && checkCooldown(user, targetUUID)) { + if (getSettings().getCoopCooldown() > 0 && checkCooldown(user, island.getUniqueId(), targetUUID.toString())) { return false; } // Player cannot coop themselves diff --git a/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamInviteCommand.java b/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamInviteCommand.java index 79bfada28..4e1b65831 100644 --- a/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamInviteCommand.java +++ b/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamInviteCommand.java @@ -77,7 +77,7 @@ public class IslandTeamInviteCommand extends CompositeCommand { return false; } // Check cool down - if (getSettings().getInviteCooldown() > 0 && checkCooldown(user, invitedPlayerUUID)) { + if (getSettings().getInviteCooldown() > 0 && checkCooldown(user, getIslands().getIsland(getWorld(), user).getUniqueId(), invitedPlayerUUID.toString())) { return false; } // Player cannot invite someone already on a team diff --git a/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamKickCommand.java b/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamKickCommand.java index 3ca341b5d..adc442bd7 100644 --- a/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamKickCommand.java +++ b/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamKickCommand.java @@ -105,7 +105,10 @@ public class IslandTeamKickCommand extends ConfirmableCommand { // Add cooldown for this player and target if (getSettings().getInviteCooldown() > 0 && getParent() != null) { // Get the invite class from the parent - getParent().getSubCommand("invite").ifPresent(c -> c.setCooldown(user.getUniqueId(), targetUUID, getSettings().getInviteCooldown() * 60)); + getParent().getSubCommand("invite").ifPresent(c -> c.setCooldown( + oldIsland.getUniqueId(), + targetUUID.toString(), + getSettings().getInviteCooldown() * 60)); } } } diff --git a/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamLeaveCommand.java b/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamLeaveCommand.java index 12dadc577..7292d2e29 100644 --- a/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamLeaveCommand.java +++ b/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamLeaveCommand.java @@ -62,6 +62,11 @@ public class IslandTeamLeaveCommand extends ConfirmableCommand { if (getSettings().isUseEconomy() && getIWM().isOnLeaveResetMoney(getWorld())) { getPlugin().getVault().ifPresent(vault -> vault.withdraw(user, vault.getBalance(user))); } + // Add cooldown for this player and target + if (getSettings().getInviteCooldown() > 0 && getParent() != null) { + // Get the invite class from the parent + getParent().getSubCommand("invite").ifPresent(c -> c.setCooldown(island.getUniqueId(), user.getUniqueId().toString(), getSettings().getInviteCooldown() * 60)); + } user.sendMessage("general.success"); // Fire event IslandBaseEvent e = TeamEvent.builder() diff --git a/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamTrustCommand.java b/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamTrustCommand.java index 1f8dbee19..59f2a922d 100644 --- a/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamTrustCommand.java +++ b/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamTrustCommand.java @@ -44,7 +44,8 @@ public class IslandTeamTrustCommand extends CompositeCommand { return false; } // Check rank to use command - if (getIslands().getIsland(getWorld(), user).getRank(user) < getPlugin().getSettings().getRankCommand(getUsage())) { + Island island = getIslands().getIsland(getWorld(), user); + if (island.getRank(user) < getPlugin().getSettings().getRankCommand(getUsage())) { user.sendMessage("general.errors.no-permission"); return false; } @@ -54,7 +55,7 @@ public class IslandTeamTrustCommand extends CompositeCommand { user.sendMessage("general.errors.unknown-player", TextVariables.NAME, args.get(0)); return false; } - return (getSettings().getTrustCooldown() <= 0 || !checkCooldown(user, targetUUID)) && trustCmd(user, targetUUID); + return (getSettings().getTrustCooldown() <= 0 || !checkCooldown(user, island.getUniqueId(), targetUUID.toString())) && trustCmd(user, targetUUID); } private boolean trustCmd(User user, UUID targetUUID) { diff --git a/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamUncoopCommand.java b/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamUncoopCommand.java index 8091d7b30..08dd0a7dc 100644 --- a/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamUncoopCommand.java +++ b/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamUncoopCommand.java @@ -86,7 +86,7 @@ public class IslandTeamUncoopCommand extends CompositeCommand { // Set cooldown if (getSettings().getCoopCooldown() > 0 && getParent() != null) { getParent().getSubCommand("coop").ifPresent(subCommand -> - subCommand.setCooldown(user.getUniqueId(), targetUUID, getSettings().getCoopCooldown() * 60)); + subCommand.setCooldown(island.getUniqueId(), targetUUID.toString(), getSettings().getCoopCooldown() * 60)); } return true; } else { @@ -107,7 +107,7 @@ public class IslandTeamUncoopCommand extends CompositeCommand { List options = island.getMemberSet().stream() .filter(uuid -> island.getRank(User.getInstance(uuid)) == RanksManager.COOP_RANK) .map(Bukkit::getOfflinePlayer) - .map(OfflinePlayer::getName).collect(Collectors.toList()); + .map(OfflinePlayer::getName).collect(Collectors.toList()); String lastArg = !args.isEmpty() ? args.get(args.size()-1) : ""; return Optional.of(Util.tabLimit(options, lastArg)); diff --git a/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamUntrustCommand.java b/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamUntrustCommand.java index 6a7bfb207..c4582e421 100644 --- a/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamUntrustCommand.java +++ b/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamUntrustCommand.java @@ -86,7 +86,7 @@ public class IslandTeamUntrustCommand extends CompositeCommand { // Set cooldown if (getSettings().getTrustCooldown() > 0 && getParent() != null) { getParent().getSubCommand("trust").ifPresent(subCommand -> - subCommand.setCooldown(user.getUniqueId(), targetUUID, getSettings().getTrustCooldown() * 60)); + subCommand.setCooldown(island.getUniqueId(), targetUUID.toString(), getSettings().getTrustCooldown() * 60)); } return true; } else { @@ -107,7 +107,7 @@ public class IslandTeamUntrustCommand extends CompositeCommand { List options = island.getMemberSet().stream() .filter(uuid -> island.getRank(User.getInstance(uuid)) == RanksManager.TRUSTED_RANK) .map(Bukkit::getOfflinePlayer) - .map(OfflinePlayer::getName).collect(Collectors.toList()); + .map(OfflinePlayer::getName).collect(Collectors.toList()); String lastArg = !args.isEmpty() ? args.get(args.size()-1) : ""; return Optional.of(Util.tabLimit(options, lastArg)); diff --git a/src/test/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamKickCommandTest.java b/src/test/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamKickCommandTest.java index 109ed802e..c79db99d8 100644 --- a/src/test/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamKickCommandTest.java +++ b/src/test/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamKickCommandTest.java @@ -33,6 +33,7 @@ import world.bentobox.bentobox.Settings; import world.bentobox.bentobox.api.commands.CompositeCommand; import world.bentobox.bentobox.api.localization.TextVariables; import world.bentobox.bentobox.api.user.User; +import world.bentobox.bentobox.database.objects.Island; import world.bentobox.bentobox.managers.CommandsManager; import world.bentobox.bentobox.managers.IslandWorldManager; import world.bentobox.bentobox.managers.IslandsManager; @@ -140,6 +141,11 @@ public class IslandTeamKickCommandTest { when(server.getPluginManager()).thenReturn(pim); when(Bukkit.getServer()).thenReturn(server); + // Island + Island island = mock(Island.class); + when(island.getUniqueId()).thenReturn("uniqueid"); + when(im.getIsland(Mockito.any(), Mockito.any(UUID.class))).thenReturn(island); + } /** @@ -296,6 +302,6 @@ public class IslandTeamKickCommandTest { // 10 minutes = 600 seconds when(s.getInviteCooldown()).thenReturn(10); testExecuteNoConfirmation(); - Mockito.verify(subCommand).setCooldown(uuid, notUUID, 600); + Mockito.verify(subCommand).setCooldown("uniqueid", notUUID.toString(), 600); } } diff --git a/src/test/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamLeaveCommandTest.java b/src/test/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamLeaveCommandTest.java index 4da3809d4..1de731f83 100644 --- a/src/test/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamLeaveCommandTest.java +++ b/src/test/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamLeaveCommandTest.java @@ -7,6 +7,7 @@ import static org.mockito.Mockito.when; import java.util.ArrayList; import java.util.HashMap; +import java.util.Optional; import java.util.UUID; import org.bukkit.Bukkit; @@ -19,6 +20,7 @@ import org.bukkit.scheduler.BukkitScheduler; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Mock; import org.mockito.Mockito; import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PrepareForTest; @@ -29,6 +31,7 @@ import world.bentobox.bentobox.BentoBox; import world.bentobox.bentobox.Settings; import world.bentobox.bentobox.api.commands.CompositeCommand; import world.bentobox.bentobox.api.user.User; +import world.bentobox.bentobox.database.objects.Island; import world.bentobox.bentobox.managers.CommandsManager; import world.bentobox.bentobox.managers.IslandWorldManager; import world.bentobox.bentobox.managers.IslandsManager; @@ -49,6 +52,8 @@ public class IslandTeamLeaveCommandTest { private IslandsManager im; private IslandWorldManager iwm; private Player player; + @Mock + private CompositeCommand subCommand; /** * @throws java.lang.Exception @@ -81,6 +86,8 @@ public class IslandTeamLeaveCommandTest { // Parent command has no aliases ic = mock(CompositeCommand.class); when(ic.getSubCommandAliases()).thenReturn(new HashMap<>()); + Optional optionalCommand = Optional.of(subCommand); + when(ic.getSubCommand(Mockito.anyString())).thenReturn(optionalCommand); // Player has island to begin with im = mock(IslandsManager.class); @@ -107,6 +114,11 @@ public class IslandTeamLeaveCommandTest { PluginManager pim = mock(PluginManager.class); when(server.getPluginManager()).thenReturn(pim); when(Bukkit.getServer()).thenReturn(server); + + // Island + Island island = mock(Island.class); + when(island.getUniqueId()).thenReturn("uniqueid"); + when(im.getIsland(Mockito.any(), Mockito.any(User.class))).thenReturn(island); } /** @@ -194,4 +206,15 @@ public class IslandTeamLeaveCommandTest { Mockito.verify(enderChest).clear(); Mockito.verify(inv).clear(); } + + /** + * Test method for {@link IslandTeamLeaveCommand#execute(User, String, java.util.List)} + */ + @Test + public void testCooldown() { + // 10 minutes = 600 seconds + when(s.getInviteCooldown()).thenReturn(10); + testExecuteNoConfirmation(); + Mockito.verify(subCommand).setCooldown("uniqueid", uuid.toString(), 600); + } }