diff --git a/pom.xml b/pom.xml index 2200b852f..b04a46fc0 100644 --- a/pom.xml +++ b/pom.xml @@ -88,7 +88,7 @@ -LOCAL - 1.24.2 + 2.0.0 bentobox-world https://sonarcloud.io ${project.basedir}/lib diff --git a/src/main/java/world/bentobox/bentobox/BentoBox.java b/src/main/java/world/bentobox/bentobox/BentoBox.java index 48a45b937..aaa3a3e99 100644 --- a/src/main/java/world/bentobox/bentobox/BentoBox.java +++ b/src/main/java/world/bentobox/bentobox/BentoBox.java @@ -31,6 +31,7 @@ import world.bentobox.bentobox.listeners.DeathListener; import world.bentobox.bentobox.listeners.JoinLeaveListener; import world.bentobox.bentobox.listeners.PanelListenerManager; +import world.bentobox.bentobox.listeners.PrimaryIslandListener; import world.bentobox.bentobox.listeners.StandardSpawnProtectionListener; import world.bentobox.bentobox.listeners.teleports.EntityTeleportListener; import world.bentobox.bentobox.listeners.teleports.PlayerTeleportListener; @@ -308,6 +309,8 @@ private void registerListeners() { // Island Delete Manager islandDeletionManager = new IslandDeletionManager(this); manager.registerEvents(islandDeletionManager, this); + // Primary Island Listener + manager.registerEvents(new PrimaryIslandListener(this), this); } @Override diff --git a/src/main/java/world/bentobox/bentobox/Settings.java b/src/main/java/world/bentobox/bentobox/Settings.java index 758cfaf78..543fae9ed 100644 --- a/src/main/java/world/bentobox/bentobox/Settings.java +++ b/src/main/java/world/bentobox/bentobox/Settings.java @@ -190,6 +190,12 @@ public class Settings implements ConfigObject { /* * Island */ + // Number of islands + @ConfigComment("The default number of concurrent islands a player may have.") + @ConfigComment("This may be overridden by individual game mode config settings.") + @ConfigEntry(path = "island.concurrent-islands") + private int islandNumber = 1; + // Cooldowns @ConfigComment("How long a player must wait until they can rejoin a team island after being kicked in minutes.") @ConfigComment("This slows the effectiveness of players repeating challenges") @@ -1045,4 +1051,21 @@ public List getReadyCommands() { public void setReadyCommands(List readyCommands) { this.readyCommands = readyCommands; } + + /** + * @return the islandNumber + * @since 2.0.0 + */ + public int getIslandNumber() { + return islandNumber; + } + + /** + * @param islandNumber the islandNumber to set + * @since 2.0.0 + */ + public void setIslandNumber(int islandNumber) { + this.islandNumber = islandNumber; + } + } 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 9533dbd5e..fe53f16c8 100644 --- a/src/main/java/world/bentobox/bentobox/api/commands/CompositeCommand.java +++ b/src/main/java/world/bentobox/bentobox/api/commands/CompositeCommand.java @@ -461,17 +461,6 @@ public Map getSubCommands(boolean ignoreHelp) { return getSubCommands(); } - /** - * Convenience method to obtain the user's island owner - * @param world world to check - * @param user the User - * @return UUID of player's island owner or null if user has no island - */ - @Nullable - protected UUID getOwner(@NonNull World world, @NonNull User user) { - return plugin.getIslands().getOwner(world, user.getUniqueId()); - } - @Override public @NonNull String getUsage() { return "/" + usage; diff --git a/src/main/java/world/bentobox/bentobox/api/commands/admin/AdminDeleteCommand.java b/src/main/java/world/bentobox/bentobox/api/commands/admin/AdminDeleteCommand.java index c8e6be0d1..f5988210c 100644 --- a/src/main/java/world/bentobox/bentobox/api/commands/admin/AdminDeleteCommand.java +++ b/src/main/java/world/bentobox/bentobox/api/commands/admin/AdminDeleteCommand.java @@ -5,8 +5,6 @@ import java.util.Optional; import java.util.UUID; -import org.bukkit.util.Vector; - import world.bentobox.bentobox.api.commands.CompositeCommand; import world.bentobox.bentobox.api.commands.ConfirmableCommand; import world.bentobox.bentobox.api.events.island.IslandEvent; @@ -41,14 +39,14 @@ public boolean canExecute(User user, String label, List args) { user.sendMessage("general.errors.unknown-player", TextVariables.NAME, args.get(0)); return false; } - UUID owner = getIslands().getOwner(getWorld(), targetUUID); - if (owner == null) { + Island island = getIslands().getIsland(getWorld(), user); + if (island == null) { user.sendMessage("general.errors.player-has-no-island"); return false; } // Team members should be kicked before deleting otherwise the whole team will become weird - if (getIslands().inTeam(getWorld(), targetUUID) && owner.equals(targetUUID)) { + if (getIslands().inTeam(getWorld(), targetUUID) && user.getUniqueId().equals(island.getOwner())) { user.sendMessage("commands.admin.delete.cannot-delete-owner"); return false; } @@ -66,10 +64,7 @@ public boolean execute(User user, String label, List args) { private void deletePlayer(User user, UUID targetUUID) { // Delete player and island - // Get the target's island - Island oldIsland = getIslands().getIsland(getWorld(), targetUUID); - Vector vector = null; - if (oldIsland != null) { + for (Island oldIsland : getIslands().getIslands(getWorld(), targetUUID)) { // Fire island preclear event IslandEvent.builder() .involvedPlayer(user.getUniqueId()) @@ -78,21 +73,17 @@ private void deletePlayer(User user, UUID targetUUID) { .oldIsland(oldIsland) .location(oldIsland.getCenter()) .build(); - // Check if player is online and on the island - User target = User.getInstance(targetUUID); - // Remove them from this island (it still exists and will be deleted later) - getIslands().removePlayer(getWorld(), targetUUID); - if (target.isPlayer() && target.isOnline()) { - cleanUp(target); - } - vector = oldIsland.getCenter().toVector(); + user.sendMessage("commands.admin.delete.deleted-island", TextVariables.XYZ, Util.xyz(oldIsland.getCenter().toVector())); getIslands().deleteIsland(oldIsland, true, targetUUID); } - if (vector == null) { - user.sendMessage("general.success"); - } else { - user.sendMessage("commands.admin.delete.deleted-island", TextVariables.XYZ, Util.xyz(vector)); + // Check if player is online and on the island + User target = User.getInstance(targetUUID); + // Remove them from this island (it still exists and will be deleted later) + getIslands().removePlayer(getWorld(), targetUUID); + if (target.isPlayer() && target.isOnline()) { + cleanUp(target); } + user.sendMessage("general.success"); } private void cleanUp(User target) { diff --git a/src/main/java/world/bentobox/bentobox/api/commands/admin/team/AdminTeamDisbandCommand.java b/src/main/java/world/bentobox/bentobox/api/commands/admin/team/AdminTeamDisbandCommand.java index a682d0abc..c28598174 100644 --- a/src/main/java/world/bentobox/bentobox/api/commands/admin/team/AdminTeamDisbandCommand.java +++ b/src/main/java/world/bentobox/bentobox/api/commands/admin/team/AdminTeamDisbandCommand.java @@ -57,7 +57,7 @@ public boolean execute(User user, String label, List args) { mUser.sendMessage("commands.admin.team.disband.disbanded"); // The owner gets to keep the island if (!m.equals(targetUUID)) { - getIslands().setLeaveTeam(getWorld(), m); + island.removeMember(m); TeamEvent.builder() .island(island) .reason(TeamEvent.Reason.KICK) 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 5426b764b..186f28685 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 @@ -42,14 +42,20 @@ public void setup() { public boolean canExecute(User user, String label, List args) { // Check if the island is reserved @Nullable - Island island = getIslands().getIsland(getWorld(), user); + Island island = getIslands().getPrimaryIsland(getWorld(), user.getUniqueId()); if (island != null) { // Reserved islands can be made if (island.isReserved()) { return true; } + // Get how many islands this player has + int num = this.getIslands().getNumberOfConcurrentIslands(user.getUniqueId(), getWorld()); + int max = this.getIWM().getWorldSettings(getWorld()).getConcurrentIslands(); + if (num < max) { + return true; + } // You cannot make an island - user.sendMessage("general.errors.already-have-island"); + user.sendMessage("general.errors.you-cannot-make"); return false; } if (getIWM().getMaxIslands(getWorld()) > 0 diff --git a/src/main/java/world/bentobox/bentobox/api/commands/island/IslandDeletehomeCommand.java b/src/main/java/world/bentobox/bentobox/api/commands/island/IslandDeletehomeCommand.java index 903750fb3..d2b1ccd15 100644 --- a/src/main/java/world/bentobox/bentobox/api/commands/island/IslandDeletehomeCommand.java +++ b/src/main/java/world/bentobox/bentobox/api/commands/island/IslandDeletehomeCommand.java @@ -1,12 +1,12 @@ package world.bentobox.bentobox.api.commands.island; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.Optional; -import org.eclipse.jdt.annotation.Nullable; - import world.bentobox.bentobox.api.commands.CompositeCommand; import world.bentobox.bentobox.api.commands.ConfirmableCommand; import world.bentobox.bentobox.api.localization.TextVariables; @@ -22,8 +22,6 @@ */ public class IslandDeletehomeCommand extends ConfirmableCommand { - private @Nullable Island island; - /** * Deletes a home * @param islandCommand parent command @@ -48,7 +46,7 @@ public boolean canExecute(User user, String label, List args) { this.showHelp(this, user); return false; } - island = getIslands().getIsland(getWorld(), user); + Island island = getIslands().getIsland(getWorld(), user); // Check island if (island == null) { user.sendMessage("general.errors.no-island"); @@ -63,19 +61,21 @@ public boolean canExecute(User user, String label, List args) { return false; } - // Check if the name is known - if (!getIslands().isHomeLocation(island, String.join(" ", args))) { - user.sendMessage("commands.island.go.unknown-home"); - user.sendMessage("commands.island.sethome.homes-are"); - island.getHomes().keySet().stream().filter(s -> !s.isEmpty()).forEach(s -> user.sendMessage("commands.island.sethome.home-list-syntax", TextVariables.NAME, s)); - return false; - } return true; } @Override public boolean execute(User user, String label, List args) { - this.askConfirmation(user, () -> delete(island, user, String.join(" ", args))); + // Check if the name is known + Map map = getNameIslandMap(user); + String name = String.join(" ", args); + if (!map.containsKey(name)) { + user.sendMessage("commands.island.go.unknown-home"); + user.sendMessage("commands.island.sethome.homes-are"); + map.keySet().stream().filter(s -> !s.isEmpty()).forEach(s -> user.sendMessage("commands.island.sethome.home-list-syntax", TextVariables.NAME, s)); + return false; + } + this.askConfirmation(user, () -> delete(map.get(name), user, name)); return true; } @@ -88,11 +88,19 @@ private void delete(Island island, User user, String name) { @Override public Optional> tabComplete(User user, String alias, List args) { String lastArg = !args.isEmpty() ? args.get(args.size()-1) : ""; - Island is = getIslands().getIsland(getWorld(), user.getUniqueId()); - if (is != null) { - return Optional.of(Util.tabLimit(new ArrayList<>(is.getHomes().keySet()), lastArg)); - } else { - return Optional.empty(); + + return Optional.of(Util.tabLimit(new ArrayList<>(getNameIslandMap(user).keySet()), lastArg)); + + } + + private Map getNameIslandMap(User user) { + Map islandMap = new HashMap<>(); + for (Island isle : getIslands().getIslands(getWorld(), user.getUniqueId())) { + // Add homes. + isle.getHomes().keySet().forEach(name -> islandMap.put(name, isle)); } + return islandMap; + } + } diff --git a/src/main/java/world/bentobox/bentobox/api/commands/island/IslandGoCommand.java b/src/main/java/world/bentobox/bentobox/api/commands/island/IslandGoCommand.java index dba774532..be302ebe6 100644 --- a/src/main/java/world/bentobox/bentobox/api/commands/island/IslandGoCommand.java +++ b/src/main/java/world/bentobox/bentobox/api/commands/island/IslandGoCommand.java @@ -2,8 +2,11 @@ import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Optional; +import java.util.Set; import world.bentobox.bentobox.api.commands.CompositeCommand; import world.bentobox.bentobox.api.commands.DelayedTeleportCommand; @@ -12,6 +15,7 @@ import world.bentobox.bentobox.database.objects.Island; import world.bentobox.bentobox.lists.Flags; import world.bentobox.bentobox.util.Util; +import world.bentobox.bentobox.util.teleport.SafeSpotTeleport; /** * @author tastybento @@ -38,47 +42,101 @@ public boolean canExecute(User user, String label, List args) { user.sendMessage("commands.island.go.teleport"); return false; } - // Check if the island is reserved - Island island = getIslands().getIsland(getWorld(), user.getUniqueId()); - if (island == null) { + Set islands = getIslands().getIslands(getWorld(), user.getUniqueId()); + if (islands.isEmpty()) { user.sendMessage("general.errors.no-island"); return false; } - if (island.isReserved()) { - // Send player to create an island - getParent().getSubCommand("create").ifPresent(createCmd -> createCmd.call(user, createCmd.getLabel(), Collections.emptyList())); + // Check if the island is reserved + if (checkReserved(user, islands)) { return false; } + // Prevent command if player is falling and its not allowed if ((getIWM().inWorld(user.getWorld()) && Flags.PREVENT_TELEPORT_WHEN_FALLING.isSetForWorld(user.getWorld())) && user.getPlayer().getFallDistance() > 0) { // We're sending the "hint" to the player to tell them they cannot teleport while falling. user.sendMessage(Flags.PREVENT_TELEPORT_WHEN_FALLING.getHintReference()); return false; } - if (!args.isEmpty() && !getIslands().isHomeLocation(island, String.join(" ", args))) { - user.sendMessage("commands.island.go.unknown-home"); - user.sendMessage("commands.island.sethome.homes-are"); - island.getHomes().keySet().stream().filter(s -> !s.isEmpty()).forEach(s -> user.sendMessage("commands.island.sethome.home-list-syntax", TextVariables.NAME, s)); - return false; - } return true; } @Override public boolean execute(User user, String label, List args) { - this.delayCommand(user, () -> getIslands().homeTeleportAsync(getWorld(), user.getPlayer(), String.join(" ", args))); + // Check if the home is known + if (!args.isEmpty()) { + Map names = getNameIslandMap(user); + final String name = String.join(" ", args); + if (!names.containsKey(name)) { + // Failed home name check + user.sendMessage("commands.island.go.unknown-home"); + user.sendMessage("commands.island.sethome.homes-are"); + names.keySet().forEach(n -> user.sendMessage("commands.island.sethome.home-list-syntax", TextVariables.NAME, n)); + return false; + } else { + IslandInfo info = names.get(name); + getIslands().setPrimaryIsland(user.getUniqueId(), info.island); + if (info.islandName) { + this.delayCommand(user, () -> new SafeSpotTeleport.Builder(getPlugin()) + .entity(user.getPlayer()) + .location(getIslands().getHomeLocation(info.island)) + .thenRun(() -> user.sendMessage("general.success")) + .build()); + } else { + this.delayCommand(user, () -> new SafeSpotTeleport.Builder(getPlugin()) + .entity(user.getPlayer()) + .location(getIslands().getHomeLocation(info.island, name)) + .thenRun(() -> user.sendMessage("general.success")) + .build()); + } + } + } else { + this.delayCommand(user, () -> getIslands().homeTeleportAsync(getWorld(), user.getPlayer())); + } return true; } + private boolean checkReserved(User user, Set islands) { + for (Island island : islands) { + if (island.isReserved()) { + // Send player to create an island + getParent().getSubCommand("create").ifPresent(createCmd -> createCmd.call(user, createCmd.getLabel(), Collections.emptyList())); + return true; + } + } + return false; + } + + @Override public Optional> tabComplete(User user, String alias, List args) { String lastArg = !args.isEmpty() ? args.get(args.size()-1) : ""; - Island island = getIslands().getIsland(getWorld(), user.getUniqueId()); - if (island != null) { - return Optional.of(Util.tabLimit(new ArrayList<>(island.getHomes().keySet()), lastArg)); - } else { - return Optional.empty(); + + return Optional.of(Util.tabLimit(new ArrayList<>(getNameIslandMap(user).keySet()), lastArg)); + + } + + private record IslandInfo(Island island, boolean islandName) {} + + private Map getNameIslandMap(User user) { + Map islandMap = new HashMap<>(); + int index = 0; + for (Island island : getIslands().getIslands(getWorld(), user.getUniqueId())) { + index++; + if (island.getName() != null && !island.getName().isBlank()) { + // Name has been set + islandMap.put(island.getName(), new IslandInfo(island, true)); + } else { + // Name has not been set + String text = user.getTranslation("protection.flags.ENTER_EXIT_MESSAGES.island", TextVariables.NAME, user.getName(), TextVariables.DISPLAY_NAME, user.getDisplayName()) + " " + index; + islandMap.put(text, new IslandInfo(island, true)); + } + // Add homes. Homes do not need an island specified + island.getHomes().keySet().forEach(n -> islandMap.put(n, new IslandInfo(island, false))); } + + return islandMap; + } } diff --git a/src/main/java/world/bentobox/bentobox/api/commands/island/IslandHomesCommand.java b/src/main/java/world/bentobox/bentobox/api/commands/island/IslandHomesCommand.java index 796cc689a..bb31708f4 100644 --- a/src/main/java/world/bentobox/bentobox/api/commands/island/IslandHomesCommand.java +++ b/src/main/java/world/bentobox/bentobox/api/commands/island/IslandHomesCommand.java @@ -1,18 +1,20 @@ package world.bentobox.bentobox.api.commands.island; +import java.util.ArrayList; import java.util.List; - -import org.eclipse.jdt.annotation.Nullable; +import java.util.Optional; +import java.util.Set; import world.bentobox.bentobox.api.commands.CompositeCommand; import world.bentobox.bentobox.api.commands.ConfirmableCommand; 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.util.Util; public class IslandHomesCommand extends ConfirmableCommand { - private @Nullable Island island; + private Set islands; public IslandHomesCommand(CompositeCommand islandCommand) { super(islandCommand, "homes"); @@ -27,9 +29,9 @@ public void setup() { @Override public boolean canExecute(User user, String label, List args) { - island = getIslands().getIsland(getWorld(), user); + islands = getIslands().getIslands(getWorld(), user); // Check island - if (island == null || island.getOwner() == null) { + if (islands.isEmpty()) { user.sendMessage("general.errors.no-island"); return false; } @@ -39,9 +41,21 @@ public boolean canExecute(User user, String label, List args) { @Override public boolean execute(User user, String label, List args) { user.sendMessage("commands.island.sethome.homes-are"); + islands.forEach(island -> island.getHomes().keySet().stream().filter(s -> !s.isEmpty()) - .forEach(s -> user.sendMessage("commands.island.sethome.home-list-syntax", TextVariables.NAME, s)); + .forEach(s -> user.sendMessage("commands.island.sethome.home-list-syntax", TextVariables.NAME, s))); return true; } + @Override + public Optional> tabComplete(User user, String alias, List args) { + String lastArg = !args.isEmpty() ? args.get(args.size()-1) : ""; + List result = new ArrayList<>(); + for (Island island : getIslands().getIslands(getWorld(), user.getUniqueId())) { + result.addAll(island.getHomes().keySet()); + } + return Optional.of(Util.tabLimit(result, lastArg)); + + } + } 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 128ae6370..92169b9d4 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 @@ -124,9 +124,8 @@ private void selectBundle(@NonNull User user, @NonNull String label) { private boolean resetIsland(User user, String name) { // Get the player's old island Island oldIsland = getIslands().getIsland(getWorld(), user); - if (oldIsland != null) { - deleteOldIsland(user, oldIsland); - } + deleteOldIsland(user, oldIsland); + user.sendMessage("commands.island.create.creating-island"); // Create new island and then delete the old one try { diff --git a/src/main/java/world/bentobox/bentobox/api/commands/island/IslandSethomeCommand.java b/src/main/java/world/bentobox/bentobox/api/commands/island/IslandSethomeCommand.java index c4c598c27..7b50b3c52 100644 --- a/src/main/java/world/bentobox/bentobox/api/commands/island/IslandSethomeCommand.java +++ b/src/main/java/world/bentobox/bentobox/api/commands/island/IslandSethomeCommand.java @@ -51,11 +51,13 @@ public boolean canExecute(User user, String label, List args) { } // Check number of homes - int maxHomes = getIslands().getMaxHomes(island); + + int maxHomes = getIslands().getIslands(getWorld(), user).stream().mapToInt(getIslands()::getMaxHomes).sum(); if (getIslands().getNumberOfHomesIfAdded(island, String.join(" ", args)) > maxHomes) { user.sendMessage("commands.island.sethome.too-many-homes", TextVariables.NUMBER, String.valueOf(maxHomes)); user.sendMessage("commands.island.sethome.homes-are"); - island.getHomes().keySet().stream().filter(s -> !s.isEmpty()).forEach(s -> user.sendMessage("commands.island.sethome.home-list-syntax", TextVariables.NAME, s)); + getIslands().getIslands(getWorld(), user).forEach(is -> + is.getHomes().keySet().stream().filter(s -> !s.isEmpty()).forEach(s -> user.sendMessage("commands.island.sethome.home-list-syntax", TextVariables.NAME, s))); return false; } return true; diff --git a/src/main/java/world/bentobox/bentobox/api/commands/island/team/Invite.java b/src/main/java/world/bentobox/bentobox/api/commands/island/team/Invite.java index aec829c17..c6328d066 100644 --- a/src/main/java/world/bentobox/bentobox/api/commands/island/team/Invite.java +++ b/src/main/java/world/bentobox/bentobox/api/commands/island/team/Invite.java @@ -3,6 +3,8 @@ import java.util.Objects; import java.util.UUID; +import world.bentobox.bentobox.database.objects.Island; + /** * Represents an invite * @author tastybento @@ -23,16 +25,19 @@ public enum Type { private final Type type; private final UUID inviter; private final UUID invitee; + private final Island island; /** * @param type - invitation type, e.g., coop, team, trust * @param inviter - UUID of inviter * @param invitee - UUID of invitee + * @param island - the island this invite is for */ - public Invite(Type type, UUID inviter, UUID invitee) { + public Invite(Type type, UUID inviter, UUID invitee, Island island) { this.type = type; this.inviter = inviter; this.invitee = invitee; + this.island = island; } /** @@ -56,6 +61,13 @@ public UUID getInvitee() { return invitee; } + /** + * @return the island + */ + public Island getIsland() { + return island; + } + /* (non-Javadoc) * @see java.lang.Object#hashCode() */ diff --git a/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamCommand.java b/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamCommand.java index c8c8935b8..f78a7d318 100644 --- a/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamCommand.java +++ b/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamCommand.java @@ -58,24 +58,20 @@ public void setup() { @Override public boolean execute(User user, String label, List args) { // Player issuing the command must have an island - UUID ownerUUID = getOwner(getWorld(), user); - if (ownerUUID == null) { + Island island = getIslands().getPrimaryIsland(getWorld(), user.getUniqueId()); + if (island == null) { user.sendMessage("general.errors.no-island"); return false; } UUID playerUUID = user.getUniqueId(); // Fire event so add-ons can run commands, etc. - if (fireEvent(user)) { + if (fireEvent(user, island)) { // Cancelled return false; } - Island island = getIslands().getIsland(getWorld(), playerUUID); - if (island == null) { - return false; - } Set teamMembers = getMembers(getWorld(), user); - if (ownerUUID.equals(playerUUID)) { + if (playerUUID.equals(island.getOwner())) { int maxSize = getIslands().getMaxMembers(island, RanksManager.MEMBER_RANK); if (teamMembers.size() < maxSize) { user.sendMessage("commands.island.team.invite.you-can-invite", TextVariables.NUMBER, String.valueOf(maxSize - teamMembers.size())); @@ -169,10 +165,9 @@ private void displayOnOffline(User user, int rank, Island island, List onl } - private boolean fireEvent(User user) { + private boolean fireEvent(User user, Island island) { IslandBaseEvent e = TeamEvent.builder() - .island(getIslands() - .getIsland(getWorld(), user.getUniqueId())) + .island(island) .reason(TeamEvent.Reason.INFO) .involvedPlayer(user.getUniqueId()) .build(); @@ -187,8 +182,8 @@ private boolean fireEvent(User user) { * @param invitee - uuid of invitee * @since 1.8.0 */ - public void addInvite(Invite.Type type, @NonNull UUID inviter, @NonNull UUID invitee) { - inviteMap.put(invitee, new Invite(type, inviter, invitee)); + public void addInvite(Invite.Type type, @NonNull UUID inviter, @NonNull UUID invitee, @NonNull Island island) { + inviteMap.put(invitee, new Invite(type, inviter, invitee, island)); } /** 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 5da40ae6d..437e8c89a 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 @@ -93,7 +93,7 @@ public boolean execute(User user, String label, List args) { if (getPlugin().getSettings().isInviteConfirmation()) { // Put the invited player (key) onto the list with inviter (value) // If someone else has invited a player, then this invite will overwrite the previous invite! - itc.addInvite(Invite.Type.COOP, user.getUniqueId(), target.getUniqueId()); + itc.addInvite(Invite.Type.COOP, user.getUniqueId(), target.getUniqueId(), island); user.sendMessage("commands.island.team.invite.invitation-sent", TextVariables.NAME, target.getName()); // Send message to online player target.sendMessage("commands.island.team.coop.name-has-invited-you", TextVariables.NAME, user.getName()); diff --git a/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamInviteAcceptCommand.java b/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamInviteAcceptCommand.java index 89bd8ab64..7e7d018ee 100644 --- a/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamInviteAcceptCommand.java +++ b/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamInviteAcceptCommand.java @@ -1,6 +1,7 @@ package world.bentobox.bentobox.api.commands.island.team; import java.util.List; +import java.util.Set; import java.util.UUID; import world.bentobox.bentobox.api.commands.CompositeCommand; @@ -23,7 +24,6 @@ public class IslandTeamInviteAcceptCommand extends ConfirmableCommand { private static final String INVALID_INVITE = "commands.island.team.invite.errors.invalid-invite"; private final IslandTeamCommand itc; private UUID playerUUID; - private UUID prospectiveOwnerUUID; public IslandTeamInviteAcceptCommand(IslandTeamCommand islandTeamCommand) { super(islandTeamCommand, "accept"); @@ -46,7 +46,7 @@ public boolean canExecute(User user, String label, List args) { return false; } // Get the island owner - prospectiveOwnerUUID = itc.getInviter(playerUUID); + UUID prospectiveOwnerUUID = itc.getInviter(playerUUID); if (prospectiveOwnerUUID == null) { user.sendMessage(INVALID_INVITE); return false; @@ -96,7 +96,7 @@ private void acceptTrustInvite(User user, Invite invite) { // Remove the invite itc.removeInvite(playerUUID); User inviter = User.getInstance(invite.getInviter()); - Island island = getIslands().getIsland(getWorld(), inviter); + Island island = invite.getIsland(); if (island != null) { if (island.getMemberSet(RanksManager.TRUSTED_RANK, false).size() > getIslands().getMaxMembers(island, RanksManager.TRUSTED_RANK)) { user.sendMessage("commands.island.team.trust.is-full"); @@ -123,7 +123,7 @@ private void acceptCoopInvite(User user, Invite invite) { // Remove the invite itc.removeInvite(playerUUID); User inviter = User.getInstance(invite.getInviter()); - Island island = getIslands().getIsland(getWorld(), inviter); + Island island = invite.getIsland(); if (island != null) { if (island.getMemberSet(RanksManager.COOP_RANK, false).size() > getIslands().getMaxMembers(island, RanksManager.COOP_RANK)) { user.sendMessage("commands.island.team.coop.is-full"); @@ -150,9 +150,9 @@ private void acceptTeamInvite(User user, Invite invite) { // Remove the invite itc.removeInvite(playerUUID); // Get the player's island - may be null if the player has no island - Island island = getIslands().getIsland(getWorld(), playerUUID); + Set islands = getIslands().getIslands(getWorld(), playerUUID); // Get the team's island - Island teamIsland = getIslands().getIsland(getWorld(), prospectiveOwnerUUID); + Island teamIsland = invite.getIsland(); if (teamIsland == null) { user.sendMessage(INVALID_INVITE); return; @@ -169,10 +169,9 @@ private void acceptTeamInvite(User user, Invite invite) { getIslands().setJoinTeam(teamIsland, playerUUID); // Move player to team's island getIslands().homeTeleportAsync(getWorld(), user.getPlayer()).thenRun(() -> { - // Delete the old island - if (island != null) { - getIslands().deleteIsland(island, true, user.getUniqueId()); - } + // Delete the old islands + islands.forEach(island -> getIslands().deleteIsland(island, true, user.getUniqueId())); + // Put player back into normal mode user.setGameMode(getIWM().getDefaultGameMode(getWorld())); @@ -193,7 +192,7 @@ private void acceptTeamInvite(User user, Invite invite) { getIslands().save(teamIsland); // Fire event TeamEvent.builder() - .island(getIslands().getIsland(getWorld(), prospectiveOwnerUUID)) + .island(teamIsland) .reason(TeamEvent.Reason.JOINED) .involvedPlayer(playerUUID) .build(); 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 15c2aaa84..2f054e1d4 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 @@ -166,9 +166,14 @@ public boolean execute(User user, String label, List args) { itc.removeInvite(invitedPlayer.getUniqueId()); user.sendMessage("commands.island.team.invite.removing-invite"); } + Island island = getIslands().getIsland(getWorld(), user.getUniqueId()); + if (island == null) { + user.sendMessage("general.errors.no-island"); + return false; + } // Fire event so add-ons can run commands, etc. IslandBaseEvent e = TeamEvent.builder() - .island(getIslands().getIsland(getWorld(), user.getUniqueId())) + .island(island) .reason(TeamEvent.Reason.INVITE) .involvedPlayer(invitedPlayer.getUniqueId()) .build(); @@ -177,7 +182,7 @@ public boolean execute(User user, String label, List args) { } // Put the invited player (key) onto the list with inviter (value) // If someone else has invited a player, then this invite will overwrite the previous invite! - itc.addInvite(Invite.Type.TEAM, user.getUniqueId(), invitedPlayer.getUniqueId()); + itc.addInvite(Invite.Type.TEAM, user.getUniqueId(), invitedPlayer.getUniqueId(), island); user.sendMessage("commands.island.team.invite.invitation-sent", TextVariables.NAME, invitedPlayer.getName(), TextVariables.DISPLAY_NAME, invitedPlayer.getDisplayName()); // Send message to online player invitedPlayer.sendMessage("commands.island.team.invite.name-has-invited-you", TextVariables.NAME, user.getName(), TextVariables.DISPLAY_NAME, user.getDisplayName()); 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 01d455fa8..21d40f3bf 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 @@ -67,6 +67,10 @@ private void showResets(User user) { private void leave(User user) { Island island = getIslands().getIsland(getWorld(), user); + if (island == null) { + user.sendMessage("general.errors.no-island"); + return; + } // Fire event IslandBaseEvent event = TeamEvent.builder() .island(island) @@ -76,11 +80,11 @@ private void leave(User user) { if (event.isCancelled()) { return; } - UUID ownerUUID = getIslands().getOwner(getWorld(), user.getUniqueId()); + UUID ownerUUID = island.getOwner(); if (ownerUUID != null) { User.getInstance(ownerUUID).sendMessage("commands.island.team.leave.left-your-island", TextVariables.NAME, user.getName(), TextVariables.DISPLAY_NAME, user.getDisplayName()); } - getIslands().setLeaveTeam(getWorld(), user.getUniqueId()); + island.removeMember(user.getUniqueId()); // Clean the player getPlayers().cleanLeavingPlayer(getWorld(), user, false, island); diff --git a/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamSetownerCommand.java b/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamSetownerCommand.java index f4f8b6aa3..c4b38d279 100644 --- a/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamSetownerCommand.java +++ b/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamSetownerCommand.java @@ -4,6 +4,8 @@ import java.util.Optional; import java.util.UUID; +import org.eclipse.jdt.annotation.Nullable; + import world.bentobox.bentobox.api.commands.CompositeCommand; import world.bentobox.bentobox.api.events.IslandBaseEvent; import world.bentobox.bentobox.api.events.island.IslandEvent; @@ -16,6 +18,8 @@ public class IslandTeamSetownerCommand extends CompositeCommand { + private @Nullable UUID targetUUID; + public IslandTeamSetownerCommand(CompositeCommand islandTeamCommand) { super(islandTeamCommand, "setowner"); } @@ -29,37 +33,48 @@ public void setup() { } @Override - public boolean execute(User user, String label, List args) { - UUID playerUUID = user.getUniqueId(); + public boolean canExecute(User user, String label, List args) { + // If args are not right, show help + if (args.size() != 1) { + showHelp(this, user); + return false; + } // Can use if in a team - boolean inTeam = getIslands().inTeam(getWorld(), playerUUID); + boolean inTeam = getIslands().inTeam(getWorld(), user.getUniqueId()); if (!inTeam) { user.sendMessage("general.errors.no-team"); return false; } - UUID ownerUUID = getOwner(getWorld(), user); - if (ownerUUID == null || !ownerUUID.equals(playerUUID)) { + UUID ownerUUID = getIslands().getOwner(getWorld(), user.getUniqueId()); + if (ownerUUID == null || !ownerUUID.equals(user.getUniqueId())) { user.sendMessage("general.errors.not-owner"); return false; } - // If args are not right, show help - if (args.size() != 1) { - showHelp(this, user); - return false; - } - UUID targetUUID = getPlayers().getUUID(args.get(0)); + targetUUID = getPlayers().getUUID(args.get(0)); if (targetUUID == null) { user.sendMessage("general.errors.unknown-player", TextVariables.NAME, args.get(0)); return false; } - if (targetUUID.equals(playerUUID)) { + if (targetUUID.equals(user.getUniqueId())) { user.sendMessage("commands.island.team.setowner.errors.cant-transfer-to-yourself"); return false; } - if (!getIslands().getMembers(getWorld(), playerUUID).contains(targetUUID)) { + if (!getIslands().getMembers(getWorld(), user.getUniqueId()).contains(targetUUID)) { user.sendMessage("commands.island.team.setowner.errors.target-is-not-member"); return false; } + // Check how many islands target has + if (getIslands().getNumberOfConcurrentIslands(targetUUID, getWorld()) >= this.getIWM().getWorldSettings(getWorld()).getConcurrentIslands()) { + // Too many + user.sendMessage("commands.island.team.setowner.errors.at-max"); + return false; + } + return true; + } + + + @Override + public boolean execute(User user, String label, List args) { // Fire event so add-ons can run commands, etc. Island island = getIslands().getIsland(getWorld(), user); // Fire event so add-ons can run commands, etc. @@ -83,10 +98,10 @@ public boolean execute(User user, String label, List args) { // Call the event for the previous owner IslandEvent.builder() .island(island) - .involvedPlayer(playerUUID) + .involvedPlayer(user.getUniqueId()) .admin(false) .reason(IslandEvent.Reason.RANK_CHANGE) - .rankChange(RanksManager.OWNER_RANK, island.getRank(user)) + .rankChange(RanksManager.OWNER_RANK, RanksManager.VISITOR_RANK) .build(); getIslands().save(island); return true; 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 22ea20482..633223bb3 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 @@ -95,7 +95,7 @@ public boolean execute(User user, String label, List args) { if (getPlugin().getSettings().isInviteConfirmation()) { // Put the invited player (key) onto the list with inviter (value) // If someone else has invited a player, then this invite will overwrite the previous invite! - itc.addInvite(Type.TRUST, user.getUniqueId(), target.getUniqueId()); + itc.addInvite(Type.TRUST, user.getUniqueId(), target.getUniqueId(), island); user.sendMessage("commands.island.team.invite.invitation-sent", TextVariables.NAME, target.getName(), TextVariables.DISPLAY_NAME, target.getDisplayName()); // Send message to online player target.sendMessage("commands.island.team.trust.name-has-invited-you", TextVariables.NAME, user.getName(), TextVariables.DISPLAY_NAME, user.getDisplayName()); diff --git a/src/main/java/world/bentobox/bentobox/api/configuration/WorldSettings.java b/src/main/java/world/bentobox/bentobox/api/configuration/WorldSettings.java index cd1e81d35..3aa960bd1 100644 --- a/src/main/java/world/bentobox/bentobox/api/configuration/WorldSettings.java +++ b/src/main/java/world/bentobox/bentobox/api/configuration/WorldSettings.java @@ -13,6 +13,7 @@ import org.bukkit.entity.EntityType; import org.eclipse.jdt.annotation.NonNull; +import world.bentobox.bentobox.BentoBox; import world.bentobox.bentobox.api.flags.Flag; import world.bentobox.bentobox.lists.Flags; @@ -634,4 +635,13 @@ default boolean isMakeEndPortals() { default boolean isCheckForBlocks() { return true; } + + /** + * Get the number of concurrent islands a player can have in the world + * @return 1 by default + * @since 2.0.0 + */ + default int getConcurrentIslands() { + return BentoBox.getInstance().getSettings().getIslandNumber(); + } } diff --git a/src/main/java/world/bentobox/bentobox/api/events/island/IslandEvent.java b/src/main/java/world/bentobox/bentobox/api/events/island/IslandEvent.java index 15c0109db..59510f29d 100644 --- a/src/main/java/world/bentobox/bentobox/api/events/island/IslandEvent.java +++ b/src/main/java/world/bentobox/bentobox/api/events/island/IslandEvent.java @@ -176,7 +176,7 @@ public enum Reason { * Event that will fire when an island is named or renamed * @since 1.24.0 */ - NAME, + NAME, /** * Event that will fire when the info command is executed. Allows addons to add to it * @since 1.24.0 @@ -334,7 +334,7 @@ public IslandEventBuilder previousName(@Nullable String previousName) { this.previousName = previousName; return this; } - + /** * Addon that triggered this event, e.g. BSkyBlock * @param addon Addon. @@ -389,4 +389,4 @@ public IslandBaseEvent build() { } } -} +} \ No newline at end of file diff --git a/src/main/java/world/bentobox/bentobox/commands/BentoBoxReloadCommand.java b/src/main/java/world/bentobox/bentobox/commands/BentoBoxReloadCommand.java index 4ee6838c6..1c6c1135d 100644 --- a/src/main/java/world/bentobox/bentobox/commands/BentoBoxReloadCommand.java +++ b/src/main/java/world/bentobox/bentobox/commands/BentoBoxReloadCommand.java @@ -2,11 +2,8 @@ import java.util.List; -import org.bukkit.Bukkit; - import world.bentobox.bentobox.api.commands.CompositeCommand; import world.bentobox.bentobox.api.commands.ConfirmableCommand; -import world.bentobox.bentobox.api.events.BentoBoxReadyEvent; import world.bentobox.bentobox.api.panels.reader.TemplateReader; import world.bentobox.bentobox.api.user.User; import world.bentobox.bentobox.commands.reload.BentoBoxReloadLocalesCommand; @@ -40,7 +37,7 @@ public void setup() { public boolean execute(User user, String label, List args) { if (args.isEmpty()) { this.askConfirmation(user, user.getTranslation("commands.bentobox.reload.warning"), () -> { - + // Unregister all placeholders getPlugin().getPlaceholdersManager().unregisterAll(); @@ -53,22 +50,13 @@ public boolean execute(User user, String label, List args) { getPlugin().loadSettings(); user.sendMessage("commands.bentobox.reload.settings-reloaded"); - // Reload addons - getPlugin().getAddonsManager().reloadAddons(); - user.sendMessage("commands.bentobox.reload.addons-reloaded"); - // Reload locales getPlugin().getLocalesManager().reloadLanguages(); user.sendMessage("commands.bentobox.reload.locales-reloaded"); - + // Register new default gamemode placeholders getPlugin().getAddonsManager().getGameModeAddons().forEach(getPlugin().getPlaceholdersManager()::registerDefaultPlaceholders); - // Call the all Loaded method for addons - getPlugin().getAddonsManager().allLoaded(); - - // Fire ready event - Bukkit.getPluginManager().callEvent(new BentoBoxReadyEvent()); }); } else { showHelp(this, user); diff --git a/src/main/java/world/bentobox/bentobox/database/objects/Island.java b/src/main/java/world/bentobox/bentobox/database/objects/Island.java index 344c41260..338e5c5c1 100644 --- a/src/main/java/world/bentobox/bentobox/database/objects/Island.java +++ b/src/main/java/world/bentobox/bentobox/database/objects/Island.java @@ -55,6 +55,9 @@ @Table(name = "Islands") public class Island implements DataObject, MetaDataAble { + @Expose + private boolean primary; + /** * Set to true if this data object has been changed since being loaded from the database */ @@ -1648,12 +1651,15 @@ public Map getHomes() { } /** - * @return the homes + * Get the location of a named home + * @param name home name case insensitive (name is forced to lower case) + * @return the home location or if none found the protection center of the island is returned. * @since 1.16.0 */ - @Nullable + @NonNull public Location getHome(String name) { - return getHomes().get(name.toLowerCase()); + Location l = getHomes().get(name.toLowerCase()); + return l == null ? getProtectionCenter() : l; } /** @@ -1842,6 +1848,21 @@ public void clearAllBonusRanges() { setChanged(); } + /** + * @return the primary + */ + public boolean isPrimary() { + return primary; + } + + /** + * @param primary the primary to set + */ + public void setPrimary(boolean primary) { + this.primary = primary; + setChanged(); + } + /* (non-Javadoc) * @see java.lang.Object#toString() */ diff --git a/src/main/java/world/bentobox/bentobox/listeners/JoinLeaveListener.java b/src/main/java/world/bentobox/bentobox/listeners/JoinLeaveListener.java index 48de86840..001aa46db 100644 --- a/src/main/java/world/bentobox/bentobox/listeners/JoinLeaveListener.java +++ b/src/main/java/world/bentobox/bentobox/listeners/JoinLeaveListener.java @@ -215,33 +215,30 @@ private void runAutomatedOwnershipTransfer(User user) { } private void updateIslandRange(User user) { - plugin.getIWM().getOverWorlds().stream() - .filter(world -> plugin.getIslands().isOwner(world, user.getUniqueId())) - .forEach(world -> { - Island island = plugin.getIslands().getIsland(world, user); - if (island != null) { - // Check if new owner has a different range permission than the island size - int range = user.getPermissionValue(plugin.getIWM().getAddon(island.getWorld()).map(GameModeAddon::getPermissionPrefix).orElse("") + "island.range", island.getRawProtectionRange()); - // Range cannot be greater than the island distance - range = Math.min(range, plugin.getIWM().getIslandDistance(island.getWorld())); - // Range can go up or down - if (range != island.getRawProtectionRange()) { - user.sendMessage("commands.admin.setrange.range-updated", TextVariables.NUMBER, String.valueOf(range)); - int oldRange = island.getProtectionRange(); - island.setProtectionRange(range); - - plugin.log("Island protection range changed from " + oldRange + " to " - + island.getProtectionRange() + " for " + user.getName() + " due to permission."); - // Call Protection Range Change event. Does not support canceling. - IslandEvent.builder() - .island(island) - .location(island.getProtectionCenter()) - .reason(IslandEvent.Reason.RANGE_CHANGE) - .involvedPlayer(user.getUniqueId()) - .admin(true) - .protectionRange(island.getProtectionRange(), oldRange) - .build(); - } + plugin.getIslands().getIslands().stream() + .filter(island -> island.getOwner() != null && island.getOwner().equals(user.getUniqueId())) + .forEach(island -> { + // Check if new owner has a different range permission than the island size + int range = user.getPermissionValue(plugin.getIWM().getAddon(island.getWorld()).map(GameModeAddon::getPermissionPrefix).orElse("") + "island.range", island.getRawProtectionRange()); + // Range cannot be greater than the island distance + range = Math.min(range, plugin.getIWM().getIslandDistance(island.getWorld())); + // Range can go up or down + if (range != island.getRawProtectionRange()) { + user.sendMessage("commands.admin.setrange.range-updated", TextVariables.NUMBER, String.valueOf(range)); + int oldRange = island.getProtectionRange(); + island.setProtectionRange(range); + + plugin.log("Island protection range changed from " + oldRange + " to " + + island.getProtectionRange() + " for " + user.getName() + " due to permission."); + // Call Protection Range Change event. Does not support canceling. + IslandEvent.builder() + .island(island) + .location(island.getProtectionCenter()) + .reason(IslandEvent.Reason.RANGE_CHANGE) + .involvedPlayer(user.getUniqueId()) + .admin(true) + .protectionRange(island.getProtectionRange(), oldRange) + .build(); } }); } diff --git a/src/main/java/world/bentobox/bentobox/listeners/PrimaryIslandListener.java b/src/main/java/world/bentobox/bentobox/listeners/PrimaryIslandListener.java new file mode 100644 index 000000000..122b42f33 --- /dev/null +++ b/src/main/java/world/bentobox/bentobox/listeners/PrimaryIslandListener.java @@ -0,0 +1,57 @@ +package world.bentobox.bentobox.listeners; + +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerMoveEvent; +import org.bukkit.event.player.PlayerTeleportEvent; +import org.eclipse.jdt.annotation.NonNull; + +import world.bentobox.bentobox.BentoBox; +import world.bentobox.bentobox.managers.IslandsManager; + +/** + * Sets the player's primary island based on where they teleported or moved to + * @author tastybento + * + */ +public class PrimaryIslandListener implements Listener { + + private final IslandsManager im; + + /** + * @param plugin - plugin object + */ + public PrimaryIslandListener(@NonNull BentoBox plugin) { + this.im = plugin.getIslands(); + } + + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onPlayerJoin(final PlayerJoinEvent event) { + setIsland(event.getPlayer(), event.getPlayer().getLocation()); + } + + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onPlayerMove(final PlayerMoveEvent event) { + if (event.getTo() != null && !event.getFrom().toVector().equals(event.getTo().toVector())) { + setIsland(event.getPlayer(), event.getTo()); + } + } + + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onPlayerMove(final PlayerTeleportEvent event) { + if (event.getTo() != null) { + setIsland(event.getPlayer(), event.getTo()); + } + } + + private void setIsland(Player player, Location location) { + im.getIslandAt(location) + .filter(i -> i.getOwner() != null && i.getOwner().equals(player.getUniqueId())) + .ifPresent(i -> im.setPrimaryIsland(player.getUniqueId(), i)); + } + +} diff --git a/src/main/java/world/bentobox/bentobox/managers/IslandsManager.java b/src/main/java/world/bentobox/bentobox/managers/IslandsManager.java index 60fe88449..d861d1866 100644 --- a/src/main/java/world/bentobox/bentobox/managers/IslandsManager.java +++ b/src/main/java/world/bentobox/bentobox/managers/IslandsManager.java @@ -9,7 +9,6 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; -import java.util.Map.Entry; import java.util.Objects; import java.util.Optional; import java.util.Queue; @@ -80,7 +79,9 @@ public class IslandsManager { */ private final Map last; - // Island Cache + /** + * Island Cache + */ @NonNull private IslandCache islandCache; // Quarantined islands @@ -121,80 +122,6 @@ public void setHandler(@NonNull Database handler) { this.handler = handler; } - /** - * This is a generic scan that can work in the overworld or the nether - * @param l - location around which to scan - * @param i - the range to scan for a location less than 0 means the full island. - * @return - safe location, or null if none can be found - */ - @Nullable - public Location bigScan(@NonNull Location l, int i) { - final int height; - final int depth; - if (i > 0) { - height = i; - depth = i; - } else { - Optional island = getIslandAt(l); - if (island.isEmpty()) { - return null; - } - i = island.get().getProtectionRange(); - height = l.getWorld().getMaxHeight() - l.getBlockY(); - depth = l.getBlockY(); - } - - // Work outwards from l until the closest safe location is found. - int minXradius = 0; - int maxXradius = 0; - int minZradius = 0; - int maxZradius = 0; - int minYradius = 0; - int maxYradius = 0; - - do { - int minX = l.getBlockX()-minXradius; - int minZ = l.getBlockZ()-minZradius; - int minY = l.getBlockY()-minYradius; - int maxX = l.getBlockX()+maxXradius; - int maxZ = l.getBlockZ()+maxZradius; - int maxY = l.getBlockY()+maxYradius; - for (int x = minX; x<= maxX; x++) { - for (int z = minZ; z <= maxZ; z++) { - for (int y = minY; y <= maxY; y++) { - if (!((x > minX && x < maxX) && (z > minZ && z < maxZ) && (y > minY && y < maxY))) { - Location ultimate = new Location(l.getWorld(), x + 0.5D, y, z + 0.5D); - if (isSafeLocation(ultimate)) { - return ultimate; - } - } - } - } - } - if (minXradius < i) { - minXradius++; - } - if (maxXradius < i) { - maxXradius++; - } - if (minZradius < i) { - minZradius++; - } - if (maxZradius < i) { - maxZradius++; - } - if (minYradius < depth) { - minYradius++; - } - if (maxYradius < height) { - maxYradius++; - } - } while (minXradius < i || maxXradius < i || minZradius < i || maxZradius < i || minYradius < depth - || maxYradius < height); - // Nothing worked - return null; - } - /** * Checks if this location is safe for a player to teleport to. Used by * warps and boat exits Unsafe is any liquid or air and also if there's no @@ -347,17 +274,29 @@ public void deleteIsland(@NonNull Island island, boolean removeBlocks, @Nullable } } + /** + * Get the number of islands made on this server. Used by stats. + * @return total number of islands known to this server + */ public int getIslandCount() { return islandCache.size(); } - public int getIslandCount(@NonNull World world) { + /** + * Get the number of islands made on this server in a particular world. Used to limit the number of islands + * if required by settings. + * @param world game world + * @return number of islands + */ + public long getIslandCount(@NonNull World world) { return islandCache.size(world); } /** - * Gets the island for this player. + * Gets the current active island for this player. * If they are in a team, the team island is returned. + * If they have more than one island, then the island they are on now, or the last island they were on + * is returned. * @param world world to check * @param user user * @return Island or null if not found or null user @@ -368,7 +307,33 @@ public Island getIsland(@NonNull World world, @Nullable User user){ } /** - * Gets the island for this player. If they are in a team, the team island is returned. + * Gets the islands for this player. + * If they are in a team, the team island is returned. + * @param world world to check + * @param user user + * @return List of islands or empty list if none found for user + */ + @NonNull + public Set getIslands(@NonNull World world, @NonNull User user){ + return getIslands(world, user.getUniqueId()); + } + + /** + * Gets all the islands for this player in this world. + * If they are in a team, the team island is returned. + * @param world world to check + * @param uuid user's uuid + * @return List of islands or empty list if none found for user + */ + @NonNull + public Set getIslands(@NonNull World world, UUID uniqueId) { + return islandCache.getIslands(world, uniqueId); + } + + /** + * Gets the active island for this player. If they are in a team, the team island is returned. + * User may have more than one island. + * Returns the island the player is on now, or their last known island. * @param world world to check. Includes nether and end worlds. * @param uuid user's uuid * @return Island or null @@ -430,7 +395,7 @@ public void setIslandCache(@NonNull IslandCache islandCache) { } /** - * Returns the player's island location in World based on the island protection center. + * Returns the player's current island location in World based on the island protection center. * If you need the actual island center location for some reason use {@link Island#getCenter()}

* * @param world - world to check @@ -463,6 +428,7 @@ public Location getLast(@NonNull World world) { * @param minimumRank - the minimum rank to be included in the set. * @return Set of team UUIDs */ + @NonNull public Set getMembers(@NonNull World world, @NonNull UUID playerUUID, int minimumRank) { return islandCache.getMembers(world, playerUUID, minimumRank); } @@ -476,6 +442,7 @@ public Set getMembers(@NonNull World world, @NonNull UUID playerUUID, int * @param playerUUID - the player's UUID * @return Set of team UUIDs */ + @NonNull public Set getMembers(@NonNull World world, @NonNull UUID playerUUID) { return islandCache.getMembers(world, playerUUID, RanksManager.MEMBER_RANK); } @@ -580,11 +547,11 @@ public Optional getProtectedIslandAt(@NonNull Location location) { * Get a safe home location using async chunk loading and set the home location * @param world - world * @param user - user - * @param name - home name + * @param homeName - home name * @return CompletableFuture with the location found, or null * @since 1.14.0 */ - private CompletableFuture getAsyncSafeHomeLocation(@NonNull World world, @NonNull User user, String name) { + private CompletableFuture getAsyncSafeHomeLocation(@NonNull World world, @NonNull User user, String homeName) { CompletableFuture result = new CompletableFuture<>(); // Check if the world is a gamemode world and the player has an island Location islandLoc = getIslandLocation(world, user.getUniqueId()); @@ -592,9 +559,18 @@ private CompletableFuture getAsyncSafeHomeLocation(@NonNull World worl result.complete(null); return result; } + // Check if the user is switching island and if so, switch name + String name = this.getIslands(world, user).stream() + .filter(i -> !homeName.isBlank() && i.getName() != null && !i.getName().isBlank() && i.getName().equalsIgnoreCase(homeName)) + .findFirst().map(island -> { + // This is an island, so switch to that island and then go to the default home + this.setPrimaryIsland(user.getUniqueId(), island); + return ""; + }).orElse(homeName); + // Try the home location first Location defaultHome = getHomeLocation(world, user); - Location namedHome = getHomeLocation(world, user, name); + Location namedHome = homeName.isBlank() ? null : getHomeLocation(world, user, name); Location l = namedHome != null ? namedHome : defaultHome; if (l != null) { Util.getChunkAtAsync(l).thenRun(() -> { @@ -813,27 +789,27 @@ public boolean setHomeLocation(@Nullable Island island, Location location, Strin } /** - * Get the home location for user in world + * Get the home location for user in world for their primary island * @param world - world * @param user - user - * @return home location or null if there is no home - * @since 1.16.0 + * @return home location or the protection center location if no home defined + * @since 2.0.0 */ @Nullable public Location getHomeLocation(@NonNull World world, @NonNull User user) { - return getHomeLocation(world, user, ""); + return this.getPrimaryIsland(world, user.getUniqueId()).getHome(""); } /** - * Get the home location for player's UUID in world + * Get the home location for player's UUID in world for their primary island * @param world - world * @param uuid - uuid of player - * @return home location or null if there is no home + * @return home location or the protection center location if no home defined * @since 1.16.0 */ @Nullable public Location getHomeLocation(@NonNull World world, @NonNull UUID uuid) { - return getHomeLocation(world, uuid, ""); + return this.getPrimaryIsland(world, uuid).getHome(""); } /** @@ -859,37 +835,7 @@ public Location getHomeLocation(@NonNull World world, @NonNull User user, String */ @Nullable public Location getHomeLocation(@NonNull World world, @NonNull UUID uuid, String name) { - // Migrate from player homes to island homes - Island island = this.getIsland(world, uuid); - if (island == null) { - return null; - } - migrateHomes(world, uuid, name, island); - return getHomeLocation(island, name); - } - - @SuppressWarnings("removal") - private void migrateHomes(@NonNull World world, @NonNull UUID uuid, String name, Island island) { - Map homes = plugin - .getPlayers() - .getHomeLocations(world, uuid); - if (homes.isEmpty()) { - // No migration required - return; - } - if (island.getOwner() != null && island.getOwner().equals(uuid)) { - // Owner - island.setHomes(homes.entrySet().stream().collect(Collectors.toMap(this::getHomeName, Map.Entry::getKey))); - plugin.getPlayers().clearHomeLocations(world, uuid); - } - } - - private String getHomeName(Entry e) { - // Home 1 has an empty name - if (e.getValue() == 1) { - return ""; - } - return String.valueOf(e.getValue()); + return getIslands(world, uuid).stream().map(is -> is.getHome(name)).filter(Objects::nonNull).findFirst().orElse(null); } /** @@ -912,7 +858,7 @@ public Location getHomeLocation(@NonNull Island island) { */ @NonNull public Location getHomeLocation(@NonNull Island island, @NonNull String name) { - return Objects.requireNonNullElse(island.getHome(name), island.getCenter()); + return Objects.requireNonNullElse(island.getHome(name), island.getProtectionCenter()); } /** @@ -1038,7 +984,7 @@ public CompletableFuture homeTeleportAsync(@NonNull World world, @NonNu * * @param world - world to check * @param player - the player - * @param name - a named home location. Blank means default. + * @param name - a named home location or island name. Blank means default home for current island. * @return CompletableFuture true if successful, false if not * @since 1.16.0 */ @@ -1061,6 +1007,14 @@ public CompletableFuture homeTeleportAsync(@NonNull World world, @NonNu } + /** + * Teleports player async + * @param world world + * @param player player + * @param name - a named home location or island name. Blank means default home for current island. + * @param newIsland true if this is a new island + * @return completable future that is true when the teleport has been completed + */ private CompletableFuture homeTeleportAsync(@NonNull World world, @NonNull Player player, String name, boolean newIsland) { CompletableFuture result = new CompletableFuture<>(); User user = User.getInstance(player); @@ -1081,10 +1035,6 @@ private CompletableFuture homeTeleportAsync(@NonNull World world, @NonN .thenAccept(result::complete); return; } - // Add home - if (getHomeLocations(island).isEmpty()) { - setHomeLocation(player.getUniqueId(), home); - } PaperLib.teleportAsync(player, home).thenAccept(b -> { // Only run the commands if the player is successfully teleported if (Boolean.TRUE.equals(b)) { @@ -1186,6 +1136,10 @@ public void spawnTeleport(@NonNull World world, @NonNull Player player) { } } + /** + * Prepares the player for teleporting by: stopping gliding, exiting any boats and giving the player the boat + * @param player player + */ private void readyPlayer(@NonNull Player player) { // Stop any gliding player.setGliding(false); @@ -1421,10 +1375,7 @@ public void removePlayer(World world, User user) { * @param uuid - user's uuid */ public void removePlayer(World world, UUID uuid) { - Island island = islandCache.removePlayer(world, uuid); - if (island != null) { - handler.saveObjectAsync(island); - } + islandCache.removePlayer(world, uuid).forEach(handler::saveObjectAsync); } /** @@ -1520,15 +1471,6 @@ public void setLast(Location last) { this.last.put(last.getWorld(), last); } - /** - * Called when a player leaves a team - * @param world - world - * @param uuid - the player's UUID - */ - public void setLeaveTeam(World world, UUID uuid) { - removePlayer(world, uuid); - } - public void shutdown(){ plugin.log("Removing coops from islands..."); // Remove all coop associations @@ -1563,12 +1505,15 @@ public void setOwner(World world, User user, UUID targetUUID) { /** * Sets this target as the owner for this island - * @param user requester + * @param user previous owner * @param targetUUID new owner * @param island island to register */ public void setOwner(User user, UUID targetUUID, Island island) { islandCache.setOwner(island, targetUUID); + // Remove the old owner from the island + island.removeMember(user.getUniqueId()); + user.sendMessage("commands.island.team.setowner.name-is-the-owner", "[name]", plugin.getPlayers().getName(targetUUID)); plugin.getIWM().getAddon(island.getWorld()).ifPresent(addon -> { User target = User.getInstance(targetUUID); @@ -1893,4 +1838,33 @@ public boolean isGoingHome(User user) { return goingHome.contains(user.getUniqueId()); } + /** + * Get the number of concurrent islands for this player + * @param uuid UUID of player + * @param world world to check + * @return number of islands this player owns in this game world + */ + public int getNumberOfConcurrentIslands(UUID uuid, World world) { + return islandCache.getIslands(world, uuid).size(); + } + + /** + * Sets the user's primary island + * @param uuid user's uuid + * @param i island + */ + public void setPrimaryIsland(UUID uuid, Island i) { + this.getIslandCache().setPrimaryIsland(uuid, i); + } + + /** + * Convenience method. See {@link IslandCache#get(World, UUID)} + * @param world world + * @param uuid player's UUID + * @return Island of player or null if there isn't one + */ + public Island getPrimaryIsland(World world, UUID uuid) { + return this.getIslandCache().get(world, uuid); + } + } diff --git a/src/main/java/world/bentobox/bentobox/managers/PlayersManager.java b/src/main/java/world/bentobox/bentobox/managers/PlayersManager.java index f15318ceb..a39595825 100644 --- a/src/main/java/world/bentobox/bentobox/managers/PlayersManager.java +++ b/src/main/java/world/bentobox/bentobox/managers/PlayersManager.java @@ -10,7 +10,6 @@ import java.util.Set; import java.util.UUID; -import org.bukkit.Location; import org.bukkit.World; import org.bukkit.entity.Player; import org.bukkit.entity.Tameable; @@ -191,108 +190,6 @@ public boolean isKnown(UUID uniqueID) { return uniqueID != null && (playerCache.containsKey(uniqueID) || handler.objectExists(uniqueID.toString())); } - /** - * Sets the home location for the player - * @param user - the player - * @param location - the location - * @param number - a number - 1 is default. Can be any number. - * @deprecated Use {@link IslandsManager#setHomeLocation(User, Location, String)} - */ - @Deprecated(since="1.18.0", forRemoval=true) - public void setHomeLocation(User user, Location location, int number) { - setHomeLocation(user.getUniqueId(), location,number); - } - - /** - * Sets the home location for the player - * @param playerUUID - the player's UUID - * @param location - the location - * @param number - a number - 1 is default. Can be any number. - * @deprecated Use {@link IslandsManager#setHomeLocation(UUID, Location, String)} - */ - @Deprecated(since="1.18.0", forRemoval=true) - public void setHomeLocation(UUID playerUUID, Location location, int number) { - addPlayer(playerUUID); - playerCache.get(playerUUID).setHomeLocation(location,number); - } - - /** - * Set the default home location for player - * @param playerUUID - the player's UUID - * @param location - the location - * @deprecated Use {@link IslandsManager#setHomeLocation(UUID, Location)} - */ - @Deprecated(since="1.18.0", forRemoval=true) - public void setHomeLocation(UUID playerUUID, Location location) { - setHomeLocation(playerUUID, location,1); - } - - /** - * Clears any home locations for player - * @param world - world - * @param playerUUID - the player's UUID - * @deprecated Not used anymore. Home locations are stored on islands. - */ - @Deprecated(since="1.18.0", forRemoval=true) - public void clearHomeLocations(World world, UUID playerUUID) { - addPlayer(playerUUID); - playerCache.get(playerUUID).clearHomeLocations(world); - } - - /** - * Returns the home location, or null if none - * @param world - world - * - * @param user - the player - * @param number - a number - * @return Home location or null if none - * @deprecated Use {@link IslandsManager#getHomeLocation(World, User, String)} - */ - @Deprecated(since="1.18.0", forRemoval=true) - public Location getHomeLocation(World world, User user, int number) { - addPlayer(user.getUniqueId()); - return playerCache.get(user.getUniqueId()).getHomeLocation(world, number); - } - - /** - * Returns the home location, or null if none - * @param world - world - * - * @param playerUUID - the player's UUID - * @param number - a number - * @return Home location or null if none - * @deprecated Use {@link IslandsManager#getHomeLocation(World, UUID, String)} - */ - @Deprecated(since="1.18.0", forRemoval=true) - public Location getHomeLocation(World world, UUID playerUUID, int number) { - addPlayer(playerUUID); - return playerCache.get(playerUUID).getHomeLocation(world, number); - } - - /** - * Gets the default home location for player - * @param playerUUID - the player's UUID - * @return Home location or null if none - * @deprecated Use {@link IslandsManager#getHomeLocation(World, UUID)} - */ - @Deprecated(since="1.18.0", forRemoval=true) - public Location getHomeLocation(World world, UUID playerUUID) { - addPlayer(playerUUID); - return playerCache.get(playerUUID).getHomeLocation(world, 1); - } - - /** - * Provides all home locations for player - * @param playerUUID - the player's UUID - * @return Map of home locations - * @deprecated Use {@link IslandsManager#getHomeLocations(world.bentobox.bentobox.database.objects.Island)} - */ - @Deprecated(since="1.18.0", forRemoval=true) - public Map getHomeLocations(World world, UUID playerUUID) { - addPlayer(playerUUID); - return playerCache.get(playerUUID).getHomeLocations(world); - } - /** * Attempts to return a UUID for a given player's name. * @param name - name of player diff --git a/src/main/java/world/bentobox/bentobox/managers/island/IslandCache.java b/src/main/java/world/bentobox/bentobox/managers/island/IslandCache.java index 976266070..91d886f78 100644 --- a/src/main/java/world/bentobox/bentobox/managers/island/IslandCache.java +++ b/src/main/java/world/bentobox/bentobox/managers/island/IslandCache.java @@ -5,9 +5,9 @@ import java.util.HashMap; import java.util.HashSet; import java.util.Map; -import java.util.Objects; import java.util.Set; import java.util.UUID; +import java.util.stream.Collectors; import org.bukkit.Location; import org.bukkit.World; @@ -20,6 +20,7 @@ import world.bentobox.bentobox.util.Util; /** + * This class stores the islands in memory * @author tastybento */ public class IslandCache { @@ -34,7 +35,8 @@ public class IslandCache { * Every player who is associated with an island is in this map. */ @NonNull - private final Map<@NonNull World, @NonNull Map<@NonNull UUID, @NonNull Island>> islandsByUUID; + private final Map<@NonNull UUID, Set> islandsByUUID; + @NonNull private final Map<@NonNull World, @NonNull IslandGrid> grids; @@ -62,12 +64,10 @@ public boolean addIsland(@NonNull Island island) { if (addToGrid(island)) { islandsByLocation.put(island.getCenter(), island); islandsById.put(island.getUniqueId(), island); - // Make world - islandsByUUID.putIfAbsent(island.getWorld(), new HashMap<>()); // Only add islands to this map if they are owned if (island.isOwned()) { - islandsByUUID.get(island.getWorld()).put(island.getOwner(), island); - island.getMemberSet().forEach(member -> islandsByUUID.get(island.getWorld()).put(member, island)); + islandsByUUID.computeIfAbsent(island.getOwner(), k -> new HashSet<>()).add(island); + island.getMemberSet().forEach(member -> addPlayer(member, island)); } return true; } @@ -80,7 +80,7 @@ public boolean addIsland(@NonNull Island island) { * @param island island to associate with this uuid. Only one island can be associated per world. */ public void addPlayer(@NonNull UUID uuid, @NonNull Island island) { - islandsByUUID.computeIfAbsent(island.getWorld(), k -> new HashMap<>()).put(uuid, island); + islandsByUUID.computeIfAbsent(uuid, k -> new HashSet<>()).add(island); } /** @@ -99,21 +99,27 @@ public void clear() { } /** - * Deletes an island from the cache.. Does not remove blocks + * Deletes an island from the cache. Does not remove blocks. * @param island island to delete * @return true if successful, false if not */ public boolean deleteIslandFromCache(@NonNull Island island) { - if (!islandsByLocation.remove(island.getCenter(), island) || !islandsByUUID.containsKey(island.getWorld())) { + if (!islandsByLocation.remove(island.getCenter(), island)) { return false; } islandsById.remove(island.getUniqueId()); - islandsByUUID.get(island.getWorld()).entrySet().removeIf(en -> en.getValue().equals(island)); + removeFromIslandsByUUID(island); // Remove from grid grids.putIfAbsent(island.getWorld(), new IslandGrid()); return grids.get(island.getWorld()).removeFromGrid(island); } + private void removeFromIslandsByUUID(Island island) { + for (Set set : islandsByUUID.values()) { + set.removeIf(island::equals); + } + } + /** * Delete island from the cache by ID. Does not remove blocks. * @param uniqueId - island unique ID @@ -121,7 +127,9 @@ public boolean deleteIslandFromCache(@NonNull Island island) { public void deleteIslandFromCache(@NonNull String uniqueId) { islandsById.remove(uniqueId); islandsByLocation.values().removeIf(i -> i.getUniqueId().equals(uniqueId)); - islandsByUUID.values().forEach(m -> m.values().removeIf(i -> i.getUniqueId().equals(uniqueId))); + for (Set set : islandsByUUID.values()) { + set.removeIf(i -> i.getUniqueId().equals(uniqueId)); + } } /** @@ -135,18 +143,52 @@ public Island get(@NonNull Location location) { } /** - * Returns island referenced by UUID + * Returns island referenced by player's UUID. + * Returns the island the player is on now, or their last known island * @param world world to check. Includes nether and end worlds. * @param uuid player's UUID * @return island or null if none */ @Nullable public Island get(@NonNull World world, @NonNull UUID uuid) { + Set islands = getIslands(world, uuid); + if (islands.isEmpty()) { + return null; + } + for (Island island : islands) { + if (island.isPrimary()) { + return island; + } + } + // If there is no primary set, then set one - it doesn't matter which. + Island result = islands.iterator().next(); + result.setPrimary(true); + return result; + } + + /** + * Returns all the islands referenced by player's UUID. + * @param world world to check. Includes nether and end worlds. + * @param uuid player's UUID + * @return list of island or empty list if none + */ + public Set getIslands(@NonNull World world, @NonNull UUID uuid) { World w = Util.getWorld(world); if (w == null) { - return null; + return new HashSet<>(); + } + return islandsByUUID.computeIfAbsent(uuid, k -> new HashSet<>()).stream().filter(i -> world.equals(i.getWorld())).collect(Collectors.toSet()); + } + + /** + * Sets the current island for the user as their primary island + * @param uuid UUID of user + * @param island island to make primary + */ + public void setPrimaryIsland(@NonNull UUID uuid, @NonNull Island island) { + for (Island is : getIslands(island.getWorld(), uuid)) { + is.setPrimary(island.equals(is)); } - return islandsByUUID.containsKey(w) ? islandsByUUID.get(w).get(uuid) : null; } /** @@ -192,49 +234,44 @@ public Collection getIslands(@NonNull World world) { } /** + * Get the members of the user's team * @param world world to check * @param uuid uuid of player to check * @param minimumRank minimum rank requested - * @return set of UUID's of island members. If there is no island, this set will be empty + * @return set of UUID's of island members. If there are no islands, this set will be empty */ @NonNull public Set getMembers(@NonNull World world, @NonNull UUID uuid, int minimumRank) { - World w = Util.getWorld(world); - if (w == null) { - return new HashSet<>(); - } - Island island = islandsByUUID.computeIfAbsent(w, k -> new HashMap<>()).get(uuid); - return island != null ? island.getMemberSet(minimumRank) : new HashSet<>(); + return getIslands(world, uuid) + .stream() + .flatMap(island -> island.getMemberSet(minimumRank).stream()) + .collect(Collectors.toSet()); } /** + * Get the UUID of the owner of the island of the player, which may be their UUID * @param world the world to check * @param uuid the player's UUID - * @return island owner's UUID, the player UUID if they are not in a team, or null if there is no island + * @return island owner's UUID or null if there is no island */ @Nullable public UUID getOwner(@NonNull World world, @NonNull UUID uuid) { World w = Util.getWorld(world); - if (w == null) { + Set islands = islandsByUUID.get(uuid); + if (w == null || islands == null || islands.isEmpty()) { return null; } - Island island = islandsByUUID.computeIfAbsent(w, k -> new HashMap<>()).get(uuid); - return island != null ? island.getOwner() : null; - + return islands.iterator().next().getOwner(); // This assumes that all islands in this set have the same owner } /** + * Checks is a player has an island and owns it * @param world the world to check * @param uuid the player * @return true if player has island and owns it */ public boolean hasIsland(@NonNull World world, @NonNull UUID uuid) { - World w = Util.getWorld(world); - if (w == null) { - return false; - } - Island island = islandsByUUID.computeIfAbsent(w, k -> new HashMap<>()).get(uuid); - return island != null && uuid.equals(island.getOwner()); + return uuid.equals(getOwner(world, uuid)); } /** @@ -242,27 +279,27 @@ public boolean hasIsland(@NonNull World world, @NonNull UUID uuid) { * The island is removed from the islandsByUUID map, but kept in the location map. * @param world world * @param uuid player's UUID - * @return island player had or null if none + * @return list of islands player had or empty if none */ - @Nullable - public Island removePlayer(@NonNull World world, @NonNull UUID uuid) { + public Set removePlayer(@NonNull World world, @NonNull UUID uuid) { World w = Util.getWorld(world); - if (w == null) { - return null; + Set islandSet = islandsByUUID.get(uuid); + if (w == null || islandSet == null) { + return Collections.emptySet(); // Return empty list if no islands map exists for the world } - Island island = islandsByUUID.computeIfAbsent(w, k -> new HashMap<>()).get(uuid); - if (island != null) { + + islandSet.forEach(island -> { if (uuid.equals(island.getOwner())) { - // Clear ownership and members island.getMembers().clear(); island.setOwner(null); } else { - // Remove player from the island membership island.removeMember(uuid); } - } - islandsByUUID.get(w).remove(uuid); - return island; + }); + + islandsByUUID.remove(uuid); + + return islandSet; } /** @@ -278,8 +315,8 @@ public int size() { * @param world world to get the number of islands in * @return the number of islands */ - public int size(World world) { - return islandsByUUID.getOrDefault(world, new HashMap<>(0)).size(); + public long size(World world) { + return this.islandsByLocation.keySet().stream().map(Location::getWorld).filter(world::equals).count(); } /** @@ -291,7 +328,7 @@ public int size(World world) { public void setOwner(@NonNull Island island, @Nullable UUID newOwnerUUID) { island.setOwner(newOwnerUUID); if (newOwnerUUID != null) { - islandsByUUID.computeIfAbsent(Objects.requireNonNull(Util.getWorld(island.getWorld())), k -> new HashMap<>()).put(newOwnerUUID, island); + islandsByUUID.computeIfAbsent(newOwnerUUID, k -> new HashSet<>()).add(island); } islandsByLocation.put(island.getCenter(), island); islandsById.put(island.getUniqueId(), island); @@ -316,13 +353,12 @@ public Island getIslandById(@NonNull String uniqueId) { public void removeIsland(@NonNull Island island) { islandsByLocation.values().removeIf(island::equals); islandsById.values().removeIf(island::equals); + islandsByUUID.values().removeIf(island::equals); World w = Util.getWorld(island.getWorld()); if (w == null) { return; } - if (islandsByUUID.containsKey(w)) { - islandsByUUID.get(w).values().removeIf(island::equals); - } + if (grids.containsKey(w)) { grids.get(w).removeFromGrid(island); } diff --git a/src/main/java/world/bentobox/bentobox/managers/island/NewIsland.java b/src/main/java/world/bentobox/bentobox/managers/island/NewIsland.java index 708783d73..c32ed9f1b 100644 --- a/src/main/java/world/bentobox/bentobox/managers/island/NewIsland.java +++ b/src/main/java/world/bentobox/bentobox/managers/island/NewIsland.java @@ -322,4 +322,4 @@ private void tidyUp(Island oldIsland) { .build(); } -} +} \ No newline at end of file diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 997ce06c6..84e8787f6 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -119,6 +119,9 @@ logs: # Added since 1.5.0. github-download-data: true island: + # The default number of concurrent islands a player may have. + # This may be overridden by individual game mode config settings. + concurrent-islands: 1 cooldown: time: # How long a player must wait until they can rejoin a team island after being kicked in minutes. diff --git a/src/main/resources/locales/cs.yml b/src/main/resources/locales/cs.yml index 2043d0b25..b3adbfcfd 100644 --- a/src/main/resources/locales/cs.yml +++ b/src/main/resources/locales/cs.yml @@ -863,9 +863,9 @@ protection: island: 'Ostrov [name]' name: Hlášení o návštěvě/opuštění now-entering: '&a Právě vcházíš na &b [name]&a .' - now-entering-your-island: '&a Právě vcházíš na svůj ostrov.' + now-entering-your-island: '&a Právě vcházíš na svůj ostrov: &b [name]' now-leaving: '&a Právě odcházíš od &b [name]&a .' - now-leaving-your-island: '&a Právě odcházíš ze svého ostrova.' + now-leaving-your-island: '&a Právě odcházíš ze svého ostrova: &b [name]' EXPERIENCE_BOTTLE_THROWING: name: Házení zkošenostními lahvičkami description: Přepnout házení zkušenostními lahvičkami. diff --git a/src/main/resources/locales/de.yml b/src/main/resources/locales/de.yml index 081a02d5f..62d67e1a8 100644 --- a/src/main/resources/locales/de.yml +++ b/src/main/resources/locales/de.yml @@ -978,9 +978,9 @@ protection: island: "[name]'s Insel" name: Ein- und Ausgangsmeldungen now-entering: "&b Du betrittst jetzt [name]" - now-entering-your-island: "&a Geben Sie jetzt Ihre Insel ein." + now-entering-your-island: "&a Geben Sie jetzt Ihre Insel ein: &b [name]" now-leaving: "&b Du verlässt jetzt [name]" - now-leaving-your-island: "&a Verlasse jetzt deine Insel." + now-leaving-your-island: "&a Verlasse jetzt deine Insel: &b [name]" EXPERIENCE_BOTTLE_THROWING: name: Erfahrungsflasche werfen description: Umschalten des Werfens von Erfahrungsflaschen. diff --git a/src/main/resources/locales/en-US.yml b/src/main/resources/locales/en-US.yml index 2c742076c..4a5a4c11a 100644 --- a/src/main/resources/locales/en-US.yml +++ b/src/main/resources/locales/en-US.yml @@ -1,7 +1,7 @@ -########################################################################################### +# ########################################################################################## # This is a YML file. Be careful when editing. Check your edits in a YAML checker like # # the one at http://yaml-online-parser.appspot.com # -########################################################################################### +# ########################################################################################## # This locale is always current with the latest version @@ -9,821 +9,866 @@ meta: authors: - tastybento - Poslovitch - banner: "WHITE_BANNER:1:STRIPE_SMALL:RED:SQUARE_TOP_RIGHT:CYAN:SQUARE_TOP_RIGHT:BLUE" + banner: WHITE_BANNER:1:STRIPE_SMALL:RED:SQUARE_TOP_RIGHT:CYAN:SQUARE_TOP_RIGHT:BLUE prefixes: bentobox: '&6 BentoBox &7 &l > &r ' general: - success: "&a Success!" - invalid: "Invalid" + success: '&a Success!' + invalid: Invalid errors: - command-cancelled: "&c Command cancelled." - no-permission: "&c You don't have the permission to execute this command (&7 [permission]&c )." - insufficient-rank: "&c Your rank is not high enough to do that! (&7 [rank]&c )" - use-in-game: "&c This command is only available in-game." - use-in-console: "&c This command is only available in the console." - no-team: "&c You do not have a team!" - no-island: "&c You do not have an island!" - player-has-island: "&c Player already has an island!" - player-has-no-island: "&c That player has no island!" - already-have-island: "&c You already have an island!" - no-safe-location-found: "&c Could not find a safe spot to teleport you to on the island." - not-owner: "&c You are not the owner of the island!" - player-is-not-owner: "&b [name] &c is not the owner of an island!" - not-in-team: "&c That player is not in your team!" - offline-player: "&c That player is offline or doesn't exist." - unknown-player: "&c [name] is an unknown player!" - general: "&c That command is not ready yet - contact admin" - unknown-command: "&c Unknown command. Do &b /[label] help &c for help." - wrong-world: "&c You are not in the right world to do that!" - you-must-wait: "&c You must wait [number]s before you can do that command again." - must-be-positive-number: "&c [number] is not a valid positive number." - not-on-island: "&c You are not on island!" + command-cancelled: '&c Command cancelled.' + no-permission: '&c You don''t have the permission to execute this command (&7 + [permission]&c ).' + insufficient-rank: '&c Your rank is not high enough to do that! (&7 [rank]&c )' + use-in-game: '&c This command is only available in-game.' + use-in-console: '&c This command is only available in the console.' + no-team: '&c You do not have a team!' + no-island: '&c You do not have an island!' + player-has-island: '&c Player already has an island!' + player-has-no-island: '&c That player has no island!' + already-have-island: '&c You already have an island!' + no-safe-location-found: '&c Could not find a safe spot to teleport you to on the + island.' + not-owner: '&c You are not the owner of the island!' + player-is-not-owner: '&b [name] &c is not the owner of an island!' + not-in-team: '&c That player is not in your team!' + offline-player: '&c That player is offline or doesn''t exist.' + unknown-player: '&c [name] is an unknown player!' + general: '&c That command is not ready yet - contact admin' + unknown-command: '&c Unknown command. Do &b /[label] help &c for help.' + wrong-world: '&c You are not in the right world to do that!' + you-must-wait: '&c You must wait [number]s before you can do that command again.' + must-be-positive-number: '&c [number] is not a valid positive number.' + not-on-island: '&c You are not on island!' worlds: - overworld: "Overworld" - nether: "Nether" - the-end: "The End" + overworld: Overworld + nether: Nether + the-end: The End commands: # Parameters in <> are required, parameters in [] are optional help: - header: "&7 =========== &c [label] help &7 ===========" - syntax: "&b [usage] &a [parameters]&7 : &e [description]" - syntax-no-parameters: "&b [usage]&7 : &e [description]" - end: "&7 =================================" - parameters: "[command]" - description: "help command" - console: "Console" + header: '&7 =========== &c [label] help &7 ===========' + syntax: '&b [usage] &a [parameters]&7 : &e [description]' + syntax-no-parameters: '&b [usage]&7 : &e [description]' + end: '&7 =================================' + parameters: '[command]' + description: help command + console: Console admin: help: - description: "admin command" + description: admin command resets: - description: "edit player reset values" + description: edit player reset values set: - description: "sets how many times this player has reset his island" - parameters: " " - success: "&b [name]&a 's island reset count is now &b [number]&a ." + description: sets how many times this player has reset his island + parameters: + success: '&b [name]&a ''s island reset count is now &b [number]&a .' reset: - description: "sets the player's island reset count to 0" - parameters: "" - success-everyone: "&a Successfully reset &b everyone&a 's reset count to &b 0&a ." - success: "&a Successfully reset &b [name]&a 's reset count to &b 0&a ." + description: sets the player's island reset count to 0 + parameters: + success-everyone: '&a Successfully reset &b everyone&a ''s reset count to + &b 0&a .' + success: '&a Successfully reset &b [name]&a ''s reset count to &b 0&a .' add: - description: "adds this player's island reset count" - parameters: " " - success: "&a Successfully added &b [number] &a resets to &b [name], increasing the total to &b [total]&a resets." + description: adds this player's island reset count + parameters: + success: '&a Successfully added &b [number] &a resets to &b [name], increasing + the total to &b [total]&a resets.' remove: - description: "reduces the player's island reset count" - parameters: " " - success: "&a Successfully removed &b [number] &a resets from &b [name]'s island&a, decreasing the total to &b[total]&a resets." + description: reduces the player's island reset count + parameters: + success: '&a Successfully removed &b [number] &a resets from &b [name]''s + island&a, decreasing the total to &b[total]&a resets.' purge: - parameters: "[days]" - description: "purge islands abandoned for more than [days]" - days-one-or-more: "Must be at least 1 day or more" - purgable-islands: "&a Found &b [number] &a purgable islands." - purge-in-progress: "&c Purging in progress. Use &b /[label] purge stop &c to cancel." - number-error: "&c Argument must be a number of days" - confirm: "&d Type &b /[label] purge confirm &d to start purging" - completed: "&a Purging stopped." - see-console-for-status: "&a Purge started. See console for status or use &b /[label] purge status&a." - no-purge-in-progress: "&c There is currently no purge in progress." + parameters: '[days]' + description: purge islands abandoned for more than [days] + days-one-or-more: Must be at least 1 day or more + purgable-islands: '&a Found &b [number] &a purgable islands.' + purge-in-progress: '&c Purging in progress. Use &b /[label] purge stop &c to + cancel.' + number-error: '&c Argument must be a number of days' + confirm: '&d Type &b /[label] purge confirm &d to start purging' + completed: '&a Purging stopped.' + see-console-for-status: '&a Purge started. See console for status or use &b + /[label] purge status&a.' + no-purge-in-progress: '&c There is currently no purge in progress.' protect: - description: "toggle island purge protection" - move-to-island: "&c Move to an island first!" - protecting: "&a Protecting island from purge." - unprotecting: "&a Removing purge protection." + description: toggle island purge protection + move-to-island: '&c Move to an island first!' + protecting: '&a Protecting island from purge.' + unprotecting: '&a Removing purge protection.' stop: - description: "stop a purge in progress" - stopping: "Stopping the purge" + description: stop a purge in progress + stopping: Stopping the purge unowned: - description: "purge unowned islands" - unowned-islands: "&a Found &b [number] &a unowned islands." + description: purge unowned islands + unowned-islands: '&a Found &b [number] &a unowned islands.' status: - description: "displays the status of the purge" - status: "&b [purged] &a islands purged out of &b [purgeable] &7(&b[percentage] %&7)&a." - + description: displays the status of the purge + status: '&b [purged] &a islands purged out of &b [purgeable] &7(&b[percentage] + %&7)&a.' + team: - description: "manage teams" + description: manage teams add: - parameters: " " - description: "add player to owner's team" - name-not-owner: "&c [name] is not the owner." - name-has-island: "&c [name] has an island. Unregister or delete them first!" - success: "&b [name]&a has been added to &b [owner]&a 's island." + parameters: + description: add player to owner's team + name-not-owner: '&c [name] is not the owner.' + name-has-island: '&c [name] has an island. Unregister or delete them first!' + success: '&b [name]&a has been added to &b [owner]&a ''s island.' disband: - parameters: "" - description: "disband owner's team" - use-disband-owner: "&c Not owner! Use disband [owner]." - disbanded: "&c Admin disbanded your team!" - success: "&b [name]&a 's team has been disbanded." + parameters: + description: disband owner's team + use-disband-owner: '&c Not owner! Use disband [owner].' + disbanded: '&c Admin disbanded your team!' + success: '&b [name]&a ''s team has been disbanded.' fix: - description: "scans and fixes cross island membership in database" - scanning: "Scanning database..." - duplicate-owner: "&c Player owns more than one island in the database: [name]" - player-has: "&c Player [name] has [number] islands" - duplicate-member: "&c Player [name] is a member of more than one island in the database" - rank-on-island: "&c [rank] on island at [xyz]" - fixed: "&a Fixed" - done: "&a Scan" + description: scans and fixes cross island membership in database + scanning: Scanning database... + duplicate-owner: '&c Player owns more than one island in the database: [name]' + player-has: '&c Player [name] has [number] islands' + duplicate-member: '&c Player [name] is a member of more than one island in + the database' + rank-on-island: '&c [rank] on island at [xyz]' + fixed: '&a Fixed' + done: '&a Scan' kick: - parameters: "" - description: "kick a player from a team" - cannot-kick-owner: "&c You cannot kick the owner. Kick members first." - not-in-team: "&c This player is not in a team." - admin-kicked: "&c The admin kicked you from the team." - success: "&b [name] &a has been kicked from &b [owner]&a 's island." + parameters: + description: kick a player from a team + cannot-kick-owner: '&c You cannot kick the owner. Kick members first.' + not-in-team: '&c This player is not in a team.' + admin-kicked: '&c The admin kicked you from the team.' + success: '&b [name] &a has been kicked from &b [owner]&a ''s island.' setowner: - parameters: "" - description: "transfers island ownership to the player" - already-owner: "&c [name] is already the owner of this island!" - success: "&b [name]&a is now the owner of this island." + parameters: + description: transfers island ownership to the player + already-owner: '&c [name] is already the owner of this island!' + success: '&b [name]&a is now the owner of this island.' range: - description: "admin island range command" + description: admin island range command invalid-value: - too-low: "&c The protection range must be greater than &b 1&c !" - too-high: "&c The protection range should be equal or less than &b [number]&c !" - same-as-before: "&c The protection range is already set to &b [number]&c !" + too-low: '&c The protection range must be greater than &b 1&c !' + too-high: '&c The protection range should be equal or less than &b [number]&c + !' + same-as-before: '&c The protection range is already set to &b [number]&c !' display: - already-off: "&c Indicators are already off" - already-on: "&c Indicators are already on" - description: "show/hide island range indicators" - hiding: "&2 Hiding range indicators" + already-off: '&c Indicators are already off' + already-on: '&c Indicators are already on' + description: show/hide island range indicators + hiding: '&2 Hiding range indicators' hint: |- &c Red Barrier icons &f show the current island protected range limit. &7 Gray Particles &f show the max island limit. &a Green Particles &f show the default protected range if the island protection range differs from it. - showing: "&2 Showing range indicators" + showing: '&2 Showing range indicators' set: - parameters: " " - description: "sets the island protected range" - success: "&a Set island protection range to &b [number]&a ." + parameters: + description: sets the island protected range + success: '&a Set island protection range to &b [number]&a .' reset: - parameters: "" - description: "resets the island protected range to the world default" - success: "&a Reset island protection range to &b [number]&a ." + parameters: + description: resets the island protected range to the world default + success: '&a Reset island protection range to &b [number]&a .' add: - description: "increases the island protected range" - parameters: " " - success: "&a Successfully increased &b [name]&a 's island protected range to &b [total] &7 (&b +[number]&7 )&a ." + description: increases the island protected range + parameters: + success: '&a Successfully increased &b [name]&a ''s island protected range + to &b [total] &7 (&b +[number]&7 )&a .' remove: - description: "decreases the island protected range" - parameters: " " - success: "&a Successfully decreased &b [name]&a 's island protected range to &b [total] &7 (&b -[number]&7 )&a ." + description: decreases the island protected range + parameters: + success: '&a Successfully decreased &b [name]&a ''s island protected range + to &b [total] &7 (&b -[number]&7 )&a .' register: - parameters: "" - description: "register player to unowned island you are on" - registered-island: "&a Registered [name] to island at [xyz]." - reserved-island: "&a Reserved island at [xyz] for [name]." - already-owned: "&c Island is already owned by another player!" - no-island-here: "&c There is no island here. Confirm to make one." - in-deletion: "&c This island space is currently being deleted. Try later." - cannot-make-island: "&c An island cannot be placed here, sorry. See console for possible errors." - island-is-spawn: "&6 Island is spawn. Are you sure? Enter command again to confirm." + parameters: + description: register player to unowned island you are on + registered-island: '&a Registered [name] to island at [xyz].' + reserved-island: '&a Reserved island at [xyz] for [name].' + already-owned: '&c Island is already owned by another player!' + no-island-here: '&c There is no island here. Confirm to make one.' + in-deletion: '&c This island space is currently being deleted. Try later.' + cannot-make-island: '&c An island cannot be placed here, sorry. See console + for possible errors.' + island-is-spawn: '&6 Island is spawn. Are you sure? Enter command again to confirm.' unregister: - parameters: "" - description: "unregister owner from island, but keep island blocks" - unregistered-island: "&a Unregistered [name] from island at [xyz]." + parameters: + description: unregister owner from island, but keep island blocks + unregistered-island: '&a Unregistered [name] from island at [xyz].' info: - parameters: "" - description: "get info on where you are or player's island" - no-island: "&c You are not on an island right now..." - title: "========== Island Info ============" - island-uuid: "UUID: [uuid]" - owner: "Owner: [owner] ([uuid])" - last-login: "Last login: [date]" - last-login-date-time-format: "EEE MMM dd HH:mm:ss zzz yyyy" - deaths: "Deaths: [number]" - resets-left: "Resets: [number] (Max: [total])" - team-members-title: "Team members:" - team-owner-format: "&a [name] [rank]" - team-member-format: "&b [name] [rank]" - island-protection-center: "Protection area center: [xyz]" - island-center: "Island center: [xyz]" - island-coords: "Island coordinates: [xz1] to [xz2]" - islands-in-trash: "&d Player has islands in trash." - protection-range: "Protection range: [range]" - protection-range-bonus-title: "&b Includes these bonues:" - protection-range-bonus: "Bonus: [number]" - purge-protected: "Island is purge protected" - max-protection-range: "Largest historical protection range: [range]" - protection-coords: "Protection coordinates: [xz1] to [xz2]" - is-spawn: "Island is a spawn island" - banned-players: "Banned players:" - banned-format: "&c [name]" - unowned: "&c Unowned" + parameters: + description: get info on where you are or player's island + no-island: '&c You are not on an island right now...' + title: ========== Island Info ============ + island-uuid: 'UUID: [uuid]' + owner: 'Owner: [owner] ([uuid])' + last-login: 'Last login: [date]' + last-login-date-time-format: EEE MMM dd HH:mm:ss zzz yyyy + deaths: 'Deaths: [number]' + resets-left: 'Resets: [number] (Max: [total])' + team-members-title: 'Team members:' + team-owner-format: '&a [name] [rank]' + team-member-format: '&b [name] [rank]' + island-protection-center: 'Protection area center: [xyz]' + island-center: 'Island center: [xyz]' + island-coords: 'Island coordinates: [xz1] to [xz2]' + islands-in-trash: '&d Player has islands in trash.' + protection-range: 'Protection range: [range]' + protection-range-bonus-title: '&b Includes these bonues:' + protection-range-bonus: 'Bonus: [number]' + purge-protected: Island is purge protected + max-protection-range: 'Largest historical protection range: [range]' + protection-coords: 'Protection coordinates: [xz1] to [xz2]' + is-spawn: Island is a spawn island + banned-players: 'Banned players:' + banned-format: '&c [name]' + unowned: '&c Unowned' switch: - description: "switch on/off protection bypass" - op: "&c Ops can always bypass protection. Deop to use command." - removing: "&a Removing protection bypass..." - adding: "&a Adding protection bypass..." + description: switch on/off protection bypass + op: '&c Ops can always bypass protection. Deop to use command.' + removing: '&a Removing protection bypass...' + adding: '&a Adding protection bypass...' switchto: - parameters: " " - description: "switch player's island to the numbered one in trash" - out-of-range: "&c Number must be between 1 and [number]. Use &l [label] trash [player] &r &c to see island numbers" - cannot-switch: "&c Switch failed. See console log for error." - success: "&a Successfully switched the player's island to the specified one." + parameters: + description: switch player's island to the numbered one in trash + out-of-range: '&c Number must be between 1 and [number]. Use &l [label] trash + [player] &r &c to see island numbers' + cannot-switch: '&c Switch failed. See console log for error.' + success: '&a Successfully switched the player''s island to the specified one.' trash: - no-unowned-in-trash: "&c No unowned islands in trash" - no-islands-in-trash: "&c Player has no islands in trash" - parameters: "[player]" - description: "show unowned islands or player's islands in trash" - title: "&d =========== Islands in Trash ===========" - count: "&l &d Island [number]:" - use-switch: "&a Use &l [label] switchto &r &a to switch player to island in trash" - use-emptytrash: "&a Use &l [label] emptytrash [player]&r &a to permanently remove trash items" + no-unowned-in-trash: '&c No unowned islands in trash' + no-islands-in-trash: '&c Player has no islands in trash' + parameters: '[player]' + description: show unowned islands or player's islands in trash + title: '&d =========== Islands in Trash ===========' + count: '&l &d Island [number]:' + use-switch: '&a Use &l [label] switchto &r &a to switch player + to island in trash' + use-emptytrash: '&a Use &l [label] emptytrash [player]&r &a to permanently + remove trash items' emptytrash: - parameters: "[player]" - description: "Clear trash for player, or all unowned islands in trash" - success: "&a Trash successfully emptied." + parameters: '[player]' + description: Clear trash for player, or all unowned islands in trash + success: '&a Trash successfully emptied.' version: - description: "display BentoBox and addons versions" + description: display BentoBox and addons versions setrange: - parameters: " " - description: "set the range of player's island" - range-updated: "&a Island range updated to &b [number]&a ." + parameters: + description: set the range of player's island + range-updated: '&a Island range updated to &b [number]&a .' reload: - description: "reload" + description: reload tp: - parameters: " [player to teleport]" - description: "teleport to a player's island" - manual: "&c No safe warp found! Manually tp near to &b [location] &c and check it out" + parameters: [player to teleport] + description: teleport to a player's island + manual: '&c No safe warp found! Manually tp near to &b [location] &c and check + it out' getrank: - parameters: " [island owner]" - description: "get a player's rank on their island or the island of the owner" - rank-is: "&a Rank is &b [rank] &a on &b [name]&a 's island." + parameters: [island owner] + description: get a player's rank on their island or the island of the owner + rank-is: '&a Rank is &b [rank] &a on &b [name]&a ''s island.' setrank: - parameters: " [island owner]" - description: "set a player's rank on their island or the island of the owner" - unknown-rank: "&c Unknown rank!" - not-possible: "&c Rank must be higher than visitor." - rank-set: "&a Rank set from &b [from] &a to &b [to] &a on &b [name]&a 's island." + parameters: [island owner] + description: set a player's rank on their island or the island of the owner + unknown-rank: '&c Unknown rank!' + not-possible: '&c Rank must be higher than visitor.' + rank-set: '&a Rank set from &b [from] &a to &b [to] &a on &b [name]&a ''s island.' setprotectionlocation: - parameters: "[x y z coords]" - description: "set current location or [x y z] as center of island's protection area" - island: "&c This will affect the island at [xyz] owned by '[name]'." - confirmation: "&c Are you sure you want to set [xyz] as the protection center?" - success: "&a Successfully set [xyz] as the protection center." - fail: "&c Failed to set [xyz] as the protection center." - island-location-changed: "&a [user] changed island's protection center to [xyz]." - xyz-error: "&c Specify three integer coordinates: e.g, 100 120 100" + parameters: '[x y z coords]' + description: set current location or [x y z] as center of island's protection + area + island: '&c This will affect the island at [xyz] owned by ''[name]''.' + confirmation: '&c Are you sure you want to set [xyz] as the protection center?' + success: '&a Successfully set [xyz] as the protection center.' + fail: '&c Failed to set [xyz] as the protection center.' + island-location-changed: '&a [user] changed island''s protection center to [xyz].' + xyz-error: '&c Specify three integer coordinates: e.g, 100 120 100' setspawn: - description: "set an island as spawn for this gamemode" - already-spawn: "&c This island is already a spawn!" - no-island-here: "&c There is no island here." - confirmation: "&c Are you sure you want to set this island as the spawn for this world?" - success: "&a Successfully set this island as the spawn for this world." + description: set an island as spawn for this gamemode + already-spawn: '&c This island is already a spawn!' + no-island-here: '&c There is no island here.' + confirmation: '&c Are you sure you want to set this island as the spawn for + this world?' + success: '&a Successfully set this island as the spawn for this world.' setspawnpoint: - description: "set current location as spawn point for this island" - no-island-here: "&c There is no island here." - confirmation: "&c Are you sure you want to set this location as the spawn point for this island?" - success: "&a Successfully set this location as the spawn point for this island." - island-spawnpoint-changed: "&a [user] changed the island spawn point." + description: set current location as spawn point for this island + no-island-here: '&c There is no island here.' + confirmation: '&c Are you sure you want to set this location as the spawn point + for this island?' + success: '&a Successfully set this location as the spawn point for this island.' + island-spawnpoint-changed: '&a [user] changed the island spawn point.' settings: - parameters: "[player]/[world flag]/spawn-island [flag/active/disable] [rank/active/disable]" - description: "open settings GUI or set settings" - unknown-setting: "&c Unknown setting" + parameters: '[player]/[world flag]/spawn-island [flag/active/disable] [rank/active/disable]' + description: open settings GUI or set settings + unknown-setting: '&c Unknown setting' blueprint: - parameters: "" - description: "manipulate blueprints" - bedrock-required: "&c At least one bedrock block must be in a blueprint!" - copy-first: "&c Copy first!" - file-exists: "&c File already exists, overwrite?" - no-such-file: "&c No such file!" - could-not-load: "&c Could not load that file!" - could-not-save: "&c Hmm, something went wrong saving that file: [message]" - set-pos1: "&a Position 1 set at [vector]" - set-pos2: "&a Position 2 set at [vector]" - set-different-pos: "&c Set a different location - this pos is already set!" - need-pos1-pos2: "&c Set pos1 and pos2 first!" - copying: "&b Copying blocks..." - copied-blocks: "&b Copied [number] blocks to clipboard" - look-at-a-block: "&c Look at block within 20 blocks to set" - mid-copy: "&c You are mid-copy. Wait until the copy is done." - copied-percent: "&6 Copied [number]%" + parameters: + description: manipulate blueprints + bedrock-required: '&c At least one bedrock block must be in a blueprint!' + copy-first: '&c Copy first!' + file-exists: '&c File already exists, overwrite?' + no-such-file: '&c No such file!' + could-not-load: '&c Could not load that file!' + could-not-save: '&c Hmm, something went wrong saving that file: [message]' + set-pos1: '&a Position 1 set at [vector]' + set-pos2: '&a Position 2 set at [vector]' + set-different-pos: '&c Set a different location - this pos is already set!' + need-pos1-pos2: '&c Set pos1 and pos2 first!' + copying: '&b Copying blocks...' + copied-blocks: '&b Copied [number] blocks to clipboard' + look-at-a-block: '&c Look at block within 20 blocks to set' + mid-copy: '&c You are mid-copy. Wait until the copy is done.' + copied-percent: '&6 Copied [number]%' copy: - parameters: "[air]" - description: "copy the clipboard set by pos1 and pos2 and optionally the air blocks" + parameters: '[air]' + description: copy the clipboard set by pos1 and pos2 and optionally the air + blocks delete: - parameters: "" - description: "delete the blueprint" - no-blueprint: "&b [name] &c does not exist." + parameters: + description: delete the blueprint + no-blueprint: '&b [name] &c does not exist.' confirmation: | &c Are you sure you want to delete this blueprint? &c Once deleted, there is no way to recover it. - success: "&a Successfully deleted blueprint &b [name]&a ." + success: '&a Successfully deleted blueprint &b [name]&a .' load: - parameters: "" - description: "load blueprint into the clipboard" + parameters: + description: load blueprint into the clipboard list: - description: "list available blueprints" - no-blueprints: "&c No blueprints in blueprints folder!" - available-blueprints: "&a These blueprints are available for loading:" + description: list available blueprints + no-blueprints: '&c No blueprints in blueprints folder!' + available-blueprints: '&a These blueprints are available for loading:' origin: - description: "set the blueprint's origin to your position" + description: set the blueprint's origin to your position paste: - description: "paste the clipboard to your location" - pasting: "&a Pasting..." + description: paste the clipboard to your location + pasting: '&a Pasting...' pos1: - description: "set 1st corner of cuboid clipboard" + description: set 1st corner of cuboid clipboard pos2: - description: "set 2nd corner of cuboid clipboard" + description: set 2nd corner of cuboid clipboard save: - parameters: "" - description: "save the copied clipboard" + parameters: + description: save the copied clipboard rename: - parameters: " " - description: "rename a blueprint" - success: "&a Blueprint &b [old] &a has been successfully renamed to &b [display]&a. Filename now is &b [name]&a." - pick-different-name: "&c Please specify a name that is different from the blueprint's current name." + parameters: + description: rename a blueprint + success: '&a Blueprint &b [old] &a has been successfully renamed to &b [display]&a. + Filename now is &b [name]&a.' + pick-different-name: '&c Please specify a name that is different from the + blueprint''s current name.' management: - back: "Back" - instruction: "Click on blueprint then click here" - title: "Blueprint Bundle Manager" - edit: "Click to edit" - rename: "Right-click to rename" - edit-description: "Click to edit description" - world-name-syntax: "[name] world" + back: Back + instruction: Click on blueprint then click here + title: Blueprint Bundle Manager + edit: Click to edit + rename: Right-click to rename + edit-description: Click to edit description + world-name-syntax: '[name] world' world-instructions: | Place blueprint to right to set - trash: "Trash" - no-trash: "Cannot Trash" - trash-instructions: "Right click here to delete" - no-trash-instructions: "Cannot trash default bundle" - permission: "Permission" - no-permission: "No Permission" - perm-required: "Required" - no-perm-required: "Cannot set perm for default bundle" - perm-not-required: "Not Required" - perm-format: "&e " - remove: "Right click to remove" + trash: Trash + no-trash: Cannot Trash + trash-instructions: Right click here to delete + no-trash-instructions: Cannot trash default bundle + permission: Permission + no-permission: No Permission + perm-required: Required + no-perm-required: Cannot set perm for default bundle + perm-not-required: Not Required + perm-format: '&e ' + remove: Right click to remove blueprint-instruction: | Click to select, then add to bundle. Right-click to rename. - select-first: "Select Blueprint first" - new-bundle: "New Bundle" - new-bundle-instructions: "Click to make a new bundle" + select-first: Select Blueprint first + new-bundle: New Bundle + new-bundle-instructions: Click to make a new bundle name: - quit: "quit" - prompt: "Enter a name, or 'quit' to quit" - too-long: "&c Too long name. Only 32 chars are allowed." - pick-a-unique-name: "Please pick a more unique name" - stripped-char-in-unique-name: "&c Some chars were removed because they are not allowed. &a New ID will be &b [name]&a." - success: "Success!" - conversation-prefix: ">" + quit: quit + prompt: Enter a name, or 'quit' to quit + too-long: '&c Too long name. Only 32 chars are allowed.' + pick-a-unique-name: Please pick a more unique name + stripped-char-in-unique-name: '&c Some chars were removed because they are + not allowed. &a New ID will be &b [name]&a.' + success: Success! + conversation-prefix: '>' description: - quit: "quit" + quit: quit instructions: | Enter a multi line description for [name] and 'quit' on a line by itself to finish. - default-color: "" - success: "Success!" - cancelling: "Cancelling" - slot: "&f Preferred Slot [number]" + default-color: '' + success: Success! + cancelling: Cancelling + slot: '&f Preferred Slot [number]' slot-instructions: | &a Left click to increment &a Right click to decrement resetflags: - parameters: "[flag]" - description: "Reset all islands to default flag settings in config.yml" - confirm: "&4 This will reset the flag(s) to default for all islands!" - success: "&a Successfully reset all islands' flags to the default settings." - success-one: "&a [name] flag set to default for all islands." + parameters: '[flag]' + description: Reset all islands to default flag settings in config.yml + confirm: '&4 This will reset the flag(s) to default for all islands!' + success: '&a Successfully reset all islands'' flags to the default settings.' + success-one: '&a [name] flag set to default for all islands.' world: - description: "Manage world settings" + description: Manage world settings delete: - parameters: "" - description: "deletes a player's island" - cannot-delete-owner: "&c All island members have to be kicked from the island before deleting it." - deleted-island: "&a Island at &e [xyz] &a has been successfully deleted." + parameters: + description: deletes a player's island + cannot-delete-owner: '&c All island members have to be kicked from the island + before deleting it.' + deleted-island: '&a Island at &e [xyz] &a has been successfully deleted.' deletehomes: - parameters: "" - description: "deletes all named homes from an island" - warning: "&c All named homes will be deleted from the island!" + parameters: + description: deletes all named homes from an island + warning: '&c All named homes will be deleted from the island!' why: - parameters: "" - description: "toggle console protection debug reporting" - turning-on: "&a Turning on console debug for &b [name]." - turning-off: "&a Turning off console debug for &b [name]." + parameters: + description: toggle console protection debug reporting + turning-on: '&a Turning on console debug for &b [name].' + turning-off: '&a Turning off console debug for &b [name].' deaths: - description: "edit deaths of players" + description: edit deaths of players reset: - description: "resets deaths of the player" - parameters: "" - success: "&a Successfully reset &b [name]&a 's deaths to &b 0&a ." + description: resets deaths of the player + parameters: + success: '&a Successfully reset &b [name]&a ''s deaths to &b 0&a .' set: - description: "sets deaths of the player" - parameters: " " - success: "&a Successfully set &b [name]&a 's deaths to &b [number]&a ." + description: sets deaths of the player + parameters: + success: '&a Successfully set &b [name]&a ''s deaths to &b [number]&a .' add: - description: "adds deaths to the player" - parameters: " " - success: "&a Successfully added &b [number] &a deaths to &b [name], increasing the total to &b [total]&a deaths." + description: adds deaths to the player + parameters: + success: '&a Successfully added &b [number] &a deaths to &b [name], increasing + the total to &b [total]&a deaths.' remove: - description: "removes deaths to the player" - parameters: " " - success: "&a Successfully removed &b [number] &a deaths to &b [name], decreasing the total to &b [total]&a deaths." + description: removes deaths to the player + parameters: + success: '&a Successfully removed &b [number] &a deaths to &b [name], decreasing + the total to &b [total]&a deaths.' resetname: - description: "reset player island name" - success: "&a Successfully reset [name]'s island name." + description: reset player island name + success: '&a Successfully reset [name]''s island name.' bentobox: - description: "BentoBox admin command" + description: BentoBox admin command perms: - description: "displays the effective perms for BentoBox and Addons in a YAML format" + description: displays the effective perms for BentoBox and Addons in a YAML + format about: - description: "displays copyright and license information" + description: displays copyright and license information reload: - description: "reloads BentoBox and all addons, settings and locales" - locales-reloaded: "[prefix_bentobox]&2 Languages reloaded." - addons-reloaded: "[prefix_bentobox]&2 Addons reloaded." - settings-reloaded: "[prefix_bentobox]&2 Settings reloaded." - addon: "[prefix_bentobox]&6 Reloading &b [name]&2 ." - addon-reloaded: "[prefix_bentobox]&b [name] &2 reloaded." - warning: "[prefix_bentobox]&c Warning: Reloading may cause instability, so if you see errors afterwards, restart the server." - unknown-addon: "[prefix_bentobox]&c Unknown addon!" + description: reloads BentoBox and all addons, settings and locales + locales-reloaded: '[prefix_bentobox]&2 Languages reloaded.' + addons-reloaded: '[prefix_bentobox]&2 Addons reloaded.' + settings-reloaded: '[prefix_bentobox]&2 Settings reloaded.' + addon: '[prefix_bentobox]&6 Reloading &b [name]&2 .' + addon-reloaded: '[prefix_bentobox]&b [name] &2 reloaded.' + warning: '[prefix_bentobox]&c Warning: Reloading may cause instability, so if + you see errors afterwards, restart the server.' + unknown-addon: '[prefix_bentobox]&c Unknown addon!' locales: - description: "reloads locales" + description: reloads locales version: - plugin-version: "&2 BentoBox version: &3 [version]" - description: "displays BentoBox and addons versions" - loaded-addons: "Loaded Addons:" - loaded-game-worlds: "Loaded Game Worlds:" - addon-syntax: "&2 [name] &3 [version] &7 (&3 [state]&7 )" - game-world: "&2 [name] &7 (&3 [addon]&7 ): &3 [worlds]" - server: "&2 Running &3 [name] [version]&2 ." - database: "&2 Database: &3 [database]" + plugin-version: '&2 BentoBox version: &3 [version]' + description: displays BentoBox and addons versions + loaded-addons: 'Loaded Addons:' + loaded-game-worlds: 'Loaded Game Worlds:' + addon-syntax: '&2 [name] &3 [version] &7 (&3 [state]&7 )' + game-world: '&2 [name] &7 (&3 [addon]&7 ): &3 [worlds]' + server: '&2 Running &3 [name] [version]&2 .' + database: '&2 Database: &3 [database]' manage: - description: "displays the Management Panel" + description: displays the Management Panel catalog: - description: "displays the Catalog" + description: displays the Catalog locale: - description: "performs localization files analysis" + description: performs localization files analysis see-console: |- [prefix_bentobox]&a Check the console to see the feedback. [prefix_bentobox]&a This command is so spammy that the feedback cannot be read from chat... migrate: - description: "migrates data from one database to another" - players: "[prefix_bentobox]&6 Migrating players" - names: "[prefix_bentobox]&6 Migrating names" - addons: "[prefix_bentobox]&6 Migrating addons" - class: "[prefix_bentobox]&6 Migrating [description]" - migrated: "[prefix_bentobox]&a Migrated" - + description: migrates data from one database to another + players: '[prefix_bentobox]&6 Migrating players' + names: '[prefix_bentobox]&6 Migrating names' + addons: '[prefix_bentobox]&6 Migrating addons' + class: '[prefix_bentobox]&6 Migrating [description]' + migrated: '[prefix_bentobox]&a Migrated' + confirmation: - confirm: "&c Type command again within &b [seconds]s&c to confirm." - previous-request-cancelled: "&6 Previous confirmation request cancelled." - request-cancelled: "&c Confirmation timeout - &b request cancelled." + confirm: '&c Type command again within &b [seconds]s&c to confirm.' + previous-request-cancelled: '&6 Previous confirmation request cancelled.' + request-cancelled: '&c Confirmation timeout - &b request cancelled.' delay: - previous-command-cancelled: "&c Previous command cancelled" - stand-still: "&6 Do not move! Teleporting in [seconds] seconds" - moved-so-command-cancelled: "&c You moved. Teleport cancelled!" + previous-command-cancelled: '&c Previous command cancelled' + stand-still: '&6 Do not move! Teleporting in [seconds] seconds' + moved-so-command-cancelled: '&c You moved. Teleport cancelled!' island: about: - description: "display licence details" + description: display licence details go: - parameters: "[home name]" - description: "teleport you to your island" - teleport: "&a Teleporting you to your island." - teleported: "&a Teleported you to home &e [number]." - unknown-home: "&c Unknown home name!" + parameters: '[home name]' + description: teleport you to your island + teleport: '&a Teleporting you to your island.' + teleported: '&a Teleported you to home &e [number].' + unknown-home: '&c Unknown home name!' help: - description: "the main island command" + description: the main island command spawn: - description: "teleport you to the spawn" - teleporting: "&a Teleporting you to the spawn." - no-spawn: "&c There is no spawn in this gamemode." + description: teleport you to the spawn + teleporting: '&a Teleporting you to the spawn.' + no-spawn: '&c There is no spawn in this gamemode.' create: - description: "create an island, using optional blueprint (requires permission)" - parameters: "" - too-many-islands: "&c There are too many islands in this world: there isn't enough room for yours to be created." - cannot-create-island: "&c A spot could not be found in time, please try again..." - unable-create-island: "&c Your island could not be generated, please contact an administrator." - creating-island: "&a Finding a spot for your island..." + description: create an island, using optional blueprint (requires permission) + parameters: + too-many-islands: '&c There are too many islands in this world: there isn''t + enough room for yours to be created.' + cannot-create-island: '&c A spot could not be found in time, please try again...' + unable-create-island: '&c Your island could not be generated, please contact + an administrator.' + creating-island: '&a Finding a spot for your island...' + you-cannot-make: '&c You cannot make any more islands!' pasting: - estimated-time: "&a Estimated time: &b [number] &a seconds." - blocks: "&a Building it block by block: &b [number] &a blocks in all..." - entities: "&a Filling it with entities: &b [number] &a entities in all..." - dimension-done: "&a Island in [world] is constructed." - done: "&a Done! Your island is ready and waiting for you!" - pick: "&2 Pick an island" - unknown-blueprint: "&c That blueprint has not been loaded yet." - on-first-login: "&a Welcome! We will start preparing your island in a few seconds." - you-can-teleport-to-your-island: "&a You can teleport to your island when you want." + estimated-time: '&a Estimated time: &b [number] &a seconds.' + blocks: '&a Building it block by block: &b [number] &a blocks in all...' + entities: '&a Filling it with entities: &b [number] &a entities in all...' + dimension-done: '&a Island in [world] is constructed.' + done: '&a Done! Your island is ready and waiting for you!' + pick: '&2 Pick an island' + unknown-blueprint: '&c That blueprint has not been loaded yet.' + on-first-login: '&a Welcome! We will start preparing your island in a few seconds.' + you-can-teleport-to-your-island: '&a You can teleport to your island when you + want.' deletehome: - description: "delete a home location" - parameters: "[home name]" + description: delete a home location + parameters: '[home name]' homes: - description: "list your homes" + description: list your homes info: - description: "display info about your island or the player's island" - parameters: "" + description: display info about your island or the player's island + parameters: near: - description: "show the name of neighboring islands around you" - parameters: "" - the-following-islands: "&a The following islands are nearby:" - syntax: "&6 [direction]: &a [name]" + description: show the name of neighboring islands around you + parameters: '' + the-following-islands: '&a The following islands are nearby:' + syntax: '&6 [direction]: &a [name]' north: North south: South east: East west: West - no-neighbors: "&c You have no immediate neighboring islands!" + no-neighbors: '&c You have no immediate neighboring islands!' reset: - description: "restart your island and remove the old one" - parameters: "" - none-left: "&c You have no more resets left!" - resets-left: "&c You have &b [number] &c resets left" + description: restart your island and remove the old one + parameters: + none-left: '&c You have no more resets left!' + resets-left: '&c You have &b [number] &c resets left' confirmation: |- &c Are you sure you want to do this? &c All island members will be kicked from the island, you will have to reinvite them afterwards. &c There is no going back: once your current island is deleted, there will be &l no &r &c way to retrieve it later on. - kicked-from-island: "&c You are kicked from your island in [gamemode] because the owner is resetting it." + kicked-from-island: '&c You are kicked from your island in [gamemode] because + the owner is resetting it.' sethome: - description: "set your home teleport point" - must-be-on-your-island: "&c You must be on your island to set home!" - too-many-homes: "&c Cannot set - your island is at the maximum of [number] homes." - home-set: "&6 Your island home has been set to your current location." - homes-are: "&6 Island homes are:" - home-list-syntax: "&6 [name]" + description: set your home teleport point + must-be-on-your-island: '&c You must be on your island to set home!' + too-many-homes: '&c Cannot set - your island is at the maximum of [number] homes.' + home-set: '&6 Your island home has been set to your current location.' + homes-are: '&6 Island homes are:' + home-list-syntax: '&6 [name]' nether: - not-allowed: "&c You are not allowed to set your home in the Nether." - confirmation: "&c Are you sure you want to set your home in the Nether?" + not-allowed: '&c You are not allowed to set your home in the Nether.' + confirmation: '&c Are you sure you want to set your home in the Nether?' the-end: - not-allowed: "&c You are not allowed to set your home in the End." - confirmation: "&c Are you sure you want to set your home in the End?" - parameters: "[home name]" + not-allowed: '&c You are not allowed to set your home in the End.' + confirmation: '&c Are you sure you want to set your home in the End?' + parameters: '[home name]' setname: - description: "set a name for your island" - name-too-short: "&c Too short. Minimum size is [number] characters." - name-too-long: "&c Too long. Maximum size is [number] characters." - name-already-exists: "&c There is already an island with that name in this gamemode." - parameters: "" - success: "&a Successfully set your island's name to &b [name]&a ." + description: set a name for your island + name-too-short: '&c Too short. Minimum size is [number] characters.' + name-too-long: '&c Too long. Maximum size is [number] characters.' + name-already-exists: '&c There is already an island with that name in this gamemode.' + parameters: + success: '&a Successfully set your island''s name to &b [name]&a .' renamehome: - description: "rename a home location" - parameters: "[home name]" - enter-new-name: "&6 Enter the new name" - already-exists: "&c That name already exists, try another name." + description: rename a home location + parameters: '[home name]' + enter-new-name: '&6 Enter the new name' + already-exists: '&c That name already exists, try another name.' resetname: - description: "reset your island name" - success: "&a Successfully reset your island name." + description: reset your island name + success: '&a Successfully reset your island name.' team: - description: "manage your team" + description: manage your team info: - description: "display detailed info about your team" + description: display detailed info about your team member-layout: - online: "&a &l o &r &f [name]" - offline: "&c &l o &r &f [name] &7 ([last_seen])" - offline-not-last-seen: "&c &l o &r &f [name]" + online: '&a &l o &r &f [name]' + offline: '&c &l o &r &f [name] &7 ([last_seen])' + offline-not-last-seen: '&c &l o &r &f [name]' last-seen: - layout: "&b [number] &7 [unit] ago" - days: "days" - hours: "hours" - minutes: "minutes" + layout: '&b [number] &7 [unit] ago' + days: days + hours: hours + minutes: minutes header: | &f --- &a Team details &f --- &a Members: &b [total]&7 /&b [max] &a Online members: &b [online] rank-layout: - owner: "&6 [rank]:" - generic: "&6 [rank] &7 (&b [number]&7 )&6 :" + owner: '&6 [rank]:' + generic: '&6 [rank] &7 (&b [number]&7 )&6 :' coop: - description: "make a player coop rank on your island" - parameters: "" - cannot-coop-yourself: "&c You cannot coop yourself!" - already-has-rank: "&c Player already has a rank!" - you-are-a-coop-member: "&2 You were cooped by &b[name]&a." - success: "&a You cooped &b [name]&a." - name-has-invited-you: "&a [name] has invited you to join as a coop member of their island." + description: make a player coop rank on your island + parameters: + cannot-coop-yourself: '&c You cannot coop yourself!' + already-has-rank: '&c Player already has a rank!' + you-are-a-coop-member: '&2 You were cooped by &b[name]&a.' + success: '&a You cooped &b [name]&a.' + name-has-invited-you: '&a [name] has invited you to join as a coop member + of their island.' uncoop: - description: "remove a coop rank from player" - parameters: "" - cannot-uncoop-yourself: "&c You cannot uncoop yourself!" - cannot-uncoop-member: "&c You cannot uncoop a team member!" - player-not-cooped: "&c Player is not cooped!" - you-are-no-longer-a-coop-member: "&c You are no longer a coop member of [name]'s island." - all-members-logged-off: "&c All island members logged off so you are no longer a coop member of [name]'s island." - success: "&b [name] &a is no longer a coop member of your island." - is-full: "&c You cannot coop anyone else." + description: remove a coop rank from player + parameters: + cannot-uncoop-yourself: '&c You cannot uncoop yourself!' + cannot-uncoop-member: '&c You cannot uncoop a team member!' + player-not-cooped: '&c Player is not cooped!' + you-are-no-longer-a-coop-member: '&c You are no longer a coop member of [name]''s + island.' + all-members-logged-off: '&c All island members logged off so you are no longer + a coop member of [name]''s island.' + success: '&b [name] &a is no longer a coop member of your island.' + is-full: '&c You cannot coop anyone else.' trust: - description: "give a player trusted rank on your island" - parameters: "" - trust-in-yourself: "&c Trust in yourself!" - name-has-invited-you: "&a [name] has invited you to join as a trusted member of their island." - player-already-trusted: "&c Player is already trusted!" - you-are-trusted: "&2 You are trusted by &b [name]&a !" - success: "&a You trusted &b [name]&a ." - is-full: "&c You cannot trust anyone else. Watch your back!" + description: give a player trusted rank on your island + parameters: + trust-in-yourself: '&c Trust in yourself!' + name-has-invited-you: '&a [name] has invited you to join as a trusted member + of their island.' + player-already-trusted: '&c Player is already trusted!' + you-are-trusted: '&2 You are trusted by &b [name]&a !' + success: '&a You trusted &b [name]&a .' + is-full: '&c You cannot trust anyone else. Watch your back!' untrust: - description: "remove trusted player rank from player" - parameters: "" - cannot-untrust-yourself: "&c You cannot untrust yourself!" - cannot-untrust-member: "&c You cannot untrust a team member!" - player-not-trusted: "&c Player is not trusted!" - you-are-no-longer-trusted: "&c You are no longer trusted by &b [name]&a !" - success: "&b [name] &a is no longer trusted on your island." + description: remove trusted player rank from player + parameters: + cannot-untrust-yourself: '&c You cannot untrust yourself!' + cannot-untrust-member: '&c You cannot untrust a team member!' + player-not-trusted: '&c Player is not trusted!' + you-are-no-longer-trusted: '&c You are no longer trusted by &b [name]&a !' + success: '&b [name] &a is no longer trusted on your island.' invite: - description: "invite a player to join your island" - invitation-sent: "&a Invitation sent to &b[name]&a." - removing-invite: "&c Removing invite." - name-has-invited-you: "&a [name] has invited you to join their island." - to-accept-or-reject: "&a Do /[label] team accept to accept, or /[label] team reject to reject" - you-will-lose-your-island: "&c WARNING! You will lose your island if you accept!" + description: invite a player to join your island + invitation-sent: '&a Invitation sent to &b[name]&a.' + removing-invite: '&c Removing invite.' + name-has-invited-you: '&a [name] has invited you to join their island.' + to-accept-or-reject: '&a Do /[label] team accept to accept, or /[label] team + reject to reject' + you-will-lose-your-island: '&c WARNING! You will lose your island if you accept!' errors: - cannot-invite-self: "&c You cannot invite yourself!" - cooldown: "&c You cannot invite that person for another [number] seconds." - island-is-full: "&c Your island is full, you can't invite anyone else." - none-invited-you: "&c No one invited you :c." - you-already-are-in-team: "&c You are already on a team!" - already-on-team: "&c That player is already on a team!" - invalid-invite: "&c That invite is no longer valid, sorry." - you-have-already-invited: "&c You have already invited that player!" - parameters: "" - you-can-invite: "&a You can invite [number] more players." + cannot-invite-self: '&c You cannot invite yourself!' + cooldown: '&c You cannot invite that person for another [number] seconds.' + island-is-full: '&c Your island is full, you can''t invite anyone else.' + none-invited-you: '&c No one invited you :c.' + you-already-are-in-team: '&c You are already on a team!' + already-on-team: '&c That player is already on a team!' + invalid-invite: '&c That invite is no longer valid, sorry.' + you-have-already-invited: '&c You have already invited that player!' + parameters: + you-can-invite: '&a You can invite [number] more players.' accept: - description: "accept an invitation" - you-joined-island: "&a You joined an island! Use &b/[label] team &a to see the other members." - name-joined-your-island: "&a [name] joined your island!" + description: accept an invitation + you-joined-island: '&a You joined an island! Use &b/[label] team &a to see + the other members.' + name-joined-your-island: '&a [name] joined your island!' confirmation: |- &c Are you sure you want to accept this invite? &c&l You will &n LOSE &r&c&l your current island! reject: - description: "reject an invitation" - you-rejected-invite: "&a You rejected the invitation to join an island." - name-rejected-your-invite: "&c [name] rejected your island invite!" + description: reject an invitation + you-rejected-invite: '&a You rejected the invitation to join an island.' + name-rejected-your-invite: '&c [name] rejected your island invite!' cancel: - description: "cancel the pending invite to join your island" + description: cancel the pending invite to join your island leave: - cannot-leave: "&c Owners cannot leave! Become a member first, or kick all members." - description: "leave your island" - left-your-island: "&c [name] &c left your island" - success: "&a You left this island." + cannot-leave: '&c Owners cannot leave! Become a member first, or kick all + members.' + description: leave your island + left-your-island: '&c [name] &c left your island' + success: '&a You left this island.' kick: - description: "remove a member from your island" - parameters: "" - player-kicked: "&c The [name] kicked you from the island in [gamemode]!" - cannot-kick: "&c You cannot kick yourself!" - cannot-kick-rank: "&c Your rank does not allow to kick [name]!" - success: "&b [name] &a has been kicked from your island." + description: remove a member from your island + parameters: + player-kicked: '&c The [name] kicked you from the island in [gamemode]!' + cannot-kick: '&c You cannot kick yourself!' + cannot-kick-rank: '&c Your rank does not allow to kick [name]!' + success: '&b [name] &a has been kicked from your island.' demote: - description: "demote a player on your island down a rank" - parameters: "" + description: demote a player on your island down a rank + parameters: errors: - cant-demote-yourself: "&c You can't demote yourself!" - cant-demote: "&c You can't demote higher ranks!" - failure: "&c Player cannot be demoted any further!" - success: "&a Demoted [name] to [rank]" + cant-demote-yourself: '&c You can''t demote yourself!' + cant-demote: '&c You can''t demote higher ranks!' + failure: '&c Player cannot be demoted any further!' + success: '&a Demoted [name] to [rank]' promote: - description: "promote a player on your island up a rank" - parameters: "" + description: promote a player on your island up a rank + parameters: errors: - cant-promote-yourself: "&c You can't promote yourself!" - cant-promote: "&c You can't promote above your rank!" - failure: "&c Player cannot be promoted any further!" - success: "&a Promoted [name] to [rank]" + cant-promote-yourself: '&c You can''t promote yourself!' + cant-promote: '&c You can''t promote above your rank!' + failure: '&c Player cannot be promoted any further!' + success: '&a Promoted [name] to [rank]' setowner: - description: "transfer your island ownership to a member" + description: transfer your island ownership to a member errors: - cant-transfer-to-yourself: "&c You can't transfer ownership to yourself! &7 (&o Well, in fact, you could... But we don't want you to. Because it's useless.&r &7 )" - target-is-not-member: "&c That player is not part of your island team!" - name-is-the-owner: "&a [name] is now the island owner!" - parameters: "" - you-are-the-owner: "&a You are now the island owner!" + cant-transfer-to-yourself: '&c You can''t transfer ownership to yourself! + &7 (&o Well, in fact, you could... But we don''t want you to. Because + it''s useless.&r &7 )' + target-is-not-member: '&c That player is not part of your island team!' + at-max: '&c That player already has the maximum number of islands they are allowed!' + name-is-the-owner: '&a [name] is now the island owner!' + parameters: + you-are-the-owner: '&a You are now the island owner!' ban: - description: "ban a player from your island" - parameters: "" - cannot-ban-yourself: "&c You cannot ban yourself!" - cannot-ban: "&c That player cannot be banned." - cannot-ban-member: "&c Kick the team member first, then ban." - cannot-ban-more-players: "&c You reached the ban limit, you cannot ban any more players from your island." - player-already-banned: "&c Player is already banned." - player-banned: "&b [name]&c is now banned from your island." - owner-banned-you: "&b [name]&c banned you from their island!" - you-are-banned: "&b You are banned from this island!" + description: ban a player from your island + parameters: + cannot-ban-yourself: '&c You cannot ban yourself!' + cannot-ban: '&c That player cannot be banned.' + cannot-ban-member: '&c Kick the team member first, then ban.' + cannot-ban-more-players: '&c You reached the ban limit, you cannot ban any more + players from your island.' + player-already-banned: '&c Player is already banned.' + player-banned: '&b [name]&c is now banned from your island.' + owner-banned-you: '&b [name]&c banned you from their island!' + you-are-banned: '&b You are banned from this island!' unban: - description: "unban a player from your island" - parameters: "" - cannot-unban-yourself: "&c You cannot unban yourself!" - player-not-banned: "&c Player is not banned." - player-unbanned: "&b [name]&a is now unbanned from your island." - you-are-unbanned: "&b [name]&a unbanned you from their island!" + description: unban a player from your island + parameters: + cannot-unban-yourself: '&c You cannot unban yourself!' + player-not-banned: '&c Player is not banned.' + player-unbanned: '&b [name]&a is now unbanned from your island.' + you-are-unbanned: '&b [name]&a unbanned you from their island!' banlist: - description: "list banned players" - noone: "&a No one is banned on this island." - the-following: "&b The following players are banned:" - names: "&c [line]" - you-can-ban: "&b You can ban up to &e [number] &b more players." + description: list banned players + noone: '&a No one is banned on this island.' + the-following: '&b The following players are banned:' + names: '&c [line]' + you-can-ban: '&b You can ban up to &e [number] &b more players.' settings: - description: "display island settings" + description: display island settings language: - description: "select language" - parameters: "[language]" - not-available: "&c This language is not available." - already-selected: "&c You are already using this language." + description: select language + parameters: '[language]' + not-available: '&c This language is not available.' + already-selected: '&c You are already using this language.' expel: - description: "expel a player from your island" - parameters: "" - cannot-expel-yourself: "&c You cannot expel yourself!" - cannot-expel: "&c That player cannot be expelled." - cannot-expel-member: "&c You cannot expel a team member!" - not-on-island: "&c That player is not on your island!" - player-expelled-you: "&b [name]&c expelled you from the island!" - success: "&a You expelled &b [name] &a from the island." + description: expel a player from your island + parameters: + cannot-expel-yourself: '&c You cannot expel yourself!' + cannot-expel: '&c That player cannot be expelled.' + cannot-expel-member: '&c You cannot expel a team member!' + not-on-island: '&c That player is not on your island!' + player-expelled-you: '&b [name]&c expelled you from the island!' + success: '&a You expelled &b [name] &a from the island.' ranks: - owner: "Owner" - sub-owner: "Sub-Owner" - member: "Member" - trusted: "Trusted" - coop: "Coop" - visitor: "Visitor" - banned: "Banned" - admin: "Admin" - mod: "Mod" + owner: Owner + sub-owner: Sub-Owner + member: Member + trusted: Trusted + coop: Coop + visitor: Visitor + banned: Banned + admin: Admin + mod: Mod protection: - command-is-banned: "Command is banned for visitors" + command-is-banned: Command is banned for visitors flags: ALLAY: - name: "Allay interaction" - description: "Allow giving and taking items to/from Allay" - hint: "Allay interaction disabled" + name: Allay interaction + description: Allow giving and taking items to/from Allay + hint: Allay interaction disabled ANIMAL_NATURAL_SPAWN: - description: "Toggle natural animal spawning" - name: "Animal natural spawn" + description: Toggle natural animal spawning + name: Animal natural spawn ANIMAL_SPAWNERS_SPAWN: - description: "Toggle animal spawning with spawners" - name: "Animal spawners" + description: Toggle animal spawning with spawners + name: Animal spawners ANVIL: - description: "Toggle interaction" - name: "Anvils" - hint: "Anvil use disabled" + description: Toggle interaction + name: Anvils + hint: Anvil use disabled ARMOR_STAND: - description: "Toggle interaction" - name: "Armor stands" - hint: "Armor stand use disabled" + description: Toggle interaction + name: Armor stands + hint: Armor stand use disabled AXOLOTL_SCOOPING: - name: "Axolotl Scooping" - description: "Allow scooping of axolotl using a bucket" - hint: "Axolotl scooping disabled" + name: Axolotl Scooping + description: Allow scooping of axolotl using a bucket + hint: Axolotl scooping disabled BEACON: - description: "Toggle interaction" - name: "Beacons" - hint: "Beacon use disabled" + description: Toggle interaction + name: Beacons + hint: Beacon use disabled BED: - description: "Toggle interaction" - name: "Beds" - hint: "Bed use disabled" + description: Toggle interaction + name: Beds + hint: Bed use disabled BOAT: - name: "Boats" + name: Boats description: |- Toggle placing, breaking and entering into boats. - hint: "No boat interaction allowed" + hint: No boat interaction allowed BOOKSHELF: - name: "Bookshelves" + name: Bookshelves description: |- &a Allow to place books &a or to take books. - hint: "cannot place a book or take a book." + hint: cannot place a book or take a book. BREAK_BLOCKS: - description: "Toggle breaking" - name: "Break blocks" - hint: "Block breaking disabled" + description: Toggle breaking + name: Break blocks + hint: Block breaking disabled BREAK_SPAWNERS: description: |- Toggle spawners breaking. Overrides the Break Blocks flag. - name: "Break spawners" - hint: "Spawner breaking disabled" + name: Break spawners + hint: Spawner breaking disabled BREAK_HOPPERS: description: |- Toggle hoppers breaking. Overrides the Break Blocks flag. - name: "Break hoppers" - hint: "Hoppers breaking disabled" + name: Break hoppers + hint: Hoppers breaking disabled BREEDING: - description: "Toggle breeding" - name: "Breed animals" - hint: "Animal breeding protected" + description: Toggle breeding + name: Breed animals + hint: Animal breeding protected BREWING: - description: "Toggle interaction" - name: "Brewing stands" - hint: "Brewing disabled" + description: Toggle interaction + name: Brewing stands + hint: Brewing disabled BUCKET: - description: "Toggle interaction" - name: "Buckets" - hint: "Bucket use disabled" + description: Toggle interaction + name: Buckets + hint: Bucket use disabled BUTTON: - description: "Toggle button use" - name: "Buttons" - hint: "Button use disabled" + description: Toggle button use + name: Buttons + hint: Button use disabled CAKE: - description: "Toggle cake interaction" - name: "Cakes" - hint: "Cake eating disabled" + description: Toggle cake interaction + name: Cakes + hint: Cake eating disabled CONTAINER: - name: "All containers" + name: All containers description: |- &a Toggle interaction with all containers. &a Includes: Barrel, bee hive, brewing stand, @@ -834,318 +879,316 @@ protection: &7 Changing individual settings overrides &7 this flag. - hint: "Container access disabled" + hint: Container access disabled CHEST: - name: "Chests and minecart chests" + name: Chests and minecart chests description: |- &a Toggle interaction with chests &a and chest minecarts. &a (does not include trapped chests) - hint: "Chest access disabled" + hint: Chest access disabled BARREL: - name: "Barrels" - description: "Toggle barrel interaction" - hint: "Barrel access disabled" + name: Barrels + description: Toggle barrel interaction + hint: Barrel access disabled BLOCK_EXPLODE_DAMAGE: description: |- &a Allow Bed & Respawn Anchors &a to break blocks and damage &a entities. - name: "Block explode damage" + name: Block explode damage COMPOSTER: - name: "Composters" - description: "Toggle composter interaction" - hint: "Composter interaction disabled" + name: Composters + description: Toggle composter interaction + hint: Composter interaction disabled FLOWER_POT: - name: "Flower pots" - description: "Toggle flower pot interaction" - hint: "Flower pot interaction disabled" + name: Flower pots + description: Toggle flower pot interaction + hint: Flower pot interaction disabled SHULKER_BOX: - name: "Shulker boxes" - description: "Toggle shulker box interaction" - hint: "Shulker box access disabled" + name: Shulker boxes + description: Toggle shulker box interaction + hint: Shulker box access disabled SHULKER_TELEPORT: description: |- - &a Shulker can teleport - &a if active. - name: "Shulker teleport" + &a Shulker can teleport + &a if active. + name: Shulker teleport TRAPPED_CHEST: - name: "Trapped chests" - description: "Toggle trapped chest interaction" - hint: "Trapped chest access disabled" + name: Trapped chests + description: Toggle trapped chest interaction + hint: Trapped chest access disabled DISPENSER: - name: "Dispensers" - description: "Toggle dispenser interaction" - hint: "Dispenser interaction disabled" + name: Dispensers + description: Toggle dispenser interaction + hint: Dispenser interaction disabled DROPPER: - name: "Droppers" - description: "Toggle dropper interaction" - hint: "Dropper interaction disabled" + name: Droppers + description: Toggle dropper interaction + hint: Dropper interaction disabled ELYTRA: - name: "Elytra" - description: "Toggle elytra allowed or not" - hint: "&c WARNING: Elytra cannot be used here!" + name: Elytra + description: Toggle elytra allowed or not + hint: '&c WARNING: Elytra cannot be used here!' HOPPER: - name: "Hoppers" - description: "Toggle hopper interaction" - hint: "Hopper interaction disabled" + name: Hoppers + description: Toggle hopper interaction + hint: Hopper interaction disabled CHEST_DAMAGE: - description: "Toggle chest damage from explosions" - name: "Chest Damage" + description: Toggle chest damage from explosions + name: Chest Damage CHORUS_FRUIT: - description: "Toggle teleportation" - name: "Chorus fruits" - hint: "Chorus fruit teleporting disabled" + description: Toggle teleportation + name: Chorus fruits + hint: Chorus fruit teleporting disabled CLEAN_SUPER_FLAT: description: |- - &a Enable to clean any - &a super-flat chunks in - &a island worlds - name: "Clean Super Flat" + &a Enable to clean any + &a super-flat chunks in + &a island worlds + name: Clean Super Flat COARSE_DIRT_TILLING: description: |- - &a Toggle tilling coarse - &a dirt and breaking podzol - &a to obtain dirt - name: "Coarse dirt tilling" - hint: "No coarse dirt tilling" + &a Toggle tilling coarse + &a dirt and breaking podzol + &a to obtain dirt + name: Coarse dirt tilling + hint: No coarse dirt tilling COLLECT_LAVA: description: |- - &a Toggle collecting lava - &a (override Buckets) - name: "Collect lava" - hint: "No lava collection" + &a Toggle collecting lava + &a (override Buckets) + name: Collect lava + hint: No lava collection COLLECT_WATER: description: |- - &a Toggle collecting water - &a (override Buckets) - name: "Collect water" - hint: "Water buckets disabled" + &a Toggle collecting water + &a (override Buckets) + name: Collect water + hint: Water buckets disabled COLLECT_POWDERED_SNOW: description: |- &a Toggle collecting powdered snow &a (override Buckets) - name: "Collect powdered snow" - hint: "Powdered snow buckets disabled" + name: Collect powdered snow + hint: Powdered snow buckets disabled COMMAND_RANKS: - name: "&e Command Ranks" - description: "&a Configure command ranks" + name: '&e Command Ranks' + description: '&a Configure command ranks' CRAFTING: - description: "Toggle use" - name: "Workbenches" - hint: "Workbench access disabled" + description: Toggle use + name: Workbenches + hint: Workbench access disabled CREEPER_DAMAGE: description: | &a Toggle creeper &a damage protection - name: "Creeper damage protection" + name: Creeper damage protection CREEPER_GRIEFING: description: | &a Toggle creeper griefing &a protection when ignited &a by island visitor. - name: "Creeper griefing protection" - hint: "Creeper griefing disabled" + name: Creeper griefing protection + hint: Creeper griefing disabled CROP_PLANTING: - description: |- - &a Set who can plant seeds. - name: "Crop planting" - hint: "Crop planting disabled" + description: '&a Set who can plant seeds.' + name: Crop planting + hint: Crop planting disabled CROP_TRAMPLE: - description: "Toggle crop trampling" - name: "Trample crops" - hint: "Crop trampling disabled" + description: Toggle crop trampling + name: Trample crops + hint: Crop trampling disabled DOOR: - description: "Toggle door usage" - name: "Use doors" - hint: "Door interaction disabled" + description: Toggle door usage + name: Use doors + hint: Door interaction disabled DRAGON_EGG: - name: "Dragon Egg" + name: Dragon Egg description: |- &a Prevents interaction with Dragon Eggs. &c This does not protect it from being &c placed or broken. - hint: "Dragon egg interaction disabled" + hint: Dragon egg interaction disabled DYE: - description: "Prevent dye use" - name: "Dye use" - hint: "Dyeing disabled" + description: Prevent dye use + name: Dye use + hint: Dyeing disabled EGGS: - description: "Toggle egg throwing" - name: "Egg throwing" - hint: "Egg throwing disabled" + description: Toggle egg throwing + name: Egg throwing + hint: Egg throwing disabled ENCHANTING: - description: "Toggle use" - name: "Enchanting table" - hint: "Enchantment tables disabled" + description: Toggle use + name: Enchanting table + hint: Enchantment tables disabled ENDER_CHEST: - description: "Toggle use/crafting" - name: "Ender Chests" - hint: "Ender chests are disabled in this world" + description: Toggle use/crafting + name: Ender Chests + hint: Ender chests are disabled in this world ENDERMAN_DEATH_DROP: description: |- - &a Endermen will drop - &a any block they are - &a holding if killed. - name: "Enderman Death Drop" + &a Endermen will drop + &a any block they are + &a holding if killed. + name: Enderman Death Drop ENDERMAN_GRIEFING: description: |- - &a Endermen can remove - &a blocks from islands - name: "Enderman griefing" + &a Endermen can remove + &a blocks from islands + name: Enderman griefing ENDERMAN_TELEPORT: description: |- - &a Endermen can teleport - &a if active. - name: "Enderman teleport" + &a Endermen can teleport + &a if active. + name: Enderman teleport ENDER_PEARL: - description: "Toggle use" - name: "EnderPearls" - hint: "Enderpearl use disabled" + description: Toggle use + name: EnderPearls + hint: Enderpearl use disabled ENTER_EXIT_MESSAGES: - description: "Display entry and exit messages" - island: "[name]'s island" - name: "Enter/Exit messages" - now-entering: "&a Now entering &b [name]&a ." - now-entering-your-island: "&a Now entering your island." - now-leaving: "&a Now leaving &b [name]&a ." - now-leaving-your-island: "&a Now leaving your island." + description: Display entry and exit messages + island: '[name]''s island' + name: Enter/Exit messages + now-entering: '&a Now entering &b [name]&a .' + now-entering-your-island: '&a Now entering your island: &b [name]' + now-leaving: '&a Now leaving &b [name]&a .' + now-leaving-your-island: '&a Now leaving your island: &b [name]' EXPERIENCE_BOTTLE_THROWING: - name: "Experience bottle throwing" - description: "Toggle throwing experience bottles." - hint: "Experience bottles disabled" + name: Experience bottle throwing + description: Toggle throwing experience bottles. + hint: Experience bottles disabled FIRE_BURNING: - name: "Fire burning" + name: Fire burning description: |- &a Toggle whether fire can burn &a blocks or not. FIRE_EXTINGUISH: - description: "Toggle extinguishing fires" - name: "Fire extinguish" - hint: "Extinguishing fire disabled" + description: Toggle extinguishing fires + name: Fire extinguish + hint: Extinguishing fire disabled FIRE_IGNITE: - name: "Fire ignition" + name: Fire ignition description: |- &a Toggle whether fire can be ignited &a by non-player means or not. FIRE_SPREAD: - name: "Fire spread" + name: Fire spread description: |- &a Toggle whether fire can spread &a to nearby blocks or not. FISH_SCOOPING: - name: "Fish Scooping" - description: "Allow scooping of fishes using a bucket" - hint: "Fish scooping disabled" + name: Fish Scooping + description: Allow scooping of fishes using a bucket + hint: Fish scooping disabled FLINT_AND_STEEL: - name: "Flint and steel" + name: Flint and steel description: |- &a Allow players to ignite fires or &a campfires using flint and steel &a or fire charges. - hint: "Flint and steel and fire charges disabled" + hint: Flint and steel and fire charges disabled FURNACE: - description: "Toggle use" - name: "Furnace" - hint: "Furnace use disabled" + description: Toggle use + name: Furnace + hint: Furnace use disabled GATE: - description: "Toggle use" - name: "Gates" - hint: "Gate use disabled" + description: Toggle use + name: Gates + hint: Gate use disabled GEO_LIMIT_MOBS: description: |- - &a Remove mobs that go - &a outside protected - &a island space - name: "&e Limit mobs to island" + &a Remove mobs that go + &a outside protected + &a island space + name: '&e Limit mobs to island' HARVEST: description: |- &a Set who can harvest crops. &a Don't forget to allow item &a pickup too! - name: "Crop harvesting" - hint: "Crop harvesting disabled" + name: Crop harvesting + hint: Crop harvesting disabled HIVE: - description: |- - &a Toggle hive harvesting. - name: "Hive harvesting" - hint: "Harvesting disabled" + description: '&a Toggle hive harvesting.' + name: Hive harvesting + hint: Harvesting disabled HURT_ANIMALS: - description: "Toggle hurting" - name: "Hurt animals" - hint: "Animal hurting disabled" + description: Toggle hurting + name: Hurt animals + hint: Animal hurting disabled HURT_MONSTERS: - description: "Toggle hurting" - name: "Hurt monsters" - hint: "Monster hurting disabled" + description: Toggle hurting + name: Hurt monsters + hint: Monster hurting disabled HURT_VILLAGERS: - description: "Toggle hurting" - name: "Hurt villagers" - hint: "Villager hurting disabled" + description: Toggle hurting + name: Hurt villagers + hint: Villager hurting disabled ITEM_FRAME: - name: "Item Frame" + name: Item Frame description: |- &a Toggle interaction. &a Overrides place or break blocks - hint: "Item Frame use disabled" + hint: Item Frame use disabled ITEM_FRAME_DAMAGE: description: |- - &a Mobs can damage - &a item frames - name: "Item Frame Damage" + &a Mobs can damage + &a item frames + name: Item Frame Damage INVINCIBLE_VISITORS: description: |- - &a Configure invincible visitor - &a settings. - name: "&e Invincible Visitors" - hint: "&c Visitors protected" + &a Configure invincible visitor + &a settings. + name: '&e Invincible Visitors' + hint: '&c Visitors protected' ISLAND_RESPAWN: description: |- &a Players respawn &a on island - name: "Island respawn" + name: Island respawn ITEM_DROP: - description: "Toggle dropping" - name: "Item drop" - hint: "Item dropping disabled" + description: Toggle dropping + name: Item drop + hint: Item dropping disabled ITEM_PICKUP: - description: "Toggle pickup" - name: "Item pickup" - hint: "Item pickup disabled" + description: Toggle pickup + name: Item pickup + hint: Item pickup disabled JUKEBOX: - description: "Toggle usage" - name: "Jukebox use" - hint: "Jukebox use disabled" + description: Toggle usage + name: Jukebox use + hint: Jukebox use disabled LEAF_DECAY: - name: "Leaf decay" - description: "Allow leaves to naturally decay" + name: Leaf decay + description: Allow leaves to naturally decay LEASH: - description: "Toggle use" - name: "Leash use" + description: Toggle use + name: Leash use LECTERN: - name: "Lecterns" + name: Lecterns description: |- &a Allow to place books on a lectern &a or to take books from it. &c It does not prevent players from &c reading the books. - hint: "cannot place a book on a lectern or take a book from it." + hint: cannot place a book on a lectern or take a book from it. LEVER: - description: "Toggle use" - name: "Lever use" - hint: "Lever use disabled" + description: Toggle use + name: Lever use + hint: Lever use disabled LIMIT_MOBS: description: |- - &a Limit entities from - &a spawning in this game - &a mode. - name: "&e Limit entity type spawning" - can: "&a Can spawn" - cannot: "&c Cannot spawn" + &a Limit entities from + &a spawning in this game + &a mode. + name: '&e Limit entity type spawning' + can: '&a Can spawn' + cannot: '&c Cannot spawn' LIQUIDS_FLOWING_OUT: - name: "Liquids flowing outside islands" + name: Liquids flowing outside islands description: |- &a Toggle whether liquids can flow outside &a of the island's protection range. @@ -1158,41 +1201,41 @@ protection: &c they are placed outside an island's &c protection range. LOCK: - description: "Toggle lock" - name: "Lock island" + description: Toggle lock + name: Lock island CHANGE_SETTINGS: - name: "Change Settings" + name: Change Settings description: |- &a Allow to switch which member &a role can change island settings. - MILKING: - description: "Toggle cow milking" - name: "Milking" - hint: "Milking cows disabled" + MILKING: + description: Toggle cow milking + name: Milking + hint: Milking cows disabled MINECART: - name: "Minecarts" + name: Minecarts description: |- Toggle placing, breaking and entering into minecarts. - hint: "Minecart interaction disabled" + hint: Minecart interaction disabled MONSTER_NATURAL_SPAWN: - description: "Toggle natural monster spawning" - name: "Monster natural spawn" + description: Toggle natural monster spawning + name: Monster natural spawn MONSTER_SPAWNERS_SPAWN: - description: "Toggle monster spawning with spawners" - name: "Monster spawners" - MOUNT_INVENTORY: + description: Toggle monster spawning with spawners + name: Monster spawners + MOUNT_INVENTORY: description: |- &a Toggle access &a to mount inventory - name: "Mount inventory" - hint: "Mounting inventories disabled" + name: Mount inventory + hint: Mounting inventories disabled NAME_TAG: - name: "Name tags" - description: "Toggle use" - hint: "Name tag interaction disabled" + name: Name tags + description: Toggle use + hint: Name tag interaction disabled NATURAL_SPAWNING_OUTSIDE_RANGE: - name: "Natural creature spawning outside range" + name: Natural creature spawning outside range description: |- &a Toggle whether creatures (animals and &a monsters) can spawn naturally outside @@ -1201,12 +1244,12 @@ protection: &c Note that it doesn't prevent creatures &c to spawn via a mob spawner or a spawn &c egg. - NOTE_BLOCK: - description: "Toggle use" - name: "Note block" - hint: "Noteblock interaction disabled" + NOTE_BLOCK: + description: Toggle use + name: Note block + hint: Noteblock interaction disabled OBSIDIAN_SCOOPING: - name: "Obsidian scooping" + name: Obsidian scooping description: |- &a Allow players to scoop up obsidian &a with an empty bucket back into lava. @@ -1217,156 +1260,157 @@ protection: &a Note: obsidian cannot be scooped up &a if there are other obsidian blocks &a within a 2-block radius. - scooping: "&a Changing obsidian back into lava. Be careful next time!" - obsidian-nearby: "&c There are obsidian blocks nearby, you cannot scoop up this block into lava." + scooping: '&a Changing obsidian back into lava. Be careful next time!' + obsidian-nearby: '&c There are obsidian blocks nearby, you cannot scoop up this + block into lava.' OFFLINE_GROWTH: description: |- &a When disabled, plants &a will not grow on islands &a where all members are offline. &a May help reduce lag. - name: "Offline Growth" + name: Offline Growth OFFLINE_REDSTONE: description: |- - &a When disabled, redstone - &a will not operate on islands - &a where all members are offline. - &a May help reduce lag. - &a Does not affect spawn island. - name: "Offline Redstone" + &a When disabled, redstone + &a will not operate on islands + &a where all members are offline. + &a May help reduce lag. + &a Does not affect spawn island. + name: Offline Redstone PETS_STAY_AT_HOME: description: |- &a When active, tamed pets &a can only go to and &a cannot leave the owner's &a home island. - name: "Pets Stay At Home" - PISTON_PUSH: + name: Pets Stay At Home + PISTON_PUSH: description: |- - &a Enable this to prevent - &a pistons from pushing - &a blocks outside island - name: "Piston Push Protection" - PLACE_BLOCKS: - description: "Toggle placing" - name: "Place blocks" - hint: "Block placing disabled" + &a Enable this to prevent + &a pistons from pushing + &a blocks outside island + name: Piston Push Protection + PLACE_BLOCKS: + description: Toggle placing + name: Place blocks + hint: Block placing disabled POTION_THROWING: - name: "Potion throwing" + name: Potion throwing description: |- &a Toggle throwing potions. &a This include splash and lingering potions. - hint: "Throwing potions disabled" + hint: Throwing potions disabled NETHER_PORTAL: - description: "Toggle use" - name: "Nether Portal" - hint: "Portal use disabled" + description: Toggle use + name: Nether Portal + hint: Portal use disabled END_PORTAL: - description: "Toggle use" - name: "End Portal" - hint: "Portal use disabled" - PRESSURE_PLATE: - description: "Toggle usage" - name: "Pressure Plates" - hint: "Pressure plate use disabled" - PVP_END: + description: Toggle use + name: End Portal + hint: Portal use disabled + PRESSURE_PLATE: + description: Toggle usage + name: Pressure Plates + hint: Pressure plate use disabled + PVP_END: description: |- - &c Enable/Disable PVP - &c in the End. - name: "End PVP" - hint: "PVP disabled in the End" - enabled: "&c The PVP in the End has been enabled." - disabled: "&a The PVP in the End has been disabled." - PVP_NETHER: + &c Enable/Disable PVP + &c in the End. + name: End PVP + hint: PVP disabled in the End + enabled: '&c The PVP in the End has been enabled.' + disabled: '&a The PVP in the End has been disabled.' + PVP_NETHER: description: |- - &c Enable/Disable PVP - &c in the Nether. - name: "Nether PVP" - hint: "PVP disabled in the Nether" - enabled: "&c The PVP in the Nether has been enabled." - disabled: "&a The PVP in the Nether has been disabled." - PVP_OVERWORLD: + &c Enable/Disable PVP + &c in the Nether. + name: Nether PVP + hint: PVP disabled in the Nether + enabled: '&c The PVP in the Nether has been enabled.' + disabled: '&a The PVP in the Nether has been disabled.' + PVP_OVERWORLD: description: |- - &c Enable/Disable PVP - &c on island. - name: "Overworld PVP" - hint: "&c PVP disabled in the Overworld" - enabled: "&c The PVP in the Overworld has been enabled." - disabled: "&a The PVP in the Overworld has been disabled." - REDSTONE: - description: "Toggle use" - name: "Redstone items" - hint: "Redstone interaction disabled" + &c Enable/Disable PVP + &c on island. + name: Overworld PVP + hint: '&c PVP disabled in the Overworld' + enabled: '&c The PVP in the Overworld has been enabled.' + disabled: '&a The PVP in the Overworld has been disabled.' + REDSTONE: + description: Toggle use + name: Redstone items + hint: Redstone interaction disabled REMOVE_END_EXIT_ISLAND: description: |- &a Prevents the end exit &a island from generating &a at coordinates 0,0 - name: "Remove end exit island" - REMOVE_MOBS: + name: Remove end exit island + REMOVE_MOBS: description: |- &a Remove monsters when &a teleporting to island - name: "Remove monsters" - RIDING: - description: "Toggle riding" - name: "Animal riding" - hint: "Animal riding disabled" - SHEARING: - description: "Toggle shearing" - name: "Shearing" - hint: "Shearing disabled" - SPAWN_EGGS: - description: "Toggle use" - name: "Spawn eggs" - hint: "Spawn eggs disabled" + name: Remove monsters + RIDING: + description: Toggle riding + name: Animal riding + hint: Animal riding disabled + SHEARING: + description: Toggle shearing + name: Shearing + hint: Shearing disabled + SPAWN_EGGS: + description: Toggle use + name: Spawn eggs + hint: Spawn eggs disabled SPAWNER_SPAWN_EGGS: description: |- &a Allows to change a spawner's entity type &a using spawn eggs. - name: "Spawn eggs on spawners" - hint: "changing a spawner's entity type using spawn eggs is not allowed" + name: Spawn eggs on spawners + hint: changing a spawner's entity type using spawn eggs is not allowed SCULK_SENSOR: description: |- &a Toggles sculk sensor &a activation. - name: "Sculk Sensor" - hint: "sculk sensor activation is disabled" + name: Sculk Sensor + hint: sculk sensor activation is disabled SCULK_SHRIEKER: description: |- &a Toggles sculk shrieker &a activation. - name: "Sculk Shrieker" - hint: "sculk shrieker activation is disabled" + name: Sculk Shrieker + hint: sculk shrieker activation is disabled SIGN_EDITING: description: |- &a Allows text editing &a of signs - name: "Sign Editing" - hint: "sign editing is disabled" + name: Sign Editing + hint: sign editing is disabled TNT_DAMAGE: description: |- &a Allow TNT and TNT minecarts &a to break blocks and damage &a entities. - name: "TNT damage" + name: TNT damage TNT_PRIMING: description: |- &a Prevents priming TNT. &a It does not override the &a Flint and steel protection. - name: "TNT priming" - hint: "TNT priming disabled" - TRADING: - description: "Toggle trading" - name: "Villager trading" - hint: "Villager trading disabled" + name: TNT priming + hint: TNT priming disabled + TRADING: + description: Toggle trading + name: Villager trading + hint: Villager trading disabled TRAPDOOR: - description: "Toggle access" - name: "Trap doors" - hint: "Trapdoor use disabled" + description: Toggle access + name: Trap doors + hint: Trapdoor use disabled TREES_GROWING_OUTSIDE_RANGE: - name: "Trees growing outside range" + name: Trees growing outside range description: |- &a Toggle whether trees can grow outside an &a island's protection range or not. @@ -1376,26 +1420,26 @@ protection: &a of leaves/logs outside of the island, thus &a cutting the tree. TURTLE_EGGS: - description: "Toggle crushing" - name: "Turtle Eggs" - hint: "Turtle egg crushing disabled" + description: Toggle crushing + name: Turtle Eggs + hint: Turtle egg crushing disabled FROST_WALKER: - description: "Toggle Frost Walker enchantment" - name: "Frost Walker" - hint: "Frost Walker disabled" + description: Toggle Frost Walker enchantment + name: Frost Walker + hint: Frost Walker disabled EXPERIENCE_PICKUP: - name: "Experience pickup" - description: "Toggle experience orb pickup" - hint: "Experience pickup disabled" + name: Experience pickup + description: Toggle experience orb pickup + hint: Experience pickup disabled PREVENT_TELEPORT_WHEN_FALLING: - name: "Prevent teleport when falling" + name: Prevent teleport when falling description: |- &a Prevent players from teleporting &a back to their island using commands &a if they are falling. - hint: "&c You cannot do that while falling." + hint: '&c You cannot do that while falling.' VISITOR_KEEP_INVENTORY: - name: "Visitors keep inventory on death" + name: Visitors keep inventory on death description: |- &a Prevent players from losing their &a items and experience if they die on @@ -1404,7 +1448,7 @@ protection: &a Island members still lose their items &a if they die on their own island! VISITOR_TRIGGER_RAID: - name: "Visitors triggers raids" + name: Visitors triggers raids description: |- &a Toggles if visitors can start &a a raid on an island which they are @@ -1412,13 +1456,13 @@ protection: &a &a Bad Omen effect will be removed! ENTITY_PORTAL_TELEPORT: - name: "Entity portal usage" + name: Entity portal usage description: |- &a Toggles if entities (non-player) can &a use portals to teleport between &a dimensions WITHER_DAMAGE: - name: "Toggle wither damage" + name: Toggle wither damage description: |- &a If active, withers can &a damage blocks and players @@ -1427,57 +1471,57 @@ protection: &a Allow Bed & Respawn Anchors &a to break blocks and damage &a entities outside of island limits. - name: "World block explode damage" + name: World block explode damage WORLD_TNT_DAMAGE: description: |- &a Allow TNT and TNT minecarts &a to break blocks and damage &a entities outside of island limits. - name: "World TNT damage" - locked: "&c This island is locked!" - protected: "&c Island protected: [description]." - world-protected: "&c World protected: [description]." - spawn-protected: "&c Spawn protected: [description]." - + name: World TNT damage + locked: '&c This island is locked!' + protected: '&c Island protected: [description].' + world-protected: '&c World protected: [description].' + spawn-protected: '&c Spawn protected: [description].' + panel: - next: "&f Next Page" - previous: "&f Previous Page" + next: '&f Next Page' + previous: '&f Previous Page' mode: advanced: - name: "&6 Advanced Settings" - description: "&a Displays a sensible amount of settings." + name: '&6 Advanced Settings' + description: '&a Displays a sensible amount of settings.' basic: - name: "&a Basic Settings" - description: "&a Displays the most useful settings." + name: '&a Basic Settings' + description: '&a Displays the most useful settings.' expert: - name: "&c Expert Settings" - description: "&a Displays all the available settings." - click-to-switch: "&e Click &7 to switch to the &r [next]&r &7 ." + name: '&c Expert Settings' + description: '&a Displays all the available settings.' + click-to-switch: '&e Click &7 to switch to the &r [next]&r &7 .' reset-to-default: - name: "&c Reset to default" + name: '&c Reset to default' description: | &a Resets &c &l ALL &r &a the settings to their &a default value. PROTECTION: - title: "&6 Protection" + title: '&6 Protection' description: |- &a Protection settings &a for this island SETTING: - title: "&6 Settings" + title: '&6 Settings' description: |- &a General settings &a for this island WORLD_SETTING: - title: "&b [world_name] &6 Settings" - description: "&a Settings for this game world" + title: '&b [world_name] &6 Settings' + description: '&a Settings for this game world' WORLD_DEFAULTS: - title: "&b [world_name] &6 World Protections" + title: '&b [world_name] &6 World Protections' description: | &a Protection settings when &a player is outside their island flag-item: - name-layout: "&a [name]" + name-layout: '&a [name]' description-layout: | &a [description] @@ -1485,69 +1529,69 @@ protection: &e Right Click &7 to cycle upwards. &7 Allowed for: - allowed-rank: "&3 - &a " - blocked-rank: "&3 - &c " - minimal-rank: "&3 - &2 " + allowed-rank: '&3 - &a ' + blocked-rank: '&3 - &c ' + minimal-rank: '&3 - &2 ' menu-layout: | &a [description] &e Click &7 to open. - setting-cooldown: "&c Setting is on cooldown" + setting-cooldown: '&c Setting is on cooldown' setting-layout: | &a [description] &e Click &7 to toggle. &7 Current setting: [setting] - setting-active: "&a Active" - setting-disabled: "&c Disabled" + setting-active: '&a Active' + setting-disabled: '&c Disabled' language: - panel-title: "Select your language" + panel-title: Select your language description: - selected: "&a Currently selected." - click-to-select: "&e Click &a to select." - authors: "&a Authors:" - author: "&3 - &b [name]" - edited: "&a Changed your language to &e [lang]&a ." + selected: '&a Currently selected.' + click-to-select: '&e Click &a to select.' + authors: '&a Authors:' + author: '&3 - &b [name]' + edited: '&a Changed your language to &e [lang]&a .' management: panel: - title: "BentoBox Management" + title: BentoBox Management views: gamemodes: - name: "&6 Gamemodes" - description: "&e Click &a to display currently loaded Gamemodes" + name: '&6 Gamemodes' + description: '&e Click &a to display currently loaded Gamemodes' blueprints: - name: "&6 Blueprints" - description: "&a Opens the Admin Blueprint menu." + name: '&6 Blueprints' + description: '&a Opens the Admin Blueprint menu.' gamemode: - name: "&f [name]" + name: '&f [name]' description: | &a Islands: &b [islands] addons: - name: "&6 Addons" - description: "&e Click &a to display currently loaded Addons" + name: '&6 Addons' + description: '&e Click &a to display currently loaded Addons' hooks: - name: "&6 Hooks" - description: "&e Click &a to display currently loaded Hooks" + name: '&6 Hooks' + description: '&e Click &a to display currently loaded Hooks' actions: reload: - name: "&c Reload" - description: "&e Click &c &l twice &r &a to reload BentoBox" + name: '&c Reload' + description: '&e Click &c &l twice &r &a to reload BentoBox' buttons: catalog: - name: "&6 Addons Catalog" - description: "&a Opens the Addons Catalog" + name: '&6 Addons Catalog' + description: '&a Opens the Addons Catalog' credits: - name: "&6 Credits" - description: "&a Opens the Credits for BentoBox" + name: '&6 Credits' + description: '&a Opens the Credits for BentoBox' empty-here: - name: "&b This looks empty here..." - description: "&a What if you take a look at our catalog?" + name: '&b This looks empty here...' + description: '&a What if you take a look at our catalog?' information: state: - name: "&6 Compatibility" + name: '&6 Compatibility' description: COMPATIBLE: | &a Running &e [name] [version]&a . @@ -1586,21 +1630,20 @@ management: &c Weird behaviour and bugs can occur &c and most features may be unstable. - catalog: panel: GAMEMODES: - title: "Gamemodes Catalog" + title: Gamemodes Catalog ADDONS: - title: "Addons Catalog" + title: Addons Catalog views: gamemodes: - name: "&6 Gamemodes" + name: '&6 Gamemodes' description: | &e Click &a to browse through the &a available official Gamemodes. addons: - name: "&6 Addons" + name: '&6 Addons' description: | &e Click &a to browse through the &a available official Addons. @@ -1613,17 +1656,16 @@ catalog: &e Click &a to get the link to the &a latest release. - already-installed: "Already installed!" - install-now: "Install now!" - + already-installed: Already installed! + install-now: Install now! + empty-here: - name: "&b This looks empty here..." + name: '&b This looks empty here...' description: | &c BentoBox could not connect to GitHub. &a Allow BentoBox to connect to GitHub in &a the configuration or try again later. - enums: DamageCause: CONTACT: Contact @@ -1654,23 +1696,22 @@ enums: HOT_FLOOR: Hot Floor CRAMMING: Cramming DRYOUT: Dryout - + panel: credits: - title: "&8 [name] &2 Credits" + title: '&8 [name] &2 Credits' contributor: - name: "&a [name]" + name: '&a [name]' description: | &a Commits: &b [commits] empty-here: - name: "&c This looks empty here..." + name: '&c This looks empty here...' description: | &c BentoBox could not gather the Contributors &c for this Addon. &a Allow BentoBox to connect to GitHub in &a the configuration or try again later. - successfully-loaded: |2 &6 ____ _ ____ @@ -1679,4 +1720,3 @@ successfully-loaded: |2 &6 | _ < / _ \ '_ \| __/ _ \| _ < / _ \ \/ / &6 | |_) | __/ | | | || (_) | |_) | (_) > < &b v&e [version] &6 |____/ \___|_| |_|\__\___/|____/ \___/_/\_\ &8 Loaded in &e [time]&8 ms. - diff --git a/src/main/resources/locales/es.yml b/src/main/resources/locales/es.yml index 0079512d5..cf113a558 100644 --- a/src/main/resources/locales/es.yml +++ b/src/main/resources/locales/es.yml @@ -909,9 +909,9 @@ protection: island: Isla de [name] name: Mensaje de Entrada/Salida now-entering: "&bEntrando a [name]" - now-entering-your-island: "&a Ahora entrando en tu isla." + now-entering-your-island: "&a Ahora entrando en tu isla: &b [name]" now-leaving: "&bSaliendo de [name]" - now-leaving-your-island: "&a Ahora saliendo de tu isla." + now-leaving-your-island: "&a Ahora saliendo de tu isla: &b [name]" EXPERIENCE_BOTTLE_THROWING: name: Lanzamiento de botellas de experiencia description: Modificar lanzamiento de experiencia. diff --git a/src/main/resources/locales/fr.yml b/src/main/resources/locales/fr.yml index 6257b00be..e87781f0f 100644 --- a/src/main/resources/locales/fr.yml +++ b/src/main/resources/locales/fr.yml @@ -1003,9 +1003,9 @@ protection: island: "[name]" name: Enter/Exit messages now-entering: "&a Entrer maintenant &b [nom] &a." - now-entering-your-island: "&a Vous venez d'entrer sur votre île." + now-entering-your-island: "&a Vous venez d'entrer sur votre île: &b [name]" now-leaving: "&a Quittant maintenant &b [nom] &a." - now-leaving-your-island: "&a Vous venez de quitter votre île." + now-leaving-your-island: "&a Vous venez de quitter votre île: &b [name]" EXPERIENCE_BOTTLE_THROWING: description: Toggle throwing experience bottles. hint: Bouteilles d'expérience désactivées diff --git a/src/main/resources/locales/it.yml b/src/main/resources/locales/it.yml index 99bb6a323..555added7 100644 --- a/src/main/resources/locales/it.yml +++ b/src/main/resources/locales/it.yml @@ -992,8 +992,8 @@ protection: name: Messaggi di Entrata/Uscita now-entering: "&bStai entrando in [name]" now-leaving: "&bStai uscendo da [name]" - now-entering-your-island: "&a Stai entrando nella tua isola." - now-leaving-your-island: "&a Stai uscendo dalla tua isola." + now-entering-your-island: "&a Stai entrando nella tua isola: &b [name]" + now-leaving-your-island: "&a Stai uscendo dalla tua isola: &b [name]" EXPERIENCE_BOTTLE_THROWING: description: Abilita/disabilita lancio di boccette di esperienza. hint: Lancio di boccette di esperienza disabilitato diff --git a/src/main/resources/locales/ja.yml b/src/main/resources/locales/ja.yml index b32ebe53b..da2eddc39 100644 --- a/src/main/resources/locales/ja.yml +++ b/src/main/resources/locales/ja.yml @@ -1008,9 +1008,9 @@ protection: island: "[name]の島" name: 入り口/終了メッセージ now-entering: 今[name]を入力する - now-entering-your-island: "&a今あなたの島に入っています。" now-leaving: 今[name]を残し - now-leaving-your-island: "&a今あなたの島を去ります。" + now-entering-your-island: "&a今あなたの島に入っています。 &b [name]" + now-leaving-your-island: "&a今あなたの島を去ります。 &b [name]" EXPERIENCE_BOTTLE_THROWING: name: ボトル投げ体験 description: エクスペリエンスボトルの投げを切り替えます。 diff --git a/src/main/resources/locales/ko.yml b/src/main/resources/locales/ko.yml index 60cbb16e6..253568359 100644 --- a/src/main/resources/locales/ko.yml +++ b/src/main/resources/locales/ko.yml @@ -870,9 +870,9 @@ protection: island: "[name]의 섬" name: 출입 메시지 now-entering: "&b [name]&a으로 진입했습니다 ." - now-entering-your-island: "&a 자신의 섬으로 왔습니다." + now-entering-your-island: "&a 자신의 섬으로 왔습니다. &b [name]" now-leaving: "&b [name]&a에서 떠나는 중입니다 ." - now-leaving-your-island: "&a 자신의 섬에서 떠나는 중입니다" + now-leaving-your-island: "&a 자신의 섬에서 떠나는 중입니다. &b [name]" EXPERIENCE_BOTTLE_THROWING: name: 경험치병 던지기 description: 경험치병을 던질수 있는지여부를 설정합니다 diff --git a/src/main/resources/locales/lv.yml b/src/main/resources/locales/lv.yml index a3e38a1cf..e1ef7411b 100644 --- a/src/main/resources/locales/lv.yml +++ b/src/main/resources/locales/lv.yml @@ -1009,8 +1009,8 @@ protection: name: Ieejas/Izejas ziņa now-entering: "&bTu ieej [name] salā" now-leaving: "&bTu pamet [name] salu" - now-entering-your-island: "&a Tu ieej savā salā." - now-leaving-your-island: "&a Tu pamet savu salu." + now-entering-your-island: "&a Tu ieej savā salā: &b [name]" + now-leaving-your-island: "&a Tu pamet savu salu: &b [name]" EXPERIENCE_BOTTLE_THROWING: description: Pārslēdz pieredzes pudeļu mešanu hint: Pieredžu pudeļu mešana nav atļauta diff --git a/src/main/resources/locales/nl.yml b/src/main/resources/locales/nl.yml index fa1115518..69e4b4d99 100644 --- a/src/main/resources/locales/nl.yml +++ b/src/main/resources/locales/nl.yml @@ -976,9 +976,9 @@ protection: island: Het eiland van [name] name: Berichten invoeren / verlaten now-entering: "&a Voer nu &b [name] in &a." - now-entering-your-island: "&a Nu betreedt u uw eiland." + now-entering-your-island: "&a Nu betreedt u uw eiland: &b [name]" now-leaving: "&a Nu weggaan &b [name] &a." - now-leaving-your-island: "&a Verlaat nu je eiland." + now-leaving-your-island: "&a Verlaat nu je eiland: &b [name]" EXPERIENCE_BOTTLE_THROWING: name: Ervaar het gooien van flessen description: Wissel met het werpen van ervaringsflessen. diff --git a/src/main/resources/locales/pl.yml b/src/main/resources/locales/pl.yml index 1cb2cd42d..e8b7fb211 100644 --- a/src/main/resources/locales/pl.yml +++ b/src/main/resources/locales/pl.yml @@ -884,8 +884,8 @@ protection: name: Wiadomości wejścia / wyjścia now-entering: Wchodzisz na wyspę [name] now-leaving: Wychodzisz z wyspy [name] - now-entering-your-island: '&a Wchodzisz na swoją wyspę.' - now-leaving-your-island: '&a Opuszczasz swoją wyspę.' + now-entering-your-island: '&a Wchodzisz na swoją wyspę: &b [name]' + now-leaving-your-island: '&a Opuszczasz swoją wyspę: &b [name]' EXPERIENCE_BOTTLE_THROWING: name: Rzucanie butelkami z doświadczeniem description: Przełącz rzucanie butelkami z doświadczeniem diff --git a/src/main/resources/locales/pt_BR.yml b/src/main/resources/locales/pt_BR.yml index b9b60ea17..1bc582f86 100644 --- a/src/main/resources/locales/pt_BR.yml +++ b/src/main/resources/locales/pt_BR.yml @@ -915,9 +915,9 @@ protection: island: ilha de [name] name: Mensagens de entrada/saída now-entering: '&a Entrando na &b [name]&a .' - now-entering-your-island: '&a Entrando em sua ilha.' + now-entering-your-island: '&a Entrando em sua ilha: &b [name]' now-leaving: '&a Deixando a &b [name]&a .' - now-leaving-your-island: '&a Deixando sua ilha.' + now-leaving-your-island: '&a Deixando sua ilha: &b [name]' EXPERIENCE_BOTTLE_THROWING: name: Arremesso de frasco de experiência description: Permitir arremesso de frascos de experiência diff --git a/src/main/resources/locales/ro.yml b/src/main/resources/locales/ro.yml index 4095afabd..35bf49d2b 100644 --- a/src/main/resources/locales/ro.yml +++ b/src/main/resources/locales/ro.yml @@ -949,9 +949,9 @@ protection: island: insula [numele] name: Introduceți / ieșiți din mesaje now-entering: "&a Acum introduceți &b [name] &a." - now-entering-your-island: "&a Acum intrând în insula ta." + now-entering-your-island: "&a Acum intrând în insula ta: &b [name]" now-leaving: "&a Acum plecăm de la &b [name] &a." - now-leaving-your-island: "&a Acum părăsind insula ta." + now-leaving-your-island: "&a Acum părăsind insula ta: &b [name]" EXPERIENCE_BOTTLE_THROWING: name: Experimentați aruncarea cu sticle description: Comutați aruncarea sticlelor de experiență. diff --git a/src/main/resources/locales/tr.yml b/src/main/resources/locales/tr.yml index b98a4db08..08e4f3445 100644 --- a/src/main/resources/locales/tr.yml +++ b/src/main/resources/locales/tr.yml @@ -976,9 +976,9 @@ protection: island: "[name]" name: Giriş/çıkış mesajları now-entering: "&d[name] &badasına girdin!" - now-entering-your-island: "&aAdana giriş yaptın." + now-entering-your-island: "&aAdana giriş yaptın: &b [name]" now-leaving: "&d[name] &badasından çıktın!" - now-leaving-your-island: "&aAdandan çıktın." + now-leaving-your-island: "&aAdandan çıktın: &b [name]" EXPERIENCE_BOTTLE_THROWING: name: XP şisesi fırlatması description: XP şişe fırlatılmasını değiş. diff --git a/src/main/resources/locales/vi.yml b/src/main/resources/locales/vi.yml index 5ce65a944..11c697deb 100644 --- a/src/main/resources/locales/vi.yml +++ b/src/main/resources/locales/vi.yml @@ -978,9 +978,9 @@ protection: island: đảo của [name] name: Thông báo Vào/Ra now-entering: "&a Đang vào &b [name]&a ." - now-entering-your-island: "&a Đang vào đảo của bạn." + now-entering-your-island: "&a Đang vào đảo của bạn: &b [name]" now-leaving: "&a Đang rời &b [name]&a ." - now-leaving-your-island: "&a Đang rời đảo của bạn." + now-leaving-your-island: "&a Đang rời đảo của bạn: &b [name]" EXPERIENCE_BOTTLE_THROWING: name: Quăng bình kinh nghiệm description: Bật/Tắt quăng bình kinh nghiệm. diff --git a/src/main/resources/locales/zh-CN.yml b/src/main/resources/locales/zh-CN.yml index 9ee73b3c5..c7a1ba35e 100644 --- a/src/main/resources/locales/zh-CN.yml +++ b/src/main/resources/locales/zh-CN.yml @@ -953,9 +953,9 @@ protection: island: "[name] 的岛屿" name: "&a&l进出岛屿提示" now-entering: "&a您已进入 &b[name] &a。" - now-entering-your-island: "&a您已进入自己的岛屿。" + now-entering-your-island: "&a您已进入自己的岛屿。 &b [name]" now-leaving: "&6您已离开 &b[name] &a。" - now-leaving-your-island: "&6您已离开自己的岛屿。" + now-leaving-your-island: "&6您已离开自己的岛屿。 &b [name]" EXPERIENCE_BOTTLE_THROWING: name: "&a&l投掷经验瓶" description: 允许/禁止 在岛上扔经验瓶 diff --git a/src/main/resources/locales/zh-HK.yml b/src/main/resources/locales/zh-HK.yml index b9cc2a626..ba1f136d8 100644 --- a/src/main/resources/locales/zh-HK.yml +++ b/src/main/resources/locales/zh-HK.yml @@ -973,9 +973,9 @@ protection: island: '[name] 的島嶼' name: '&a&l進出島嶼提示' now-entering: '&a您已進入 &b[name] &a。' - now-entering-your-island: '&a您已進入自己的島嶼。' + now-entering-your-island: '&a您已進入自己的島嶼。 &b [name]' now-leaving: '&6您已離開 &b[name] &a。' - now-leaving-your-island: '&6您已離開自己的島嶼。' + now-leaving-your-island: '&6您已離開自己的島嶼。 &b [name]' EXPERIENCE_BOTTLE_THROWING: name: '&a&l投擲經驗瓶' description: 允許/禁止 在島上扔經驗瓶 diff --git a/src/test/java/world/bentobox/bentobox/api/addons/AddonDescriptionTest.java b/src/test/java/world/bentobox/bentobox/api/addons/AddonDescriptionTest.java index b7f9f4398..0c72384d1 100644 --- a/src/test/java/world/bentobox/bentobox/api/addons/AddonDescriptionTest.java +++ b/src/test/java/world/bentobox/bentobox/api/addons/AddonDescriptionTest.java @@ -1,6 +1,7 @@ package world.bentobox.bentobox.api.addons; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import java.util.List; diff --git a/src/test/java/world/bentobox/bentobox/api/commands/admin/AdminDeleteCommandTest.java b/src/test/java/world/bentobox/bentobox/api/commands/admin/AdminDeleteCommandTest.java index 1649e3599..2af179c88 100644 --- a/src/test/java/world/bentobox/bentobox/api/commands/admin/AdminDeleteCommandTest.java +++ b/src/test/java/world/bentobox/bentobox/api/commands/admin/AdminDeleteCommandTest.java @@ -11,18 +11,22 @@ import java.util.Arrays; import java.util.Collections; import java.util.HashMap; +import java.util.List; import java.util.UUID; import org.bukkit.Bukkit; import org.bukkit.Location; +import org.bukkit.World; import org.bukkit.entity.Player; import org.bukkit.scheduler.BukkitScheduler; import org.bukkit.scheduler.BukkitTask; import org.bukkit.util.Vector; +import org.eclipse.jdt.annotation.Nullable; import org.junit.After; 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; @@ -49,12 +53,20 @@ @PrepareForTest({Bukkit.class, BentoBox.class, User.class }) public class AdminDeleteCommandTest { + @Mock private CompositeCommand ac; + @Mock private User user; + @Mock private IslandsManager im; + @Mock private PlayersManager pm; private UUID notUUID; private UUID uuid; + @Mock + private World world; + @Mock + private @Nullable Island island; /** */ @@ -79,7 +91,6 @@ public void setUp() throws Exception { // 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(); @@ -92,9 +103,9 @@ public void setUp() throws Exception { User.setPlugin(plugin); // Parent command has no aliases - ac = mock(CompositeCommand.class); when(ac.getSubCommandAliases()).thenReturn(new HashMap<>()); when(ac.getTopLabel()).thenReturn("admin"); + when(ac.getWorld()).thenReturn(world); // Island World Manager IslandWorldManager iwm = mock(IslandWorldManager.class); @@ -102,15 +113,17 @@ public void setUp() throws Exception { // Player has island to begin with - im = mock(IslandsManager.class); when(im.hasIsland(any(), any(UUID.class))).thenReturn(true); when(im.hasIsland(any(), any(User.class))).thenReturn(true); when(im.isOwner(any(),any())).thenReturn(true); when(im.getOwner(any(),any())).thenReturn(uuid); + when(im.getIsland(world, user)).thenReturn(island); when(plugin.getIslands()).thenReturn(im); + // Island + when(island.getOwner()).thenReturn(uuid); + // Has team - pm = mock(PlayersManager.class); when(im.inTeam(any(), eq(uuid))).thenReturn(true); when(plugin.getPlayers()).thenReturn(pm); @@ -162,10 +175,9 @@ public void testExecuteUnknownPlayer() { @Test public void testExecutePlayerNoIsland() { AdminDeleteCommand itl = new AdminDeleteCommand(ac); - String[] name = {"tastybento"}; when(pm.getUUID(any())).thenReturn(notUUID); - when(im.getOwner(any(), any())).thenReturn(null); - assertFalse(itl.canExecute(user, itl.getLabel(), Arrays.asList(name))); + when(im.getIsland(world, user)).thenReturn(null); + assertFalse(itl.canExecute(user, "", List.of("tastybento"))); verify(user).sendMessage(eq("general.errors.player-has-no-island")); } @@ -174,6 +186,7 @@ public void testExecutePlayerNoIsland() { */ @Test public void testExecuteOwner() { + when(im.inTeam(any(),any())).thenReturn(true); when(im.getOwner(any(), any())).thenReturn(notUUID); String[] name = {"tastybento"}; diff --git a/src/test/java/world/bentobox/bentobox/api/commands/admin/blueprints/AdminBlueprintLoadCommandTest.java b/src/test/java/world/bentobox/bentobox/api/commands/admin/blueprints/AdminBlueprintLoadCommandTest.java index f3c911d45..428b702b7 100644 --- a/src/test/java/world/bentobox/bentobox/api/commands/admin/blueprints/AdminBlueprintLoadCommandTest.java +++ b/src/test/java/world/bentobox/bentobox/api/commands/admin/blueprints/AdminBlueprintLoadCommandTest.java @@ -1,6 +1,9 @@ package world.bentobox.bentobox.api.commands.admin.blueprints; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.mock; diff --git a/src/test/java/world/bentobox/bentobox/api/commands/admin/team/AdminTeamDisbandCommandTest.java b/src/test/java/world/bentobox/bentobox/api/commands/admin/team/AdminTeamDisbandCommandTest.java index 52db08e11..cb6601244 100644 --- a/src/test/java/world/bentobox/bentobox/api/commands/admin/team/AdminTeamDisbandCommandTest.java +++ b/src/test/java/world/bentobox/bentobox/api/commands/admin/team/AdminTeamDisbandCommandTest.java @@ -229,8 +229,8 @@ public void testExecuteSuccess() { AdminTeamDisbandCommand itl = new AdminTeamDisbandCommand(ac); assertTrue(itl.execute(user, itl.getLabel(), Arrays.asList(name))); - verify(im, never()).setLeaveTeam(any(), eq(notUUID)); - verify(im).setLeaveTeam(any(), eq(uuid)); + verify(is, never()).removeMember(notUUID); + verify(is).removeMember(uuid); verify(user).sendMessage("commands.admin.team.disband.success", TextVariables.NAME, name[0]); verify(p).sendMessage("commands.admin.team.disband.disbanded"); verify(p2).sendMessage("commands.admin.team.disband.disbanded"); diff --git a/src/test/java/world/bentobox/bentobox/api/commands/island/IslandCreateCommandTest.java b/src/test/java/world/bentobox/bentobox/api/commands/island/IslandCreateCommandTest.java index 3ded14952..9c5572668 100644 --- a/src/test/java/world/bentobox/bentobox/api/commands/island/IslandCreateCommandTest.java +++ b/src/test/java/world/bentobox/bentobox/api/commands/island/IslandCreateCommandTest.java @@ -18,8 +18,10 @@ import java.util.UUID; import org.bukkit.Bukkit; +import org.bukkit.World; import org.bukkit.entity.Player; import org.bukkit.scheduler.BukkitScheduler; +import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; import org.junit.After; import org.junit.Before; @@ -37,6 +39,7 @@ import world.bentobox.bentobox.Settings; import world.bentobox.bentobox.api.addons.GameModeAddon; import world.bentobox.bentobox.api.commands.CompositeCommand; +import world.bentobox.bentobox.api.configuration.WorldSettings; import world.bentobox.bentobox.api.events.island.IslandEvent.Reason; import world.bentobox.bentobox.api.user.User; import world.bentobox.bentobox.blueprints.dataobjects.BlueprintBundle; @@ -75,6 +78,12 @@ public class IslandCreateCommandTest { private CompositeCommand ic; @Mock private BlueprintsManager bpm; + @Mock + private World world; + @Mock + private @NonNull WorldSettings ws; + @Mock + private Island island; /** */ @@ -115,6 +124,7 @@ public void setUp() throws Exception { when(ic.getUsage()).thenReturn(""); when(ic.getSubCommand(Mockito.anyString())).thenReturn(Optional.empty()); when(ic.getAddon()).thenReturn(addon); + when(ic.getWorld()).thenReturn(world); // No island for player to begin with (set it later in the tests) @@ -122,7 +132,7 @@ public void setUp() throws Exception { when(im.isOwner(any(), eq(uuid))).thenReturn(false); // Has team when(im.inTeam(any(), eq(uuid))).thenReturn(true); - + when(im.getPrimaryIsland(world, uuid)).thenReturn(island); when(plugin.getIslands()).thenReturn(im); @@ -136,6 +146,8 @@ public void setUp() throws Exception { // IWM friendly name when(iwm.getFriendlyName(any())).thenReturn("BSkyBlock"); + when(ws.getConcurrentIslands()).thenReturn(1); // One island allowed + when(iwm.getWorldSettings(world)).thenReturn(ws); when(plugin.getIWM()).thenReturn(iwm); // NewIsland @@ -190,11 +202,11 @@ public void testSetup() { */ @Test public void testCanExecuteUserStringListOfStringHasIsland() { - @Nullable - Island island = mock(Island.class); - when(im.getIsland(any(), Mockito.any(User.class))).thenReturn(island); + // Currently user has two islands + when(im.getNumberOfConcurrentIslands(user.getUniqueId(), world)).thenReturn(2); + // Player has an island assertFalse(cc.canExecute(user, "", Collections.emptyList())); - verify(user).sendMessage(eq("general.errors.already-have-island")); + verify(user).sendMessage("general.errors.you-cannot-make"); } /** @@ -207,7 +219,7 @@ public void testCanExecuteUserStringListOfStringHasIslandReserved() { when(im.getIsland(any(), Mockito.any(User.class))).thenReturn(island); when(island.isReserved()).thenReturn(true); assertTrue(cc.canExecute(user, "", Collections.emptyList())); - verify(user, never()).sendMessage(eq("general.errors.already-have-island")); + verify(user, never()).sendMessage("general.errors.already-have-island"); } @@ -216,12 +228,12 @@ public void testCanExecuteUserStringListOfStringHasIslandReserved() { */ @Test public void testCanExecuteUserStringListOfStringTooManyIslands() { - when(im.hasIsland(any(), Mockito.any(UUID.class))).thenReturn(false); + when(im.getPrimaryIsland(any(), Mockito.any(UUID.class))).thenReturn(null); when(im.inTeam(any(), Mockito.any(UUID.class))).thenReturn(false); when(iwm.getMaxIslands(any())).thenReturn(100); - when(im.getIslandCount(any())).thenReturn(100); + when(im.getIslandCount(any())).thenReturn(100L); assertFalse(cc.canExecute(user, "", Collections.emptyList())); - verify(user).sendMessage(eq("commands.island.create.too-many-islands")); + verify(user).sendMessage("commands.island.create.too-many-islands"); } diff --git a/src/test/java/world/bentobox/bentobox/api/commands/island/IslandDeletehomeCommandTest.java b/src/test/java/world/bentobox/bentobox/api/commands/island/IslandDeletehomeCommandTest.java index 7a3e65ff1..6e6382a8e 100644 --- a/src/test/java/world/bentobox/bentobox/api/commands/island/IslandDeletehomeCommandTest.java +++ b/src/test/java/world/bentobox/bentobox/api/commands/island/IslandDeletehomeCommandTest.java @@ -14,12 +14,14 @@ import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.Set; import java.util.UUID; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.World; import org.bukkit.entity.Player; +import org.eclipse.jdt.annotation.NonNull; import org.jetbrains.annotations.NotNull; import org.junit.After; import org.junit.Before; @@ -67,6 +69,10 @@ public class IslandDeletehomeCommandTest { private IslandDeletehomeCommand idh; @Mock private IslandWorldManager iwm; + @Mock + private @NonNull World world; + @Mock + private Location location; /** * @throws java.lang.Exception @@ -100,6 +106,7 @@ public void setUp() throws Exception { when(ic.getUsage()).thenReturn(""); when(ic.getSubCommand(Mockito.anyString())).thenReturn(Optional.empty()); when(ic.getAddon()).thenReturn(addon); + when(ic.getWorld()).thenReturn(world); when(plugin.getIslands()).thenReturn(im); // Player Player player = mock(Player.class); @@ -108,13 +115,14 @@ public void setUp() throws Exception { when(user.getUniqueId()).thenReturn(uuid); when(user.getPlayer()).thenReturn(player); when(user.getName()).thenReturn("tastybento"); - when(user.getWorld()).thenReturn(mock(World.class)); + when(user.getWorld()).thenReturn(world); when(user.getTranslation(anyString())).thenAnswer(i -> i.getArgument(0, String.class)); // Island when(island.getOwner()).thenReturn(uuid); when(island.onIsland(any())).thenReturn(true); - when(im.getIsland(any(), any(UUID.class))).thenReturn(island); - when(im.getIsland(any(), any(User.class))).thenReturn(island); + when(im.getIsland(world, uuid)).thenReturn(island); + when(im.getIsland(world, user)).thenReturn(island); + when(im.getIslands(world, uuid)).thenReturn(Set.of(island)); @NotNull Map homeMap = new HashMap<>(); homeMap.put("Home", null); @@ -175,7 +183,7 @@ public void testSetup() { @Test public void testCanExecuteHelp() { idh.canExecute(user, "label", List.of()); - verify(user).sendMessage("commands.help.header","[label]","commands.help.console"); + verify(user).sendMessage("commands.help.header","[label]","BSkyBlock"); } /** @@ -201,41 +209,28 @@ public void testCanExecuteLowRank() { } /** - * Test method for {@link world.bentobox.bentobox.api.commands.island.IslandDeletehomeCommand#canExecute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. + * Test method for {@link world.bentobox.bentobox.api.commands.island.IslandDeletehomeCommand#execute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. */ @Test - public void testCanExecuteUnknownHome() { - when(island.getRank(user)).thenReturn(RanksManager.OWNER_RANK); - when(island.getRankCommand(anyString())).thenReturn(RanksManager.COOP_RANK); - when(island.getHomes()).thenReturn(Map.of("home", mock(Location.class))); + public void testExecuteUnknownHome() { + when(island.getHomes()).thenReturn(Map.of("home", location)); when(im.isHomeLocation(eq(island), anyString())).thenReturn(false); - assertFalse(idh.canExecute(user, "label", List.of("something"))); + assertFalse(idh.execute(user, "label", List.of("something"))); verify(user).sendMessage("commands.island.go.unknown-home"); verify(user).sendMessage("commands.island.sethome.homes-are"); verify(user).sendMessage("commands.island.sethome.home-list-syntax", TextVariables.NAME, "home"); } - /** - * Test method for {@link world.bentobox.bentobox.api.commands.island.IslandDeletehomeCommand#canExecute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. - */ - @Test - public void testCanExecuteKnownHome() { - when(island.getRank(user)).thenReturn(RanksManager.OWNER_RANK); - when(island.getRankCommand(anyString())).thenReturn(RanksManager.COOP_RANK); - when(island.getHomes()).thenReturn(Map.of("home", mock(Location.class))); - - when(im.isHomeLocation(eq(island), anyString())).thenReturn(true); - - assertTrue(idh.canExecute(user, "label", List.of("home"))); - } /** * Test method for {@link world.bentobox.bentobox.api.commands.island.IslandDeletehomeCommand#execute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. */ @Test public void testExecuteUserStringListOfString() { + when(island.getHomes()).thenReturn(Map.of("home", location)); + when(im.isHomeLocation(eq(island), anyString())).thenReturn(true); assertTrue(idh.execute(user, "label", List.of("home"))); verify(user).sendMessage("commands.confirmation.confirm", "[seconds]", "10"); } @@ -245,7 +240,7 @@ public void testExecuteUserStringListOfString() { */ @Test public void testTabCompleteUserStringListOfString() { - when(island.getHomes()).thenReturn(Map.of("home", mock(Location.class))); + when(island.getHomes()).thenReturn(Map.of("home", location)); Optional> list = idh.tabComplete(user, "label", List.of("hom")); assertTrue(list.isPresent()); assertEquals("home", list.get().get(0)); @@ -256,7 +251,7 @@ public void testTabCompleteUserStringListOfString() { */ @Test public void testTabCompleteUserStringListOfStringNothing() { - when(island.getHomes()).thenReturn(Map.of("home", mock(Location.class))); + when(island.getHomes()).thenReturn(Map.of("home", location)); Optional> list = idh.tabComplete(user, "label", List.of("f")); assertTrue(list.isPresent()); assertTrue(list.get().isEmpty()); diff --git a/src/test/java/world/bentobox/bentobox/api/commands/island/IslandGoCommandTest.java b/src/test/java/world/bentobox/bentobox/api/commands/island/IslandGoCommandTest.java index 12c9c41aa..a1aff9c0b 100644 --- a/src/test/java/world/bentobox/bentobox/api/commands/island/IslandGoCommandTest.java +++ b/src/test/java/world/bentobox/bentobox/api/commands/island/IslandGoCommandTest.java @@ -90,6 +90,7 @@ public class IslandGoCommandTest { @Mock private World world; private @Nullable WorldSettings ws; + private UUID uuid = UUID.randomUUID(); /** */ @@ -108,7 +109,6 @@ public void setUp() throws Exception { // Player when(player.isOp()).thenReturn(false); - UUID uuid = UUID.randomUUID(); when(player.getUniqueId()).thenReturn(uuid); when(player.getName()).thenReturn("tastybento"); when(player.getWorld()).thenReturn(world); @@ -123,10 +123,12 @@ public void setUp() throws Exception { // Have the create command point to the ic command Optional createCommand = Optional.of(ic); when(ic.getSubCommand(eq("create"))).thenReturn(createCommand); + when(ic.getWorld()).thenReturn(world); - // No island for player to begin with (set it later in the tests) - when(im.hasIsland(any(), eq(uuid))).thenReturn(false); - when(im.isOwner(any(), eq(uuid))).thenReturn(false); + // Player has island by default + when(im.getIslands(world, uuid)).thenReturn(Set.of(island)); + when(im.hasIsland(world, uuid)).thenReturn(true); + when(im.isOwner(world, uuid)).thenReturn(true); when(plugin.getIslands()).thenReturn(im); // Has team @@ -200,7 +202,7 @@ public void testExecuteMidTeleport() { */ @Test public void testExecuteNoArgsNoIsland() { - when(im.getIsland(any(), any(UUID.class))).thenReturn(null); + when(im.getIslands(world, uuid)).thenReturn(Set.of()); assertFalse(igc.canExecute(user, igc.getLabel(), Collections.emptyList())); verify(player).sendMessage("general.errors.no-island"); } @@ -210,7 +212,6 @@ public void testExecuteNoArgsNoIsland() { */ @Test public void testExecuteNoArgs() { - when(im.getIsland(any(), any(UUID.class))).thenReturn(island); assertTrue(igc.canExecute(user, igc.getLabel(), Collections.emptyList())); } @@ -219,7 +220,6 @@ public void testExecuteNoArgs() { */ @Test public void testExecuteNoArgsReservedIsland() { - when(im.getIsland(any(), any(UUID.class))).thenReturn(island); when(ic.call(any(), any(), any())).thenReturn(true); when(island.isReserved()).thenReturn(true); assertFalse(igc.canExecute(user, igc.getLabel(), Collections.emptyList())); @@ -232,7 +232,7 @@ public void testExecuteNoArgsReservedIsland() { @Test public void testExecuteNoArgsReservedIslandNoCreateCommand() { when(ic.getSubCommand(eq("create"))).thenReturn(Optional.empty()); - when(im.getIsland(any(), any(UUID.class))).thenReturn(island); + when(ic.call(any(), any(), any())).thenReturn(true); when(island.isReserved()).thenReturn(true); assertFalse(igc.canExecute(user, igc.getLabel(), Collections.emptyList())); @@ -265,7 +265,7 @@ public void testExecuteNoArgsNoTeleportWhenFallingNotFalling() { */ @Test public void testExecuteNoArgsMultipleHomes() { - when(im.getIsland(any(), any(UUID.class))).thenReturn(island); + //when(user.getPermissionValue(anyString(), anyInt())).thenReturn(3); assertTrue(igc.execute(user, igc.getLabel(), Collections.emptyList())); } @@ -275,30 +275,10 @@ public void testExecuteNoArgsMultipleHomes() { */ @Test public void testExecuteArgs1MultipleHomes() { - when(im.getIsland(any(), any(UUID.class))).thenReturn(island); - //when(user.getPermissionValue(anyString(), anyInt())).thenReturn(3); - assertTrue(igc.execute(user, igc.getLabel(), Collections.singletonList("1"))); - } - - /** - * Test method for {@link IslandGoCommand#execute(User, String, List)} - */ - @Test - public void testExecuteArgs2MultipleHomes() { - when(im.getIsland(any(), any(UUID.class))).thenReturn(island); - //when(user.getPermissionValue(anyString(), anyInt())).thenReturn(3); - assertTrue(igc.execute(user, igc.getLabel(), Collections.singletonList("2"))); - } - - - /** - * Test method for {@link IslandGoCommand#execute(User, String, List)} - */ - @Test - public void testExecuteArgsJunkMultipleHomes() { - when(im.getIsland(any(), any(UUID.class))).thenReturn(island); - //when(user.getPermissionValue(anyString(), anyInt())).thenReturn(3); - assertTrue(igc.execute(user, igc.getLabel(), Collections.singletonList("sdfghhj"))); + assertFalse(igc.execute(user, igc.getLabel(), Collections.singletonList("1"))); + verify(player).sendMessage("commands.island.go.unknown-home"); + verify(player).sendMessage("commands.island.sethome.homes-are"); + verify(player).sendMessage("commands.island.sethome.home-list-syntax"); } /** @@ -307,7 +287,7 @@ public void testExecuteArgsJunkMultipleHomes() { @Test public void testExecuteNoArgsDelay() { when(s.getDelayTime()).thenReturn(10); - when(im.getIsland(any(), any(UUID.class))).thenReturn(island); + assertTrue(igc.execute(user, igc.getLabel(), Collections.emptyList())); verify(player).sendMessage(eq("commands.delay.stand-still")); } @@ -327,19 +307,6 @@ public void testExecuteNoArgsDelayTwice() { verify(player, Mockito.times(2)).sendMessage(eq("commands.delay.stand-still")); } - /** - * Test method for {@link IslandGoCommand#execute(User, String, List)} - */ - @Test - public void testExecuteNoArgsDelayMultiHome() { - when(im.getIsland(any(), any(UUID.class))).thenReturn(island); - //when(user.getPermissionValue(anyString(), anyInt())).thenReturn(3); - when(s.getDelayTime()).thenReturn(10); - when(im.getIsland(any(), any(UUID.class))).thenReturn(island); - assertTrue(igc.execute(user, igc.getLabel(), Collections.singletonList("2"))); - verify(player).sendMessage(eq("commands.delay.stand-still")); - } - /** * Test method for {@link IslandGoCommand#onPlayerMove(PlayerMoveEvent)} */ diff --git a/src/test/java/world/bentobox/bentobox/api/commands/island/IslandHomesCommandTest.java b/src/test/java/world/bentobox/bentobox/api/commands/island/IslandHomesCommandTest.java index 50c2869cb..f3134194a 100644 --- a/src/test/java/world/bentobox/bentobox/api/commands/island/IslandHomesCommandTest.java +++ b/src/test/java/world/bentobox/bentobox/api/commands/island/IslandHomesCommandTest.java @@ -15,6 +15,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.Map; +import java.util.Set; import java.util.UUID; import org.bukkit.Bukkit; @@ -22,6 +23,7 @@ import org.bukkit.World; import org.bukkit.entity.Player; import org.bukkit.scheduler.BukkitScheduler; +import org.eclipse.jdt.annotation.NonNull; import org.jetbrains.annotations.NotNull; import org.junit.After; import org.junit.Before; @@ -65,6 +67,8 @@ public class IslandHomesCommandTest { private Island island; @Mock private IslandWorldManager iwm; + @Mock + private @NonNull World world; /** */ @@ -89,13 +93,14 @@ public void setUp() throws Exception { when(user.getUniqueId()).thenReturn(uuid); when(user.getPlayer()).thenReturn(player); when(user.getName()).thenReturn("tastybento"); - when(user.getWorld()).thenReturn(mock(World.class)); + when(user.getWorld()).thenReturn(world); when(user.getTranslation(anyString())).thenAnswer(i -> i.getArgument(0, String.class)); // Parent command has no aliases when(ic.getSubCommandAliases()).thenReturn(new HashMap<>()); when(ic.getTopLabel()).thenReturn("island"); when(ic.getPermissionPrefix()).thenReturn("bskyblock."); + when(ic.getWorld()).thenReturn(world); // No island for player to begin with (set it later in the tests) when(im.hasIsland(any(), any(User.class))).thenReturn(false); @@ -171,8 +176,6 @@ public void testSetup() { @Test public void testCanExecuteNoIsland() { // Player doesn't have an island - when(im.getIsland(any(), eq(user))).thenReturn(null); - IslandHomesCommand isc = new IslandHomesCommand(ic); assertFalse(isc.canExecute(user, "island", Collections.emptyList())); verify(user).sendMessage("general.errors.no-island"); @@ -183,6 +186,7 @@ public void testCanExecuteNoIsland() { */ @Test public void testCanExecute() { + when(im.getIslands(world, user)).thenReturn(Set.of(island)); IslandHomesCommand isc = new IslandHomesCommand(ic); assertTrue(isc.canExecute(user, "island", Collections.emptyList())); verify(user, never()).sendMessage("general.errors.no-island"); @@ -193,6 +197,7 @@ public void testCanExecute() { */ @Test public void testExecuteUserStringListOfString() { + when(im.getIslands(world, user)).thenReturn(Set.of(island)); IslandHomesCommand isc = new IslandHomesCommand(ic); assertTrue(isc.canExecute(user, "island", Collections.emptyList())); assertTrue(isc.execute(user, "island", Collections.emptyList())); diff --git a/src/test/java/world/bentobox/bentobox/api/commands/island/IslandResetCommandTest.java b/src/test/java/world/bentobox/bentobox/api/commands/island/IslandResetCommandTest.java index 88e91c127..6ec5da12e 100644 --- a/src/test/java/world/bentobox/bentobox/api/commands/island/IslandResetCommandTest.java +++ b/src/test/java/world/bentobox/bentobox/api/commands/island/IslandResetCommandTest.java @@ -449,4 +449,4 @@ public void testNoConfirmationRequiredCustomSchemHasPermission() throws Exceptio verify(pim, times(14)).callEvent(any(IslandBaseEvent.class)); } -} +} \ No newline at end of file diff --git a/src/test/java/world/bentobox/bentobox/api/commands/island/IslandSethomeCommandTest.java b/src/test/java/world/bentobox/bentobox/api/commands/island/IslandSethomeCommandTest.java index cba130889..767b636dd 100644 --- a/src/test/java/world/bentobox/bentobox/api/commands/island/IslandSethomeCommandTest.java +++ b/src/test/java/world/bentobox/bentobox/api/commands/island/IslandSethomeCommandTest.java @@ -14,12 +14,14 @@ import java.util.Collections; import java.util.HashMap; import java.util.HashSet; +import java.util.Set; import java.util.UUID; import org.bukkit.Bukkit; import org.bukkit.World; import org.bukkit.entity.Player; import org.bukkit.scheduler.BukkitScheduler; +import org.eclipse.jdt.annotation.NonNull; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -64,6 +66,8 @@ public class IslandSethomeCommandTest { private IslandWorldManager iwm; @Mock private WorldSettings ws; + @Mock + private @NonNull World world; /** */ @@ -88,17 +92,19 @@ public void setUp() throws Exception { when(user.getUniqueId()).thenReturn(uuid); when(user.getPlayer()).thenReturn(player); when(user.getName()).thenReturn("tastybento"); - when(user.getWorld()).thenReturn(mock(World.class)); + when(user.getWorld()).thenReturn(world); when(user.getTranslation(anyString())).thenAnswer(i -> i.getArgument(0, String.class)); // Parent command has no aliases when(ic.getSubCommandAliases()).thenReturn(new HashMap<>()); when(ic.getTopLabel()).thenReturn("island"); when(ic.getPermissionPrefix()).thenReturn("bskyblock."); + when(ic.getWorld()).thenReturn(world); - // No island for player to begin with (set it later in the tests) - when(im.hasIsland(any(), any(User.class))).thenReturn(false); - when(im.isOwner(any(), eq(uuid))).thenReturn(false); + // Island for player to begin with + when(im.hasIsland(world, user)).thenReturn(true); + when(im.isOwner(world, uuid)).thenReturn(true); + when(im.getIslands(world, user)).thenReturn(Set.of(island)); when(plugin.getIslands()).thenReturn(im); // Has team @@ -168,7 +174,7 @@ public void testSetup() { @Test public void testCanExecuteNoIsland() { // Player doesn't have an island - when(im.getIsland(any(), eq(user))).thenReturn(null); + when(im.getIsland(world, user)).thenReturn(null); IslandSethomeCommand isc = new IslandSethomeCommand(ic); assertFalse(isc.canExecute(user, "island", Collections.emptyList())); diff --git a/src/test/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamCommandTest.java b/src/test/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamCommandTest.java index f2cb157d3..3bc491105 100644 --- a/src/test/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamCommandTest.java +++ b/src/test/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamCommandTest.java @@ -103,6 +103,7 @@ public void setUp() throws Exception { when(plugin.getIslands()).thenReturn(im); // is owner of island when(im.getOwner(any(), any())).thenReturn(uuid); + when(im.getPrimaryIsland(world, uuid)).thenReturn(island); // Max members when(im.getMaxMembers(eq(island), eq(RanksManager.MEMBER_RANK))).thenReturn(3); // No team members @@ -160,7 +161,7 @@ public void testSetup() { */ @Test public void testExecuteUserStringListOfStringNoIsland() { - when(im.getOwner(any(), any())).thenReturn(null); + when(im.getPrimaryIsland(world, uuid)).thenReturn(null); assertFalse(tc.execute(user, "team", Collections.emptyList())); verify(user).sendMessage(eq("general.errors.no-island")); } @@ -190,7 +191,7 @@ public void testExecuteUserStringListOfStringIslandIsFull() { */ @Test public void testAddInvite() { - tc.addInvite(Invite.Type.TEAM, uuid, invitee); + tc.addInvite(Invite.Type.TEAM, uuid, invitee, island); assertTrue(tc.isInvited(invitee)); } @@ -207,7 +208,7 @@ public void testIsInvited() { */ @Test public void testGetInviter() { - tc.addInvite(Invite.Type.TEAM, uuid, invitee); + tc.addInvite(Invite.Type.TEAM, uuid, invitee, island); assertEquals(uuid, tc.getInviter(invitee)); } @@ -225,7 +226,7 @@ public void testGetInviterNoInvite() { @Test public void testGetInvite() { assertNull(tc.getInvite(invitee)); - tc.addInvite(Invite.Type.TEAM, uuid, invitee); + tc.addInvite(Invite.Type.TEAM, uuid, invitee, island); @Nullable Invite invite = tc.getInvite(invitee); assertEquals(invitee, invite.getInvitee()); @@ -239,7 +240,7 @@ public void testGetInvite() { @Test public void testRemoveInvite() { assertNull(tc.getInvite(invitee)); - tc.addInvite(Invite.Type.TEAM, uuid, invitee); + tc.addInvite(Invite.Type.TEAM, uuid, invitee, island); tc.removeInvite(invitee); assertNull(tc.getInvite(invitee)); } diff --git a/src/test/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamInviteCommandTest.java b/src/test/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamInviteCommandTest.java index 38ae1ba94..d3308cb71 100644 --- a/src/test/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamInviteCommandTest.java +++ b/src/test/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamInviteCommandTest.java @@ -17,9 +17,11 @@ import java.util.UUID; import org.bukkit.Bukkit; +import org.bukkit.World; import org.bukkit.entity.Player; import org.bukkit.plugin.PluginManager; import org.bukkit.scheduler.BukkitScheduler; +import org.eclipse.jdt.annotation.NonNull; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -76,6 +78,8 @@ public class IslandTeamInviteCommandTest { private UUID notUUID; @Mock private Player p; + @Mock + private @NonNull World world; /** @@ -106,7 +110,7 @@ public void setUp() throws Exception { when(user.isOnline()).thenReturn(true); // Permission to invite 3 more players when(user.getPermissionValue(anyString(), anyInt())).thenReturn(3); - when(User.getInstance(eq(uuid))).thenReturn(user); + when(User.getInstance(uuid)).thenReturn(user); when(user.getTranslation(any())).thenAnswer(invocation -> invocation.getArgument(0, String.class)); // Vanished players when(p.canSee(any())).thenReturn(true); @@ -119,11 +123,12 @@ public void setUp() throws Exception { when(target.isOnline()).thenReturn(true); when(target.getName()).thenReturn("target"); when(target.getDisplayName()).thenReturn("&Ctarget"); - when(User.getInstance(eq(notUUID))).thenReturn(target); + when(User.getInstance(notUUID)).thenReturn(target); // Parent command has no aliases when(ic.getSubCommandAliases()).thenReturn(new HashMap<>()); + when(ic.getWorld()).thenReturn(world); // Island islandUUID = UUID.randomUUID(); @@ -144,8 +149,8 @@ public void setUp() throws Exception { // Player Manager when(plugin.getPlayers()).thenReturn(pm); - when(pm.getUUID(eq("tastybento"))).thenReturn(uuid); - when(pm.getUUID(eq("target"))).thenReturn(notUUID); + when(pm.getUUID("tastybento")).thenReturn(uuid); + when(pm.getUUID("target")).thenReturn(notUUID); // Server & Scheduler BukkitScheduler sch = mock(BukkitScheduler.class); @@ -227,7 +232,7 @@ public void testCanExecuteNoIsland() { public void testCanExecuteNoTarget() { assertFalse(itl.canExecute(user, itl.getLabel(), Collections.emptyList())); // Show help - verify(user).sendMessage(eq("commands.help.header"),eq(TextVariables.LABEL),eq("commands.help.console")); + verify(user).sendMessage("commands.help.header", TextVariables.LABEL, "BSkyBlock"); } /** @@ -294,12 +299,13 @@ public void testCanExecuteFullIsland() { */ @Test public void testExecuteSuccessTargetHasIsland() { - when(im.hasIsland(any(), eq(notUUID))).thenReturn(true); + when(im.getIsland(world, uuid)).thenReturn(island); + when(im.hasIsland(world, notUUID)).thenReturn(true); testCanExecuteSuccess(); assertTrue(itl.execute(user, itl.getLabel(), List.of("target"))); verify(pim).callEvent(any(IslandBaseEvent.class)); verify(user, never()).sendMessage(eq("commands.island.team.invite.removing-invite")); - verify(ic).addInvite(eq(Invite.Type.TEAM), eq(uuid), eq(notUUID)); + verify(ic).addInvite(Invite.Type.TEAM, uuid, notUUID, island); verify(user).sendMessage("commands.island.team.invite.invitation-sent", TextVariables.NAME, "target", TextVariables.DISPLAY_NAME, "&Ctarget"); verify(target).sendMessage("commands.island.team.invite.name-has-invited-you", TextVariables.NAME, "tastybento", TextVariables.DISPLAY_NAME, "&Ctastbento"); verify(target).sendMessage("commands.island.team.invite.to-accept-or-reject", TextVariables.LABEL, "island"); @@ -313,10 +319,11 @@ public void testExecuteSuccessTargetHasIsland() { @Test public void testExecuteSuccessTargetHasNoIsland() { testCanExecuteSuccess(); + when(im.getIsland(world, uuid)).thenReturn(island); assertTrue(itl.execute(user, itl.getLabel(), List.of("target"))); verify(pim).callEvent(any(IslandBaseEvent.class)); verify(user, never()).sendMessage("commands.island.team.invite.removing-invite"); - verify(ic).addInvite(Invite.Type.TEAM, uuid, notUUID); + verify(ic).addInvite(Invite.Type.TEAM, uuid, notUUID, island); verify(user).sendMessage("commands.island.team.invite.invitation-sent", TextVariables.NAME, "target", TextVariables.DISPLAY_NAME, "&Ctarget"); verify(target).sendMessage("commands.island.team.invite.name-has-invited-you", TextVariables.NAME, "tastybento", TextVariables.DISPLAY_NAME, "&Ctastbento"); verify(target).sendMessage("commands.island.team.invite.to-accept-or-reject", TextVariables.LABEL, "island"); @@ -330,7 +337,7 @@ public void testExecuteSuccessTargetHasNoIsland() { @Test public void testExecuteTargetAlreadyInvited() { testCanExecuteSuccess(); - + when(im.getIsland(world, uuid)).thenReturn(island); when(ic.isInvited(notUUID)).thenReturn(true); // Set up invite when(ic.getInviter(notUUID)).thenReturn(uuid); 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 d61dbe29a..4b5cb65ab 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 @@ -18,6 +18,7 @@ import org.bukkit.entity.Player; import org.bukkit.plugin.PluginManager; import org.bukkit.scheduler.BukkitScheduler; +import org.eclipse.jdt.annotation.Nullable; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -66,6 +67,8 @@ public class IslandTeamLeaveCommandTest { private PlayersManager pm; @Mock private World world; + @Mock + private @Nullable Island island; /** */ @@ -120,10 +123,8 @@ public void setUp() throws Exception { when(Bukkit.getPluginManager()).thenReturn(pim); // Island - Island island = mock(Island.class); when(island.getUniqueId()).thenReturn("uniqueid"); - when(im.getIsland(any(), Mockito.any(User.class))).thenReturn(island); - + when(im.getIsland(world, user)).thenReturn(island); } @@ -161,7 +162,7 @@ public void testExecuteNoConfirmation() { IslandTeamLeaveCommand itl = new IslandTeamLeaveCommand(ic); assertTrue(itl.execute(user, itl.getLabel(), new ArrayList<>())); - verify(im).setLeaveTeam(any(), eq(uuid)); + verify(island).removeMember(uuid); verify(user).sendMessage(eq("commands.island.team.leave.success")); } @@ -220,10 +221,10 @@ public void testExecuteWithLoseResetCheckHasResets() { IslandTeamLeaveCommand itl = new IslandTeamLeaveCommand(ic); assertTrue(itl.execute(user, itl.getLabel(), new ArrayList<>())); - verify(im).setLeaveTeam(any(), eq(uuid)); - verify(user).sendMessage(eq("commands.island.team.leave.success")); + verify(island).removeMember(uuid); + verify(user).sendMessage("commands.island.team.leave.success"); verify(pm).addReset(eq(world), eq(uuid)); - verify(user).sendMessage(eq("commands.island.reset.resets-left"), eq(TextVariables.NUMBER), eq("100")); + verify(user).sendMessage("commands.island.reset.resets-left", TextVariables.NUMBER, "100"); } /** diff --git a/src/test/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamSetownerCommandTest.java b/src/test/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamSetownerCommandTest.java index 58d0ab29f..d0c6ed4d4 100644 --- a/src/test/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamSetownerCommandTest.java +++ b/src/test/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamSetownerCommandTest.java @@ -12,6 +12,7 @@ import java.util.Collections; import java.util.HashMap; +import java.util.List; import java.util.Optional; import java.util.UUID; @@ -20,6 +21,7 @@ import org.bukkit.entity.Player; import org.bukkit.plugin.PluginManager; import org.bukkit.scheduler.BukkitScheduler; +import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; import org.junit.After; import org.junit.Before; @@ -35,6 +37,7 @@ import world.bentobox.bentobox.BentoBox; import world.bentobox.bentobox.Settings; import world.bentobox.bentobox.api.commands.CompositeCommand; +import world.bentobox.bentobox.api.configuration.WorldSettings; import world.bentobox.bentobox.api.localization.TextVariables; import world.bentobox.bentobox.api.user.User; import world.bentobox.bentobox.database.objects.Island; @@ -119,6 +122,10 @@ public void setUp() throws Exception { // Island World Manager when(plugin.getIWM()).thenReturn(iwm); + @NonNull + WorldSettings ws = mock(WorldSettings.class); + when(iwm.getWorldSettings(world)).thenReturn(ws); + when(ws.getConcurrentIslands()).thenReturn(3); // Plugin Manager PluginManager pim = mock(PluginManager.class); @@ -152,81 +159,101 @@ public void testSetup() { } /** - * Test method for {@link world.bentobox.bentobox.api.commands.island.team.IslandTeamSetownerCommand#execute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. + * Test method for {@link world.bentobox.bentobox.api.commands.island.team.IslandTeamSetownerCommand#canExecute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. */ @Test - public void testExecuteUserStringListOfStringNullOwner() { + public void testCanExecuteUserStringListOfStringNullOwner() { when(im.getOwner(any(), any())).thenReturn(null); - assertFalse(its.execute(user, "", Collections.emptyList())); + assertFalse(its.canExecute(user, "", List.of("gibby"))); verify(user).sendMessage("general.errors.not-owner"); } /** - * Test method for {@link world.bentobox.bentobox.api.commands.island.team.IslandTeamSetownerCommand#execute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. + * Test method for {@link world.bentobox.bentobox.api.commands.island.team.IslandTeamSetownerCommand#canExecute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. */ @Test - public void testExecuteUserStringListOfStringNotInTeam() { + public void testCanExecuteUserStringListOfStringNotInTeam() { when(im.inTeam(any(), any())).thenReturn(false); - assertFalse(its.execute(user, "", Collections.emptyList())); + assertFalse(its.canExecute(user, "", List.of("gibby"))); verify(user).sendMessage("general.errors.no-team"); } /** - * Test method for {@link world.bentobox.bentobox.api.commands.island.team.IslandTeamSetownerCommand#execute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. + * Test method for {@link world.bentobox.bentobox.api.commands.island.team.IslandTeamSetownerCommand#canExecute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. */ @Test - public void testExecuteUserStringListOfStringNotOwner() { + public void testCanExecuteUserStringListOfStringNotOwner() { when(im.inTeam(any(), any())).thenReturn(true); when(im.getOwner(any(), any())).thenReturn(UUID.randomUUID()); - assertFalse(its.execute(user, "", Collections.emptyList())); + assertFalse(its.canExecute(user, "", List.of("gibby"))); verify(user).sendMessage("general.errors.not-owner"); } /** - * Test method for {@link world.bentobox.bentobox.api.commands.island.team.IslandTeamSetownerCommand#execute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. + * Test method for {@link world.bentobox.bentobox.api.commands.island.team.IslandTeamSetownerCommand#canExecute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. */ @Test - public void testExecuteUserStringListOfStringShowHelp() { + public void testCanExecuteUserStringListOfStringShowHelp() { when(im.inTeam(any(), any())).thenReturn(true); when(im.getOwner(any(), any())).thenReturn(uuid); - assertFalse(its.execute(user, "", Collections.emptyList())); + assertFalse(its.canExecute(user, "", Collections.emptyList())); verify(user).sendMessage("commands.help.header","[label]", null); } /** - * Test method for {@link world.bentobox.bentobox.api.commands.island.team.IslandTeamSetownerCommand#execute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. + * Test method for {@link world.bentobox.bentobox.api.commands.island.team.IslandTeamSetownerCommand#canExecute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. */ @Test - public void testExecuteUserStringListOfStringUnknownPlayer() { + public void testCanExecuteUserStringListOfStringUnknownPlayer() { when(im.inTeam(any(), any())).thenReturn(true); when(im.getOwner(any(), any())).thenReturn(uuid); when(pm.getUUID(anyString())).thenReturn(null); - assertFalse(its.execute(user, "", Collections.singletonList("tastybento"))); + assertFalse(its.canExecute(user, "", Collections.singletonList("tastybento"))); verify(user).sendMessage("general.errors.unknown-player", TextVariables.NAME, "tastybento"); } /** - * Test method for {@link world.bentobox.bentobox.api.commands.island.team.IslandTeamSetownerCommand#execute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. + * Test method for {@link world.bentobox.bentobox.api.commands.island.team.IslandTeamSetownerCommand#canExecute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. */ @Test - public void testExecuteUserStringListOfStringSamePlayer() { + public void testCanExecuteUserStringListOfStringSamePlayer() { when(im.inTeam(any(), any())).thenReturn(true); when(im.getOwner(any(), any())).thenReturn(uuid); when(pm.getUUID(anyString())).thenReturn(uuid); - assertFalse(its.execute(user, "", Collections.singletonList("tastybento"))); + assertFalse(its.canExecute(user, "", Collections.singletonList("tastybento"))); verify(user).sendMessage("commands.island.team.setowner.errors.cant-transfer-to-yourself"); } /** - * Test method for {@link world.bentobox.bentobox.api.commands.island.team.IslandTeamSetownerCommand#execute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. + * Test method for {@link world.bentobox.bentobox.api.commands.island.team.IslandTeamSetownerCommand#canExecute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. */ @Test - public void testExecuteUserStringListOfStringTargetNotInTeam() { + public void testCanExecuteUserStringListOfStringTargetAtMaxIslands() { + when(im.inTeam(any(), any())).thenReturn(true); + when(im.getOwner(any(), any())).thenReturn(uuid); + UUID target = UUID.randomUUID(); + when(pm.getUUID(anyString())).thenReturn(target); + when(im.getMembers(any(), any())).thenReturn(Collections.singleton(target)); + @Nullable + Island island = mock(Island.class); + when(im.getIsland(any(), any(User.class))).thenReturn(island); + + when(im.getNumberOfConcurrentIslands(target, world)).thenReturn(3); + + assertFalse(its.canExecute(user, "", Collections.singletonList("tastybento"))); + verify(user).sendMessage("commands.island.team.setowner.errors.at-max"); + } + + /** + * Test method for {@link world.bentobox.bentobox.api.commands.island.team.IslandTeamSetownerCommand#canExecute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. + */ + @Test + public void testCanExecuteUserStringListOfStringTargetNotInTeam() { when(im.inTeam(any(), any())).thenReturn(true); when(im.getOwner(any(), any())).thenReturn(uuid); when(pm.getUUID(anyString())).thenReturn(UUID.randomUUID()); when(im.getMembers(any(), any())).thenReturn(Collections.singleton(uuid)); - assertFalse(its.execute(user, "", Collections.singletonList("tastybento"))); + assertFalse(its.canExecute(user, "", Collections.singletonList("tastybento"))); verify(user).sendMessage("commands.island.team.setowner.errors.target-is-not-member"); } @@ -243,7 +270,7 @@ public void testExecuteUserStringListOfStringSuccess() { @Nullable Island island = mock(Island.class); when(im.getIsland(any(), any(User.class))).thenReturn(island); - + assertTrue(its.canExecute(user, "", Collections.singletonList("tastybento"))); assertTrue(its.execute(user, "", Collections.singletonList("tastybento"))); verify(im).setOwner(any(), eq(user), eq(target)); verify(im).save(island); diff --git a/src/test/java/world/bentobox/bentobox/database/objects/IslandTest.java b/src/test/java/world/bentobox/bentobox/database/objects/IslandTest.java index 0e5aad290..eb9be5d71 100644 --- a/src/test/java/world/bentobox/bentobox/database/objects/IslandTest.java +++ b/src/test/java/world/bentobox/bentobox/database/objects/IslandTest.java @@ -1,6 +1,3 @@ -/** - * - */ package world.bentobox.bentobox.database.objects; import static org.junit.Assert.assertEquals; @@ -1156,7 +1153,7 @@ public void testGetHomes() { */ @Test public void testGetHome() { - assertNull(i.getHome("default")); + assertEquals(i.getProtectionCenter(), i.getHome("default")); } /** diff --git a/src/test/java/world/bentobox/bentobox/listeners/JoinLeaveListenerTest.java b/src/test/java/world/bentobox/bentobox/listeners/JoinLeaveListenerTest.java index 9e767a9b7..4a78518aa 100644 --- a/src/test/java/world/bentobox/bentobox/listeners/JoinLeaveListenerTest.java +++ b/src/test/java/world/bentobox/bentobox/listeners/JoinLeaveListenerTest.java @@ -162,6 +162,7 @@ public void setUp() throws Exception { when(im.getIsland(any(), any(User.class))).thenReturn(island); when(im.getIsland(any(), any(UUID.class))).thenReturn(island); + when(im.getIslands()).thenReturn(Collections.singletonList(island)); Map memberMap = new HashMap<>(); memberMap.put(uuid, RanksManager.OWNER_RANK); diff --git a/src/test/java/world/bentobox/bentobox/listeners/flags/protection/BreakBlocksListenerTest.java b/src/test/java/world/bentobox/bentobox/listeners/flags/protection/BreakBlocksListenerTest.java index 687916edd..d7d7e0d81 100644 --- a/src/test/java/world/bentobox/bentobox/listeners/flags/protection/BreakBlocksListenerTest.java +++ b/src/test/java/world/bentobox/bentobox/listeners/flags/protection/BreakBlocksListenerTest.java @@ -58,8 +58,6 @@ public class BreakBlocksListenerTest extends AbstractCommonSetup { private BreakBlocksListener bbl; - /** - */ @Override @Before public void setUp() throws Exception { @@ -100,7 +98,7 @@ public void testOnBlockBreakNotAllowed() { assertTrue(e.isCancelled()); verify(notifier).notify(any(), eq("protection.protected")); } - + /** * Test method for {@link world.bentobox.bentobox.listeners.flags.protection.BreakBlocksListener#onBlockBreak(org.bukkit.event.block.BlockBreakEvent)}. */ @@ -115,7 +113,7 @@ public void testOnBlockHarvestNotAllowed() { assertTrue(e.isCancelled()); verify(notifier).notify(any(), eq("protection.protected")); } - + /** * Test method for {@link world.bentobox.bentobox.listeners.flags.protection.BreakBlocksListener#onBlockBreak(org.bukkit.event.block.BlockBreakEvent)}. */ diff --git a/src/test/java/world/bentobox/bentobox/listeners/flags/worldsettings/RemoveMobsListenerTest.java b/src/test/java/world/bentobox/bentobox/listeners/flags/worldsettings/RemoveMobsListenerTest.java index a74929e35..7a9883951 100644 --- a/src/test/java/world/bentobox/bentobox/listeners/flags/worldsettings/RemoveMobsListenerTest.java +++ b/src/test/java/world/bentobox/bentobox/listeners/flags/worldsettings/RemoveMobsListenerTest.java @@ -16,8 +16,8 @@ import org.bukkit.World; import org.bukkit.entity.Player; import org.bukkit.event.player.PlayerRespawnEvent; -import org.bukkit.event.player.PlayerTeleportEvent; import org.bukkit.event.player.PlayerRespawnEvent.RespawnReason; +import org.bukkit.event.player.PlayerTeleportEvent; import org.bukkit.scheduler.BukkitScheduler; import org.junit.After; import org.junit.Before; diff --git a/src/test/java/world/bentobox/bentobox/managers/IslandsManagerTest.java b/src/test/java/world/bentobox/bentobox/managers/IslandsManagerTest.java index b1f626c43..70923f226 100644 --- a/src/test/java/world/bentobox/bentobox/managers/IslandsManagerTest.java +++ b/src/test/java/world/bentobox/bentobox/managers/IslandsManagerTest.java @@ -249,6 +249,7 @@ public void setUp() throws Exception { when(islandCache.getIslandAt(any(Location.class))).thenReturn(island); when(islandCache.get(any(), any())).thenReturn(island); optionalIsland = Optional.ofNullable(island); + when(islandCache.getIslands(world, uuid)).thenReturn(Set.of(island)); // User location when(user.getLocation()).thenReturn(location); @@ -531,16 +532,6 @@ public void testSolidBlocks() { assertTrue("Wall sign 2", im.isSafeLocation(location)); } - /** - * Test method for {@link world.bentobox.bentobox.managers.IslandsManager#bigScan(org.bukkit.Location, int)}. - */ - @Test - public void testBigScan() { - // Negative value = full island scan - // No island here yet - assertNull(im.bigScan(location, -1)); - } - /** * Test method for {@link world.bentobox.bentobox.managers.IslandsManager#createIsland(org.bukkit.Location)}. */ @@ -716,7 +707,6 @@ public void testGetSafeHomeLocation() { im.setIslandCache(islandCache); when(island.getHome(any())).thenReturn(location); when(iwm.inWorld(eq(world))).thenReturn(true); - assertEquals(location, im.getSafeHomeLocation(world, user, "")); // Change location so that it is not safe diff --git a/src/test/java/world/bentobox/bentobox/managers/PlayersManagerTest.java b/src/test/java/world/bentobox/bentobox/managers/PlayersManagerTest.java index 451c5e25a..acc3cf611 100644 --- a/src/test/java/world/bentobox/bentobox/managers/PlayersManagerTest.java +++ b/src/test/java/world/bentobox/bentobox/managers/PlayersManagerTest.java @@ -1,6 +1,10 @@ package world.bentobox.bentobox.managers; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; diff --git a/src/test/java/world/bentobox/bentobox/managers/island/IslandCacheTest.java b/src/test/java/world/bentobox/bentobox/managers/island/IslandCacheTest.java index fd11d337b..81b976335 100644 --- a/src/test/java/world/bentobox/bentobox/managers/island/IslandCacheTest.java +++ b/src/test/java/world/bentobox/bentobox/managers/island/IslandCacheTest.java @@ -16,6 +16,7 @@ import org.bukkit.Location; import org.bukkit.World; +import org.eclipse.jdt.annotation.NonNull; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -81,6 +82,9 @@ public void setUp() throws Exception { // Island when(island.getWorld()).thenReturn(world); + @NonNull + String uniqueId = UUID.randomUUID().toString(); + when(island.getUniqueId()).thenReturn(uniqueId); // Location when(location.getWorld()).thenReturn(world); when(location.getBlockX()).thenReturn(0); @@ -248,9 +252,8 @@ public void testGetMembers() { @Test public void testGetOwner() { ic.addIsland(island); - + // Should be no owner, so null assertEquals(owner, ic.getOwner(world, owner)); - assertNull(ic.getOwner(world, null)); assertNull(ic.getOwner(world, UUID.randomUUID())); } @@ -263,7 +266,6 @@ public void testHasIsland() { assertTrue(ic.hasIsland(world, owner)); assertFalse(ic.hasIsland(world, UUID.randomUUID())); - assertFalse(ic.hasIsland(world, null)); } /** @@ -273,7 +275,6 @@ public void testHasIsland() { public void testRemovePlayer() { ic.addIsland(island); assertTrue(ic.hasIsland(world, owner)); - ic.removePlayer(world, null); assertTrue(ic.hasIsland(world, owner)); ic.removePlayer(world, UUID.randomUUID()); assertTrue(ic.hasIsland(world, owner)); diff --git a/src/test/java/world/bentobox/bentobox/managers/island/NewIslandTest.java b/src/test/java/world/bentobox/bentobox/managers/island/NewIslandTest.java index e0e7c8958..3171015df 100644 --- a/src/test/java/world/bentobox/bentobox/managers/island/NewIslandTest.java +++ b/src/test/java/world/bentobox/bentobox/managers/island/NewIslandTest.java @@ -317,4 +317,4 @@ public void testBuilderHasIslandFailnoReserve() throws Exception { verify(plugin).logError("New island for user tastybento was not reserved!"); } -} +} \ No newline at end of file