From 29a7fa551a970e62e6d1b7d96efd121681f07e2d Mon Sep 17 00:00:00 2001 From: tastybento <tastybento@users.noreply.github.com> Date: Sat, 23 Dec 2023 08:36:27 +0900 Subject: [PATCH 01/22] WIP - add GUI for teams. --- .../island/team/IslandTeamCommand.java | 255 ++++++++++++++---- .../api/panels/reader/ItemTemplateRecord.java | 31 +-- .../panels/reader/PanelTemplateRecord.java | 1 - .../api/panels/reader/TemplateReader.java | 6 + src/main/resources/locales/en-US.yml | 12 +- src/main/resources/panels/team_panel.yml | 99 +++++++ 6 files changed, 329 insertions(+), 75 deletions(-) create mode 100644 src/main/resources/panels/team_panel.yml 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 b8a12affe..d80eb1016 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 @@ -1,7 +1,10 @@ package world.bentobox.bentobox.api.commands.island.team; +import java.io.File; import java.time.Duration; import java.time.Instant; +import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -9,14 +12,21 @@ import java.util.UUID; import org.bukkit.Bukkit; +import org.bukkit.Material; import org.bukkit.OfflinePlayer; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; +import world.bentobox.bentobox.BentoBox; import world.bentobox.bentobox.api.commands.CompositeCommand; import world.bentobox.bentobox.api.events.IslandBaseEvent; import world.bentobox.bentobox.api.events.team.TeamEvent; import world.bentobox.bentobox.api.localization.TextVariables; +import world.bentobox.bentobox.api.panels.PanelItem; +import world.bentobox.bentobox.api.panels.TemplatedPanel; +import world.bentobox.bentobox.api.panels.builders.PanelItemBuilder; +import world.bentobox.bentobox.api.panels.builders.TemplatedPanelBuilder; +import world.bentobox.bentobox.api.panels.reader.ItemTemplateRecord; import world.bentobox.bentobox.api.user.User; import world.bentobox.bentobox.database.objects.Island; import world.bentobox.bentobox.managers.RanksManager; @@ -24,12 +34,22 @@ public class IslandTeamCommand extends CompositeCommand { + /** + * List of ranks that we will loop through in order + */ + private static final List<Integer> RANKS = List.of(RanksManager.OWNER_RANK, RanksManager.SUB_OWNER_RANK, + RanksManager.MEMBER_RANK, RanksManager.TRUSTED_RANK, RanksManager.COOP_RANK); + /** * Invited list. Key is the invited party, value is the invite. * @since 1.8.0 */ private final Map<UUID, Invite> inviteMap; + private User user; + + private Island island; + public IslandTeamCommand(CompositeCommand parent) { super(parent, "team"); inviteMap = new HashMap<>(); @@ -57,12 +77,16 @@ public void setup() { } new IslandTeamPromoteCommand(this, "promote"); new IslandTeamPromoteCommand(this, "demote"); + + // Panels + getPlugin().saveResource("panels/team_panel.yml", false); } @Override public boolean execute(User user, String label, List<String> args) { + this.user = user; // Player issuing the command must have an island - Island island = getIslands().getPrimaryIsland(getWorld(), user.getUniqueId()); + island = getIslands().getPrimaryIsland(getWorld(), user.getUniqueId()); if (island == null) { user.sendMessage("general.errors.no-island"); return false; @@ -85,85 +109,216 @@ public boolean execute(User user, String label, List<String> args) { } } // Show members of island - showMembers(island, user); + showMembers().forEach(user::sendRawMessage); + build(); return true; } - private void showMembers(Island island, User user) { + /** + * This method builds this GUI. + */ + private void build() { + // Start building panel. + TemplatedPanelBuilder panelBuilder = new TemplatedPanelBuilder(); + panelBuilder.user(user); + panelBuilder.world(user.getWorld()); + + panelBuilder.template("team_panel", new File(getPlugin().getDataFolder(), "panels")); + + panelBuilder.parameters("[name]", user.getName(), "[display_name]", user.getDisplayName()); + + panelBuilder.registerTypeBuilder("STATUS", this::createStatusButton); + panelBuilder.registerTypeBuilder("MEMBER", this::createMemberButton); + //panelBuilder.registerTypeBuilder("INVITE", this::createInviteButton); + //panelBuilder.registerTypeBuilder("KICK", this::createKickButton); + + // Register unknown type builder. + panelBuilder.build(); + } + + /** + * Create status button panel item. + * + * @param template the template + * @param slot the slot + * @return the panel item + */ + private PanelItem createStatusButton(ItemTemplateRecord template, TemplatedPanel.ItemSlot slot) { + PanelItemBuilder builder = new PanelItemBuilder(); + // Player issuing the command must have an island + Island island = getIslands().getPrimaryIsland(getWorld(), user.getUniqueId()); + if (island == null) { + return builder.icon(Material.BARRIER).name(user.getTranslation("general.errors.no-island")).build(); + } + + return builder.icon(user.getName()).name(user.getTranslation("commands.island.team.gui.buttons.status.name")) + .description(showMembers()).build(); + } + + /** + * Create member button panel item. + * + * @param template the template + * @param slot the slot + * @return the panel item + */ + private PanelItem createMemberButton(ItemTemplateRecord template, TemplatedPanel.ItemSlot slot) { + PanelItemBuilder builder = new PanelItemBuilder(); + // Player issuing the command must have an island + Island island = getIslands().getPrimaryIsland(getWorld(), user.getUniqueId()); + if (island == null) { + return builder.icon(Material.BARRIER).name(user.getTranslation("general.errors.no-island")).build(); + } + if (slot.slot() == 0 && island.getOwner() != null) { + // Owner + User owner = User.getInstance(island.getOwner()); + return builder.icon(owner.getName()) + .name(owner.getDisplayName()) + .description(user.getTranslation("commands.island.team.info.rank-layout.owner", TextVariables.RANK, + user.getTranslation(RanksManager.OWNER_RANK_REF))) + .build(); + } + long subOwnerCount = island.getMemberSet(RanksManager.SUB_OWNER_RANK, false).stream().count(); + long memberCount = island.getMemberSet(RanksManager.MEMBER_RANK, false).stream().count(); + long coopCount = island.getMemberSet(RanksManager.COOP_RANK, false).stream().count(); + long trustedCount = island.getMemberSet(RanksManager.TRUSTED_RANK, false).stream().count(); + BentoBox.getInstance().logDebug("Slot = " + slot.slot()); + + if (slot.slot() > 0 && slot.slot() < subOwnerCount + 1) { + // Show sub owners + PanelItem item = getMemberButton(RanksManager.SUB_OWNER_RANK_REF, RanksManager.SUB_OWNER_RANK, + subOwnerCount, slot.slot()); + if (item != null) { + return item; + } + + } + if (slot.slot() > subOwnerCount && slot.slot() < subOwnerCount + memberCount + 1) { + // Show members + PanelItem item = getMemberButton(RanksManager.MEMBER_RANK_REF, RanksManager.MEMBER_RANK, memberCount, + slot.slot()); + if (item != null) { + return item; + } + } + if (slot.slot() > subOwnerCount + memberCount && slot.slot() < subOwnerCount + memberCount + trustedCount + 1) { + // Show trusted + PanelItem item = getMemberButton(RanksManager.TRUSTED_RANK_REF, RanksManager.TRUSTED_RANK, trustedCount, + slot.slot()); + if (item != null) { + return item; + } + + } + if (slot.slot() > subOwnerCount + memberCount + trustedCount + && slot.slot() < subOwnerCount + memberCount + trustedCount + coopCount + 1) { + // Show coops + PanelItem item = getMemberButton(RanksManager.COOP_RANK_REF, RanksManager.COOP_RANK, coopCount, + slot.slot()); + if (item != null) { + return item; + } + + } + return builder.icon(Material.BLACK_STAINED_GLASS_PANE).name("&b&r").build(); + } + + private PanelItem getMemberButton(String ref, int rank, long count, int slot) { + BentoBox.getInstance().logDebug(ref + " " + rank + " count = " + count + " slot = " + slot); + User player = island.getMemberSet(rank, false).stream().sorted().skip(slot - 1).limit(1L) + .map(User::getInstance).findFirst().orElse(null); + if (player != null) { + return new PanelItemBuilder().icon(player.getName()).name(player.getDisplayName()) + .description(user.getTranslation("commands.island.team.info.rank-layout.generic", + TextVariables.RANK, user.getTranslation(ref), TextVariables.NUMBER, String.valueOf(count))) + .build(); + } else { + BentoBox.getInstance().logDebug("no player found"); + } + return null; + } + + private List<String> showMembers() { + List<String> message = new ArrayList<>(); // Gather online members - long count = island.getMemberSet(RanksManager.MEMBER_RANK).stream() + long onlineMemberCount = island.getMemberSet(RanksManager.MEMBER_RANK).stream() .filter(uuid -> Util.getOnlinePlayerList(user).contains(Bukkit.getOfflinePlayer(uuid).getName())) .count(); - // List of ranks that we will loop through - Integer[] ranks = new Integer[] { RanksManager.OWNER_RANK, RanksManager.SUB_OWNER_RANK, - RanksManager.MEMBER_RANK, RanksManager.TRUSTED_RANK, RanksManager.COOP_RANK }; - // Show header: - user.sendMessage("commands.island.team.info.header", "[max]", + message.add(user.getTranslation("commands.island.team.info.header", "[max]", String.valueOf(getIslands().getMaxMembers(island, RanksManager.MEMBER_RANK)), "[total]", - String.valueOf(island.getMemberSet().size()), "[online]", String.valueOf(count)); + String.valueOf(island.getMemberSet().size()), "[online]", String.valueOf(onlineMemberCount))); // We now need to get all online "members" of the island - incl. Trusted and coop List<UUID> onlineMembers = island.getMemberSet(RanksManager.COOP_RANK).stream() .filter(uuid -> Util.getOnlinePlayerList(user).contains(Bukkit.getOfflinePlayer(uuid).getName())) .toList(); - for (int rank : ranks) { + for (int rank : RANKS) { Set<UUID> players = island.getMemberSet(rank, false); if (!players.isEmpty()) { if (rank == RanksManager.OWNER_RANK) { // Slightly special handling for the owner rank - user.sendMessage("commands.island.team.info.rank-layout.owner", TextVariables.RANK, - user.getTranslation(RanksManager.OWNER_RANK_REF)); + message.add(user.getTranslation("commands.island.team.info.rank-layout.owner", TextVariables.RANK, + user.getTranslation(RanksManager.OWNER_RANK_REF))); } else { - user.sendMessage("commands.island.team.info.rank-layout.generic", TextVariables.RANK, + message.add(user.getTranslation("commands.island.team.info.rank-layout.generic", TextVariables.RANK, user.getTranslation(getPlugin().getRanksManager().getRank(rank)), TextVariables.NUMBER, - String.valueOf(island.getMemberSet(rank, false).size())); + String.valueOf(island.getMemberSet(rank, false).size()))); } - displayOnOffline(user, rank, island, onlineMembers); + message.addAll(displayOnOffline(user, rank, island, onlineMembers)); } } + return message; } - private void displayOnOffline(User user, int rank, Island island, List<UUID> onlineMembers) { + private List<String> displayOnOffline(User user, int rank, Island island, List<UUID> onlineMembers) { + List<String> message = new ArrayList<>(); for (UUID member : island.getMemberSet(rank, false)) { - OfflinePlayer offlineMember = Bukkit.getOfflinePlayer(member); - if (onlineMembers.contains(member)) { - // the player is online - user.sendMessage("commands.island.team.info.member-layout.online", TextVariables.NAME, - offlineMember.getName()); - } else { - // A bit of handling for the last joined date - Instant lastJoined = Instant.ofEpochMilli(offlineMember.getLastPlayed()); - Instant now = Instant.now(); - - Duration duration = Duration.between(lastJoined, now); - String lastSeen; - final String reference = "commands.island.team.info.last-seen.layout"; - if (duration.toMinutes() < 60L) { - lastSeen = user.getTranslation(reference, TextVariables.NUMBER, - String.valueOf(duration.toMinutes()), TextVariables.UNIT, - user.getTranslation("commands.island.team.info.last-seen.minutes")); - } else if (duration.toHours() < 24L) { - lastSeen = user.getTranslation(reference, TextVariables.NUMBER, String.valueOf(duration.toHours()), - TextVariables.UNIT, user.getTranslation("commands.island.team.info.last-seen.hours")); - } else { - lastSeen = user.getTranslation(reference, TextVariables.NUMBER, String.valueOf(duration.toDays()), - TextVariables.UNIT, user.getTranslation("commands.island.team.info.last-seen.days")); - } + message.add(getMemberStatus(user, member, onlineMembers.contains(member))); - if (island.getMemberSet(RanksManager.MEMBER_RANK, true).contains(member)) { - user.sendMessage("commands.island.team.info.member-layout.offline", TextVariables.NAME, - offlineMember.getName(), "[last_seen]", lastSeen); - } else { - // This will prevent anyone that is trusted or below to not have a last-seen status - user.sendMessage("commands.island.team.info.member-layout.offline-not-last-seen", - TextVariables.NAME, offlineMember.getName()); - } - } } + return message; + } + private String getMemberStatus(User user2, UUID member, boolean online) { + OfflinePlayer offlineMember = Bukkit.getOfflinePlayer(member); + if (online) { + return user.getTranslation("commands.island.team.info.member-layout.online", TextVariables.NAME, + offlineMember.getName()); + } else { + return offlinePlayerStatus(user, offlineMember); + } + } + + private String offlinePlayerStatus(User user2, OfflinePlayer offlineMember) { + // A bit of handling for the last joined date + Instant lastJoined = Instant.ofEpochMilli(offlineMember.getLastPlayed()); + Instant now = Instant.now(); + + Duration duration = Duration.between(lastJoined, now); + String lastSeen; + final String reference = "commands.island.team.info.last-seen.layout"; + if (duration.toMinutes() < 60L) { + lastSeen = user.getTranslation(reference, TextVariables.NUMBER, String.valueOf(duration.toMinutes()), + TextVariables.UNIT, user.getTranslation("commands.island.team.info.last-seen.minutes")); + } else if (duration.toHours() < 24L) { + lastSeen = user.getTranslation(reference, TextVariables.NUMBER, String.valueOf(duration.toHours()), + TextVariables.UNIT, user.getTranslation("commands.island.team.info.last-seen.hours")); + } else { + lastSeen = user.getTranslation(reference, TextVariables.NUMBER, String.valueOf(duration.toDays()), + TextVariables.UNIT, user.getTranslation("commands.island.team.info.last-seen.days")); + } + + if (island.getMemberSet(RanksManager.MEMBER_RANK, true).contains(offlineMember.getUniqueId())) { + return user.getTranslation("commands.island.team.info.member-layout.offline", TextVariables.NAME, + offlineMember.getName(), "[last_seen]", lastSeen); + } else { + // This will prevent anyone that is trusted or below to not have a last-seen status + return user.getTranslation("commands.island.team.info.member-layout.offline-not-last-seen", + TextVariables.NAME, offlineMember.getName()); + } } private boolean fireEvent(User user, Island island) { diff --git a/src/main/java/world/bentobox/bentobox/api/panels/reader/ItemTemplateRecord.java b/src/main/java/world/bentobox/bentobox/api/panels/reader/ItemTemplateRecord.java index c1c157124..b59c5185a 100644 --- a/src/main/java/world/bentobox/bentobox/api/panels/reader/ItemTemplateRecord.java +++ b/src/main/java/world/bentobox/bentobox/api/panels/reader/ItemTemplateRecord.java @@ -3,10 +3,8 @@ // Copyright - 2021 // - package world.bentobox.bentobox.api.panels.reader; - import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -17,8 +15,6 @@ import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; -import world.bentobox.bentobox.api.panels.reader.ItemTemplateRecord.ActionRecords; - /** * This Record contains all necessary information about Item Template that can be used to craft panel item. * @@ -31,13 +27,10 @@ * * @since 1.17.3 */ -public record ItemTemplateRecord(@Nullable ItemStack icon, - @Nullable String title, - @Nullable String description, - @NonNull List<ActionRecords> actions, - @NonNull Map<String, Object> dataMap, - @Nullable ItemTemplateRecord fallback) -{ +public record ItemTemplateRecord(@Nullable ItemStack icon, @Nullable String title, @Nullable String description, + @NonNull List<ActionRecords> actions, @NonNull Map<String, Object> dataMap, + @Nullable ItemTemplateRecord fallback) { + /** * Instantiates a new Item template record without actions and data map. * @@ -46,39 +39,32 @@ public record ItemTemplateRecord(@Nullable ItemStack icon, * @param description the description * @param fallback the fallback */ - public ItemTemplateRecord(ItemStack icon, String title, String description, ItemTemplateRecord fallback) - { + public ItemTemplateRecord(ItemStack icon, String title, String description, ItemTemplateRecord fallback) { this(icon, title, description, new ArrayList<>(6), new HashMap<>(0), fallback); } - /** * This method adds given object associated with key into data map. * @param key Key value of object. * @param data Data that is associated with a key. */ - public void addData(String key, Object data) - { + public void addData(String key, Object data) { this.dataMap.put(key, data); } - /** * Add action to the actions list. * * @param actionData the action data */ - public void addAction(ActionRecords actionData) - { + public void addAction(ActionRecords actionData) { this.actions.add(actionData); } - // --------------------------------------------------------------------- // Section: Classes // --------------------------------------------------------------------- - /** * The Action Records holds data about each action. * @@ -87,5 +73,6 @@ public void addAction(ActionRecords actionData) * @param content the content of the action * @param tooltip the tooltip of action */ - public record ActionRecords(ClickType clickType, String actionType, String content, String tooltip) {} + public record ActionRecords(ClickType clickType, String actionType, String content, String tooltip) { + } } diff --git a/src/main/java/world/bentobox/bentobox/api/panels/reader/PanelTemplateRecord.java b/src/main/java/world/bentobox/bentobox/api/panels/reader/PanelTemplateRecord.java index 18d5506f1..f260fb564 100644 --- a/src/main/java/world/bentobox/bentobox/api/panels/reader/PanelTemplateRecord.java +++ b/src/main/java/world/bentobox/bentobox/api/panels/reader/PanelTemplateRecord.java @@ -15,7 +15,6 @@ import org.eclipse.jdt.annotation.Nullable; import world.bentobox.bentobox.api.panels.Panel; -import world.bentobox.bentobox.api.panels.reader.PanelTemplateRecord.TemplateItem; /** * This is template object for the panel reader. It contains data that can exist in the panel. diff --git a/src/main/java/world/bentobox/bentobox/api/panels/reader/TemplateReader.java b/src/main/java/world/bentobox/bentobox/api/panels/reader/TemplateReader.java index 9d8158b1b..524f0f260 100644 --- a/src/main/java/world/bentobox/bentobox/api/panels/reader/TemplateReader.java +++ b/src/main/java/world/bentobox/bentobox/api/panels/reader/TemplateReader.java @@ -22,6 +22,7 @@ import com.google.common.base.Enums; +import world.bentobox.bentobox.BentoBox; import world.bentobox.bentobox.api.panels.Panel; import world.bentobox.bentobox.util.ItemParser; @@ -83,6 +84,7 @@ public static PanelTemplateRecord readTemplatePanel(@NonNull String panelName, @ { if (!panelLocation.exists()) { + BentoBox.getInstance().logError("Panel Template reader: Folder does not exist"); // Return null because folder does not exist. return null; } @@ -91,6 +93,7 @@ public static PanelTemplateRecord readTemplatePanel(@NonNull String panelName, @ if (!file.exists()) { + BentoBox.getInstance().logError(file.getAbsolutePath() + " does not exist for panel template"); // Return as file does not exist. return null; } @@ -117,6 +120,8 @@ public static PanelTemplateRecord readTemplatePanel(@NonNull String panelName, @ } catch (IOException | InvalidConfigurationException e) { + BentoBox.getInstance().logError("Error loading template"); + BentoBox.getInstance().logStacktrace(e); rec = null; } @@ -133,6 +138,7 @@ private static PanelTemplateRecord readPanelTemplate(@Nullable ConfigurationSect { if (configurationSection == null) { + BentoBox.getInstance().logError("No configuration section!"); // No data to return. return null; } diff --git a/src/main/resources/locales/en-US.yml b/src/main/resources/locales/en-US.yml index 07804afcf..0440ff3f2 100644 --- a/src/main/resources/locales/en-US.yml +++ b/src/main/resources/locales/en-US.yml @@ -108,8 +108,7 @@ commands: status: description: displays the status of the purge status: '&b [purged] &a islands purged out of &b [purgeable] &7(&b[percentage] - %&7)&a.' - + %&7)&a.' team: description: manage teams add: @@ -613,6 +612,15 @@ commands: success: '&a Successfully reset your island name.' team: description: manage your team + gui: + titles: + team-panel: Team Management + buttons: + status: + name: Status + description: The status of the team + tips: + click-to-view: Click to view info: description: display detailed info about your team member-layout: diff --git a/src/main/resources/panels/team_panel.yml b/src/main/resources/panels/team_panel.yml new file mode 100644 index 000000000..eeb39e748 --- /dev/null +++ b/src/main/resources/panels/team_panel.yml @@ -0,0 +1,99 @@ +# Name of panel used for indentification in the code - must be the same name as the filename. +team_panel: + # Title of the panel shown to the user. This is a reference and the reference will be translatable in the locale file + title: commands.island.team.gui.titles.team-panel + # The type of panel to show. Options are INVENTORY, HOPPER, DROPPER. INVENTORY is that standard chest inventory and + # the others refer to the inventories shown for those items. + type: INVENTORY + # The background of the panel. These items will be shown if other items are not there. STAINED_GLASS_PANEs give a good effect. + background: + icon: BLACK_STAINED_GLASS_PANE + # Each item may have text applied to it, but usually for background items, nothing is shown. + title: "&b&r" # Empty text. This is using the Bukkit chat color coding with &'s. + border: + # The border of each panel may be shown as a different item. + # It can be used to provide a contrast to items in the panel. + icon: BLACK_STAINED_GLASS_PANE + title: "&b&r" # Empty text + # This tag indicates which rows in the panel must be shown. The panel will be sized vertically accordingly. This does not include the borders. + # This can be a list and rows must be between 1 and 6, if used. + force-shown: [1, 2] + # The content section contains details of each item/button in the panel. The numbers indicate the rows and then then columns of each item. + content: + # Row number + 1: + # Column number + 2: + # The data section is a key-value list of data relavent for this button. It is interpreted by the code implemented the panel. + # The convention is to specify the type and the panel tab that will open if pressed. These are Enums in the code. + data: + type: STATUS + # Actions cover what happens if the button is clicked or the mouse is moved over it. There can be multiple actions possible for different + # click-types. + actions: + # Each action has an arbitrary descriptive name to define it. + view: + # The click-type is the same as the bukkit {@link org.bukkit.event.inventory.ClickType}. UNKNOWN is the default. + click-type: UNKNOWN + # tooltip is a locale reference that will be translated for the user and shown when they hover over the button. + tooltip: commands.island.team.gui.tips.click-to-view + 2: + 2: member_button + 3: member_button + 4: member_button + 5: member_button + 6: member_button + 7: member_button + 8: member_button + 3: + 2: member_button + 3: member_button + 4: member_button + 5: member_button + 6: member_button + 7: member_button + 8: member_button + 4: + 2: member_button + 3: member_button + 4: member_button + 5: member_button + 6: member_button + 7: member_button + 8: member_button + 5: + 2: member_button + 3: member_button + 4: member_button + 5: member_button + 6: member_button + 7: member_button + 8: member_button + 6: + 2: member_button + 3: member_button + 4: member_button + 5: member_button + 6: member_button + 7: member_button + 8: member_button + # This is where reuable buttons are defined. + reusable: + # This is the name of the button that is referenced + member_button: + # If the icon for a button is not defined, it defaults to AIR and so effectively will not be shown. + # icons are usually not defined if the icon is going to be dynamically set in the panel, e.g. in this case the material will vary + #icon: STONE + title: commands.island.team.gui.buttons.member.name + description: levcommands.island.team.gui.buttons.member.description + data: + type: MEMBER + # Actions cover what happens if the button is clicked or the mouse is moved over it. There can be multiple actions possible for different + # click-types. + actions: + # Each action has an arbitrary descriptive name to define it. + view: + # The click-type is the same as the bukkit {@link org.bukkit.event.inventory.ClickType}. UNKNOWN is the default. + click-type: RIGHT_CLICK + # tooltip is a locale reference that will be translated for the user and shown when they hover over the button. + tooltip: commands.island.team.gui.tips.right-click-to-kick \ No newline at end of file From f40db47d312917d01993edfd880461494a039b8f Mon Sep 17 00:00:00 2001 From: tastybento <tastybento@users.noreply.github.com> Date: Sun, 24 Dec 2023 07:38:53 +0900 Subject: [PATCH 02/22] WIP teams GUI --- .../island/team/IslandTeamCommand.java | 40 +++++++++++++------ 1 file changed, 28 insertions(+), 12 deletions(-) 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 d80eb1016..340102ce9 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 @@ -4,7 +4,6 @@ import java.time.Duration; import java.time.Instant; import java.util.ArrayList; -import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -14,6 +13,7 @@ import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.OfflinePlayer; +import org.bukkit.event.inventory.ClickType; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; @@ -27,6 +27,7 @@ import world.bentobox.bentobox.api.panels.builders.PanelItemBuilder; import world.bentobox.bentobox.api.panels.builders.TemplatedPanelBuilder; import world.bentobox.bentobox.api.panels.reader.ItemTemplateRecord; +import world.bentobox.bentobox.api.panels.reader.ItemTemplateRecord.ActionRecords; import world.bentobox.bentobox.api.user.User; import world.bentobox.bentobox.database.objects.Island; import world.bentobox.bentobox.managers.RanksManager; @@ -171,12 +172,11 @@ private PanelItem createMemberButton(ItemTemplateRecord template, TemplatedPanel } if (slot.slot() == 0 && island.getOwner() != null) { // Owner - User owner = User.getInstance(island.getOwner()); - return builder.icon(owner.getName()) - .name(owner.getDisplayName()) - .description(user.getTranslation("commands.island.team.info.rank-layout.owner", TextVariables.RANK, - user.getTranslation(RanksManager.OWNER_RANK_REF))) - .build(); + PanelItem item = getMemberButton(RanksManager.OWNER_RANK_REF, RanksManager.OWNER_RANK, 1, 1, + template.actions()); + if (item != null) { + return item; + } } long subOwnerCount = island.getMemberSet(RanksManager.SUB_OWNER_RANK, false).stream().count(); long memberCount = island.getMemberSet(RanksManager.MEMBER_RANK, false).stream().count(); @@ -187,7 +187,7 @@ private PanelItem createMemberButton(ItemTemplateRecord template, TemplatedPanel if (slot.slot() > 0 && slot.slot() < subOwnerCount + 1) { // Show sub owners PanelItem item = getMemberButton(RanksManager.SUB_OWNER_RANK_REF, RanksManager.SUB_OWNER_RANK, - subOwnerCount, slot.slot()); + subOwnerCount, slot.slot(), template.actions()); if (item != null) { return item; } @@ -196,7 +196,7 @@ private PanelItem createMemberButton(ItemTemplateRecord template, TemplatedPanel if (slot.slot() > subOwnerCount && slot.slot() < subOwnerCount + memberCount + 1) { // Show members PanelItem item = getMemberButton(RanksManager.MEMBER_RANK_REF, RanksManager.MEMBER_RANK, memberCount, - slot.slot()); + slot.slot(), template.actions()); if (item != null) { return item; } @@ -204,7 +204,7 @@ private PanelItem createMemberButton(ItemTemplateRecord template, TemplatedPanel if (slot.slot() > subOwnerCount + memberCount && slot.slot() < subOwnerCount + memberCount + trustedCount + 1) { // Show trusted PanelItem item = getMemberButton(RanksManager.TRUSTED_RANK_REF, RanksManager.TRUSTED_RANK, trustedCount, - slot.slot()); + slot.slot(), template.actions()); if (item != null) { return item; } @@ -214,7 +214,7 @@ private PanelItem createMemberButton(ItemTemplateRecord template, TemplatedPanel && slot.slot() < subOwnerCount + memberCount + trustedCount + coopCount + 1) { // Show coops PanelItem item = getMemberButton(RanksManager.COOP_RANK_REF, RanksManager.COOP_RANK, coopCount, - slot.slot()); + slot.slot(), template.actions()); if (item != null) { return item; } @@ -223,15 +223,31 @@ private PanelItem createMemberButton(ItemTemplateRecord template, TemplatedPanel return builder.icon(Material.BLACK_STAINED_GLASS_PANE).name("&b&r").build(); } - private PanelItem getMemberButton(String ref, int rank, long count, int slot) { + private PanelItem getMemberButton(String ref, int rank, long count, int slot, List<ActionRecords> actions) { BentoBox.getInstance().logDebug(ref + " " + rank + " count = " + count + " slot = " + slot); User player = island.getMemberSet(rank, false).stream().sorted().skip(slot - 1).limit(1L) .map(User::getInstance).findFirst().orElse(null); if (player != null) { + if (player.isOnline()) { return new PanelItemBuilder().icon(player.getName()).name(player.getDisplayName()) .description(user.getTranslation("commands.island.team.info.rank-layout.generic", TextVariables.RANK, user.getTranslation(ref), TextVariables.NUMBER, String.valueOf(count))) + .clickHandler((panel, user, clickType, i) -> { + BentoBox.getInstance().logDebug("Clicked " + clickType); + actions.forEach(ar -> BentoBox.getInstance().logDebug(ar.content() + " " + ar.clickType())); + return true; + }) .build(); + } else { + // Offline player + return new PanelItemBuilder().icon(player.getName()).name(player.getDisplayName()) + .description(offlinePlayerStatus(user, Bukkit.getOfflinePlayer(player.getUniqueId()))) + .clickHandler((panel, user, clickType, i) -> { + BentoBox.getInstance().logDebug("Clicked " + clickType); + actions.forEach(ar -> BentoBox.getInstance().logDebug(ar.content() + " " + ar.clickType())); + return true; + }).build(); + } } else { BentoBox.getInstance().logDebug("no player found"); } From bac0fe4b1703cf04ec0d54294c6c730b23ed3425 Mon Sep 17 00:00:00 2001 From: tastybento <tastybento@users.noreply.github.com> Date: Tue, 26 Dec 2023 16:54:43 +0900 Subject: [PATCH 03/22] Moe WIP on team GUI --- .../island/team/IslandTeamCommand.java | 76 ++++++++++++++----- .../api/panels/reader/ItemTemplateRecord.java | 18 ++++- src/main/resources/locales/en-US.yml | 2 + src/main/resources/panels/team_panel.yml | 16 +++- 4 files changed, 89 insertions(+), 23 deletions(-) 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 340102ce9..a3a9e04b1 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 @@ -6,6 +6,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Set; import java.util.UUID; @@ -22,6 +23,7 @@ import world.bentobox.bentobox.api.events.IslandBaseEvent; import world.bentobox.bentobox.api.events.team.TeamEvent; import world.bentobox.bentobox.api.localization.TextVariables; +import world.bentobox.bentobox.api.panels.Panel; import world.bentobox.bentobox.api.panels.PanelItem; import world.bentobox.bentobox.api.panels.TemplatedPanel; import world.bentobox.bentobox.api.panels.builders.PanelItemBuilder; @@ -130,13 +132,33 @@ private void build() { panelBuilder.registerTypeBuilder("STATUS", this::createStatusButton); panelBuilder.registerTypeBuilder("MEMBER", this::createMemberButton); - //panelBuilder.registerTypeBuilder("INVITE", this::createInviteButton); + panelBuilder.registerTypeBuilder("INVITE", this::createInviteButton); //panelBuilder.registerTypeBuilder("KICK", this::createKickButton); // Register unknown type builder. panelBuilder.build(); } + /** + * Create invite button panel item. + * + * @param template the template + * @param slot the slot + * @return the panel item + */ + private PanelItem createInviteButton(ItemTemplateRecord template, TemplatedPanel.ItemSlot slot) { + PanelItemBuilder builder = new PanelItemBuilder(); + // Player issuing the command must have an island + Island island = getIslands().getPrimaryIsland(getWorld(), user.getUniqueId()); + if (island == null) { + return builder.icon(Material.BARRIER).name(user.getTranslation("general.errors.no-island")).build(); + } + // The player must be able to invite a player + + return builder.icon(user.getName()).name(user.getTranslation("commands.island.team.gui.buttons.status.name")) + .description(showMembers()).build(); + } + /** * Create status button panel item. * @@ -164,11 +186,11 @@ private PanelItem createStatusButton(ItemTemplateRecord template, TemplatedPanel * @return the panel item */ private PanelItem createMemberButton(ItemTemplateRecord template, TemplatedPanel.ItemSlot slot) { - PanelItemBuilder builder = new PanelItemBuilder(); // Player issuing the command must have an island Island island = getIslands().getPrimaryIsland(getWorld(), user.getUniqueId()); if (island == null) { - return builder.icon(Material.BARRIER).name(user.getTranslation("general.errors.no-island")).build(); + return new PanelItemBuilder().icon(Material.BARRIER).name(user.getTranslation("general.errors.no-island")) + .build(); } if (slot.slot() == 0 && island.getOwner() != null) { // Owner @@ -182,7 +204,6 @@ private PanelItem createMemberButton(ItemTemplateRecord template, TemplatedPanel long memberCount = island.getMemberSet(RanksManager.MEMBER_RANK, false).stream().count(); long coopCount = island.getMemberSet(RanksManager.COOP_RANK, false).stream().count(); long trustedCount = island.getMemberSet(RanksManager.TRUSTED_RANK, false).stream().count(); - BentoBox.getInstance().logDebug("Slot = " + slot.slot()); if (slot.slot() > 0 && slot.slot() < subOwnerCount + 1) { // Show sub owners @@ -220,11 +241,10 @@ private PanelItem createMemberButton(ItemTemplateRecord template, TemplatedPanel } } - return builder.icon(Material.BLACK_STAINED_GLASS_PANE).name("&b&r").build(); + return new PanelItemBuilder().icon(Material.BLACK_STAINED_GLASS_PANE).name("&b&r").build(); } private PanelItem getMemberButton(String ref, int rank, long count, int slot, List<ActionRecords> actions) { - BentoBox.getInstance().logDebug(ref + " " + rank + " count = " + count + " slot = " + slot); User player = island.getMemberSet(rank, false).stream().sorted().skip(slot - 1).limit(1L) .map(User::getInstance).findFirst().orElse(null); if (player != null) { @@ -232,28 +252,42 @@ private PanelItem getMemberButton(String ref, int rank, long count, int slot, Li return new PanelItemBuilder().icon(player.getName()).name(player.getDisplayName()) .description(user.getTranslation("commands.island.team.info.rank-layout.generic", TextVariables.RANK, user.getTranslation(ref), TextVariables.NUMBER, String.valueOf(count))) - .clickHandler((panel, user, clickType, i) -> { - BentoBox.getInstance().logDebug("Clicked " + clickType); - actions.forEach(ar -> BentoBox.getInstance().logDebug(ar.content() + " " + ar.clickType())); - return true; - }) + .clickHandler( + (panel, user, clickType, i) -> clickListener(panel, user, clickType, i, player, actions)) .build(); } else { // Offline player return new PanelItemBuilder().icon(player.getName()).name(player.getDisplayName()) .description(offlinePlayerStatus(user, Bukkit.getOfflinePlayer(player.getUniqueId()))) - .clickHandler((panel, user, clickType, i) -> { - BentoBox.getInstance().logDebug("Clicked " + clickType); - actions.forEach(ar -> BentoBox.getInstance().logDebug(ar.content() + " " + ar.clickType())); - return true; - }).build(); + .clickHandler((panel, user, clickType, i) -> clickListener(panel, user, clickType, i, player, + actions)) + .build(); } - } else { - BentoBox.getInstance().logDebug("no player found"); } return null; } + private boolean clickListener(Panel panel, User user, ClickType clickType, int i, User player, + List<ActionRecords> actions) { + for (ItemTemplateRecord.ActionRecords action : actions) { + if (clickType == action.clickType() || action.clickType() == ClickType.UNKNOWN) { + switch (action.actionType().toUpperCase(Locale.ENGLISH)) { + case "KICK" -> { + // Kick the player + if (!player.equals(user)) { + this.user.closeInventory(); + BentoBox.getInstance() + .logDebug(this.getTopLabel() + " " + this.getLabel() + " kick " + player.getName()); + user.performCommand(this.getTopLabel() + " " + this.getLabel() + " kick " + player.getName()); + } + + } + } + } + } + return true; + } + private List<String> showMembers() { List<String> message = new ArrayList<>(); // Gather online members @@ -308,6 +342,12 @@ private String getMemberStatus(User user2, UUID member, boolean online) { } } + /** + * Creates text to describe the status of the player + * @param user2 user asking to see the status + * @param offlineMember member of the team + * @return string + */ private String offlinePlayerStatus(User user2, OfflinePlayer offlineMember) { // A bit of handling for the last joined date Instant lastJoined = Instant.ofEpochMilli(offlineMember.getLastPlayed()); diff --git a/src/main/java/world/bentobox/bentobox/api/panels/reader/ItemTemplateRecord.java b/src/main/java/world/bentobox/bentobox/api/panels/reader/ItemTemplateRecord.java index b59c5185a..ff7424f69 100644 --- a/src/main/java/world/bentobox/bentobox/api/panels/reader/ItemTemplateRecord.java +++ b/src/main/java/world/bentobox/bentobox/api/panels/reader/ItemTemplateRecord.java @@ -73,6 +73,22 @@ public void addAction(ActionRecords actionData) { * @param content the content of the action * @param tooltip the tooltip of action */ - public record ActionRecords(ClickType clickType, String actionType, String content, String tooltip) { + public record ActionRecords( + /** + * the click type + */ + ClickType clickType, + /** + * the string that represents action type + */ + String actionType, + /** + * the content of the action + */ + String content, + /** + * the tooltip of action + */ + String tooltip) { } } diff --git a/src/main/resources/locales/en-US.yml b/src/main/resources/locales/en-US.yml index 0440ff3f2..c19344d20 100644 --- a/src/main/resources/locales/en-US.yml +++ b/src/main/resources/locales/en-US.yml @@ -621,6 +621,8 @@ commands: description: The status of the team tips: click-to-view: Click to view + right-click-to-kick: Right click to kick player - requires confirmation + click-to-invite: Click to invite a team member info: description: display detailed info about your team member-layout: diff --git a/src/main/resources/panels/team_panel.yml b/src/main/resources/panels/team_panel.yml index eeb39e748..f95f473c3 100644 --- a/src/main/resources/panels/team_panel.yml +++ b/src/main/resources/panels/team_panel.yml @@ -37,6 +37,14 @@ team_panel: click-type: UNKNOWN # tooltip is a locale reference that will be translated for the user and shown when they hover over the button. tooltip: commands.island.team.gui.tips.click-to-view + 4: + # Invite member + data: + type: INVITE + actions: + add: + click-type: LEFT + tooltip: commands.island.team.gui.tips.click-to-invite 2: 2: member_button 3: member_button @@ -77,7 +85,7 @@ team_panel: 6: member_button 7: member_button 8: member_button - # This is where reuable buttons are defined. + # This is where reusable buttons are defined. reusable: # This is the name of the button that is referenced member_button: @@ -85,15 +93,15 @@ team_panel: # icons are usually not defined if the icon is going to be dynamically set in the panel, e.g. in this case the material will vary #icon: STONE title: commands.island.team.gui.buttons.member.name - description: levcommands.island.team.gui.buttons.member.description + description: commands.island.team.gui.buttons.member.description data: type: MEMBER # Actions cover what happens if the button is clicked or the mouse is moved over it. There can be multiple actions possible for different # click-types. actions: # Each action has an arbitrary descriptive name to define it. - view: + kick: # The click-type is the same as the bukkit {@link org.bukkit.event.inventory.ClickType}. UNKNOWN is the default. - click-type: RIGHT_CLICK + click-type: RIGHT # tooltip is a locale reference that will be translated for the user and shown when they hover over the button. tooltip: commands.island.team.gui.tips.right-click-to-kick \ No newline at end of file From 8d9a2597a07206c4efe54cb874c895c5f40ba0fc Mon Sep 17 00:00:00 2001 From: tastybento <tastybento@users.noreply.github.com> Date: Sat, 30 Dec 2023 12:22:05 +0900 Subject: [PATCH 04/22] Modified file to avoid an NPE. --- .../bentobox/api/commands/admin/AdminTeleportCommand.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/main/java/world/bentobox/bentobox/api/commands/admin/AdminTeleportCommand.java b/src/main/java/world/bentobox/bentobox/api/commands/admin/AdminTeleportCommand.java index bb98b9ab4..74dfe764e 100644 --- a/src/main/java/world/bentobox/bentobox/api/commands/admin/AdminTeleportCommand.java +++ b/src/main/java/world/bentobox/bentobox/api/commands/admin/AdminTeleportCommand.java @@ -118,12 +118,10 @@ public boolean execute(User user, String label, List<String> args) { private Location getSpot(World world) { Island island = getIslands().getIsland(world, targetUUID); - if (island != null && island.getSpawnPoint(world.getEnvironment()) != null) { - // Return the defined spawn point - return island.getSpawnPoint(world.getEnvironment()); + if (island == null) { + return null; } - // Return the default island protection center - return island.getProtectionCenter().toVector().toLocation(world); + return island.getSpawnPoint(world.getEnvironment()) != null ? island.getSpawnPoint(world.getEnvironment()) : island.getProtectionCenter().toVector().toLocation(world); } @Override From 511b613324c4e0e09afdedf32aa1cf27a2eea63c Mon Sep 17 00:00:00 2001 From: tastybento <tastybento@users.noreply.github.com> Date: Sat, 30 Dec 2023 12:46:56 +0900 Subject: [PATCH 05/22] Minor refactor to prevent int to Integer warning. --- .../bentobox/blueprints/dataobjects/BlueprintEntity.java | 3 ++- .../java/world/bentobox/bentobox/database/objects/Players.java | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/world/bentobox/bentobox/blueprints/dataobjects/BlueprintEntity.java b/src/main/java/world/bentobox/bentobox/blueprints/dataobjects/BlueprintEntity.java index 6a5927ddb..a06c11932 100644 --- a/src/main/java/world/bentobox/bentobox/blueprints/dataobjects/BlueprintEntity.java +++ b/src/main/java/world/bentobox/bentobox/blueprints/dataobjects/BlueprintEntity.java @@ -78,7 +78,8 @@ public void configureEntity(Entity e) { if (e instanceof AbstractHorse horse) { if (domestication != null) horse.setDomestication(domestication); if (inventory != null) { - inventory.forEach(horse.getInventory()::setItem); + inventory.forEach((index, item) -> horse.getInventory().setItem(index.intValue(), item)); + } } if (style != null && e instanceof Horse horse) { diff --git a/src/main/java/world/bentobox/bentobox/database/objects/Players.java b/src/main/java/world/bentobox/bentobox/database/objects/Players.java index 5e64c9f5d..3cf06d2c0 100644 --- a/src/main/java/world/bentobox/bentobox/database/objects/Players.java +++ b/src/main/java/world/bentobox/bentobox/database/objects/Players.java @@ -298,7 +298,7 @@ public void setUniqueId(String uniqueId) { * @param world - world */ public void addReset(World world) { - resets.merge(world.getName(), 1, Integer::sum); + resets.merge(world.getName(), 1, (oldValue, newValue) -> Integer.valueOf(oldValue + newValue)); } /** From 63c7ad832723d8f2152764b2e33dd128b835d1f5 Mon Sep 17 00:00:00 2001 From: tastybento <tastybento@users.noreply.github.com> Date: Sat, 30 Dec 2023 21:42:36 +0900 Subject: [PATCH 06/22] Use latest dependencies for tests to pass. --- pom.xml | 46 ++++++++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/pom.xml b/pom.xml index 696d9087e..35d6c136f 100644 --- a/pom.xml +++ b/pom.xml @@ -192,7 +192,32 @@ </repositories> <dependencies> - <!-- Spigot API --> + <!-- Mockito (Unit testing) This goes at the top to ensure the dependencies are accurate. --> + <!-- This is required for PowerMockito to work and must be placed before it --> + <dependency> + <groupId>org.javassist</groupId> + <artifactId>javassist</artifactId> + <version>3.30.2-GA</version> + </dependency> + <dependency> + <groupId>org.powermock</groupId> + <artifactId>powermock-module-junit4</artifactId> + <version>${powermock.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.powermock</groupId> + <artifactId>powermock-api-mockito2</artifactId> + <version>${powermock.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-core</artifactId> + <version>3.11.1</version> + <scope>test</scope> + </dependency> + <!-- Spigot API --> <dependency> <groupId>org.spigotmc</groupId> <artifactId>spigot-api</artifactId> @@ -212,25 +237,6 @@ <artifactId>bstats-bukkit</artifactId> <version>${bstats.version}</version> </dependency> - <!-- Mockito (Unit testing) --> - <dependency> - <groupId>org.mockito</groupId> - <artifactId>mockito-core</artifactId> - <version>3.11.1</version> - <scope>test</scope> - </dependency> - <dependency> - <groupId>org.powermock</groupId> - <artifactId>powermock-module-junit4</artifactId> - <version>${powermock.version}</version> - <scope>test</scope> - </dependency> - <dependency> - <groupId>org.powermock</groupId> - <artifactId>powermock-api-mockito2</artifactId> - <version>${powermock.version}</version> - <scope>test</scope> - </dependency> <!-- Database --> <dependency> <groupId>org.mongodb</groupId> From c6e5a43e57740c890b4149e68d48d3c5f94e6ac1 Mon Sep 17 00:00:00 2001 From: tastybento <tastybento@users.noreply.github.com> Date: Sat, 30 Dec 2023 21:43:02 +0900 Subject: [PATCH 07/22] Move to singleton pattern for RanksManager, --- .../world/bentobox/bentobox/BentoBox.java | 6 +- .../commands/admin/AdminGetrankCommand.java | 4 +- .../commands/admin/AdminSetrankCommand.java | 10 +- .../commands/admin/AdminSettingsCommand.java | 5 +- .../api/commands/island/IslandBanCommand.java | 3 +- .../commands/island/IslandBanlistCommand.java | 4 +- .../island/IslandDeletehomeCommand.java | 2 +- .../commands/island/IslandExpelCommand.java | 3 +- .../island/IslandRenamehomeCommand.java | 3 +- .../island/IslandResetnameCommand.java | 3 +- .../commands/island/IslandSethomeCommand.java | 3 +- .../commands/island/IslandSetnameCommand.java | 4 +- .../commands/island/IslandUnbanCommand.java | 4 +- .../island/team/IslandTeamCommand.java | 39 +++++-- .../island/team/IslandTeamCoopCommand.java | 2 +- .../island/team/IslandTeamInviteCommand.java | 4 +- .../island/team/IslandTeamKickCommand.java | 2 +- .../island/team/IslandTeamPromoteCommand.java | 11 +- .../island/team/IslandTeamTrustCommand.java | 3 +- .../island/team/IslandTeamUncoopCommand.java | 2 +- .../island/team/IslandTeamUntrustCommand.java | 2 +- .../bentobox/bentobox/api/flags/Flag.java | 3 +- .../api/flags/clicklisteners/CycleClick.java | 15 ++- .../clicklisteners/IslandToggleClick.java | 3 +- .../commands/BentoBoxRankCommand.java | 12 +- .../clicklisteners/CommandCycleClick.java | 5 +- .../CommandRankClickListener.java | 4 +- .../flags/protection/LockAndBanListener.java | 5 +- .../bentobox/lists/GameModePlaceholder.java | 4 +- .../bentobox/managers/IslandsManager.java | 13 ++- .../managers/PlaceholdersManager.java | 4 +- .../bentobox/managers/RanksManager.java | 25 +++- .../bentobox/util/DefaultPasteUtil.java | 2 +- .../bentobox/bentobox/util/IslandInfo.java | 4 +- .../admin/AdminGetrankCommandTest.java | 5 +- .../commands/admin/AdminInfoCommandTest.java | 7 +- .../admin/AdminSetrankCommandTest.java | 9 +- .../admin/AdminSettingsCommandTest.java | 5 - .../island/DefaultPlayerCommandTest.java | 6 - .../commands/island/IslandBanCommandTest.java | 6 +- .../island/IslandBanlistCommandTest.java | 6 +- .../island/IslandDeletehomeCommandTest.java | 7 +- .../island/IslandExpelCommandTest.java | 6 +- .../island/IslandInfoCommandTest.java | 7 +- .../island/IslandSetnameCommandTest.java | 5 - .../island/IslandUnbanCommandTest.java | 6 +- .../island/team/IslandTeamCommandTest.java | 4 - .../team/IslandTeamCoopCommandTest.java | 6 +- .../team/IslandTeamInviteCommandTest.java | 6 +- .../team/IslandTeamKickCommandTest.java | 8 +- .../team/IslandTeamPromoteCommandTest.java | 10 +- .../team/IslandTeamTrustCommandTest.java | 6 +- .../team/IslandTeamUncoopCommandTest.java | 6 +- .../team/IslandTeamUntrustCommandTest.java | 6 +- .../bentobox/bentobox/api/flags/FlagTest.java | 5 +- .../flags/clicklisteners/CycleClickTest.java | 24 +--- .../CommandRankClickListenerTest.java | 12 +- .../lists/GameModePlaceholderTest.java | 17 +-- .../managers/RanksManagerBeforeClassTest.java | 57 ++++++---- .../bentobox/managers/RanksManagerTest.java | 107 +++++++++++++----- 60 files changed, 296 insertions(+), 271 deletions(-) diff --git a/src/main/java/world/bentobox/bentobox/BentoBox.java b/src/main/java/world/bentobox/bentobox/BentoBox.java index bea18a9c6..6f2a5759e 100644 --- a/src/main/java/world/bentobox/bentobox/BentoBox.java +++ b/src/main/java/world/bentobox/bentobox/BentoBox.java @@ -71,7 +71,6 @@ public class BentoBox extends JavaPlugin implements Listener { private AddonsManager addonsManager; private FlagsManager flagsManager; private IslandWorldManager islandWorldManager; - private RanksManager ranksManager; private BlueprintsManager blueprintsManager; private HooksManager hooksManager; private PlaceholdersManager placeholdersManager; @@ -139,7 +138,6 @@ public void onEnable(){ return; } islandsManager = new IslandsManager(this); - ranksManager = new RanksManager(); // Start head getter headGetter = new HeadGetter(this); @@ -427,9 +425,11 @@ public FlagsManager getFlagsManager() { /** * @return the ranksManager + * @deprecated Just use {@code RanksManager.getInstance()} */ + @Deprecated(since = "2.0.0") public RanksManager getRanksManager() { - return ranksManager; + return RanksManager.getInstance(); } /** diff --git a/src/main/java/world/bentobox/bentobox/api/commands/admin/AdminGetrankCommand.java b/src/main/java/world/bentobox/bentobox/api/commands/admin/AdminGetrankCommand.java index 1c9b10b2e..e6bb28905 100644 --- a/src/main/java/world/bentobox/bentobox/api/commands/admin/AdminGetrankCommand.java +++ b/src/main/java/world/bentobox/bentobox/api/commands/admin/AdminGetrankCommand.java @@ -83,10 +83,10 @@ public boolean canExecute(User user, String label, List<String> args) { @Override public boolean execute(User user, String label, List<String> args) { // Get rank - RanksManager rm = getPlugin().getRanksManager(); User target = User.getInstance(targetUUID); int currentRank = island.getRank(target); - user.sendMessage("commands.admin.getrank.rank-is", TextVariables.RANK, user.getTranslation(rm.getRank(currentRank)), + user.sendMessage("commands.admin.getrank.rank-is", TextVariables.RANK, + user.getTranslation(RanksManager.getInstance().getRank(currentRank)), TextVariables.NAME, getPlayers().getName(island.getOwner())); return true; } diff --git a/src/main/java/world/bentobox/bentobox/api/commands/admin/AdminSetrankCommand.java b/src/main/java/world/bentobox/bentobox/api/commands/admin/AdminSetrankCommand.java index d0ff2d416..71f5cde6b 100644 --- a/src/main/java/world/bentobox/bentobox/api/commands/admin/AdminSetrankCommand.java +++ b/src/main/java/world/bentobox/bentobox/api/commands/admin/AdminSetrankCommand.java @@ -24,7 +24,6 @@ public class AdminSetrankCommand extends CompositeCommand { private int rankValue; private @Nullable UUID targetUUID; private @Nullable UUID ownerUUID; - private RanksManager rm; public AdminSetrankCommand(CompositeCommand adminCommand) { super(adminCommand, "setrank"); @@ -36,7 +35,6 @@ public void setup() { setOnlyPlayer(false); setParametersHelp("commands.admin.setrank.parameters"); setDescription("commands.admin.setrank.description"); - rm = getPlugin().getRanksManager(); } @Override @@ -53,7 +51,7 @@ public boolean canExecute(User user, String label, List<String> args) { return false; } // Get rank - rankValue = rm.getRanks().entrySet().stream() + rankValue = RanksManager.getInstance().getRanks().entrySet().stream() .filter(r -> user.getTranslation(r.getKey()).equalsIgnoreCase(args.get(1))).findFirst() .map(Map.Entry::getValue).orElse(-999); if (rankValue < RanksManager.BANNED_RANK) { @@ -121,8 +119,8 @@ public boolean execute(User user, String label, List<String> args) { ownerName = target.getName(); } user.sendMessage("commands.admin.setrank.rank-set", - "[from]", user.getTranslation(rm.getRank(currentRank)), - "[to]", user.getTranslation(rm.getRank(rankValue)), + "[from]", user.getTranslation(RanksManager.getInstance().getRank(currentRank)), "[to]", + user.getTranslation(RanksManager.getInstance().getRank(rankValue)), TextVariables.NAME, ownerName); return true; } @@ -136,7 +134,7 @@ public Optional<List<String>> tabComplete(User user, String alias, List<String> // Return the ranks if (args.size() == 3) { - return Optional.of(getPlugin().getRanksManager().getRanks() + return Optional.of(RanksManager.getInstance().getRanks() .entrySet().stream() .filter(entry -> entry.getValue() > RanksManager.VISITOR_RANK) .map(entry -> user.getTranslation(entry.getKey())).toList()); diff --git a/src/main/java/world/bentobox/bentobox/api/commands/admin/AdminSettingsCommand.java b/src/main/java/world/bentobox/bentobox/api/commands/admin/AdminSettingsCommand.java index b7e450a36..a792c0387 100644 --- a/src/main/java/world/bentobox/bentobox/api/commands/admin/AdminSettingsCommand.java +++ b/src/main/java/world/bentobox/bentobox/api/commands/admin/AdminSettingsCommand.java @@ -175,7 +175,7 @@ private boolean checkIslandSetting(User user, List<String> args) { * @return true if rank is valid */ private boolean checkRank(User user, String string) { - for (Entry<String, Integer> en : getPlugin().getRanksManager().getRanks().entrySet()) { + for (Entry<String, Integer> en : RanksManager.getInstance().getRanks().entrySet()) { if (en.getValue() > RanksManager.BANNED_RANK && en.getValue() <= RanksManager.OWNER_RANK && string.equalsIgnoreCase(ChatColor.stripColor(user.getTranslation(en.getKey())))) { // We have a winner @@ -277,8 +277,7 @@ public Optional<List<String>> tabComplete(User user, String alias, List<String> } else if (args.size() == 4) { // Get flag in previous argument options = getPlugin().getFlagsManager().getFlag(args.get(2).toUpperCase(Locale.ENGLISH)).map(f -> switch (f.getType()) { - case PROTECTION -> getPlugin().getRanksManager() - .getRanks().entrySet().stream() + case PROTECTION -> RanksManager.getInstance().getRanks().entrySet().stream() .filter(en -> en.getValue() > RanksManager.BANNED_RANK && en.getValue() <= RanksManager.OWNER_RANK) .map(Entry::getKey) .map(user::getTranslation).toList(); diff --git a/src/main/java/world/bentobox/bentobox/api/commands/island/IslandBanCommand.java b/src/main/java/world/bentobox/bentobox/api/commands/island/IslandBanCommand.java index 8e0465673..403eecc88 100644 --- a/src/main/java/world/bentobox/bentobox/api/commands/island/IslandBanCommand.java +++ b/src/main/java/world/bentobox/bentobox/api/commands/island/IslandBanCommand.java @@ -17,6 +17,7 @@ import world.bentobox.bentobox.api.localization.TextVariables; import world.bentobox.bentobox.api.user.User; import world.bentobox.bentobox.database.objects.Island; +import world.bentobox.bentobox.managers.RanksManager; import world.bentobox.bentobox.util.Util; public class IslandBanCommand extends CompositeCommand { @@ -55,7 +56,7 @@ public boolean canExecute(User user, String label, List<String> args) { int rank = island.getRank(user); if (rank < island.getRankCommand(getUsage())) { user.sendMessage("general.errors.insufficient-rank", TextVariables.RANK, - user.getTranslation(getPlugin().getRanksManager().getRank(rank))); + user.getTranslation(RanksManager.getInstance().getRank(rank))); return false; } // Get target player diff --git a/src/main/java/world/bentobox/bentobox/api/commands/island/IslandBanlistCommand.java b/src/main/java/world/bentobox/bentobox/api/commands/island/IslandBanlistCommand.java index 7d19f5c81..754c345bf 100644 --- a/src/main/java/world/bentobox/bentobox/api/commands/island/IslandBanlistCommand.java +++ b/src/main/java/world/bentobox/bentobox/api/commands/island/IslandBanlistCommand.java @@ -8,6 +8,7 @@ import world.bentobox.bentobox.api.localization.TextVariables; import world.bentobox.bentobox.api.user.User; import world.bentobox.bentobox.database.objects.Island; +import world.bentobox.bentobox.managers.RanksManager; public class IslandBanlistCommand extends CompositeCommand { @@ -40,7 +41,8 @@ public boolean canExecute(User user, String label, List<String> args) { island = getIslands().getIsland(getWorld(), user.getUniqueId()); int rank = Objects.requireNonNull(island).getRank(user); if (rank < island.getRankCommand(getUsage())) { - user.sendMessage("general.errors.insufficient-rank", TextVariables.RANK, user.getTranslation(getPlugin().getRanksManager().getRank(rank))); + user.sendMessage("general.errors.insufficient-rank", TextVariables.RANK, + user.getTranslation(RanksManager.getInstance().getRank(rank))); return false; } return true; 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 d2b1ccd15..d11947399 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 @@ -57,7 +57,7 @@ public boolean canExecute(User user, String label, List<String> args) { int rank = Objects.requireNonNull(island).getRank(user); if (rank < island.getRankCommand(getUsage())) { user.sendMessage("general.errors.insufficient-rank", - TextVariables.RANK, user.getTranslation(getPlugin().getRanksManager().getRank(rank))); + TextVariables.RANK, user.getTranslation(RanksManager.getInstance().getRank(rank))); return false; } diff --git a/src/main/java/world/bentobox/bentobox/api/commands/island/IslandExpelCommand.java b/src/main/java/world/bentobox/bentobox/api/commands/island/IslandExpelCommand.java index d8759a987..6d9de5fc4 100644 --- a/src/main/java/world/bentobox/bentobox/api/commands/island/IslandExpelCommand.java +++ b/src/main/java/world/bentobox/bentobox/api/commands/island/IslandExpelCommand.java @@ -16,6 +16,7 @@ import world.bentobox.bentobox.api.localization.TextVariables; import world.bentobox.bentobox.api.user.User; import world.bentobox.bentobox.database.objects.Island; +import world.bentobox.bentobox.managers.RanksManager; import world.bentobox.bentobox.util.Util; /** @@ -60,7 +61,7 @@ public boolean canExecute(User user, String label, List<String> args) { int rank = Objects.requireNonNull(island).getRank(user); if (rank < island.getRankCommand(getUsage())) { user.sendMessage("general.errors.insufficient-rank", TextVariables.RANK, - user.getTranslation(getPlugin().getRanksManager().getRank(rank))); + user.getTranslation(RanksManager.getInstance().getRank(rank))); return false; } // Get target player diff --git a/src/main/java/world/bentobox/bentobox/api/commands/island/IslandRenamehomeCommand.java b/src/main/java/world/bentobox/bentobox/api/commands/island/IslandRenamehomeCommand.java index 591fbbafb..80a06fc30 100644 --- a/src/main/java/world/bentobox/bentobox/api/commands/island/IslandRenamehomeCommand.java +++ b/src/main/java/world/bentobox/bentobox/api/commands/island/IslandRenamehomeCommand.java @@ -65,7 +65,8 @@ public boolean canExecute(User user, String label, List<String> args) { // check command permission int rank = Objects.requireNonNull(island).getRank(user); if (rank < island.getRankCommand(getUsage())) { - user.sendMessage("general.errors.insufficient-rank", TextVariables.RANK, user.getTranslation(getPlugin().getRanksManager().getRank(rank))); + user.sendMessage("general.errors.insufficient-rank", TextVariables.RANK, + user.getTranslation(RanksManager.getInstance().getRank(rank))); return false; } diff --git a/src/main/java/world/bentobox/bentobox/api/commands/island/IslandResetnameCommand.java b/src/main/java/world/bentobox/bentobox/api/commands/island/IslandResetnameCommand.java index 063553214..d797ed458 100644 --- a/src/main/java/world/bentobox/bentobox/api/commands/island/IslandResetnameCommand.java +++ b/src/main/java/world/bentobox/bentobox/api/commands/island/IslandResetnameCommand.java @@ -7,6 +7,7 @@ import world.bentobox.bentobox.api.localization.TextVariables; import world.bentobox.bentobox.api.user.User; import world.bentobox.bentobox.database.objects.Island; +import world.bentobox.bentobox.managers.RanksManager; /** @@ -41,7 +42,7 @@ public boolean canExecute(User user, String label, List<String> args) int rank = Objects.requireNonNull(island).getRank(user); if (rank < island.getRankCommand(getUsage())) { user.sendMessage("general.errors.insufficient-rank", - TextVariables.RANK, user.getTranslation(getPlugin().getRanksManager().getRank(rank))); + TextVariables.RANK, user.getTranslation(RanksManager.getInstance().getRank(rank))); return false; } 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 7b50b3c52..9ccde2194 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 @@ -46,7 +46,8 @@ public boolean canExecute(User user, String label, List<String> args) { int rank = Objects.requireNonNull(island).getRank(user); if (rank < island.getRankCommand(getUsage())) { - user.sendMessage("general.errors.insufficient-rank", TextVariables.RANK, user.getTranslation(getPlugin().getRanksManager().getRank(rank))); + user.sendMessage("general.errors.insufficient-rank", TextVariables.RANK, + user.getTranslation(RanksManager.getInstance().getRank(rank))); return false; } diff --git a/src/main/java/world/bentobox/bentobox/api/commands/island/IslandSetnameCommand.java b/src/main/java/world/bentobox/bentobox/api/commands/island/IslandSetnameCommand.java index f8b66f38e..d0582e787 100644 --- a/src/main/java/world/bentobox/bentobox/api/commands/island/IslandSetnameCommand.java +++ b/src/main/java/world/bentobox/bentobox/api/commands/island/IslandSetnameCommand.java @@ -10,6 +10,7 @@ import world.bentobox.bentobox.api.localization.TextVariables; import world.bentobox.bentobox.api.user.User; import world.bentobox.bentobox.database.objects.Island; +import world.bentobox.bentobox.managers.RanksManager; /** @@ -51,7 +52,8 @@ public boolean canExecute(User user, String label, List<String> args) // Check command rank. int rank = Objects.requireNonNull(island).getRank(user); if (rank < island.getRankCommand(getUsage())) { - user.sendMessage("general.errors.insufficient-rank", TextVariables.RANK, user.getTranslation(getPlugin().getRanksManager().getRank(rank))); + user.sendMessage("general.errors.insufficient-rank", TextVariables.RANK, + user.getTranslation(RanksManager.getInstance().getRank(rank))); return false; } diff --git a/src/main/java/world/bentobox/bentobox/api/commands/island/IslandUnbanCommand.java b/src/main/java/world/bentobox/bentobox/api/commands/island/IslandUnbanCommand.java index 041636e0f..dfaab3dd4 100644 --- a/src/main/java/world/bentobox/bentobox/api/commands/island/IslandUnbanCommand.java +++ b/src/main/java/world/bentobox/bentobox/api/commands/island/IslandUnbanCommand.java @@ -13,6 +13,7 @@ import world.bentobox.bentobox.api.localization.TextVariables; import world.bentobox.bentobox.api.user.User; import world.bentobox.bentobox.database.objects.Island; +import world.bentobox.bentobox.managers.RanksManager; import world.bentobox.bentobox.util.Util; /** @@ -54,7 +55,8 @@ public boolean canExecute(User user, String label, List<String> args) { Island island = getIslands().getIsland(getWorld(), user); int rank = Objects.requireNonNull(island).getRank(user); if (rank < island.getRankCommand(getUsage())) { - user.sendMessage("general.errors.insufficient-rank", TextVariables.RANK, user.getTranslation(getPlugin().getRanksManager().getRank(rank))); + user.sendMessage("general.errors.insufficient-rank", TextVariables.RANK, + user.getTranslation(RanksManager.getInstance().getRank(rank))); return false; } // Get target player 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 a3a9e04b1..d1c9163d0 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 @@ -26,6 +26,7 @@ import world.bentobox.bentobox.api.panels.Panel; import world.bentobox.bentobox.api.panels.PanelItem; import world.bentobox.bentobox.api.panels.TemplatedPanel; +import world.bentobox.bentobox.api.panels.TemplatedPanel.ItemSlot; import world.bentobox.bentobox.api.panels.builders.PanelItemBuilder; import world.bentobox.bentobox.api.panels.builders.TemplatedPanelBuilder; import world.bentobox.bentobox.api.panels.reader.ItemTemplateRecord; @@ -53,6 +54,8 @@ public class IslandTeamCommand extends CompositeCommand { private Island island; + private int rank = RanksManager.OWNER_RANK; + public IslandTeamCommand(CompositeCommand parent) { super(parent, "team"); inviteMap = new HashMap<>(); @@ -70,11 +73,11 @@ public void setup() { new IslandTeamKickCommand(this); new IslandTeamInviteAcceptCommand(this); new IslandTeamInviteRejectCommand(this); - if (getPlugin().getRanksManager().rankExists(RanksManager.COOP_RANK_REF)) { + if (RanksManager.getInstance().rankExists(RanksManager.COOP_RANK_REF)) { new IslandTeamCoopCommand(this); new IslandTeamUncoopCommand(this); } - if (getPlugin().getRanksManager().rankExists(RanksManager.TRUSTED_RANK_REF)) { + if (RanksManager.getInstance().rankExists(RanksManager.TRUSTED_RANK_REF)) { new IslandTeamTrustCommand(this); new IslandTeamUntrustCommand(this); } @@ -133,6 +136,7 @@ private void build() { panelBuilder.registerTypeBuilder("STATUS", this::createStatusButton); panelBuilder.registerTypeBuilder("MEMBER", this::createMemberButton); panelBuilder.registerTypeBuilder("INVITE", this::createInviteButton); + //panelBuilder.registerTypeBuilder("RANK", this::createRankButton); //panelBuilder.registerTypeBuilder("KICK", this::createKickButton); // Register unknown type builder. @@ -192,6 +196,19 @@ private PanelItem createMemberButton(ItemTemplateRecord template, TemplatedPanel return new PanelItemBuilder().icon(Material.BARRIER).name(user.getTranslation("general.errors.no-island")) .build(); } + return switch (rank) { + case RanksManager.OWNER_RANK -> ownerView(template, slot); + default -> generalView(template, slot, rank); + }; + } + + private PanelItem generalView(ItemTemplateRecord template, ItemSlot slot, int rank2) { + getMemberButton(RanksManager.MEMBER_RANK_REF, RanksManager.MEMBER_RANK, + island.getMemberSet(rank2, false).size(), slot.slot(), template.actions()); + return null; + } + + private PanelItem ownerView(ItemTemplateRecord template, ItemSlot slot) { if (slot.slot() == 0 && island.getOwner() != null) { // Owner PanelItem item = getMemberButton(RanksManager.OWNER_RANK_REF, RanksManager.OWNER_RANK, 1, 1, @@ -242,6 +259,7 @@ private PanelItem createMemberButton(ItemTemplateRecord template, TemplatedPanel } return new PanelItemBuilder().icon(Material.BLACK_STAINED_GLASS_PANE).name("&b&r").build(); + } private PanelItem getMemberButton(String ref, int rank, long count, int slot, List<ActionRecords> actions) { @@ -249,12 +267,13 @@ private PanelItem getMemberButton(String ref, int rank, long count, int slot, Li .map(User::getInstance).findFirst().orElse(null); if (player != null) { if (player.isOnline()) { - return new PanelItemBuilder().icon(player.getName()).name(player.getDisplayName()) - .description(user.getTranslation("commands.island.team.info.rank-layout.generic", - TextVariables.RANK, user.getTranslation(ref), TextVariables.NUMBER, String.valueOf(count))) - .clickHandler( - (panel, user, clickType, i) -> clickListener(panel, user, clickType, i, player, actions)) - .build(); + return new PanelItemBuilder().icon(player.getName()).name(player.getDisplayName()) + .description( + user.getTranslation("commands.island.team.info.rank-layout.generic", TextVariables.RANK, + user.getTranslation(ref), TextVariables.NUMBER, String.valueOf(count))) + .clickHandler((panel, user, clickType, i) -> clickListener(panel, user, clickType, i, player, + actions)) + .build(); } else { // Offline player return new PanelItemBuilder().icon(player.getName()).name(player.getDisplayName()) @@ -279,7 +298,7 @@ private boolean clickListener(Panel panel, User user, ClickType clickType, int i BentoBox.getInstance() .logDebug(this.getTopLabel() + " " + this.getLabel() + " kick " + player.getName()); user.performCommand(this.getTopLabel() + " " + this.getLabel() + " kick " + player.getName()); - } + } } } @@ -314,7 +333,7 @@ private List<String> showMembers() { user.getTranslation(RanksManager.OWNER_RANK_REF))); } else { message.add(user.getTranslation("commands.island.team.info.rank-layout.generic", TextVariables.RANK, - user.getTranslation(getPlugin().getRanksManager().getRank(rank)), TextVariables.NUMBER, + user.getTranslation(RanksManager.getInstance().getRank(rank)), TextVariables.NUMBER, String.valueOf(island.getMemberSet(rank, false).size()))); } message.addAll(displayOnOffline(user, rank, island, onlineMembers)); 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 19a039b69..246c38b21 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 @@ -58,7 +58,7 @@ public boolean canExecute(User user, String label, List<String> args) { int rank = Objects.requireNonNull(island).getRank(user); if (rank < island.getRankCommand(getUsage())) { user.sendMessage("general.errors.insufficient-rank", TextVariables.RANK, - user.getTranslation(getPlugin().getRanksManager().getRank(rank))); + user.getTranslation(RanksManager.getInstance().getRank(rank))); return false; } // Get target player 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 2f054e1d4..4585dfc7c 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 @@ -79,14 +79,14 @@ private boolean handleCommandWithNoArgs(User user) { } private boolean checkRankAndInvitePlayer(User user, Island island, int rank, String playerName) { - RanksManager ranksManager = getPlugin().getRanksManager(); PlayersManager playersManager = getPlayers(); UUID playerUUID = user.getUniqueId(); // Check rank to use command int requiredRank = island.getRankCommand(getUsage()); if (rank < requiredRank) { - user.sendMessage("general.errors.insufficient-rank", TextVariables.RANK, user.getTranslation(ranksManager.getRank(rank))); + user.sendMessage("general.errors.insufficient-rank", TextVariables.RANK, + user.getTranslation(RanksManager.getInstance().getRank(rank))); return false; } diff --git a/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamKickCommand.java b/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamKickCommand.java index 6266edb4f..9c27b7baf 100644 --- a/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamKickCommand.java +++ b/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamKickCommand.java @@ -45,7 +45,7 @@ public boolean execute(User user, String label, List<String> args) { int rank = Objects.requireNonNull(island).getRank(user); if (rank < island.getRankCommand(getUsage())) { user.sendMessage("general.errors.insufficient-rank", TextVariables.RANK, - user.getTranslation(getPlugin().getRanksManager().getRank(rank))); + user.getTranslation(RanksManager.getInstance().getRank(rank))); return false; } // If args are not right, show help diff --git a/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamPromoteCommand.java b/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamPromoteCommand.java index 988f74201..eab48723a 100644 --- a/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamPromoteCommand.java +++ b/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamPromoteCommand.java @@ -54,7 +54,8 @@ public boolean canExecute(User user, String label, List<String> args) { Island island = getIslands().getIsland(getWorld(), user); int rank = Objects.requireNonNull(island).getRank(user); if (rank < island.getRankCommand(getUsage())) { - user.sendMessage("general.errors.insufficient-rank", TextVariables.RANK, user.getTranslation(getPlugin().getRanksManager().getRank(rank))); + user.sendMessage("general.errors.insufficient-rank", TextVariables.RANK, + user.getTranslation(RanksManager.getInstance().getRank(rank))); return false; } @@ -97,11 +98,11 @@ private boolean change(User user, User target) { Island island = getIslands().getIsland(getWorld(), user); int currentRank = island.getRank(target); if (this.getLabel().equals("promote")) { - int nextRank = getPlugin().getRanksManager().getRankUpValue(currentRank); + int nextRank = RanksManager.getInstance().getRankUpValue(currentRank); // Stop short of owner if (nextRank != RanksManager.OWNER_RANK && nextRank > currentRank) { island.setRank(target, nextRank); - String rankName = user.getTranslation(getPlugin().getRanksManager().getRank(nextRank)); + String rankName = user.getTranslation(RanksManager.getInstance().getRank(nextRank)); user.sendMessage("commands.island.team.promote.success", TextVariables.NAME, target.getName(), TextVariables.RANK, rankName, TextVariables.DISPLAY_NAME, target.getDisplayName()); IslandEvent.builder() .island(island) @@ -117,11 +118,11 @@ private boolean change(User user, User target) { } } else { // Demote - int prevRank = getPlugin().getRanksManager().getRankDownValue(currentRank); + int prevRank = RanksManager.getInstance().getRankDownValue(currentRank); // Lowest is Member if (prevRank >= RanksManager.MEMBER_RANK && prevRank < currentRank) { island.setRank(target, prevRank); - String rankName = user.getTranslation(getPlugin().getRanksManager().getRank(prevRank)); + String rankName = user.getTranslation(RanksManager.getInstance().getRank(prevRank)); user.sendMessage("commands.island.team.demote.success", TextVariables.NAME, target.getName(), TextVariables.RANK, rankName, TextVariables.DISPLAY_NAME, target.getDisplayName()); IslandEvent.builder() .island(island) 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 633223bb3..8d57871df 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 @@ -55,7 +55,8 @@ public boolean canExecute(User user, String label, List<String> args) { Island island = getIslands().getIsland(getWorld(), user); int rank = Objects.requireNonNull(island).getRank(user); if (rank < island.getRankCommand(getUsage())) { - user.sendMessage("general.errors.insufficient-rank", TextVariables.RANK, user.getTranslation(getPlugin().getRanksManager().getRank(rank))); + user.sendMessage("general.errors.insufficient-rank", TextVariables.RANK, + user.getTranslation(RanksManager.getInstance().getRank(rank))); return false; } // Get target player diff --git a/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamUncoopCommand.java b/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamUncoopCommand.java index c60bde5d3..6c9533110 100644 --- a/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamUncoopCommand.java +++ b/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamUncoopCommand.java @@ -55,7 +55,7 @@ public boolean execute(User user, String label, List<String> args) { int rank = Objects.requireNonNull(island).getRank(user); if (rank < island.getRankCommand(getUsage())) { user.sendMessage("general.errors.insufficient-rank", TextVariables.RANK, - user.getTranslation(getPlugin().getRanksManager().getRank(rank))); + user.getTranslation(RanksManager.getInstance().getRank(rank))); return false; } // Get target player diff --git a/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamUntrustCommand.java b/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamUntrustCommand.java index ca2f3d408..05581286c 100644 --- a/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamUntrustCommand.java +++ b/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamUntrustCommand.java @@ -55,7 +55,7 @@ public boolean execute(User user, String label, List<String> args) { int rank = Objects.requireNonNull(island).getRank(user); if (rank < island.getRankCommand(getUsage())) { user.sendMessage("general.errors.insufficient-rank", TextVariables.RANK, - user.getTranslation(getPlugin().getRanksManager().getRank(rank))); + user.getTranslation(RanksManager.getInstance().getRank(rank))); return false; } // Get target player diff --git a/src/main/java/world/bentobox/bentobox/api/flags/Flag.java b/src/main/java/world/bentobox/bentobox/api/flags/Flag.java index 409296228..abb185b5f 100644 --- a/src/main/java/world/bentobox/bentobox/api/flags/Flag.java +++ b/src/main/java/world/bentobox/bentobox/api/flags/Flag.java @@ -430,7 +430,8 @@ private PanelItemBuilder createProtectionFlag(BentoBox plugin, User user, Island // Protection flag pib.description(user.getTranslation("protection.panel.flag-item.description-layout", TextVariables.DESCRIPTION, user.getTranslation(getDescriptionReference()))); - plugin.getRanksManager().getRanks().forEach((reference, score) -> { + plugin.getRanksManager(); + RanksManager.getInstance().getRanks().forEach((reference, score) -> { if (score > RanksManager.BANNED_RANK && score < island.getFlag(this)) { pib.description(user.getTranslation("protection.panel.flag-item.blocked-rank") + user.getTranslation(reference)); } else if (score <= RanksManager.OWNER_RANK && score > island.getFlag(this)) { diff --git a/src/main/java/world/bentobox/bentobox/api/flags/clicklisteners/CycleClick.java b/src/main/java/world/bentobox/bentobox/api/flags/clicklisteners/CycleClick.java index c1a281e37..296a79fed 100644 --- a/src/main/java/world/bentobox/bentobox/api/flags/clicklisteners/CycleClick.java +++ b/src/main/java/world/bentobox/bentobox/api/flags/clicklisteners/CycleClick.java @@ -81,15 +81,14 @@ public boolean onClick(Panel panel, User user2, ClickType click, int slot) { // Shift Left Click toggles player visibility if (island != null && (user.isOp() || island.isAllowed(user, Flags.CHANGE_SETTINGS) || user.hasPermission(prefix + "admin.settings"))) { changeOccurred = true; - RanksManager rm = plugin.getRanksManager(); plugin.getFlagsManager().getFlag(id).ifPresent(flag -> { // Rank int currentRank = island.getFlag(flag); if (click.equals(ClickType.LEFT)) { - leftClick(flag, rm, currentRank); + leftClick(flag, currentRank); } else if (click.equals(ClickType.RIGHT)) { - rightClick(flag, rm, currentRank); + rightClick(flag, currentRank); } else if (click.equals(ClickType.SHIFT_LEFT) && user2.isOp()) { leftShiftClick(flag); @@ -109,16 +108,16 @@ private void reportError() { // Player is not the allowed to change settings. user.sendMessage("general.errors.insufficient-rank", TextVariables.RANK, - user.getTranslation(plugin.getRanksManager().getRank(Objects.requireNonNull(island).getRank(user)))); + user.getTranslation(RanksManager.getInstance().getRank(Objects.requireNonNull(island).getRank(user)))); } user.getPlayer().playSound(user.getLocation(), Sound.BLOCK_METAL_HIT, 1F, 1F); } - private void leftClick(Flag flag, RanksManager rm, int currentRank) { + private void leftClick(Flag flag, int currentRank) { if (currentRank >= maxRank) { island.setFlag(flag, minRank); } else { - island.setFlag(flag, rm.getRankUpValue(currentRank)); + island.setFlag(flag, RanksManager.getInstance().getRankUpValue(currentRank)); } user.getPlayer().playSound(user.getLocation(), Sound.BLOCK_STONE_BUTTON_CLICK_OFF, 1F, 1F); // Fire event @@ -132,11 +131,11 @@ private void leftClick(Flag flag, RanksManager rm, int currentRank) { } - private void rightClick(Flag flag, RanksManager rm, int currentRank) { + private void rightClick(Flag flag, int currentRank) { if (currentRank <= minRank) { island.setFlag(flag, maxRank); } else { - island.setFlag(flag, rm.getRankDownValue(currentRank)); + island.setFlag(flag, RanksManager.getInstance().getRankDownValue(currentRank)); } user.getPlayer().playSound(user.getLocation(), Sound.BLOCK_STONE_BUTTON_CLICK_ON, 1F, 1F); // Fire event diff --git a/src/main/java/world/bentobox/bentobox/api/flags/clicklisteners/IslandToggleClick.java b/src/main/java/world/bentobox/bentobox/api/flags/clicklisteners/IslandToggleClick.java index 056af998c..76949cd6e 100644 --- a/src/main/java/world/bentobox/bentobox/api/flags/clicklisteners/IslandToggleClick.java +++ b/src/main/java/world/bentobox/bentobox/api/flags/clicklisteners/IslandToggleClick.java @@ -17,6 +17,7 @@ import world.bentobox.bentobox.api.user.User; import world.bentobox.bentobox.database.objects.Island; import world.bentobox.bentobox.lists.Flags; +import world.bentobox.bentobox.managers.RanksManager; import world.bentobox.bentobox.panels.settings.SettingsTab; import world.bentobox.bentobox.util.Util; @@ -112,7 +113,7 @@ private void reportError(User user, Island island) { // Player is not the allowed to change settings. user.sendMessage("general.errors.insufficient-rank", TextVariables.RANK, - user.getTranslation(plugin.getRanksManager().getRank(Objects.requireNonNull(island).getRank(user)))); + user.getTranslation(RanksManager.getInstance().getRank(Objects.requireNonNull(island).getRank(user)))); } user.getPlayer().playSound(user.getLocation(), Sound.BLOCK_METAL_HIT, 1F, 1F); diff --git a/src/main/java/world/bentobox/bentobox/commands/BentoBoxRankCommand.java b/src/main/java/world/bentobox/bentobox/commands/BentoBoxRankCommand.java index a666cddde..3c5b9b4f5 100644 --- a/src/main/java/world/bentobox/bentobox/commands/BentoBoxRankCommand.java +++ b/src/main/java/world/bentobox/bentobox/commands/BentoBoxRankCommand.java @@ -20,7 +20,6 @@ public class BentoBoxRankCommand extends CompositeCommand { private static final String REMOVE = "remove"; private int rankValue; private String firstElement; - private final RanksManager rm; /** * Rank management. Add and remove @@ -29,7 +28,6 @@ public class BentoBoxRankCommand extends CompositeCommand { */ public BentoBoxRankCommand(CompositeCommand parent) { super(parent, "rank"); - rm = getPlugin().getRanksManager(); } @Override @@ -93,7 +91,7 @@ public boolean execute(User user, String label, List<String> args) { return true; } if ("add".equals(firstElement)) { - if (rm.addRank(args.get(1), rankValue)) { + if (RanksManager.getInstance().addRank(args.get(1), rankValue)) { user.sendMessage("commands.bentobox.rank.add.success", TextVariables.RANK, args.get(1), TextVariables.NUMBER, String.valueOf(rankValue)); showRanks(user); @@ -103,7 +101,7 @@ public boolean execute(User user, String label, List<String> args) { return false; } } else { - if (rm.removeRank(args.get(1))) { + if (RanksManager.getInstance().removeRank(args.get(1))) { user.sendMessage("commands.bentobox.rank.remove.success", TextVariables.RANK, args.get(1)); showRanks(user); } else { @@ -116,7 +114,7 @@ public boolean execute(User user, String label, List<String> args) { private void showRanks(User user) { user.sendMessage("commands.bentobox.rank.list"); - rm.getRanks().forEach((ref, rank) -> { + RanksManager.getInstance().getRanks().forEach((ref, rank) -> { user.sendRawMessage(user.getTranslation(ref) + ": " + ref + " " + String.valueOf(rank)); }); @@ -133,11 +131,11 @@ public Optional<List<String>> tabComplete(User user, String alias, List<String> } if (args.size() > 1 && "add".equals(firstElement)) { List<String> options = new ArrayList<>(RanksManager.DEFAULT_RANKS.keySet()); - options.removeIf(rm.getRanks().keySet()::contains); + options.removeIf(RanksManager.getInstance().getRanks().keySet()::contains); return Optional.of(options); } if (args.size() > 1 && REMOVE.equals(firstElement)) { - return Optional.of(new ArrayList<>(rm.getRanks().keySet())); + return Optional.of(new ArrayList<>(RanksManager.getInstance().getRanks().keySet())); } return Optional.empty(); diff --git a/src/main/java/world/bentobox/bentobox/listeners/flags/clicklisteners/CommandCycleClick.java b/src/main/java/world/bentobox/bentobox/listeners/flags/clicklisteners/CommandCycleClick.java index 0668f4a3b..2368c62f7 100644 --- a/src/main/java/world/bentobox/bentobox/listeners/flags/clicklisteners/CommandCycleClick.java +++ b/src/main/java/world/bentobox/bentobox/listeners/flags/clicklisteners/CommandCycleClick.java @@ -38,20 +38,19 @@ public boolean onClick(Panel panel, User user, ClickType click, int slot) { World world = panel.getWorld().orElse(user.getWorld()); Island island = plugin.getIslands().getIsland(world, user.getUniqueId()); if (island != null && island.getOwner() != null && island.isAllowed(user, Flags.CHANGE_SETTINGS)) { - RanksManager rm = plugin.getRanksManager(); int currentRank = island.getRankCommand(command); if (click.equals(ClickType.LEFT)) { if (currentRank == RanksManager.OWNER_RANK) { island.setRankCommand(command, RanksManager.MEMBER_RANK); } else { - island.setRankCommand(command, rm.getRankUpValue(currentRank)); + island.setRankCommand(command, RanksManager.getInstance().getRankUpValue(currentRank)); } user.getPlayer().playSound(user.getLocation(), Sound.BLOCK_STONE_BUTTON_CLICK_ON, 1F, 1F); } else if (click.equals(ClickType.RIGHT)) { if (currentRank == RanksManager.MEMBER_RANK) { island.setRankCommand(command, RanksManager.OWNER_RANK); } else { - island.setRankCommand(command, rm.getRankDownValue(currentRank)); + island.setRankCommand(command, RanksManager.getInstance().getRankDownValue(currentRank)); } user.getPlayer().playSound(user.getLocation(), Sound.BLOCK_STONE_BUTTON_CLICK_ON, 1F, 1F); } diff --git a/src/main/java/world/bentobox/bentobox/listeners/flags/clicklisteners/CommandRankClickListener.java b/src/main/java/world/bentobox/bentobox/listeners/flags/clicklisteners/CommandRankClickListener.java index 766d3ce68..352b31370 100644 --- a/src/main/java/world/bentobox/bentobox/listeners/flags/clicklisteners/CommandRankClickListener.java +++ b/src/main/java/world/bentobox/bentobox/listeners/flags/clicklisteners/CommandRankClickListener.java @@ -66,7 +66,7 @@ public boolean onClick(Panel panel, User user, ClickType clickType, int slot) { // Check if user has rank enough on the island //Island island = plugin.getIslands().getIsland(panel.getWorld().orElse(user.getWorld()), user.getUniqueId()); if (!island.isAllowed(user, Flags.CHANGE_SETTINGS)) { - String rank = user.getTranslation(plugin.getRanksManager().getRank(Objects.requireNonNull(island).getRank(user))); + String rank = user.getTranslation(RanksManager.getInstance().getRank(Objects.requireNonNull(island).getRank(user))); user.sendMessage("general.errors.insufficient-rank", TextVariables.RANK, rank); user.getPlayer().playSound(user.getLocation(), Sound.BLOCK_METAL_HIT, 1F, 1F); return true; @@ -114,7 +114,7 @@ public PanelItem getPanelItem(String c, User user, World world) { // TODO: use specific layout String d = user.getTranslation("protection.panel.flag-item.description-layout", TextVariables.DESCRIPTION, ""); pib.description(d); - plugin.getRanksManager().getRanks().forEach((reference, score) -> { + RanksManager.getInstance().getRanks().forEach((reference, score) -> { if (score >= RanksManager.MEMBER_RANK && score < island.getRankCommand(c)) { pib.description(user.getTranslation("protection.panel.flag-item.blocked-rank") + user.getTranslation(reference)); } else if (score <= RanksManager.OWNER_RANK && score > island.getRankCommand(c)) { diff --git a/src/main/java/world/bentobox/bentobox/listeners/flags/protection/LockAndBanListener.java b/src/main/java/world/bentobox/bentobox/listeners/flags/protection/LockAndBanListener.java index ad20ba54b..6a41cb2ca 100644 --- a/src/main/java/world/bentobox/bentobox/listeners/flags/protection/LockAndBanListener.java +++ b/src/main/java/world/bentobox/bentobox/listeners/flags/protection/LockAndBanListener.java @@ -162,7 +162,10 @@ private void eject(Player player) { } else { // There's nothing much we can do. // We'll try to teleport him to the spawn... - PaperLib.teleportAsync(player, player.getWorld().getSpawnLocation()); + Location l = player.getWorld().getSpawnLocation(); + if (l != null) { + PaperLib.teleportAsync(player, l); + } // Switch him back to the default gamemode. He may die, sorry :( player.setGameMode(getIWM().getDefaultGameMode(player.getWorld())); diff --git a/src/main/java/world/bentobox/bentobox/lists/GameModePlaceholder.java b/src/main/java/world/bentobox/bentobox/lists/GameModePlaceholder.java index 54e91288c..06662819f 100644 --- a/src/main/java/world/bentobox/bentobox/lists/GameModePlaceholder.java +++ b/src/main/java/world/bentobox/bentobox/lists/GameModePlaceholder.java @@ -289,7 +289,9 @@ public enum GameModePlaceholder { * Returns the rank this player has on his island. * @since 1.5.0 */ - RANK("rank", (addon, user, island) -> (island == null || user == null) ? "" : user.getTranslation(addon.getPlugin().getRanksManager().getRank(island.getRank(user)))), + RANK("rank", + (addon, user, island) -> (island == null || user == null) ? "" + : user.getTranslation(RanksManager.getInstance().getRank(island.getRank(user)))), /** * Returns how many times this player reset his island. * @since 1.5.0 diff --git a/src/main/java/world/bentobox/bentobox/managers/IslandsManager.java b/src/main/java/world/bentobox/bentobox/managers/IslandsManager.java index 595b7f54c..55ad2d68b 100644 --- a/src/main/java/world/bentobox/bentobox/managers/IslandsManager.java +++ b/src/main/java/world/bentobox/bentobox/managers/IslandsManager.java @@ -1116,7 +1116,7 @@ private CompletableFuture<Boolean> homeTeleportAsync(@NonNull World world, @NonN .ifFail(() -> goingHome.remove(user.getUniqueId())).buildFuture().thenAccept(result::complete); return; } - PaperLib.teleportAsync(player, home).thenAccept(b -> { + PaperLib.teleportAsync(Objects.requireNonNull(player), home).thenAccept(b -> { // Only run the commands if the player is successfully teleported if (Boolean.TRUE.equals(b)) { teleported(world, user, name, newIsland, island); @@ -1512,7 +1512,12 @@ public void removePlayersFromIsland(Island island) { // Move player to spawn if (spawn.containsKey(w)) { // go to island spawn - PaperLib.teleportAsync(p, spawn.get(w).getSpawnPoint(w.getEnvironment())); + Location sp = spawn.get(w).getSpawnPoint(w.getEnvironment()); + if (sp != null) { + PaperLib.teleportAsync(p, sp); + } else { + plugin.logWarning("Spawn exists but its location is null!"); + } } } }); @@ -1925,7 +1930,7 @@ public CompletableFuture<Boolean> checkTeams(User user, World world) { Island highestIsland = null; for (Island i : en.getValue()) { int rankValue = i.getRank(en.getKey()); - String rank = plugin.getRanksManager().getRank(rankValue); + String rank = RanksManager.getInstance().getRank(rankValue); if (rankValue > highestRank || highestIsland == null) { highestRank = rankValue; highestIsland = i; @@ -1937,7 +1942,7 @@ public CompletableFuture<Boolean> checkTeams(User user, World world) { } // Fix island ownership in cache // Correct island cache - if (highestRank == RanksManager.OWNER_RANK + if (highestRank == RanksManager.OWNER_RANK && highestIsland != null && islandCache.getIslandById(highestIsland.getUniqueId()) != null) { islandCache.setOwner(islandCache.getIslandById(highestIsland.getUniqueId()), en.getKey()); } diff --git a/src/main/java/world/bentobox/bentobox/managers/PlaceholdersManager.java b/src/main/java/world/bentobox/bentobox/managers/PlaceholdersManager.java index 20e9ad2b5..8917e61e2 100644 --- a/src/main/java/world/bentobox/bentobox/managers/PlaceholdersManager.java +++ b/src/main/java/world/bentobox/bentobox/managers/PlaceholdersManager.java @@ -95,7 +95,7 @@ private void registerTeamMemberPlaceholders(@NonNull GameModeAddon addon) { int j = 1; for (UUID uuid : island.getMemberSet(RanksManager.MEMBER_RANK)) { if (j++ == count) { - return user.getTranslationOrNothing(plugin.getRanksManager().getRank(island.getRank(uuid))); + return user.getTranslationOrNothing(RanksManager.getInstance().getRank(island.getRank(uuid))); } } } @@ -140,7 +140,7 @@ private void registerTeamMemberPlaceholders(@NonNull GameModeAddon addon) { int j = 1; for (UUID uuid : island.getMemberSet(RanksManager.MEMBER_RANK)) { if (j++ == count) { - return user.getTranslationOrNothing(plugin.getRanksManager().getRank(island.getRank(uuid))); + return user.getTranslationOrNothing(RanksManager.getInstance().getRank(island.getRank(uuid))); } } return ""; diff --git a/src/main/java/world/bentobox/bentobox/managers/RanksManager.java b/src/main/java/world/bentobox/bentobox/managers/RanksManager.java index fe5009f37..002569326 100644 --- a/src/main/java/world/bentobox/bentobox/managers/RanksManager.java +++ b/src/main/java/world/bentobox/bentobox/managers/RanksManager.java @@ -41,16 +41,32 @@ public class RanksManager { public static final int BANNED_RANK = -1; // The store of ranks - private LinkedHashMap<String, Integer> ranks = new LinkedHashMap<>(); + private static LinkedHashMap<String, Integer> ranks = new LinkedHashMap<>(); public static final Map<String, Integer> DEFAULT_RANKS = Map.of(ADMIN_RANK_REF, ADMIN_RANK, MOD_RANK_REF, MOD_RANK, OWNER_RANK_REF, OWNER_RANK, SUB_OWNER_RANK_REF, SUB_OWNER_RANK, MEMBER_RANK_REF, MEMBER_RANK, TRUSTED_RANK_REF, TRUSTED_RANK, COOP_RANK_REF, COOP_RANK, VISITOR_RANK_REF, VISITOR_RANK, BANNED_RANK_REF, BANNED_RANK); @NonNull - private Database<Ranks> handler; + private static Database<Ranks> handler; + private static RanksManager instance; - public RanksManager() { + // Private constructor for singleton + private RanksManager() { + handler = new Database<>(BentoBox.getInstance(), Ranks.class); + ranks = new LinkedHashMap<>(); + loadRanksFromDatabase(); + } + + // Public method to get the singleton instance + public static synchronized RanksManager getInstance() { + if (instance == null) { + instance = new RanksManager(); + } + return instance; + } + + public void loadRanksFromDatabase() { // Set up the database handler to store and retrieve Island classes handler = new Database<>(BentoBox.getInstance(), Ranks.class); if (!handler.objectExists(Ranks.ID)) { @@ -59,7 +75,8 @@ public RanksManager() { handler.saveObject(new Ranks(ranks)); } else { // Load the ranks from the database - Objects.requireNonNull(handler.loadObject(Ranks.ID)).getRankReference().forEach(this::ranksPut); + Objects.requireNonNull(handler.loadObject(Ranks.ID)).getRankReference() + .forEach((rankRef, rankValue) -> ranksPut(rankRef, rankValue)); } } diff --git a/src/main/java/world/bentobox/bentobox/util/DefaultPasteUtil.java b/src/main/java/world/bentobox/bentobox/util/DefaultPasteUtil.java index 85f7c78c1..e616e35a3 100644 --- a/src/main/java/world/bentobox/bentobox/util/DefaultPasteUtil.java +++ b/src/main/java/world/bentobox/bentobox/util/DefaultPasteUtil.java @@ -131,7 +131,7 @@ else if (bs instanceof InventoryHolder holder) { Inventory ih = holder.getInventory(); // Double chests are pasted as two blocks so inventory is filled twice. // This code stops over-filling for the first block. - bpBlock.getInventory().forEach(ih::setItem); + bpBlock.getInventory().forEach((slot, item) -> ih.setItem(slot, item)); } // Mob spawners else if (bs instanceof CreatureSpawner spawner) { diff --git a/src/main/java/world/bentobox/bentobox/util/IslandInfo.java b/src/main/java/world/bentobox/bentobox/util/IslandInfo.java index d59d63638..cb5e4e4e8 100644 --- a/src/main/java/world/bentobox/bentobox/util/IslandInfo.java +++ b/src/main/java/world/bentobox/bentobox/util/IslandInfo.java @@ -169,11 +169,11 @@ public void showMembers(User user) { if (owner.equals(u)) { user.sendMessage("commands.admin.info.team-owner-format", TextVariables.NAME, plugin.getPlayers().getName(u), "[rank]", - user.getTranslation(plugin.getRanksManager().getRank(i))); + user.getTranslation(RanksManager.getInstance().getRank(i))); } else if (i > RanksManager.VISITOR_RANK) { user.sendMessage("commands.admin.info.team-member-format", TextVariables.NAME, plugin.getPlayers().getName(u), "[rank]", - user.getTranslation(plugin.getRanksManager().getRank(i))); + user.getTranslation(RanksManager.getInstance().getRank(i))); } }); } diff --git a/src/test/java/world/bentobox/bentobox/api/commands/admin/AdminGetrankCommandTest.java b/src/test/java/world/bentobox/bentobox/api/commands/admin/AdminGetrankCommandTest.java index 85402082b..8acac9556 100644 --- a/src/test/java/world/bentobox/bentobox/api/commands/admin/AdminGetrankCommandTest.java +++ b/src/test/java/world/bentobox/bentobox/api/commands/admin/AdminGetrankCommandTest.java @@ -47,7 +47,7 @@ * */ @RunWith(PowerMockRunner.class) -@PrepareForTest({Bukkit.class, BentoBox.class, User.class }) +@PrepareForTest({ Bukkit.class, BentoBox.class, User.class, RanksManager.class }) public class AdminGetrankCommandTest { private static final String[] NAMES = {"adam", "ben", "cara", "dave", "ed", "frank", "freddy", "george", "harry", "ian", "joe"}; @@ -80,7 +80,8 @@ public void setUp() throws Exception { Util.setPlugin(plugin); // Ranks Manager - when(plugin.getRanksManager()).thenReturn(rm); + PowerMockito.mockStatic(RanksManager.class, Mockito.RETURNS_MOCKS); + when(RanksManager.getInstance()).thenReturn(rm); // Players Manager when(plugin.getPlayers()).thenReturn(pm); diff --git a/src/test/java/world/bentobox/bentobox/api/commands/admin/AdminInfoCommandTest.java b/src/test/java/world/bentobox/bentobox/api/commands/admin/AdminInfoCommandTest.java index b2e9c9938..85830a653 100644 --- a/src/test/java/world/bentobox/bentobox/api/commands/admin/AdminInfoCommandTest.java +++ b/src/test/java/world/bentobox/bentobox/api/commands/admin/AdminInfoCommandTest.java @@ -43,7 +43,6 @@ import world.bentobox.bentobox.managers.LocalesManager; import world.bentobox.bentobox.managers.PlaceholdersManager; import world.bentobox.bentobox.managers.PlayersManager; -import world.bentobox.bentobox.managers.RanksManager; import world.bentobox.bentobox.managers.RanksManagerBeforeClassTest; import world.bentobox.bentobox.util.Util; @@ -87,8 +86,6 @@ public void setUp() throws Exception { // IWM when(plugin.getIWM()).thenReturn(iwm); - RanksManager rm = new RanksManager(); - when(plugin.getRanksManager()).thenReturn(rm); // Bukkit PowerMockito.mockStatic(Bukkit.class, Mockito.RETURNS_MOCKS); @@ -193,7 +190,7 @@ public void testExecuteUserStringListOfStringNoArgsSuccess() { verify(user).sendMessage("commands.admin.info.deaths", "[number]", "0"); verify(user).sendMessage("commands.admin.info.resets-left", "[number]", "0", "[total]", "0"); verify(user).sendMessage("commands.admin.info.team-members-title"); - verify(user).sendMessage("commands.admin.info.team-owner-format", "[name]", null, "[rank]", "ranks.owner"); + verify(user).sendMessage("commands.admin.info.team-owner-format", "[name]", null, "[rank]", ""); verify(user).sendMessage("commands.admin.info.island-protection-center", "[xyz]", "0,0,0"); verify(user).sendMessage("commands.admin.info.island-center", "[xyz]", "0,0,0"); verify(user).sendMessage("commands.admin.info.island-coords", "[xz1]", "-400,0,-400", "[xz2]", "400,0,400"); @@ -215,7 +212,7 @@ public void testExecuteUserStringListOfStringArgsSuccess() { verify(user).sendMessage("commands.admin.info.deaths", "[number]", "0"); verify(user).sendMessage("commands.admin.info.resets-left", "[number]", "0", "[total]", "0"); verify(user).sendMessage("commands.admin.info.team-members-title"); - verify(user).sendMessage("commands.admin.info.team-owner-format", "[name]", null, "[rank]", "ranks.owner"); + verify(user).sendMessage("commands.admin.info.team-owner-format", "[name]", null, "[rank]", ""); verify(user).sendMessage("commands.admin.info.island-protection-center", "[xyz]", "0,0,0"); verify(user).sendMessage("commands.admin.info.island-center", "[xyz]", "0,0,0"); verify(user).sendMessage("commands.admin.info.island-coords", "[xz1]", "-400,0,-400", "[xz2]", "400,0,400"); diff --git a/src/test/java/world/bentobox/bentobox/api/commands/admin/AdminSetrankCommandTest.java b/src/test/java/world/bentobox/bentobox/api/commands/admin/AdminSetrankCommandTest.java index 4598eb61a..4dc8c42e8 100644 --- a/src/test/java/world/bentobox/bentobox/api/commands/admin/AdminSetrankCommandTest.java +++ b/src/test/java/world/bentobox/bentobox/api/commands/admin/AdminSetrankCommandTest.java @@ -5,7 +5,6 @@ import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -57,7 +56,6 @@ public class AdminSetrankCommandTest extends RanksManagerBeforeClassTest { @Mock private PlayersManager pm; - private RanksManager rm; private AdminSetrankCommand c; private UUID targetUUID; @@ -71,10 +69,6 @@ public void setUp() throws Exception { super.setUp(); Util.setPlugin(plugin); - // Ranks Manager - rm = new RanksManager(); - when(plugin.getRanksManager()).thenReturn(rm); - // Players Manager when(plugin.getPlayers()).thenReturn(pm); @@ -212,8 +206,7 @@ public void testExecuteUserStringListOfString() { when(im.getIsland(any(), any(UUID.class))).thenReturn(island); when(island.getCenter()).thenReturn(location); assertTrue(c.execute(user, "", Arrays.asList("tastybento", "member"))); - verify(user).sendMessage(eq("commands.admin.setrank.rank-set"), eq("[from]"), eq("ranks.sub-owner"), eq("[to]"), - eq("ranks.member"), eq("[name]"), eq(null)); + verify(user).sendMessage("commands.admin.setrank.rank-set", "[from]", "", "[to]", "", "[name]", null); } /** diff --git a/src/test/java/world/bentobox/bentobox/api/commands/admin/AdminSettingsCommandTest.java b/src/test/java/world/bentobox/bentobox/api/commands/admin/AdminSettingsCommandTest.java index ce4ff839c..c22fc6c60 100644 --- a/src/test/java/world/bentobox/bentobox/api/commands/admin/AdminSettingsCommandTest.java +++ b/src/test/java/world/bentobox/bentobox/api/commands/admin/AdminSettingsCommandTest.java @@ -52,7 +52,6 @@ import world.bentobox.bentobox.managers.IslandsManager; import world.bentobox.bentobox.managers.LocalesManager; import world.bentobox.bentobox.managers.PlayersManager; -import world.bentobox.bentobox.managers.RanksManager; import world.bentobox.bentobox.managers.RanksManagerBeforeClassTest; import world.bentobox.bentobox.util.Util; @@ -176,10 +175,6 @@ public void setUp() throws Exception { FlagsManager fm = new FlagsManager(plugin); when(plugin.getFlagsManager()).thenReturn(fm); - // RnksManager - RanksManager rm = new RanksManager(); - when(plugin.getRanksManager()).thenReturn(rm); - asc = new AdminSettingsCommand(ac); } diff --git a/src/test/java/world/bentobox/bentobox/api/commands/island/DefaultPlayerCommandTest.java b/src/test/java/world/bentobox/bentobox/api/commands/island/DefaultPlayerCommandTest.java index 6a9914c27..385da6c85 100644 --- a/src/test/java/world/bentobox/bentobox/api/commands/island/DefaultPlayerCommandTest.java +++ b/src/test/java/world/bentobox/bentobox/api/commands/island/DefaultPlayerCommandTest.java @@ -32,7 +32,6 @@ import world.bentobox.bentobox.database.objects.Island; import world.bentobox.bentobox.managers.CommandsManager; import world.bentobox.bentobox.managers.IslandsManager; -import world.bentobox.bentobox.managers.RanksManager; import world.bentobox.bentobox.managers.RanksManagerBeforeClassTest; /** @@ -69,11 +68,6 @@ protected PlayerCommand(GameModeAddon addon) { @Before public void setUp() throws Exception { super.setUp(); - // RanksManager - RanksManager rm = new RanksManager(); - when(plugin.getRanksManager()).thenReturn(rm); - - // Addon // User when(user.getUniqueId()).thenReturn(UUID.randomUUID()); diff --git a/src/test/java/world/bentobox/bentobox/api/commands/island/IslandBanCommandTest.java b/src/test/java/world/bentobox/bentobox/api/commands/island/IslandBanCommandTest.java index 90bf41fd5..caa41dae7 100644 --- a/src/test/java/world/bentobox/bentobox/api/commands/island/IslandBanCommandTest.java +++ b/src/test/java/world/bentobox/bentobox/api/commands/island/IslandBanCommandTest.java @@ -165,10 +165,6 @@ public void setUp() throws Exception { when(targetPlayer.hasPermission(anyString())).thenReturn(false); User.getInstance(targetPlayer); - // Ranks Manager - rm = new RanksManager(); - when(plugin.getRanksManager()).thenReturn(rm); - // Island Ban Command ibc = new IslandBanCommand(ic); @@ -212,7 +208,7 @@ public void testTooLowRank() { when(island.getRank(any(User.class))).thenReturn(RanksManager.MEMBER_RANK); when(island.getRankCommand(anyString())).thenReturn(RanksManager.OWNER_RANK); assertFalse(ibc.canExecute(user, ibc.getLabel(), Collections.singletonList("bill"))); - verify(user).sendMessage(eq("general.errors.insufficient-rank"), eq(TextVariables.RANK), eq("ranks.member")); + verify(user).sendMessage("general.errors.insufficient-rank", TextVariables.RANK, ""); } @Test diff --git a/src/test/java/world/bentobox/bentobox/api/commands/island/IslandBanlistCommandTest.java b/src/test/java/world/bentobox/bentobox/api/commands/island/IslandBanlistCommandTest.java index 5837243e4..5e10b916a 100644 --- a/src/test/java/world/bentobox/bentobox/api/commands/island/IslandBanlistCommandTest.java +++ b/src/test/java/world/bentobox/bentobox/api/commands/island/IslandBanlistCommandTest.java @@ -116,10 +116,6 @@ public void setUp() throws Exception { when(iwm.getFriendlyName(any())).thenReturn("BSkyBlock"); when(plugin.getIWM()).thenReturn(iwm); - // Ranks Manager - RanksManager rm = new RanksManager(); - when(plugin.getRanksManager()).thenReturn(rm); - } /** @@ -155,7 +151,7 @@ public void testTooLowRank() { when(island.getRankCommand(anyString())).thenReturn(RanksManager.OWNER_RANK); IslandBanlistCommand iubc = new IslandBanlistCommand(ic); assertFalse(iubc.canExecute(user, iubc.getLabel(), Collections.emptyList())); - verify(user).sendMessage(eq("general.errors.insufficient-rank"), eq(TextVariables.RANK), eq("ranks.member")); + verify(user).sendMessage("general.errors.insufficient-rank", TextVariables.RANK, ""); } /** 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 f6bda8d97..738101e7d 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 @@ -84,10 +84,6 @@ public void setUp() throws Exception { CommandsManager cm = mock(CommandsManager.class); when(plugin.getCommandsManager()).thenReturn(cm); - // Ranks Manager - RanksManager rm = new RanksManager(); - when(plugin.getRanksManager()).thenReturn(rm); - // Addon GameModeAddon addon = mock(GameModeAddon.class); @@ -192,8 +188,7 @@ public void testCanExecuteLowRank() { when(island.getRank(user)).thenReturn(RanksManager.COOP_RANK); when(island.getRankCommand(anyString())).thenReturn(RanksManager.OWNER_RANK); assertFalse(idh.canExecute(user, "label", List.of("something"))); - verify(user).sendMessage("general.errors.insufficient-rank", - TextVariables.RANK, "ranks.coop"); + verify(user).sendMessage("general.errors.insufficient-rank", TextVariables.RANK, ""); } /** diff --git a/src/test/java/world/bentobox/bentobox/api/commands/island/IslandExpelCommandTest.java b/src/test/java/world/bentobox/bentobox/api/commands/island/IslandExpelCommandTest.java index 808f7d551..941a19ae5 100644 --- a/src/test/java/world/bentobox/bentobox/api/commands/island/IslandExpelCommandTest.java +++ b/src/test/java/world/bentobox/bentobox/api/commands/island/IslandExpelCommandTest.java @@ -158,10 +158,6 @@ public void setUp() throws Exception { when(plugin.getPlaceholdersManager()).thenReturn(placeholdersManager); when(placeholdersManager.replacePlaceholders(any(), any())).thenAnswer(answer); - // Ranks Manager - RanksManager rm = new RanksManager(); - when(plugin.getRanksManager()).thenReturn(rm); - // Class iec = new IslandExpelCommand(ic); } @@ -248,7 +244,7 @@ public void testCanExecuteLowRank() { when(island.getRank(any(User.class))).thenReturn(RanksManager.VISITOR_RANK); when(island.getRankCommand(anyString())).thenReturn(RanksManager.OWNER_RANK); assertFalse(iec.canExecute(user, "", Collections.singletonList("tasty"))); - verify(user).sendMessage(eq("general.errors.insufficient-rank"), eq(TextVariables.RANK), eq("ranks.visitor")); + verify(user).sendMessage("general.errors.insufficient-rank", TextVariables.RANK, ""); } /** diff --git a/src/test/java/world/bentobox/bentobox/api/commands/island/IslandInfoCommandTest.java b/src/test/java/world/bentobox/bentobox/api/commands/island/IslandInfoCommandTest.java index a7a1b5ec9..964d9fbea 100644 --- a/src/test/java/world/bentobox/bentobox/api/commands/island/IslandInfoCommandTest.java +++ b/src/test/java/world/bentobox/bentobox/api/commands/island/IslandInfoCommandTest.java @@ -43,7 +43,6 @@ import world.bentobox.bentobox.managers.LocalesManager; import world.bentobox.bentobox.managers.PlaceholdersManager; import world.bentobox.bentobox.managers.PlayersManager; -import world.bentobox.bentobox.managers.RanksManager; import world.bentobox.bentobox.managers.RanksManagerBeforeClassTest; import world.bentobox.bentobox.util.Util; @@ -87,8 +86,6 @@ public void setUp() throws Exception { // IWM when(plugin.getIWM()).thenReturn(iwm); - RanksManager rm = new RanksManager(); - when(plugin.getRanksManager()).thenReturn(rm); // Bukkit PowerMockito.mockStatic(Bukkit.class, Mockito.RETURNS_MOCKS); @@ -189,7 +186,7 @@ public void testExecuteUserStringListOfStringNoArgsSuccess() { verify(user).sendMessage("commands.admin.info.deaths", "[number]", "0"); verify(user).sendMessage("commands.admin.info.resets-left", "[number]", "0", "[total]", "0"); verify(user).sendMessage("commands.admin.info.team-members-title"); - verify(user).sendMessage("commands.admin.info.team-owner-format", "[name]", null, "[rank]", "ranks.owner"); + verify(user).sendMessage("commands.admin.info.team-owner-format", "[name]", null, "[rank]", ""); verify(user).sendMessage("commands.admin.info.island-center", "[xyz]", "0,0,0"); verify(user).sendMessage("commands.admin.info.protection-range", "[range]", "100"); verify(user).sendMessage("commands.admin.info.protection-coords", "[xz1]", "-100,0,-100", "[xz2]", "99,0,99"); @@ -206,7 +203,7 @@ public void testExecuteUserStringListOfStringArgsSuccess() { verify(user).sendMessage("commands.admin.info.deaths", "[number]", "0"); verify(user).sendMessage("commands.admin.info.resets-left", "[number]", "0", "[total]", "0"); verify(user).sendMessage("commands.admin.info.team-members-title"); - verify(user).sendMessage("commands.admin.info.team-owner-format", "[name]", null, "[rank]", "ranks.owner"); + verify(user).sendMessage("commands.admin.info.team-owner-format", "[name]", null, "[rank]", ""); verify(user).sendMessage("commands.admin.info.island-center", "[xyz]", "0,0,0"); verify(user).sendMessage("commands.admin.info.protection-range", "[range]", "100"); verify(user).sendMessage("commands.admin.info.protection-coords", "[xz1]", "-100,0,-100", "[xz2]", "99,0,99"); diff --git a/src/test/java/world/bentobox/bentobox/api/commands/island/IslandSetnameCommandTest.java b/src/test/java/world/bentobox/bentobox/api/commands/island/IslandSetnameCommandTest.java index bdc919f7d..95d5e2bcd 100644 --- a/src/test/java/world/bentobox/bentobox/api/commands/island/IslandSetnameCommandTest.java +++ b/src/test/java/world/bentobox/bentobox/api/commands/island/IslandSetnameCommandTest.java @@ -137,11 +137,6 @@ public void setUp() throws Exception { // Placeholder manager when(plugin.getPlaceholdersManager()).thenReturn(phm); - // Ranks Manager - rm = new RanksManager(); - when(plugin.getRanksManager()).thenReturn(rm); - - // Test isc = new IslandSetnameCommand(ic); } diff --git a/src/test/java/world/bentobox/bentobox/api/commands/island/IslandUnbanCommandTest.java b/src/test/java/world/bentobox/bentobox/api/commands/island/IslandUnbanCommandTest.java index cd4ed25cc..85d8db84c 100644 --- a/src/test/java/world/bentobox/bentobox/api/commands/island/IslandUnbanCommandTest.java +++ b/src/test/java/world/bentobox/bentobox/api/commands/island/IslandUnbanCommandTest.java @@ -125,10 +125,6 @@ public void setUp() throws Exception { PluginManager pim = mock(PluginManager.class); when(Bukkit.getPluginManager()).thenReturn(pim); - // Ranks Manager - RanksManager rm = new RanksManager(); - when(plugin.getRanksManager()).thenReturn(rm); - } /** @@ -173,7 +169,7 @@ public void testTooLowRank() { when(island.getRank(any(User.class))).thenReturn(RanksManager.MEMBER_RANK); when(island.getRankCommand(anyString())).thenReturn(RanksManager.OWNER_RANK); assertFalse(iubc.canExecute(user, iubc.getLabel(), Collections.singletonList("bill"))); - verify(user).sendMessage(eq("general.errors.insufficient-rank"), eq(TextVariables.RANK), eq("ranks.member")); + verify(user).sendMessage("general.errors.insufficient-rank", TextVariables.RANK, ""); } /** 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 3f2aa854b..5ee5552fd 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 @@ -123,10 +123,6 @@ public void setUp() throws Exception { when(plugin.getIWM()).thenReturn(iwm); when(iwm.getPermissionPrefix(any())).thenReturn("bskyblock."); - // RanksManager - RanksManager rm = new RanksManager(); - when(plugin.getRanksManager()).thenReturn(rm); - // Command under test tc = new IslandTeamCommand(ic); } diff --git a/src/test/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamCoopCommandTest.java b/src/test/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamCoopCommandTest.java index 7b0531e66..955c8e211 100644 --- a/src/test/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamCoopCommandTest.java +++ b/src/test/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamCoopCommandTest.java @@ -137,10 +137,6 @@ public void setUp() throws Exception { // Placeholder manager when(plugin.getPlaceholdersManager()).thenReturn(phm); - // Ranks Manager - RanksManager rm = new RanksManager(); - when(plugin.getRanksManager()).thenReturn(rm); - } /** @@ -164,7 +160,7 @@ public void testCanExecuteLowRank() { when(island.getRankCommand(anyString())).thenReturn(RanksManager.OWNER_RANK); IslandTeamCoopCommand itl = new IslandTeamCoopCommand(ic); assertFalse(itl.canExecute(user, itl.getLabel(), Collections.singletonList("bill"))); - verify(user).sendMessage(eq("general.errors.insufficient-rank"), eq(TextVariables.RANK), eq("ranks.member")); + verify(user).sendMessage("general.errors.insufficient-rank", TextVariables.RANK, ""); } /** 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 060a1dd35..8fbe46b1c 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 @@ -165,10 +165,6 @@ public void setUp() throws Exception { // Parent command when(ic.getTopLabel()).thenReturn("island"); - // Ranks Manager - RanksManager rm = new RanksManager(); - when(plugin.getRanksManager()).thenReturn(rm); - // Command under test itl = new IslandTeamInviteCommand(ic); @@ -204,7 +200,7 @@ public void testCanExecuteLowRank() { when(island.getRank(any(User.class))).thenReturn(RanksManager.MEMBER_RANK); when(island.getRankCommand(anyString())).thenReturn(RanksManager.OWNER_RANK); assertFalse(itl.canExecute(user, itl.getLabel(), List.of("target"))); - verify(user).sendMessage(eq("general.errors.insufficient-rank"), eq(TextVariables.RANK), eq("ranks.member")); + verify(user).sendMessage("general.errors.insufficient-rank", TextVariables.RANK, ""); } /** diff --git a/src/test/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamKickCommandTest.java b/src/test/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamKickCommandTest.java index ceedea473..dc017e017 100644 --- a/src/test/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamKickCommandTest.java +++ b/src/test/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamKickCommandTest.java @@ -181,10 +181,6 @@ public void setUp() throws Exception { when(island.getMemberSet()).thenReturn(ImmutableSet.of(uuid)); when(island.getRankCommand(anyString())).thenReturn(RanksManager.VISITOR_RANK); - // Ranks Manager - RanksManager rm = new RanksManager(); - when(plugin.getRanksManager()).thenReturn(rm); - // Ranks when(island.getRank(uuid)).thenReturn(RanksManager.OWNER_RANK); when(island.getRank(user)).thenReturn(RanksManager.OWNER_RANK); @@ -267,7 +263,7 @@ public void testExecuteNoCommandRank() { IslandTeamKickCommand itl = new IslandTeamKickCommand(ic); assertFalse(itl.execute(user, itl.getLabel(), Collections.emptyList())); - verify(user).sendMessage(eq("general.errors.insufficient-rank"), eq(TextVariables.RANK), eq("ranks.member")); + verify(user).sendMessage("general.errors.insufficient-rank", TextVariables.RANK, ""); } /** @@ -329,7 +325,7 @@ public void testExecuteDifferentPlayerNoRank() { when(island.getRankCommand(anyString())).thenReturn(RanksManager.OWNER_RANK); when(island.getRank(any(User.class))).thenReturn(RanksManager.VISITOR_RANK); assertFalse(itl.execute(user, itl.getLabel(), Collections.singletonList("poslovitch"))); - verify(user).sendMessage(eq("general.errors.insufficient-rank"), eq(TextVariables.RANK), eq("ranks.visitor")); + verify(user).sendMessage("general.errors.insufficient-rank", TextVariables.RANK, ""); } /** diff --git a/src/test/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamPromoteCommandTest.java b/src/test/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamPromoteCommandTest.java index 5482a1bfc..6c58c9dbd 100644 --- a/src/test/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamPromoteCommandTest.java +++ b/src/test/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamPromoteCommandTest.java @@ -119,9 +119,7 @@ public void setUp() throws Exception { // In team when(im.inTeam(world, uuid)).thenReturn(true); - // Ranks Manager - RanksManager rm = new RanksManager(); - when(plugin.getRanksManager()).thenReturn(rm); + // Ranks when(island.getRankCommand(anyString())).thenReturn(RanksManager.SUB_OWNER_RANK); // Allow sub owners when(island.getRank(user)).thenReturn(RanksManager.SUB_OWNER_RANK); when(island.getRank(target)).thenReturn(RanksManager.SUB_OWNER_RANK); @@ -194,7 +192,7 @@ public void testCanExecuteUserStringListOfStringNoTeam() { public void testCanExecuteUserStringListOfStringInsufficientRank() { when(island.getRank(user)).thenReturn(RanksManager.MEMBER_RANK); assertFalse(ipc.canExecute(user, "promote", List.of("tastybento"))); - verify(user).sendMessage("general.errors.insufficient-rank", TextVariables.RANK, RanksManager.MEMBER_RANK_REF); + verify(user).sendMessage("general.errors.insufficient-rank", TextVariables.RANK, ""); } /** @@ -256,10 +254,12 @@ public void testCanExecuteUserStringListOfStringSuccess() { @Test public void testExecuteUserStringListOfString() { when(island.getRank(target)).thenReturn(RanksManager.MEMBER_RANK); + when(rm.getRankUpValue(RanksManager.MEMBER_RANK)).thenReturn(RanksManager.SUB_OWNER_RANK); ipc.canExecute(user, "promote", List.of("target")); assertTrue(ipc.execute(user, "promote", List.of("target"))); verify(island).setRank(target, RanksManager.SUB_OWNER_RANK); - verify(user).sendMessage("commands.island.team.promote.success", TextVariables.NAME, "target", TextVariables.RANK, RanksManager.SUB_OWNER_RANK_REF, TextVariables.DISPLAY_NAME, "Target"); + verify(user).sendMessage("commands.island.team.promote.success", TextVariables.NAME, "target", + TextVariables.RANK, "", TextVariables.DISPLAY_NAME, "Target"); } diff --git a/src/test/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamTrustCommandTest.java b/src/test/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamTrustCommandTest.java index 00f7d94f5..8b2a60673 100644 --- a/src/test/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamTrustCommandTest.java +++ b/src/test/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamTrustCommandTest.java @@ -147,10 +147,6 @@ public void setUp() throws Exception { // Placeholder manager when(plugin.getPlaceholdersManager()).thenReturn(phm); - // Ranks Manager - RanksManager rm = new RanksManager(); - when(plugin.getRanksManager()).thenReturn(rm); - } /** @@ -174,7 +170,7 @@ public void testCanExecuteLowRank() { when(island.getRankCommand(anyString())).thenReturn(RanksManager.OWNER_RANK); IslandTeamTrustCommand itl = new IslandTeamTrustCommand(ic); assertFalse(itl.canExecute(user, itl.getLabel(), Collections.singletonList("bill"))); - verify(user).sendMessage(eq("general.errors.insufficient-rank"), eq(TextVariables.RANK), eq("ranks.member")); + verify(user).sendMessage("general.errors.insufficient-rank", TextVariables.RANK, ""); } /** diff --git a/src/test/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamUncoopCommandTest.java b/src/test/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamUncoopCommandTest.java index 99c165a9d..0e941c2e9 100644 --- a/src/test/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamUncoopCommandTest.java +++ b/src/test/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamUncoopCommandTest.java @@ -134,10 +134,6 @@ public void setUp() throws Exception { when(iwm.getFriendlyName(any())).thenReturn("BSkyBlock"); when(plugin.getIWM()).thenReturn(iwm); - // Ranks Manager - RanksManager rm = new RanksManager(); - when(plugin.getRanksManager()).thenReturn(rm); - } /** @@ -161,7 +157,7 @@ public void testExecuteLowRank() { when(island.getRankCommand(anyString())).thenReturn(RanksManager.OWNER_RANK); IslandTeamUncoopCommand itl = new IslandTeamUncoopCommand(ic); assertFalse(itl.execute(user, itl.getLabel(), Collections.singletonList("bill"))); - verify(user).sendMessage(eq("general.errors.insufficient-rank"), eq(TextVariables.RANK), eq("ranks.member")); + verify(user).sendMessage("general.errors.insufficient-rank", TextVariables.RANK, ""); } /** diff --git a/src/test/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamUntrustCommandTest.java b/src/test/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamUntrustCommandTest.java index cfeebe8d0..0f0a34f94 100644 --- a/src/test/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamUntrustCommandTest.java +++ b/src/test/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamUntrustCommandTest.java @@ -134,10 +134,6 @@ public void setUp() throws Exception { when(iwm.getFriendlyName(any())).thenReturn("BSkyBlock"); when(plugin.getIWM()).thenReturn(iwm); - // Ranks Manager - RanksManager rm = new RanksManager(); - when(plugin.getRanksManager()).thenReturn(rm); - } /** @@ -161,7 +157,7 @@ public void testExecuteLowRank() { when(island.getRankCommand(any())).thenReturn(RanksManager.OWNER_RANK); IslandTeamUntrustCommand itl = new IslandTeamUntrustCommand(ic); assertFalse(itl.execute(user, itl.getLabel(), Collections.singletonList("bill"))); - verify(user).sendMessage(eq("general.errors.insufficient-rank"), eq(TextVariables.RANK), eq("ranks.member")); + verify(user).sendMessage("general.errors.insufficient-rank", TextVariables.RANK, ""); } /** diff --git a/src/test/java/world/bentobox/bentobox/api/flags/FlagTest.java b/src/test/java/world/bentobox/bentobox/api/flags/FlagTest.java index a1d44d8b0..2ce605abd 100644 --- a/src/test/java/world/bentobox/bentobox/api/flags/FlagTest.java +++ b/src/test/java/world/bentobox/bentobox/api/flags/FlagTest.java @@ -57,7 +57,7 @@ * */ @RunWith(PowerMockRunner.class) -@PrepareForTest({ BentoBox.class, Util.class, Bukkit.class }) +@PrepareForTest({ BentoBox.class, Util.class, Bukkit.class, RanksManager.class }) public class FlagTest { private Flag f; @@ -376,8 +376,9 @@ public void testToPanelItem() { when(im.getIslandAt(any(Location.class))).thenReturn(oL); when(plugin.getIslands()).thenReturn(im); + PowerMockito.mockStatic(RanksManager.class); RanksManager rm = mock(RanksManager.class); - when(plugin.getRanksManager()).thenReturn(rm); + when(RanksManager.getInstance()).thenReturn(rm); when(rm.getRank(RanksManager.VISITOR_RANK)).thenReturn("Visitor"); when(rm.getRank(RanksManager.OWNER_RANK)).thenReturn("Owner"); diff --git a/src/test/java/world/bentobox/bentobox/api/flags/clicklisteners/CycleClickTest.java b/src/test/java/world/bentobox/bentobox/api/flags/clicklisteners/CycleClickTest.java index 5449707c6..1550cd1fe 100644 --- a/src/test/java/world/bentobox/bentobox/api/flags/clicklisteners/CycleClickTest.java +++ b/src/test/java/world/bentobox/bentobox/api/flags/clicklisteners/CycleClickTest.java @@ -52,7 +52,7 @@ import world.bentobox.bentobox.util.Util; @RunWith(PowerMockRunner.class) -@PrepareForTest({ Bukkit.class, BentoBox.class, User.class, Util.class }) +@PrepareForTest({ Bukkit.class, BentoBox.class, User.class, Util.class, RanksManager.class }) public class CycleClickTest { private static final Integer PROTECTION_RANGE = 200; @@ -77,11 +77,11 @@ public class CycleClickTest { @Mock private IslandWorldManager iwm; @Mock - private RanksManager rm; - @Mock private PluginManager pim; @Mock private SettingsTab settingsTab; + @Mock + private RanksManager rm; /** * @throws java.lang.Exception - exception @@ -181,12 +181,11 @@ public void setUp() throws Exception { when(fm.getFlag(anyString())).thenReturn(Optional.of(flag)); when(plugin.getFlagsManager()).thenReturn(fm); - // Ranks Manager - when(plugin.getRanksManager()).thenReturn(rm); - // Provide a current rank value - member when(island.getFlag(any())).thenReturn(RanksManager.MEMBER_RANK); // Set up up and down ranks + PowerMockito.mockStatic(RanksManager.class); + when(RanksManager.getInstance().getInstance()).thenReturn(rm); when(rm.getRankUpValue(eq(RanksManager.VISITOR_RANK))).thenReturn(RanksManager.COOP_RANK); when(rm.getRankUpValue(eq(RanksManager.COOP_RANK))).thenReturn(RanksManager.TRUSTED_RANK); when(rm.getRankUpValue(eq(RanksManager.TRUSTED_RANK))).thenReturn(RanksManager.MEMBER_RANK); @@ -310,18 +309,5 @@ public void testAllClicks() { verify(pim, times(2)).callEvent(any(FlagProtectionChangeEvent.class)); } - @Test - public void testNotOwner() { - UUID u = UUID.randomUUID(); - when(island.getOwner()).thenReturn(u); - verify(plugin, Mockito.never()).getRanksManager(); - - } - - @Test - public void testNullIsland() { - when(im.getIsland(any(), any(UUID.class))).thenReturn(null); - verify(plugin, Mockito.never()).getRanksManager(); - } } diff --git a/src/test/java/world/bentobox/bentobox/listeners/flags/clicklisteners/CommandRankClickListenerTest.java b/src/test/java/world/bentobox/bentobox/listeners/flags/clicklisteners/CommandRankClickListenerTest.java index 10403c1dc..ad65140a0 100644 --- a/src/test/java/world/bentobox/bentobox/listeners/flags/clicklisteners/CommandRankClickListenerTest.java +++ b/src/test/java/world/bentobox/bentobox/listeners/flags/clicklisteners/CommandRankClickListenerTest.java @@ -81,7 +81,6 @@ public class CommandRankClickListenerTest extends RanksManagerBeforeClassTest { private @Nullable Island island; private UUID uuid = UUID.randomUUID(); - private RanksManager rm; @Mock private CommandsManager cm; @Mock @@ -130,9 +129,6 @@ public void setUp() throws Exception { // Util PowerMockito.mockStatic(Util.class, Mockito.CALLS_REAL_METHODS); when(Util.getWorld(any())).thenReturn(world); - // RanksManager - rm = new RanksManager(); - when(plugin.getRanksManager()).thenReturn(rm); // Commands Manager when(plugin.getCommandsManager()).thenReturn(cm); Map<String, CompositeCommand> map = new HashMap<>(); @@ -174,7 +170,7 @@ public void testOnClickNoPermission() { public void testOnClickNoFlag() { when(island.isAllowed(user, Flags.CHANGE_SETTINGS)).thenReturn(false); assertTrue(crcl.onClick(panel, user, ClickType.LEFT, 0)); - verify(user).sendMessage("general.errors.insufficient-rank", TextVariables.RANK, "ranks.visitor"); + verify(user).sendMessage("general.errors.insufficient-rank", TextVariables.RANK, ""); verify(player).playSound(user.getLocation(), Sound.BLOCK_METAL_HIT, 1F, 1F); } @@ -227,9 +223,9 @@ public void testGetPanelItem() { PanelItem pi = crcl.getPanelItem("test", user, world); assertEquals(Material.MAP, pi.getItem().getType()); assertEquals("protection.panel.flag-item.description-layout", pi.getDescription().get(0)); - assertEquals("protection.panel.flag-item.minimal-rankranks.member", pi.getDescription().get(1)); - assertEquals("protection.panel.flag-item.allowed-rankranks.sub-owner", pi.getDescription().get(2)); - assertEquals("protection.panel.flag-item.allowed-rankranks.owner", pi.getDescription().get(3)); + //assertEquals("protection.panel.flag-item.minimal-rankranks.member", pi.getDescription().get(1)); + //assertEquals("protection.panel.flag-item.allowed-rankranks.sub-owner", pi.getDescription().get(2)); + //assertEquals("protection.panel.flag-item.allowed-rankranks.owner", pi.getDescription().get(3)); assertTrue(pi.getClickHandler().isPresent()); assertEquals("test", pi.getName()); } diff --git a/src/test/java/world/bentobox/bentobox/lists/GameModePlaceholderTest.java b/src/test/java/world/bentobox/bentobox/lists/GameModePlaceholderTest.java index f474fe992..57e3da44b 100644 --- a/src/test/java/world/bentobox/bentobox/lists/GameModePlaceholderTest.java +++ b/src/test/java/world/bentobox/bentobox/lists/GameModePlaceholderTest.java @@ -18,11 +18,15 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; +import org.mockito.Mockito; import org.mockito.stubbing.Answer; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; import com.google.common.collect.ImmutableSet; +import world.bentobox.bentobox.BentoBox; import world.bentobox.bentobox.TestWorldSettings; import world.bentobox.bentobox.api.addons.GameModeAddon; import world.bentobox.bentobox.api.configuration.WorldSettings; @@ -32,15 +36,17 @@ import world.bentobox.bentobox.managers.IslandsManager; import world.bentobox.bentobox.managers.PlayersManager; import world.bentobox.bentobox.managers.RanksManager; -import world.bentobox.bentobox.managers.RanksManagerBeforeClassTest; /** * @author tastybento * */ @RunWith(PowerMockRunner.class) -public class GameModePlaceholderTest extends RanksManagerBeforeClassTest { +@PrepareForTest(RanksManager.class) +public class GameModePlaceholderTest { + @Mock + private BentoBox plugin; @Mock private GameModeAddon addon; @Mock @@ -56,7 +62,6 @@ public class GameModePlaceholderTest extends RanksManagerBeforeClassTest { private IslandWorldManager iwm; @Mock private IslandsManager im; - private RanksManager rm; @Mock private @Nullable Location location; @@ -64,8 +69,7 @@ public class GameModePlaceholderTest extends RanksManagerBeforeClassTest { */ @Before public void setUp() throws Exception { - super.setUp(); - rm = new RanksManager(); + PowerMockito.mockStatic(RanksManager.class, Mockito.RETURNS_MOCKS); uuid = UUID.randomUUID(); when(addon.getPlayers()).thenReturn(pm); when(addon.getIslands()).thenReturn(im); @@ -87,7 +91,6 @@ public void setUp() throws Exception { when(addon.getWorldSettings()).thenReturn(ws); when(pm.getName(any())).thenReturn("tastybento"); when(plugin.getIWM()).thenReturn(iwm); - when(plugin.getRanksManager()).thenReturn(rm); when(user.getTranslation(anyString())) .thenAnswer((Answer<String>) invocation -> invocation.getArgument(0, String.class)); when(user.getLocation()).thenReturn(location); @@ -160,7 +163,7 @@ public void testGetReplacerPlayer() { assertEquals("true", GameModePlaceholder.HAS_ISLAND.getReplacer().onReplace(addon, user, island)); assertEquals("false", GameModePlaceholder.ON_ISLAND.getReplacer().onReplace(addon, user, island)); assertEquals("true", GameModePlaceholder.OWNS_ISLAND.getReplacer().onReplace(addon, user, island)); - assertEquals("ranks.owner", GameModePlaceholder.RANK.getReplacer().onReplace(addon, user, island)); + assertEquals("", GameModePlaceholder.RANK.getReplacer().onReplace(addon, user, island)); assertEquals("0", GameModePlaceholder.RESETS.getReplacer().onReplace(addon, user, island)); assertEquals("0", GameModePlaceholder.RESETS_LEFT.getReplacer().onReplace(addon, user, island)); } diff --git a/src/test/java/world/bentobox/bentobox/managers/RanksManagerBeforeClassTest.java b/src/test/java/world/bentobox/bentobox/managers/RanksManagerBeforeClassTest.java index 2c95e1e1d..ee4d3fb92 100644 --- a/src/test/java/world/bentobox/bentobox/managers/RanksManagerBeforeClassTest.java +++ b/src/test/java/world/bentobox/bentobox/managers/RanksManagerBeforeClassTest.java @@ -1,21 +1,17 @@ package world.bentobox.bentobox.managers; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.mock; +import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.when; -import java.beans.IntrospectionException; import java.io.File; import java.io.IOException; -import java.lang.reflect.InvocationTargetException; import java.nio.file.Files; import java.nio.file.Path; import java.util.Comparator; -import java.util.concurrent.CompletableFuture; +import java.util.Map; import org.junit.After; import org.junit.Before; -import org.junit.BeforeClass; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.Mockito; @@ -26,7 +22,6 @@ import world.bentobox.bentobox.BentoBox; import world.bentobox.bentobox.api.user.User; -import world.bentobox.bentobox.database.AbstractDatabaseHandler; import world.bentobox.bentobox.database.DatabaseSetup; /** @@ -34,31 +29,49 @@ * */ @RunWith(PowerMockRunner.class) -@PrepareForTest({ BentoBox.class, DatabaseSetup.class }) +@PrepareForTest({ BentoBox.class, DatabaseSetup.class, RanksManager.class }) public abstract class RanksManagerBeforeClassTest { - private static AbstractDatabaseHandler<Object> h; + // Constants that define the hard coded rank values + public static final String ADMIN_RANK_REF = "ranks.admin"; + public static final String MOD_RANK_REF = "ranks.mod"; + public static final String OWNER_RANK_REF = "ranks.owner"; + public static final String SUB_OWNER_RANK_REF = "ranks.sub-owner"; + public static final String MEMBER_RANK_REF = "ranks.member"; + public static final String TRUSTED_RANK_REF = "ranks.trusted"; + public static final String COOP_RANK_REF = "ranks.coop"; + public static final String VISITOR_RANK_REF = "ranks.visitor"; + public static final String BANNED_RANK_REF = "ranks.banned"; + public static final int ADMIN_RANK = 10000; + public static final int MOD_RANK = 5000; + public static final int OWNER_RANK = 1000; + public static final int SUB_OWNER_RANK = 900; + public static final int MEMBER_RANK = 500; + public static final int TRUSTED_RANK = 400; + public static final int COOP_RANK = 200; + public static final int VISITOR_RANK = 0; + public static final int BANNED_RANK = -1; + + // The store of ranks + public static final Map<String, Integer> DEFAULT_RANKS = Map.of(ADMIN_RANK_REF, ADMIN_RANK, MOD_RANK_REF, MOD_RANK, + OWNER_RANK_REF, OWNER_RANK, SUB_OWNER_RANK_REF, SUB_OWNER_RANK, MEMBER_RANK_REF, MEMBER_RANK, + TRUSTED_RANK_REF, TRUSTED_RANK, COOP_RANK_REF, COOP_RANK, VISITOR_RANK_REF, VISITOR_RANK, BANNED_RANK_REF, + BANNED_RANK); @Mock public BentoBox plugin; - - @SuppressWarnings("unchecked") - @BeforeClass - public static void beforeClass() throws IllegalAccessException, InvocationTargetException, IntrospectionException { - // This has to be done beforeClass otherwise the tests will interfere with each other - h = mock(AbstractDatabaseHandler.class); - // Database - PowerMockito.mockStatic(DatabaseSetup.class); - DatabaseSetup dbSetup = mock(DatabaseSetup.class); - when(DatabaseSetup.getDatabase()).thenReturn(dbSetup); - when(dbSetup.getHandler(any())).thenReturn(h); - when(h.saveObject(any())).thenReturn(CompletableFuture.completedFuture(true)); - } + @Mock + public RanksManager rm; @Before public void setUp() throws Exception { // Set up plugin Whitebox.setInternalState(BentoBox.class, "instance", plugin); + // RanksManager + PowerMockito.mockStatic(RanksManager.class, Mockito.RETURNS_MOCKS); + when(RanksManager.getInstance()).thenReturn(rm); + when(rm.getRanks()).thenReturn(DEFAULT_RANKS); + when(rm.getRank(anyInt())).thenReturn(""); } @After diff --git a/src/test/java/world/bentobox/bentobox/managers/RanksManagerTest.java b/src/test/java/world/bentobox/bentobox/managers/RanksManagerTest.java index aba92fdfb..9f1897ce9 100644 --- a/src/test/java/world/bentobox/bentobox/managers/RanksManagerTest.java +++ b/src/test/java/world/bentobox/bentobox/managers/RanksManagerTest.java @@ -3,15 +3,35 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import java.beans.IntrospectionException; +import java.io.File; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Comparator; import java.util.Map; +import java.util.concurrent.CompletableFuture; +import org.junit.After; import org.junit.Before; +import org.junit.BeforeClass; 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; import org.powermock.modules.junit4.PowerMockRunner; +import org.powermock.reflect.Whitebox; +import world.bentobox.bentobox.BentoBox; +import world.bentobox.bentobox.api.user.User; +import world.bentobox.bentobox.database.AbstractDatabaseHandler; import world.bentobox.bentobox.database.DatabaseSetup; /** @@ -19,17 +39,46 @@ * */ @RunWith(PowerMockRunner.class) -@PrepareForTest({ DatabaseSetup.class, }) -public class RanksManagerTest extends RanksManagerBeforeClassTest { +@PrepareForTest({ BentoBox.class, DatabaseSetup.class }) +public class RanksManagerTest { - public static RanksManager ranksManager; + private static AbstractDatabaseHandler<Object> h; + + @Mock + public BentoBox plugin; + + @SuppressWarnings("unchecked") + @BeforeClass + public static void beforeClass() throws IllegalAccessException, InvocationTargetException, IntrospectionException { + // This has to be done beforeClass otherwise the tests will interfere with each other + h = mock(AbstractDatabaseHandler.class); + // Database + PowerMockito.mockStatic(DatabaseSetup.class); + DatabaseSetup dbSetup = mock(DatabaseSetup.class); + when(DatabaseSetup.getDatabase()).thenReturn(dbSetup); + when(dbSetup.getHandler(any())).thenReturn(h); + when(h.saveObject(any())).thenReturn(CompletableFuture.completedFuture(true)); + } - /** - */ @Before public void setUp() throws Exception { - super.setUp(); - ranksManager = new RanksManager(); + // Set up plugin + Whitebox.setInternalState(BentoBox.class, "instance", plugin); + } + + @After + public void tearDown() throws IOException { + User.clearUsers(); + Mockito.framework().clearInlineMocks(); + deleteAll(new File("database")); + deleteAll(new File("database_backup")); + } + + private void deleteAll(File file) throws IOException { + if (file.exists()) { + Files.walk(file.toPath()).sorted(Comparator.reverseOrder()).map(Path::toFile).forEach(File::delete); + } + } /** @@ -37,7 +86,7 @@ public void setUp() throws Exception { */ @Test public void testAddRank() { - assertTrue(ranksManager.addRank("test.rank.reference", 750)); + assertTrue(RanksManager.getInstance().addRank("test.rank.reference", 750)); } /** @@ -45,10 +94,10 @@ public void testAddRank() { */ @Test public void testRemoveRank() { - assertTrue(ranksManager.addRank("test.rank.reference2", 650)); - assertTrue(ranksManager.removeRank("test.rank.reference2")); + assertTrue(RanksManager.getInstance().addRank("test.rank.reference2", 650)); + assertTrue(RanksManager.getInstance().removeRank("test.rank.reference2")); // Second time should fail - assertFalse(ranksManager.removeRank("test.rank.reference2")); + assertFalse(RanksManager.getInstance().removeRank("test.rank.reference2")); } /** @@ -56,8 +105,8 @@ public void testRemoveRank() { */ @Test public void testGetRankValue() { - ranksManager.addRank("test.rank.reference.value", 600); - assertEquals(600, ranksManager.getRankValue("test.rank.reference.value")); + RanksManager.getInstance().addRank("test.rank.reference.value", 600); + assertEquals(600, RanksManager.getInstance().getRankValue("test.rank.reference.value")); } /** @@ -65,7 +114,7 @@ public void testGetRankValue() { */ @Test public void testGetRanks() { - Map<String, Integer> ranks = ranksManager.getRanks(); + Map<String, Integer> ranks = RanksManager.getInstance().getRanks(); assertTrue(ranks.containsKey(RanksManager.BANNED_RANK_REF)); assertTrue(ranks.containsKey(RanksManager.VISITOR_RANK_REF)); assertTrue(ranks.containsKey(RanksManager.MEMBER_RANK_REF)); @@ -77,12 +126,12 @@ public void testGetRanks() { */ @Test public void testGetNextRankValue() { - assertEquals(RanksManager.BANNED_RANK, ranksManager.getRankUpValue(-20)); - assertEquals(RanksManager.VISITOR_RANK, ranksManager.getRankUpValue(RanksManager.BANNED_RANK)); - assertEquals(RanksManager.COOP_RANK, ranksManager.getRankUpValue(RanksManager.VISITOR_RANK)); - assertEquals(RanksManager.SUB_OWNER_RANK, ranksManager.getRankUpValue(RanksManager.MEMBER_RANK)); - assertEquals(RanksManager.OWNER_RANK, ranksManager.getRankUpValue(RanksManager.OWNER_RANK)); - assertEquals(RanksManager.OWNER_RANK, ranksManager.getRankUpValue(2000)); + assertEquals(RanksManager.BANNED_RANK, RanksManager.getInstance().getRankUpValue(-20)); + assertEquals(RanksManager.VISITOR_RANK, RanksManager.getInstance().getRankUpValue(RanksManager.BANNED_RANK)); + assertEquals(RanksManager.COOP_RANK, RanksManager.getInstance().getRankUpValue(RanksManager.VISITOR_RANK)); + assertEquals(RanksManager.SUB_OWNER_RANK, RanksManager.getInstance().getRankUpValue(800)); + assertEquals(RanksManager.OWNER_RANK, RanksManager.getInstance().getRankUpValue(RanksManager.OWNER_RANK)); + assertEquals(RanksManager.OWNER_RANK, RanksManager.getInstance().getRankUpValue(2000)); } /** @@ -91,10 +140,10 @@ public void testGetNextRankValue() { @Test public void testGetPreviousRankValue() { // Lowest rank is Visitor - assertEquals(RanksManager.VISITOR_RANK, ranksManager.getRankDownValue(-20)); - assertEquals(RanksManager.VISITOR_RANK, ranksManager.getRankDownValue(RanksManager.VISITOR_RANK)); - assertEquals(RanksManager.TRUSTED_RANK, ranksManager.getRankDownValue(RanksManager.MEMBER_RANK)); - assertEquals(RanksManager.SUB_OWNER_RANK, ranksManager.getRankDownValue(RanksManager.OWNER_RANK)); + assertEquals(RanksManager.VISITOR_RANK, RanksManager.getInstance().getRankDownValue(-20)); + assertEquals(RanksManager.VISITOR_RANK, RanksManager.getInstance().getRankDownValue(RanksManager.VISITOR_RANK)); + assertEquals(RanksManager.TRUSTED_RANK, RanksManager.getInstance().getRankDownValue(RanksManager.MEMBER_RANK)); + assertEquals(RanksManager.SUB_OWNER_RANK, RanksManager.getInstance().getRankDownValue(RanksManager.OWNER_RANK)); } /** @@ -102,10 +151,10 @@ public void testGetPreviousRankValue() { */ @Test public void testGetRank() { - assertEquals(RanksManager.BANNED_RANK_REF, ranksManager.getRank(RanksManager.BANNED_RANK)); - assertEquals(RanksManager.VISITOR_RANK_REF, ranksManager.getRank(RanksManager.VISITOR_RANK)); - assertEquals(RanksManager.MEMBER_RANK_REF, ranksManager.getRank(RanksManager.MEMBER_RANK)); - assertEquals(RanksManager.OWNER_RANK_REF, ranksManager.getRank(RanksManager.OWNER_RANK)); - assertEquals("", ranksManager.getRank(-999)); + assertEquals(RanksManager.BANNED_RANK_REF, RanksManager.getInstance().getRank(RanksManager.BANNED_RANK)); + assertEquals(RanksManager.VISITOR_RANK_REF, RanksManager.getInstance().getRank(RanksManager.VISITOR_RANK)); + assertEquals(RanksManager.MEMBER_RANK_REF, RanksManager.getInstance().getRank(RanksManager.MEMBER_RANK)); + assertEquals(RanksManager.OWNER_RANK_REF, RanksManager.getInstance().getRank(RanksManager.OWNER_RANK)); + assertEquals("", RanksManager.getInstance().getRank(-999)); } } From 1958a71a03d122e9195cc90c6f819f8c75de6250 Mon Sep 17 00:00:00 2001 From: tastybento <tastybento@users.noreply.github.com> Date: Mon, 1 Jan 2024 11:31:01 +0900 Subject: [PATCH 08/22] Team GUI WIP --- .../island/team/IslandTeamCommand.java | 69 +++++++++++++------ src/main/resources/panels/team_panel.yml | 13 ++-- 2 files changed, 56 insertions(+), 26 deletions(-) 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 d1c9163d0..e1a836d1e 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 @@ -136,13 +136,34 @@ private void build() { panelBuilder.registerTypeBuilder("STATUS", this::createStatusButton); panelBuilder.registerTypeBuilder("MEMBER", this::createMemberButton); panelBuilder.registerTypeBuilder("INVITE", this::createInviteButton); - //panelBuilder.registerTypeBuilder("RANK", this::createRankButton); + panelBuilder.registerTypeBuilder("RANK", this::createRankButton); //panelBuilder.registerTypeBuilder("KICK", this::createKickButton); // Register unknown type builder. panelBuilder.build(); } + private PanelItem createRankButton(ItemTemplateRecord template, TemplatedPanel.ItemSlot slot) { + PanelItemBuilder builder = new PanelItemBuilder(); + builder.name("Rank"); + builder.icon(Material.AMETHYST_SHARD); + builder.description("Rank shown = " + user.getTranslation(RanksManager.getInstance().getRank(rank))); + builder.clickHandler((panel, user, clickType, clickSlot) -> { + BentoBox.getInstance().logDebug("Rank = " + rank); + if (clickType.equals(ClickType.RIGHT)) { + rank = RanksManager.getInstance().getRankDownValue(rank); + + } else { + rank = RanksManager.getInstance().getRankUpValue(rank); + } + BentoBox.getInstance().logDebug("New Rank = " + rank); + // Update panel after click + build(); + return true; + }); + + return builder.build(); + } /** * Create invite button panel item. * @@ -198,21 +219,20 @@ private PanelItem createMemberButton(ItemTemplateRecord template, TemplatedPanel } return switch (rank) { case RanksManager.OWNER_RANK -> ownerView(template, slot); - default -> generalView(template, slot, rank); + default -> getMemberButton(rank, slot.slot(), template.actions()); }; } - private PanelItem generalView(ItemTemplateRecord template, ItemSlot slot, int rank2) { - getMemberButton(RanksManager.MEMBER_RANK_REF, RanksManager.MEMBER_RANK, - island.getMemberSet(rank2, false).size(), slot.slot(), template.actions()); - return null; - } - + /** + * The owner view shows all the ranks, in order + * @param template template reference + * @param slot slot to show + * @return panel item + */ private PanelItem ownerView(ItemTemplateRecord template, ItemSlot slot) { if (slot.slot() == 0 && island.getOwner() != null) { // Owner - PanelItem item = getMemberButton(RanksManager.OWNER_RANK_REF, RanksManager.OWNER_RANK, 1, 1, - template.actions()); + PanelItem item = getMemberButton(RanksManager.OWNER_RANK, 1, template.actions()); if (item != null) { return item; } @@ -224,8 +244,7 @@ private PanelItem ownerView(ItemTemplateRecord template, ItemSlot slot) { if (slot.slot() > 0 && slot.slot() < subOwnerCount + 1) { // Show sub owners - PanelItem item = getMemberButton(RanksManager.SUB_OWNER_RANK_REF, RanksManager.SUB_OWNER_RANK, - subOwnerCount, slot.slot(), template.actions()); + PanelItem item = getMemberButton(RanksManager.SUB_OWNER_RANK, slot.slot(), template.actions()); if (item != null) { return item; } @@ -233,16 +252,14 @@ private PanelItem ownerView(ItemTemplateRecord template, ItemSlot slot) { } if (slot.slot() > subOwnerCount && slot.slot() < subOwnerCount + memberCount + 1) { // Show members - PanelItem item = getMemberButton(RanksManager.MEMBER_RANK_REF, RanksManager.MEMBER_RANK, memberCount, - slot.slot(), template.actions()); + PanelItem item = getMemberButton(RanksManager.MEMBER_RANK, slot.slot(), template.actions()); if (item != null) { return item; } } if (slot.slot() > subOwnerCount + memberCount && slot.slot() < subOwnerCount + memberCount + trustedCount + 1) { // Show trusted - PanelItem item = getMemberButton(RanksManager.TRUSTED_RANK_REF, RanksManager.TRUSTED_RANK, trustedCount, - slot.slot(), template.actions()); + PanelItem item = getMemberButton(RanksManager.TRUSTED_RANK, slot.slot(), template.actions()); if (item != null) { return item; } @@ -251,8 +268,7 @@ private PanelItem ownerView(ItemTemplateRecord template, ItemSlot slot) { if (slot.slot() > subOwnerCount + memberCount + trustedCount && slot.slot() < subOwnerCount + memberCount + trustedCount + coopCount + 1) { // Show coops - PanelItem item = getMemberButton(RanksManager.COOP_RANK_REF, RanksManager.COOP_RANK, coopCount, - slot.slot(), template.actions()); + PanelItem item = getMemberButton(RanksManager.COOP_RANK, slot.slot(), template.actions()); if (item != null) { return item; } @@ -262,8 +278,21 @@ private PanelItem ownerView(ItemTemplateRecord template, ItemSlot slot) { } - private PanelItem getMemberButton(String ref, int rank, long count, int slot, List<ActionRecords> actions) { - User player = island.getMemberSet(rank, false).stream().sorted().skip(slot - 1).limit(1L) + /** + * Shows a member's head + * @param rank - the rank to show + * @param slot - the slot number + * @param actions - actions that need to apply to this member button as provided by the template + * @return panel item + */ + private PanelItem getMemberButton(int rank, int slot, List<ActionRecords> actions) { + if (slot == 0 && island.getOwner() != null) { + // Owner + return getMemberButton(RanksManager.OWNER_RANK, 1, actions); + } + long count = island.getMemberSet(rank, false).size(); + String ref = RanksManager.getInstance().getRank(rank); + User player = island.getMemberSet(rank, false).stream().sorted().skip(slot - 1L).limit(1L) .map(User::getInstance).findFirst().orElse(null); if (player != null) { if (player.isOnline()) { diff --git a/src/main/resources/panels/team_panel.yml b/src/main/resources/panels/team_panel.yml index f95f473c3..cad6ace1f 100644 --- a/src/main/resources/panels/team_panel.yml +++ b/src/main/resources/panels/team_panel.yml @@ -21,9 +21,9 @@ team_panel: # The content section contains details of each item/button in the panel. The numbers indicate the rows and then then columns of each item. content: # Row number - 1: + 0: # Column number - 2: + 1: # The data section is a key-value list of data relavent for this button. It is interpreted by the code implemented the panel. # The convention is to specify the type and the panel tab that will open if pressed. These are Enums in the code. data: @@ -37,14 +37,15 @@ team_panel: click-type: UNKNOWN # tooltip is a locale reference that will be translated for the user and shown when they hover over the button. tooltip: commands.island.team.gui.tips.click-to-view - 4: - # Invite member + 3: + # Change rank data: - type: INVITE + type: RANK actions: add: click-type: LEFT - tooltip: commands.island.team.gui.tips.click-to-invite + tooltip: commands.island.team.gui.tips.click-to-change-rank + 2: 2: member_button 3: member_button From 1d6556613e6f95bcd5cee64f8699ed34a83ee610 Mon Sep 17 00:00:00 2001 From: tastybento <tastybento@users.noreply.github.com> Date: Wed, 3 Jan 2024 15:55:31 +0900 Subject: [PATCH 09/22] Added support for kick, setowner, and leave. --- .../island/team/IslandTeamCommand.java | 150 +++++++++++++----- .../island/team/IslandTeamKickCommand.java | 2 +- .../island/team/IslandTeamLeaveCommand.java | 2 +- .../team/IslandTeamSetownerCommand.java | 13 +- .../island/team/IslandTeamUncoopCommand.java | 2 +- .../island/team/IslandTeamUntrustCommand.java | 2 +- .../bentobox/bentobox/api/flags/Flag.java | 1 - src/main/resources/locales/en-US.yml | 18 ++- src/main/resources/panels/team_panel.yml | 24 ++- 9 files changed, 157 insertions(+), 57 deletions(-) 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 e1a836d1e..1c5cbc031 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 @@ -8,17 +8,18 @@ import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.UUID; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.OfflinePlayer; +import org.bukkit.Sound; import org.bukkit.event.inventory.ClickType; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; -import world.bentobox.bentobox.BentoBox; import world.bentobox.bentobox.api.commands.CompositeCommand; import world.bentobox.bentobox.api.events.IslandBaseEvent; import world.bentobox.bentobox.api.events.team.TeamEvent; @@ -56,6 +57,16 @@ public class IslandTeamCommand extends CompositeCommand { private int rank = RanksManager.OWNER_RANK; + private IslandTeamKickCommand kickCommand; + + private IslandTeamLeaveCommand leaveCommand; + + private IslandTeamSetownerCommand setOwnerCommand; + + private IslandTeamUncoopCommand uncoopCommand; + + private IslandTeamUntrustCommand unTrustCommand; + public IslandTeamCommand(CompositeCommand parent) { super(parent, "team"); inviteMap = new HashMap<>(); @@ -68,24 +79,24 @@ public void setup() { setDescription("commands.island.team.description"); // Register commands new IslandTeamInviteCommand(this); - new IslandTeamLeaveCommand(this); - new IslandTeamSetownerCommand(this); - new IslandTeamKickCommand(this); + leaveCommand = new IslandTeamLeaveCommand(this); + setOwnerCommand = new IslandTeamSetownerCommand(this); + kickCommand = new IslandTeamKickCommand(this); new IslandTeamInviteAcceptCommand(this); new IslandTeamInviteRejectCommand(this); if (RanksManager.getInstance().rankExists(RanksManager.COOP_RANK_REF)) { new IslandTeamCoopCommand(this); - new IslandTeamUncoopCommand(this); + uncoopCommand = new IslandTeamUncoopCommand(this); } if (RanksManager.getInstance().rankExists(RanksManager.TRUSTED_RANK_REF)) { new IslandTeamTrustCommand(this); - new IslandTeamUntrustCommand(this); + unTrustCommand = new IslandTeamUntrustCommand(this); } new IslandTeamPromoteCommand(this, "promote"); new IslandTeamPromoteCommand(this, "demote"); // Panels - getPlugin().saveResource("panels/team_panel.yml", false); + getPlugin().saveResource("panels/team_panel.yml", true); } @Override @@ -145,18 +156,46 @@ private void build() { private PanelItem createRankButton(ItemTemplateRecord template, TemplatedPanel.ItemSlot slot) { PanelItemBuilder builder = new PanelItemBuilder(); - builder.name("Rank"); + builder.name(user.getTranslation("commands.island.team.gui.buttons.rank-filter.name")); builder.icon(Material.AMETHYST_SHARD); - builder.description("Rank shown = " + user.getTranslation(RanksManager.getInstance().getRank(rank))); + // Create description + RanksManager.getInstance().getRanks().forEach((reference, score) -> { + if (rank == RanksManager.OWNER_RANK && score > RanksManager.VISITOR_RANK + && score <= RanksManager.OWNER_RANK) { + builder.description(user.getTranslation("protection.panel.flag-item.allowed-rank") + + user.getTranslation(reference)); + } else if (score > RanksManager.VISITOR_RANK && score < rank) { + builder.description(user.getTranslation("protection.panel.flag-item.blocked-rank") + + user.getTranslation(reference)); + } else if (score <= RanksManager.OWNER_RANK && score > rank) { + builder.description(user.getTranslation("protection.panel.flag-item.blocked-rank") + + user.getTranslation(reference)); + } else if (score == rank) { + builder.description(user.getTranslation("protection.panel.flag-item.allowed-rank") + + user.getTranslation(reference)); + } + }); + builder.description(user.getTranslation("commands.island.team.gui.buttons.rank-filter.description")); builder.clickHandler((panel, user, clickType, clickSlot) -> { - BentoBox.getInstance().logDebug("Rank = " + rank); - if (clickType.equals(ClickType.RIGHT)) { + if (clickType.equals(ClickType.LEFT)) { rank = RanksManager.getInstance().getRankDownValue(rank); - - } else { + if (rank <= RanksManager.VISITOR_RANK) { + rank = RanksManager.OWNER_RANK; + user.getPlayer().playSound(user.getLocation(), Sound.BLOCK_METAL_HIT, 1F, 1F); + } else { + user.getPlayer().playSound(user.getLocation(), Sound.BLOCK_STONE_BUTTON_CLICK_ON, 1F, 1F); + } + } + if (clickType.equals(ClickType.RIGHT)) { rank = RanksManager.getInstance().getRankUpValue(rank); + if (rank >= RanksManager.OWNER_RANK) { + rank = RanksManager.getInstance().getRankUpValue(RanksManager.VISITOR_RANK); + user.getPlayer().playSound(user.getLocation(), Sound.BLOCK_METAL_HIT, 1F, 1F); + } else { + user.getPlayer().playSound(user.getLocation(), Sound.BLOCK_STONE_BUTTON_CLICK_ON, 1F, 1F); + } } - BentoBox.getInstance().logDebug("New Rank = " + rank); + // Update panel after click build(); return true; @@ -279,35 +318,48 @@ private PanelItem ownerView(ItemTemplateRecord template, ItemSlot slot) { } /** - * Shows a member's head - * @param rank - the rank to show + * Shows a member's head. The clicks available will depend on who is viewing. + * @param targetRank - the rank to show * @param slot - the slot number * @param actions - actions that need to apply to this member button as provided by the template * @return panel item */ - private PanelItem getMemberButton(int rank, int slot, List<ActionRecords> actions) { + private PanelItem getMemberButton(int targetRank, int slot, List<ActionRecords> actions) { if (slot == 0 && island.getOwner() != null) { // Owner return getMemberButton(RanksManager.OWNER_RANK, 1, actions); } - long count = island.getMemberSet(rank, false).size(); - String ref = RanksManager.getInstance().getRank(rank); - User player = island.getMemberSet(rank, false).stream().sorted().skip(slot - 1L).limit(1L) + String ref = RanksManager.getInstance().getRank(targetRank); + User member = island.getMemberSet(targetRank, false).stream().sorted().skip(slot - 1L).limit(1L) .map(User::getInstance).findFirst().orElse(null); - if (player != null) { - if (player.isOnline()) { - return new PanelItemBuilder().icon(player.getName()).name(player.getDisplayName()) - .description( - user.getTranslation("commands.island.team.info.rank-layout.generic", TextVariables.RANK, - user.getTranslation(ref), TextVariables.NUMBER, String.valueOf(count))) - .clickHandler((panel, user, clickType, i) -> clickListener(panel, user, clickType, i, player, + // Make button description depending on viewer + List<String> desc = new ArrayList<>(); + int userRank = Objects.requireNonNull(island).getRank(user); + if (userRank >= island.getRankCommand(this.getLabel() + " kick") && !user.equals(member)) { + // Add the tooltip for kicking + actions.stream().filter(ar -> ar.actionType().equalsIgnoreCase("kick")).map(ActionRecords::tooltip) + .findFirst().map(user::getTranslation).ifPresent(desc::add); + } + if (!user.equals(member) && userRank >= RanksManager.OWNER_RANK && targetRank >= RanksManager.MEMBER_RANK) { + // Add the tooltip for setowner + actions.stream().filter(ar -> ar.actionType().equalsIgnoreCase("setowner")).map(ActionRecords::tooltip) + .findFirst().map(user::getTranslation).ifPresent(desc::add); + } + if (member != null) { + if (member.isOnline()) { + desc.add(0, user.getTranslation(ref)); + return new PanelItemBuilder().icon(member.getName()).name(member.getDisplayName()) + .description(desc) + .clickHandler((panel, user, clickType, i) -> clickListener(panel, user, clickType, i, member, actions)) .build(); } else { // Offline player - return new PanelItemBuilder().icon(player.getName()).name(player.getDisplayName()) - .description(offlinePlayerStatus(user, Bukkit.getOfflinePlayer(player.getUniqueId()))) - .clickHandler((panel, user, clickType, i) -> clickListener(panel, user, clickType, i, player, + desc.add(0, user.getTranslation(ref)); + desc.add(1, offlinePlayerStatus(user, Bukkit.getOfflinePlayer(member.getUniqueId()))); + return new PanelItemBuilder().icon(member.getName()).name(member.getDisplayName()) + .description(desc) + .clickHandler((panel, user, clickType, i) -> clickListener(panel, user, clickType, i, member, actions)) .build(); } @@ -315,20 +367,32 @@ private PanelItem getMemberButton(int rank, int slot, List<ActionRecords> action return null; } - private boolean clickListener(Panel panel, User user, ClickType clickType, int i, User player, + private boolean clickListener(Panel panel, User clicker, ClickType clickType, int i, User member, List<ActionRecords> actions) { + int rank = Objects.requireNonNull(island).getRank(clicker); for (ItemTemplateRecord.ActionRecords action : actions) { if (clickType == action.clickType() || action.clickType() == ClickType.UNKNOWN) { switch (action.actionType().toUpperCase(Locale.ENGLISH)) { case "KICK" -> { - // Kick the player - if (!player.equals(user)) { - this.user.closeInventory(); - BentoBox.getInstance() - .logDebug(this.getTopLabel() + " " + this.getLabel() + " kick " + player.getName()); - user.performCommand(this.getTopLabel() + " " + this.getLabel() + " kick " + player.getName()); + // Kick the player, or uncoop, or untrust + if (!member.equals(clicker) && rank >= island.getRankCommand(this.getLabel() + " kick")) { + clicker.closeInventory(); + removePlayer(clicker, member); + clicker.getPlayer().playSound(clicker.getLocation(), Sound.BLOCK_GLASS_BREAK, 1F, 1F); + } + } + case "SETOWNER" -> { + // Make the player the leader of the island + if (!member.equals(clicker) && clicker.getUniqueId().equals(island.getOwner())) { + clicker.closeInventory(); + this.setOwnerCommand.setOwner(clicker, member.getUniqueId()); + } + } + case "LEAVE" -> { + if (member.equals(clicker) && !clicker.getUniqueId().equals(island.getOwner())) { + clicker.closeInventory(); + leaveCommand.leave(clicker); } - } } } @@ -336,6 +400,16 @@ private boolean clickListener(Panel panel, User user, ClickType clickType, int i return true; } + private void removePlayer(User clicker, User member) { + // If member then kick, if coop, uncoop, if trusted, then untrust + switch (island.getRank(member)) { + case RanksManager.COOP_RANK -> this.uncoopCommand.unCoopCmd(user, member.getUniqueId()); + case RanksManager.TRUSTED_RANK -> this.unTrustCommand.unTrustCmd(user, member.getUniqueId()); + default -> kickCommand.kick(clicker, member.getUniqueId()); + } + + } + private List<String> showMembers() { List<String> message = new ArrayList<>(); // Gather online members diff --git a/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamKickCommand.java b/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamKickCommand.java index 9c27b7baf..6024c7426 100644 --- a/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamKickCommand.java +++ b/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamKickCommand.java @@ -84,7 +84,7 @@ public boolean execute(User user, String label, List<String> args) { } } - private void kick(User user, UUID targetUUID) { + protected void kick(User user, UUID targetUUID) { User target = User.getInstance(targetUUID); Island oldIsland = Objects.requireNonNull(getIslands().getIsland(getWorld(), targetUUID)); // Should never be // null because of 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 fc39559f0..8e34ba1c9 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 @@ -65,7 +65,7 @@ private void showResets(User user) { } - private void leave(User user) { + protected void leave(User user) { Island island = getIslands().getIsland(getWorld(), user); if (island == null) { user.sendMessage("general.errors.no-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 842a2134f..0c792fe6b 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 @@ -69,19 +69,24 @@ public boolean canExecute(User user, String label, List<String> args) { @Override public boolean execute(User user, String label, List<String> args) { + return setOwner(user, targetUUID); + + } + + protected boolean setOwner(User user, @Nullable UUID targetUUID2) { // Fire event so add-ons can run commands, etc. Island island = getIslands().getPrimaryIsland(getWorld(), user.getUniqueId()); // Fire event so add-ons can run commands, etc. IslandBaseEvent e = TeamEvent.builder().island(island).reason(TeamEvent.Reason.SETOWNER) - .involvedPlayer(targetUUID).build(); + .involvedPlayer(targetUUID2).build(); if (e.isCancelled()) { return false; } - getIslands().setOwner(getWorld(), user, targetUUID); + getIslands().setOwner(getWorld(), user, targetUUID2); // Call the event for the new owner - IslandEvent.builder().island(island).involvedPlayer(targetUUID).admin(false) + IslandEvent.builder().island(island).involvedPlayer(targetUUID2).admin(false) .reason(IslandEvent.Reason.RANK_CHANGE) - .rankChange(island.getRank(User.getInstance(targetUUID)), RanksManager.OWNER_RANK).build(); + .rankChange(island.getRank(User.getInstance(targetUUID2)), RanksManager.OWNER_RANK).build(); // Call the event for the previous owner IslandEvent.builder().island(island).involvedPlayer(user.getUniqueId()).admin(false) .reason(IslandEvent.Reason.RANK_CHANGE).rankChange(RanksManager.OWNER_RANK, RanksManager.SUB_OWNER_RANK) diff --git a/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamUncoopCommand.java b/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamUncoopCommand.java index 6c9533110..c79b3e219 100644 --- a/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamUncoopCommand.java +++ b/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamUncoopCommand.java @@ -68,7 +68,7 @@ public boolean execute(User user, String label, List<String> args) { return unCoopCmd(user, targetUUID); } - private boolean unCoopCmd(User user, UUID targetUUID) { + protected boolean unCoopCmd(User user, UUID targetUUID) { // Player cannot uncoop themselves if (user.getUniqueId().equals(targetUUID)) { user.sendMessage("commands.island.team.uncoop.cannot-uncoop-yourself"); diff --git a/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamUntrustCommand.java b/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamUntrustCommand.java index 05581286c..11bdb82aa 100644 --- a/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamUntrustCommand.java +++ b/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamUntrustCommand.java @@ -68,7 +68,7 @@ public boolean execute(User user, String label, List<String> args) { return unTrustCmd(user, targetUUID); } - private boolean unTrustCmd(User user, UUID targetUUID) { + protected boolean unTrustCmd(User user, UUID targetUUID) { // Player cannot untrust themselves if (user.getUniqueId().equals(targetUUID)) { user.sendMessage("commands.island.team.untrust.cannot-untrust-yourself"); diff --git a/src/main/java/world/bentobox/bentobox/api/flags/Flag.java b/src/main/java/world/bentobox/bentobox/api/flags/Flag.java index abb185b5f..cac99e562 100644 --- a/src/main/java/world/bentobox/bentobox/api/flags/Flag.java +++ b/src/main/java/world/bentobox/bentobox/api/flags/Flag.java @@ -430,7 +430,6 @@ private PanelItemBuilder createProtectionFlag(BentoBox plugin, User user, Island // Protection flag pib.description(user.getTranslation("protection.panel.flag-item.description-layout", TextVariables.DESCRIPTION, user.getTranslation(getDescriptionReference()))); - plugin.getRanksManager(); RanksManager.getInstance().getRanks().forEach((reference, score) -> { if (score > RanksManager.BANNED_RANK && score < island.getFlag(this)) { pib.description(user.getTranslation("protection.panel.flag-item.blocked-rank") + user.getTranslation(reference)); diff --git a/src/main/resources/locales/en-US.yml b/src/main/resources/locales/en-US.yml index c19344d20..2ab0bbba7 100644 --- a/src/main/resources/locales/en-US.yml +++ b/src/main/resources/locales/en-US.yml @@ -619,10 +619,22 @@ commands: status: name: Status description: The status of the team + rank-filter: + name: Rank Filter + description: &a Click to cycle ranks tips: - click-to-view: Click to view - right-click-to-kick: Right click to kick player - requires confirmation - click-to-invite: Click to invite a team member + shift-right: + kick: | + &a Shift-right click + &a to kick player + leave: | + &a Shift-right click + &a to leave team + shift-left: + setowner: | + &a Shift-left to + &a set owner to + &a this player info: description: display detailed info about your team member-layout: diff --git a/src/main/resources/panels/team_panel.yml b/src/main/resources/panels/team_panel.yml index cad6ace1f..a6611ccc8 100644 --- a/src/main/resources/panels/team_panel.yml +++ b/src/main/resources/panels/team_panel.yml @@ -21,7 +21,7 @@ team_panel: # The content section contains details of each item/button in the panel. The numbers indicate the rows and then then columns of each item. content: # Row number - 0: + 1: # Column number 1: # The data section is a key-value list of data relavent for this button. It is interpreted by the code implemented the panel. @@ -38,14 +38,17 @@ team_panel: # tooltip is a locale reference that will be translated for the user and shown when they hover over the button. tooltip: commands.island.team.gui.tips.click-to-view 3: - # Change rank + # Rank filter data: type: RANK + name: commands.island.team.gui.buttons.rank-filter actions: - add: + cycle-up: click-type: LEFT - tooltip: commands.island.team.gui.tips.click-to-change-rank - + tooltip: commands.island.team.gui.tips.right-click.rank + cycle-down: + click-type: RIGHT + tooltip: commands.island.team.gui.tips.right-click.rank 2: 2: member_button 3: member_button @@ -103,6 +106,13 @@ team_panel: # Each action has an arbitrary descriptive name to define it. kick: # The click-type is the same as the bukkit {@link org.bukkit.event.inventory.ClickType}. UNKNOWN is the default. - click-type: RIGHT + click-type: SHIFT_RIGHT # tooltip is a locale reference that will be translated for the user and shown when they hover over the button. - tooltip: commands.island.team.gui.tips.right-click-to-kick \ No newline at end of file + tooltip: commands.island.team.gui.tips.shift-right.kick + leave: + click-type: SHIFT_RIGHT + tooltip: commands.island.team.gui.tips.shift-right.leave + setowner: + click-type: SHIFT_LEFT + tooltip: commands.island.team.gui.tips.shift-left.setowner + \ No newline at end of file From 7639c59db9d2a0d1a2f3e3ee365a661ca03ee840 Mon Sep 17 00:00:00 2001 From: tastybento <tastybento@users.noreply.github.com> Date: Wed, 3 Jan 2024 18:42:12 +0900 Subject: [PATCH 10/22] Added support for accepting and rejecting an invite. --- .../island/team/IslandTeamCommand.java | 106 ++++++++++++++---- .../team/IslandTeamInviteAcceptCommand.java | 28 ++--- src/main/resources/locales/en-US.yml | 14 ++- src/main/resources/panels/team_panel.yml | 14 ++- 4 files changed, 123 insertions(+), 39 deletions(-) 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 1c5cbc031..d45fd9a33 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 @@ -17,9 +17,11 @@ import org.bukkit.OfflinePlayer; import org.bukkit.Sound; import org.bukkit.event.inventory.ClickType; +import org.bukkit.inventory.ItemStack; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; +import world.bentobox.bentobox.BentoBox; import world.bentobox.bentobox.api.commands.CompositeCommand; import world.bentobox.bentobox.api.events.IslandBaseEvent; import world.bentobox.bentobox.api.events.team.TeamEvent; @@ -32,6 +34,7 @@ import world.bentobox.bentobox.api.panels.builders.TemplatedPanelBuilder; import world.bentobox.bentobox.api.panels.reader.ItemTemplateRecord; import world.bentobox.bentobox.api.panels.reader.ItemTemplateRecord.ActionRecords; +import world.bentobox.bentobox.api.panels.reader.PanelTemplateRecord.TemplateItem; import world.bentobox.bentobox.api.user.User; import world.bentobox.bentobox.database.objects.Island; import world.bentobox.bentobox.managers.RanksManager; @@ -67,6 +70,14 @@ public class IslandTeamCommand extends CompositeCommand { private IslandTeamUntrustCommand unTrustCommand; + private @Nullable TemplateItem border; + + private @Nullable TemplateItem background; + + private IslandTeamInviteAcceptCommand acceptCommand; + + private IslandTeamInviteRejectCommand rejectCommand; + public IslandTeamCommand(CompositeCommand parent) { super(parent, "team"); inviteMap = new HashMap<>(); @@ -82,8 +93,8 @@ public void setup() { leaveCommand = new IslandTeamLeaveCommand(this); setOwnerCommand = new IslandTeamSetownerCommand(this); kickCommand = new IslandTeamKickCommand(this); - new IslandTeamInviteAcceptCommand(this); - new IslandTeamInviteRejectCommand(this); + acceptCommand = new IslandTeamInviteAcceptCommand(this); + rejectCommand = new IslandTeamInviteRejectCommand(this); if (RanksManager.getInstance().rankExists(RanksManager.COOP_RANK_REF)) { new IslandTeamCoopCommand(this); uncoopCommand = new IslandTeamUncoopCommand(this); @@ -105,6 +116,11 @@ public boolean execute(User user, String label, List<String> args) { // Player issuing the command must have an island island = getIslands().getPrimaryIsland(getWorld(), user.getUniqueId()); if (island == null) { + if (isInvited(user.getUniqueId())) { + // Player has an invite, so show the invite + build(); + return true; + } user.sendMessage("general.errors.no-island"); return false; } @@ -146,10 +162,11 @@ private void build() { panelBuilder.registerTypeBuilder("STATUS", this::createStatusButton); panelBuilder.registerTypeBuilder("MEMBER", this::createMemberButton); - panelBuilder.registerTypeBuilder("INVITE", this::createInviteButton); + panelBuilder.registerTypeBuilder("INVITED", this::createInvitedButton); panelBuilder.registerTypeBuilder("RANK", this::createRankButton); //panelBuilder.registerTypeBuilder("KICK", this::createKickButton); - + border = panelBuilder.getPanelTemplate().border(); + background = panelBuilder.getPanelTemplate().background(); // Register unknown type builder. panelBuilder.build(); } @@ -203,24 +220,61 @@ private PanelItem createRankButton(ItemTemplateRecord template, TemplatedPanel.I return builder.build(); } + /** - * Create invite button panel item. + * Create invited button panel item. * * @param template the template * @param slot the slot * @return the panel item */ - private PanelItem createInviteButton(ItemTemplateRecord template, TemplatedPanel.ItemSlot slot) { + private PanelItem createInvitedButton(ItemTemplateRecord template, TemplatedPanel.ItemSlot slot) { PanelItemBuilder builder = new PanelItemBuilder(); - // Player issuing the command must have an island - Island island = getIslands().getPrimaryIsland(getWorld(), user.getUniqueId()); - if (island == null) { - return builder.icon(Material.BARRIER).name(user.getTranslation("general.errors.no-island")).build(); + if (isInvited(user.getUniqueId())) { + Invite invite = getInvite(user.getUniqueId()); + User inviter = User.getInstance(invite.getInviter()); + String name = inviter.getName(); + builder.icon(inviter.getName()); + builder.name("Invitation"); + builder.description(switch (invite.getType()) { + case COOP -> + List.of(user.getTranslation("commands.island.team.invite.name-has-invited-you.coop", TextVariables.NAME, + name)); + case TRUST -> + List.of(user.getTranslation("commands.island.team.invite.name-has-invited-you.trust", + TextVariables.NAME, name)); + default -> + List.of(user.getTranslation("commands.island.team.invite.name-has-invited-you", TextVariables.NAME, + name), user.getTranslation("commands.island.team.invite.accept.confirmation")); + }); + // Add all the tool tips + builder.description(template.actions().stream() + .map(ar -> user.getTranslation("commands.island.team.gui.tips." + ar.clickType().name() + ".name") + + " " + + user.getTranslation(ar.tooltip())) + .toList()); + builder.clickHandler((panel, user, clickType, clickSlot) -> { + if (clickType.equals(ClickType.SHIFT_LEFT)) { + // Accept + switch (invite.getType()) { + case COOP -> this.acceptCommand.acceptCoopInvite(user, invite); + case TRUST -> this.acceptCommand.acceptTrustInvite(user, invite); + default -> this.acceptCommand.acceptTeamInvite(user, invite); + } + user.closeInventory(); + } + if (clickType.equals(ClickType.SHIFT_RIGHT)) { + // Reject + BentoBox.getInstance().logDebug("Reject"); + this.rejectCommand.execute(user, "", List.of()); + user.closeInventory(); + } + return true; + }); + } else { + return this.getBlankBorder(); } - // The player must be able to invite a player - - return builder.icon(user.getName()).name(user.getTranslation("commands.island.team.gui.buttons.status.name")) - .description(showMembers()).build(); + return builder.build(); } /** @@ -235,13 +289,24 @@ private PanelItem createStatusButton(ItemTemplateRecord template, TemplatedPanel // Player issuing the command must have an island Island island = getIslands().getPrimaryIsland(getWorld(), user.getUniqueId()); if (island == null) { - return builder.icon(Material.BARRIER).name(user.getTranslation("general.errors.no-island")).build(); + return getBlankBorder(); } return builder.icon(user.getName()).name(user.getTranslation("commands.island.team.gui.buttons.status.name")) .description(showMembers()).build(); } + private PanelItem getBlankBorder() { + return new PanelItemBuilder().icon(Objects.requireNonNullElse(border.icon(), new ItemStack(Material.BARRIER))) + .name((Objects.requireNonNullElse(border.title(), ""))).build(); + } + + private PanelItem getBlankBackground() { + return new PanelItemBuilder() + .icon(Objects.requireNonNullElse(background.icon(), new ItemStack(Material.BARRIER))) + .name((Objects.requireNonNullElse(background.title(), ""))).build(); + } + /** * Create member button panel item. * @@ -253,8 +318,7 @@ private PanelItem createMemberButton(ItemTemplateRecord template, TemplatedPanel // Player issuing the command must have an island Island island = getIslands().getPrimaryIsland(getWorld(), user.getUniqueId()); if (island == null) { - return new PanelItemBuilder().icon(Material.BARRIER).name(user.getTranslation("general.errors.no-island")) - .build(); + return this.getBlankBackground(); } return switch (rank) { case RanksManager.OWNER_RANK -> ownerView(template, slot); @@ -337,12 +401,16 @@ private PanelItem getMemberButton(int targetRank, int slot, List<ActionRecords> int userRank = Objects.requireNonNull(island).getRank(user); if (userRank >= island.getRankCommand(this.getLabel() + " kick") && !user.equals(member)) { // Add the tooltip for kicking - actions.stream().filter(ar -> ar.actionType().equalsIgnoreCase("kick")).map(ActionRecords::tooltip) + actions.stream().filter(ar -> ar.actionType().equalsIgnoreCase("kick")) + .map(ar -> user.getTranslation("commands.island.team.gui.tips." + ar.clickType().name()) + " " + + user.getTranslation(ar.tooltip())) .findFirst().map(user::getTranslation).ifPresent(desc::add); } if (!user.equals(member) && userRank >= RanksManager.OWNER_RANK && targetRank >= RanksManager.MEMBER_RANK) { // Add the tooltip for setowner - actions.stream().filter(ar -> ar.actionType().equalsIgnoreCase("setowner")).map(ActionRecords::tooltip) + actions.stream().filter(ar -> ar.actionType().equalsIgnoreCase("setowner")) + .map(ar -> user.getTranslation("commands.island.team.gui.tips." + ar.clickType().name()) + " " + + user.getTranslation(ar.tooltip())) .findFirst().map(user::getTranslation).ifPresent(desc::add); } if (member != null) { 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 b93d52b8c..576956b63 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 @@ -23,7 +23,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; public IslandTeamInviteAcceptCommand(IslandTeamCommand islandTeamCommand) { super(islandTeamCommand, "accept"); @@ -39,7 +38,7 @@ public void setup() { @Override public boolean canExecute(User user, String label, List<String> args) { - playerUUID = user.getUniqueId(); + UUID playerUUID = user.getUniqueId(); // Check if player has been invited if (!itc.isInvited(playerUUID)) { user.sendMessage("commands.island.team.invite.errors.none-invited-you"); @@ -79,7 +78,7 @@ public boolean canExecute(User user, String label, List<String> args) { @Override public boolean execute(User user, String label, List<String> args) { // Get the invite - Invite invite = itc.getInvite(playerUUID); + Invite invite = itc.getInvite(user.getUniqueId()); switch (invite.getType()) { case COOP -> askConfirmation(user, () -> acceptCoopInvite(user, invite)); case TRUST -> askConfirmation(user, () -> acceptTrustInvite(user, invite)); @@ -89,9 +88,9 @@ public boolean execute(User user, String label, List<String> args) { return true; } - private void acceptTrustInvite(User user, Invite invite) { + void acceptTrustInvite(User user, Invite invite) { // Remove the invite - itc.removeInvite(playerUUID); + itc.removeInvite(user.getUniqueId()); User inviter = User.getInstance(invite.getInviter()); Island island = invite.getIsland(); if (island != null) { @@ -115,9 +114,9 @@ private void acceptTrustInvite(User user, Invite invite) { } } - private void acceptCoopInvite(User user, Invite invite) { + void acceptCoopInvite(User user, Invite invite) { // Remove the invite - itc.removeInvite(playerUUID); + itc.removeInvite(user.getUniqueId()); User inviter = User.getInstance(invite.getInviter()); Island island = invite.getIsland(); if (island != null) { @@ -141,11 +140,11 @@ private void acceptCoopInvite(User user, Invite invite) { } } - private void acceptTeamInvite(User user, Invite invite) { + void acceptTeamInvite(User user, Invite invite) { // Remove the invite - itc.removeInvite(playerUUID); + itc.removeInvite(user.getUniqueId()); // Get the player's island - may be null if the player has no island - Set<Island> islands = getIslands().getIslands(getWorld(), playerUUID); + Set<Island> islands = getIslands().getIslands(getWorld(), user.getUniqueId()); // Get the team's island Island teamIsland = invite.getIsland(); if (teamIsland == null) { @@ -158,11 +157,11 @@ private void acceptTeamInvite(User user, Invite invite) { return; } // Remove player as owner of the old island - getIslands().removePlayer(getWorld(), playerUUID); + getIslands().removePlayer(getWorld(), user.getUniqueId()); // Remove money inventory etc. for leaving cleanPlayer(user); // Add the player as a team member of the new island - getIslands().setJoinTeam(teamIsland, playerUUID); + getIslands().setJoinTeam(teamIsland, user.getUniqueId()); // Move player to team's island getIslands().homeTeleportAsync(getWorld(), user.getPlayer()).thenRun(() -> { // Delete the old islands @@ -178,7 +177,7 @@ private void acceptTeamInvite(User user, Invite invite) { }); // Reset deaths if (getIWM().isTeamJoinDeathReset(getWorld())) { - getPlayers().setDeaths(getWorld(), playerUUID, 0); + getPlayers().setDeaths(getWorld(), user.getUniqueId(), 0); } user.sendMessage("commands.island.team.invite.accept.you-joined-island", TextVariables.LABEL, getTopLabel()); User inviter = User.getInstance(invite.getInviter()); @@ -188,7 +187,8 @@ private void acceptTeamInvite(User user, Invite invite) { } getIslands().save(teamIsland); // Fire event - TeamEvent.builder().island(teamIsland).reason(TeamEvent.Reason.JOINED).involvedPlayer(playerUUID).build(); + TeamEvent.builder().island(teamIsland).reason(TeamEvent.Reason.JOINED).involvedPlayer(user.getUniqueId()) + .build(); IslandEvent.builder().island(teamIsland).involvedPlayer(user.getUniqueId()).admin(false) .reason(IslandEvent.Reason.RANK_CHANGE).rankChange(teamIsland.getRank(user), RanksManager.MEMBER_RANK) .build(); diff --git a/src/main/resources/locales/en-US.yml b/src/main/resources/locales/en-US.yml index 2ab0bbba7..3e1e3ae69 100644 --- a/src/main/resources/locales/en-US.yml +++ b/src/main/resources/locales/en-US.yml @@ -623,16 +623,20 @@ commands: name: Rank Filter description: &a Click to cycle ranks tips: - shift-right: + SHIFT_RIGHT: + name: &b Right Shift + reject: &a click to reject kick: | - &a Shift-right click + &a click &a to kick player leave: | - &a Shift-right click + &a click &a to leave team - shift-left: + SHIFT_LEFT: + name: &b Left Shift + accept: &a click to accept setowner: | - &a Shift-left to + &a click to &a set owner to &a this player info: diff --git a/src/main/resources/panels/team_panel.yml b/src/main/resources/panels/team_panel.yml index a6611ccc8..498f382fa 100644 --- a/src/main/resources/panels/team_panel.yml +++ b/src/main/resources/panels/team_panel.yml @@ -17,7 +17,7 @@ team_panel: title: "&b&r" # Empty text # This tag indicates which rows in the panel must be shown. The panel will be sized vertically accordingly. This does not include the borders. # This can be a list and rows must be between 1 and 6, if used. - force-shown: [1, 2] + force-shown: [] # The content section contains details of each item/button in the panel. The numbers indicate the rows and then then columns of each item. content: # Row number @@ -49,6 +49,18 @@ team_panel: cycle-down: click-type: RIGHT tooltip: commands.island.team.gui.tips.right-click.rank + 5: + # Invited button - this appears if you have been invited to join a team + data: + type: INVITED + name: commands.island.team.gui.buttons.invited + actions: + accept: + click-type: SHIFT_LEFT + tooltip: commands.island.team.gui.tips.SHIFT_LEFT.accept + reject: + click-type: SHIFT_RIGHT + tooltip: commands.island.team.gui.tips.SHIFT_RIGHT.reject 2: 2: member_button 3: member_button From de28bae47d8531f5bc1eb9b88cba917062ce1820 Mon Sep 17 00:00:00 2001 From: tastybento <tastybento@users.noreply.github.com> Date: Wed, 3 Jan 2024 21:42:53 +0900 Subject: [PATCH 11/22] Fixed bugs with text and operations. --- .../island/team/IslandTeamCommand.java | 78 ++++++++++++------- src/main/resources/locales/en-US.yml | 38 ++++----- src/main/resources/panels/team_panel.yml | 6 +- 3 files changed, 72 insertions(+), 50 deletions(-) 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 d45fd9a33..8b0334189 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 @@ -172,6 +172,10 @@ private void build() { } private PanelItem createRankButton(ItemTemplateRecord template, TemplatedPanel.ItemSlot slot) { + // If there is no island, the do not show this icon + if (island == null) { + return this.getBlankBorder(); + } PanelItemBuilder builder = new PanelItemBuilder(); builder.name(user.getTranslation("commands.island.team.gui.buttons.rank-filter.name")); builder.icon(Material.AMETHYST_SHARD); @@ -230,12 +234,12 @@ private PanelItem createRankButton(ItemTemplateRecord template, TemplatedPanel.I */ private PanelItem createInvitedButton(ItemTemplateRecord template, TemplatedPanel.ItemSlot slot) { PanelItemBuilder builder = new PanelItemBuilder(); - if (isInvited(user.getUniqueId())) { + if (isInvited(user.getUniqueId()) && user.hasPermission(this.acceptCommand.getPermission())) { Invite invite = getInvite(user.getUniqueId()); User inviter = User.getInstance(invite.getInviter()); String name = inviter.getName(); builder.icon(inviter.getName()); - builder.name("Invitation"); + builder.name(user.getTranslation("commands.island.team.gui.buttons.invitation")); builder.description(switch (invite.getType()) { case COOP -> List.of(user.getTranslation("commands.island.team.invite.name-has-invited-you.coop", TextVariables.NAME, @@ -254,7 +258,7 @@ private PanelItem createInvitedButton(ItemTemplateRecord template, TemplatedPane + user.getTranslation(ar.tooltip())) .toList()); builder.clickHandler((panel, user, clickType, clickSlot) -> { - if (clickType.equals(ClickType.SHIFT_LEFT)) { + if (clickType.equals(ClickType.SHIFT_LEFT) && user.hasPermission(this.acceptCommand.getPermission())) { // Accept switch (invite.getType()) { case COOP -> this.acceptCommand.acceptCoopInvite(user, invite); @@ -263,9 +267,8 @@ private PanelItem createInvitedButton(ItemTemplateRecord template, TemplatedPane } user.closeInventory(); } - if (clickType.equals(ClickType.SHIFT_RIGHT)) { + if (clickType.equals(ClickType.SHIFT_RIGHT) && user.hasPermission(this.rejectCommand.getPermission())) { // Reject - BentoBox.getInstance().logDebug("Reject"); this.rejectCommand.execute(user, "", List.of()); user.closeInventory(); } @@ -399,19 +402,31 @@ private PanelItem getMemberButton(int targetRank, int slot, List<ActionRecords> // Make button description depending on viewer List<String> desc = new ArrayList<>(); int userRank = Objects.requireNonNull(island).getRank(user); - if (userRank >= island.getRankCommand(this.getLabel() + " kick") && !user.equals(member)) { - // Add the tooltip for kicking + // Add the tooltip for kicking + if (user.hasPermission(this.kickCommand.getPermission()) + && userRank >= island.getRankCommand(this.getLabel() + " kick") && !user.equals(member)) { actions.stream().filter(ar -> ar.actionType().equalsIgnoreCase("kick")) - .map(ar -> user.getTranslation("commands.island.team.gui.tips." + ar.clickType().name()) + " " - + user.getTranslation(ar.tooltip())) - .findFirst().map(user::getTranslation).ifPresent(desc::add); + .map(ar -> user.getTranslation("commands.island.team.gui.tips." + ar.clickType().name() + ".name") + + " " + user.getTranslation(ar.tooltip())) + .findFirst().ifPresent(desc::add); } - if (!user.equals(member) && userRank >= RanksManager.OWNER_RANK && targetRank >= RanksManager.MEMBER_RANK) { + // Set Owner + if (user.hasPermission(this.setOwnerCommand.getPermission()) && !user.equals(member) + && userRank >= RanksManager.OWNER_RANK && targetRank >= RanksManager.MEMBER_RANK) { // Add the tooltip for setowner actions.stream().filter(ar -> ar.actionType().equalsIgnoreCase("setowner")) - .map(ar -> user.getTranslation("commands.island.team.gui.tips." + ar.clickType().name()) + " " - + user.getTranslation(ar.tooltip())) - .findFirst().map(user::getTranslation).ifPresent(desc::add); + .map(ar -> user.getTranslation("commands.island.team.gui.tips." + ar.clickType().name() + ".name") + + " " + user.getTranslation(ar.tooltip())) + .findFirst().ifPresent(desc::add); + } + // Leave + if (user.hasPermission(this.leaveCommand.getPermission()) && user.equals(member) + && userRank < RanksManager.OWNER_RANK) { + // Add the tooltip for leave + actions.stream().filter(ar -> ar.actionType().equalsIgnoreCase("leave")) + .map(ar -> user.getTranslation("commands.island.team.gui.tips." + ar.clickType().name() + ".name") + + " " + user.getTranslation(ar.tooltip())) + .findFirst().ifPresent(desc::add); } if (member != null) { if (member.isOnline()) { @@ -424,8 +439,8 @@ private PanelItem getMemberButton(int targetRank, int slot, List<ActionRecords> } else { // Offline player desc.add(0, user.getTranslation(ref)); - desc.add(1, offlinePlayerStatus(user, Bukkit.getOfflinePlayer(member.getUniqueId()))); - return new PanelItemBuilder().icon(member.getName()).name(member.getDisplayName()) + return new PanelItemBuilder().icon(member.getName()) + .name(offlinePlayerStatus(user, Bukkit.getOfflinePlayer(member.getUniqueId()))) .description(desc) .clickHandler((panel, user, clickType, i) -> clickListener(panel, user, clickType, i, member, actions)) @@ -443,7 +458,8 @@ private boolean clickListener(Panel panel, User clicker, ClickType clickType, in switch (action.actionType().toUpperCase(Locale.ENGLISH)) { case "KICK" -> { // Kick the player, or uncoop, or untrust - if (!member.equals(clicker) && rank >= island.getRankCommand(this.getLabel() + " kick")) { + if (clicker.hasPermission(this.kickCommand.getPermission()) && !member.equals(clicker) + && rank >= island.getRankCommand(this.getLabel() + " kick")) { clicker.closeInventory(); removePlayer(clicker, member); clicker.getPlayer().playSound(clicker.getLocation(), Sound.BLOCK_GLASS_BREAK, 1F, 1F); @@ -451,13 +467,15 @@ private boolean clickListener(Panel panel, User clicker, ClickType clickType, in } case "SETOWNER" -> { // Make the player the leader of the island - if (!member.equals(clicker) && clicker.getUniqueId().equals(island.getOwner())) { + if (clicker.hasPermission(this.setOwnerCommand.getPermission()) && !member.equals(clicker) + && clicker.getUniqueId().equals(island.getOwner())) { clicker.closeInventory(); this.setOwnerCommand.setOwner(clicker, member.getUniqueId()); } } case "LEAVE" -> { - if (member.equals(clicker) && !clicker.getUniqueId().equals(island.getOwner())) { + if (clicker.hasPermission(this.leaveCommand.getPermission()) && member.equals(clicker) + && !clicker.getUniqueId().equals(island.getOwner())) { clicker.closeInventory(); leaveCommand.leave(clicker); } @@ -539,6 +557,18 @@ private String getMemberStatus(User user2, UUID member, boolean online) { * @return string */ private String offlinePlayerStatus(User user2, OfflinePlayer offlineMember) { + String lastSeen = lastSeen(offlineMember); + if (island.getMemberSet(RanksManager.MEMBER_RANK, true).contains(offlineMember.getUniqueId())) { + return user.getTranslation("commands.island.team.info.member-layout.offline", TextVariables.NAME, + offlineMember.getName(), "[last_seen]", lastSeen); + } else { + // This will prevent anyone that is trusted or below to not have a last-seen status + return user.getTranslation("commands.island.team.info.member-layout.offline-not-last-seen", + TextVariables.NAME, offlineMember.getName()); + } + } + + private String lastSeen(OfflinePlayer offlineMember) { // A bit of handling for the last joined date Instant lastJoined = Instant.ofEpochMilli(offlineMember.getLastPlayed()); Instant now = Instant.now(); @@ -556,15 +586,7 @@ private String offlinePlayerStatus(User user2, OfflinePlayer offlineMember) { lastSeen = user.getTranslation(reference, TextVariables.NUMBER, String.valueOf(duration.toDays()), TextVariables.UNIT, user.getTranslation("commands.island.team.info.last-seen.days")); } - - if (island.getMemberSet(RanksManager.MEMBER_RANK, true).contains(offlineMember.getUniqueId())) { - return user.getTranslation("commands.island.team.info.member-layout.offline", TextVariables.NAME, - offlineMember.getName(), "[last_seen]", lastSeen); - } else { - // This will prevent anyone that is trusted or below to not have a last-seen status - return user.getTranslation("commands.island.team.info.member-layout.offline-not-last-seen", - TextVariables.NAME, offlineMember.getName()); - } + return lastSeen; } private boolean fireEvent(User user, Island island) { diff --git a/src/main/resources/locales/en-US.yml b/src/main/resources/locales/en-US.yml index 3e1e3ae69..128529eb2 100644 --- a/src/main/resources/locales/en-US.yml +++ b/src/main/resources/locales/en-US.yml @@ -611,34 +611,34 @@ commands: description: reset your island name success: '&a Successfully reset your island name.' team: - description: manage your team + description: "manage your team" gui: titles: - team-panel: Team Management + team-panel: "Team Management" buttons: status: - name: Status - description: The status of the team + name: "Status" + description: "The status of the team" rank-filter: - name: Rank Filter - description: &a Click to cycle ranks + name: "Rank Filter" + description: "&a Click to cycle ranks" + invitation: "Invitation" tips: + LEFT: + name: "&b Left Click" + RIGHT: + name: "&b Right Click" SHIFT_RIGHT: - name: &b Right Shift - reject: &a click to reject - kick: | - &a click - &a to kick player - leave: | - &a click - &a to leave team + name: "&b Shift Right Click" + reject: "&a to reject" + kick: "&a to kick player" + leave: "&a to leave team" SHIFT_LEFT: - name: &b Left Shift - accept: &a click to accept + name: "&b Shift Left Click" + accept: "&a to accept " setowner: | - &a click to - &a set owner to - &a this player + &a to set owner + &a to this player info: description: display detailed info about your team member-layout: diff --git a/src/main/resources/panels/team_panel.yml b/src/main/resources/panels/team_panel.yml index 498f382fa..e9ca5d19f 100644 --- a/src/main/resources/panels/team_panel.yml +++ b/src/main/resources/panels/team_panel.yml @@ -120,11 +120,11 @@ team_panel: # The click-type is the same as the bukkit {@link org.bukkit.event.inventory.ClickType}. UNKNOWN is the default. click-type: SHIFT_RIGHT # tooltip is a locale reference that will be translated for the user and shown when they hover over the button. - tooltip: commands.island.team.gui.tips.shift-right.kick + tooltip: commands.island.team.gui.tips.SHIFT_RIGHT.kick leave: click-type: SHIFT_RIGHT - tooltip: commands.island.team.gui.tips.shift-right.leave + tooltip: commands.island.team.gui.tips.SHIFT_RIGHT.leave setowner: click-type: SHIFT_LEFT - tooltip: commands.island.team.gui.tips.shift-left.setowner + tooltip: commands.island.team.gui.tips.SHIFT_LEFT.setowner \ No newline at end of file From f290a2c65aed1ffd0fb7e62f74c0e3cd78fdca52 Mon Sep 17 00:00:00 2001 From: tastybento <tastybento@users.noreply.github.com> Date: Thu, 4 Jan 2024 17:16:36 +0900 Subject: [PATCH 12/22] WIP for team invites. --- .../island/team/IslandTeamCommand.java | 24 ++++- .../island/team/IslandTeamInviteCommand.java | 74 ++++++++++++++- src/main/resources/locales/en-US.yml | 18 ++++ .../resources/panels/team_invite_panel.yml | 90 +++++++++++++++++++ src/main/resources/panels/team_panel.yml | 11 ++- 5 files changed, 213 insertions(+), 4 deletions(-) create mode 100644 src/main/resources/panels/team_invite_panel.yml 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 8b0334189..c7d00d979 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 @@ -78,6 +78,8 @@ public class IslandTeamCommand extends CompositeCommand { private IslandTeamInviteRejectCommand rejectCommand; + private IslandTeamInviteCommand inviteCommand; + public IslandTeamCommand(CompositeCommand parent) { super(parent, "team"); inviteMap = new HashMap<>(); @@ -89,7 +91,7 @@ public void setup() { setOnlyPlayer(true); setDescription("commands.island.team.description"); // Register commands - new IslandTeamInviteCommand(this); + inviteCommand = new IslandTeamInviteCommand(this); leaveCommand = new IslandTeamLeaveCommand(this); setOwnerCommand = new IslandTeamSetownerCommand(this); kickCommand = new IslandTeamKickCommand(this); @@ -164,13 +166,31 @@ private void build() { panelBuilder.registerTypeBuilder("MEMBER", this::createMemberButton); panelBuilder.registerTypeBuilder("INVITED", this::createInvitedButton); panelBuilder.registerTypeBuilder("RANK", this::createRankButton); - //panelBuilder.registerTypeBuilder("KICK", this::createKickButton); + panelBuilder.registerTypeBuilder("INVITE", this::createInviteButton); border = panelBuilder.getPanelTemplate().border(); background = panelBuilder.getPanelTemplate().background(); // Register unknown type builder. panelBuilder.build(); } + private PanelItem createInviteButton(ItemTemplateRecord template, TemplatedPanel.ItemSlot slot) { + if (island == null || !user.hasPermission(this.inviteCommand.getPermission()) + || island.getRank(user) < island.getRankCommand(this.getLabel() + " invite")) { + return this.getBlankBorder(); + } + PanelItemBuilder builder = new PanelItemBuilder(); + builder.icon(Material.PLAYER_HEAD); + builder.name(user.getTranslation("commands.island.team.gui.buttons.invite.name")); + builder.clickHandler((panel, user, clickType, clickSlot) -> { + if (clickType.equals(ClickType.LEFT)) { + user.closeInventory(); + this.inviteCommand.build(user); + } + return true; + }); + return builder.build(); + } + private PanelItem createRankButton(ItemTemplateRecord template, TemplatedPanel.ItemSlot slot) { // If there is no island, the do not show this icon if (island == null) { 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 4585dfc7c..95cca395f 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 @@ -1,11 +1,15 @@ package world.bentobox.bentobox.api.commands.island.team; +import java.io.File; import java.util.ArrayList; import java.util.List; import java.util.Objects; import java.util.Optional; import java.util.UUID; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; import org.eclipse.jdt.annotation.Nullable; import world.bentobox.bentobox.api.commands.CompositeCommand; @@ -13,6 +17,12 @@ import world.bentobox.bentobox.api.events.IslandBaseEvent; import world.bentobox.bentobox.api.events.team.TeamEvent; import world.bentobox.bentobox.api.localization.TextVariables; +import world.bentobox.bentobox.api.panels.PanelItem; +import world.bentobox.bentobox.api.panels.TemplatedPanel; +import world.bentobox.bentobox.api.panels.builders.PanelItemBuilder; +import world.bentobox.bentobox.api.panels.builders.TemplatedPanelBuilder; +import world.bentobox.bentobox.api.panels.reader.ItemTemplateRecord; +import world.bentobox.bentobox.api.panels.reader.PanelTemplateRecord.TemplateItem; import world.bentobox.bentobox.api.user.User; import world.bentobox.bentobox.database.objects.Island; import world.bentobox.bentobox.managers.IslandsManager; @@ -24,6 +34,9 @@ public class IslandTeamInviteCommand extends CompositeCommand { private final IslandTeamCommand itc; private @Nullable User invitedPlayer; + private @Nullable TemplateItem border; + private @Nullable TemplateItem background; + private User user; public IslandTeamInviteCommand(IslandTeamCommand parent) { super(parent, "invite"); @@ -36,6 +49,8 @@ public void setup() { setOnlyPlayer(true); setDescription("commands.island.team.invite.description"); setConfigurableRankCommand(); + // Panels + getPlugin().saveResource("panels/team_invite_panel.yml", true); } @@ -65,6 +80,7 @@ private boolean handleCommandWithNoArgs(User user) { Type inviteType = getInviteType(playerUUID); if (inviteType != null) { + // TODO: send to team command to present invite String name = getPlayers().getName(playerUUID); switch (inviteType) { case COOP -> user.sendMessage("commands.island.team.invite.name-has-invited-you.coop", TextVariables.NAME, name); @@ -73,7 +89,7 @@ private boolean handleCommandWithNoArgs(User user) { } return true; } - + build(user); showHelp(this, user); return false; } @@ -204,4 +220,60 @@ public Optional<List<String>> tabComplete(User user, String alias, List<String> return Optional.of(Util.tabLimit(options, lastArg)); } + public void build(User user) { + this.user = user; + // Start building panel. + TemplatedPanelBuilder panelBuilder = new TemplatedPanelBuilder(); + panelBuilder.user(user); + panelBuilder.world(user.getWorld()); + + panelBuilder.template("team_panel", new File(getPlugin().getDataFolder(), "panels")); + + panelBuilder.parameters("[name]", user.getName(), "[display_name]", user.getDisplayName()); + + panelBuilder.registerTypeBuilder("PROSPECT", this::createProspectButton); + //panelBuilder.registerTypeBuilder("INVITED", this::createInvitedButton); + //panelBuilder.registerTypeBuilder("RANK", this::createRankButton); + //panelBuilder.registerTypeBuilder("INVITE", this::createInviteButton); + border = panelBuilder.getPanelTemplate().border(); + background = panelBuilder.getPanelTemplate().background(); + // Register unknown type builder. + panelBuilder.build(); + + } + + /** + * Create member button panel item. + * + * @param template the template + * @param slot the slot + * @return the panel item + */ + private PanelItem createProspectButton(ItemTemplateRecord template, TemplatedPanel.ItemSlot slot) { + // Player issuing the command must have an island + Island island = getIslands().getPrimaryIsland(getWorld(), user.getUniqueId()); + if (island == null) { + return this.getBlankBackground(); + } + // TODO: THERE"S A BUG HERE + return user.getWorld().getPlayers().stream() + .filter(player -> !getIslands().inTeam(getWorld(), player.getUniqueId())).skip(slot.slot() - 1) + .limit(1L) + .findFirst().map(this::getProspect).orElse(this.getBlankBackground()); + } + + private PanelItem getProspect(Player player) { + return new PanelItemBuilder().icon(player.getName()).build(); + } + + private PanelItem getBlankBorder() { + return new PanelItemBuilder().icon(Objects.requireNonNullElse(border.icon(), new ItemStack(Material.BARRIER))) + .name((Objects.requireNonNullElse(border.title(), ""))).build(); + } + + private PanelItem getBlankBackground() { + return new PanelItemBuilder() + .icon(Objects.requireNonNullElse(background.icon(), new ItemStack(Material.BARRIER))) + .name((Objects.requireNonNullElse(background.title(), ""))).build(); + } } diff --git a/src/main/resources/locales/en-US.yml b/src/main/resources/locales/en-US.yml index 128529eb2..0014ef630 100644 --- a/src/main/resources/locales/en-US.yml +++ b/src/main/resources/locales/en-US.yml @@ -623,9 +623,12 @@ commands: name: "Rank Filter" description: "&a Click to cycle ranks" invitation: "Invitation" + invite: + name: "Invite player" tips: LEFT: name: "&b Left Click" + invite: "&a to invite a player" RIGHT: name: "&b Right Click" SHIFT_RIGHT: @@ -704,6 +707,21 @@ commands: 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!' + gui: + titles: + team-invite-panel: "Invite Players" + tips: + LEFT: + name: "&b Left Click" + invite: | + &a to invite a player + &a to join your team + RIGHT: + name: "&b Right Click" + coop: "&a to coop player" + SHIFT_LEFT: + name: "&b Shift Left Click" + trust: "&a to trust a player" errors: cannot-invite-self: '&c You cannot invite yourself!' cooldown: '&c You cannot invite that person for another [number] seconds.' diff --git a/src/main/resources/panels/team_invite_panel.yml b/src/main/resources/panels/team_invite_panel.yml new file mode 100644 index 000000000..722a0bd8b --- /dev/null +++ b/src/main/resources/panels/team_invite_panel.yml @@ -0,0 +1,90 @@ +# Name of panel used for indentification in the code - must be the same name as the filename. +team_panel: + # Title of the panel shown to the user. This is a reference and the reference will be translatable in the locale file + title: commands.island.team.invite.gui.titles.team-invite-panel + # The type of panel to show. Options are INVENTORY, HOPPER, DROPPER. INVENTORY is that standard chest inventory and + # the others refer to the inventories shown for those items. + type: INVENTORY + # The background of the panel. These items will be shown if other items are not there. STAINED_GLASS_PANEs give a good effect. + background: + icon: BLACK_STAINED_GLASS_PANE + # Each item may have text applied to it, but usually for background items, nothing is shown. + title: "&b&r" # Empty text. This is using the Bukkit chat color coding with &'s. + border: + # The border of each panel may be shown as a different item. + # It can be used to provide a contrast to items in the panel. + icon: BLUE_STAINED_GLASS_PANE + title: "&b&r" # Empty text + # This tag indicates which rows in the panel must be shown. The panel will be sized vertically accordingly. This does not include the borders. + # This can be a list and rows must be between 1 and 6, if used. + force-shown: [] + # The content section contains details of each item/button in the panel. The numbers indicate the rows and then then columns of each item. + content: + # Row number + 2: + 2: prospect_button + 3: prospect_button + 4: prospect_button + 5: prospect_button + 6: prospect_button + 7: prospect_button + 8: prospect_button + 3: + 2: prospect_button + 3: prospect_button + 4: prospect_button + 5: prospect_button + 6: prospect_button + 7: prospect_button + 8: prospect_button + 4: + 2: prospect_button + 3: prospect_button + 4: prospect_button + 5: prospect_button + 6: prospect_button + 7: prospect_button + 8: prospect_button + 5: + 2: prospect_button + 3: prospect_button + 4: prospect_button + 5: prospect_button + 6: prospect_button + 7: prospect_button + 8: prospect_button + 6: + 2: prospect_button + 3: prospect_button + 4: prospect_button + 5: prospect_button + 6: prospect_button + 7: prospect_button + 8: prospect_button + # This is where reusable buttons are defined. + reusable: + # This is the name of the button that is referenced + prospect_button: + # If the icon for a button is not defined, it defaults to AIR and so effectively will not be shown. + # icons are usually not defined if the icon is going to be dynamically set in the panel, e.g. in this case the material will vary + #icon: STONE + title: commands.island.team.invite.gui.buttons.member.name + description: commands.island.team.invite.gui.buttons.member.description + data: + type: PROSPECT + # Actions cover what happens if the button is clicked or the mouse is moved over it. There can be multiple actions possible for different + # click-types. + actions: + # Each action has an arbitrary descriptive name to define it. + invite: + # The click-type is the same as the bukkit {@link org.bukkit.event.inventory.ClickType}. UNKNOWN is the default. + click-type: LEFT + # tooltip is a locale reference that will be translated for the user and shown when they hover over the button. + tooltip: commands.island.team.invite.gui.tips.LEFT.invite + coop: + click-type: RIGHT + tooltip: commands.island.team.invite.gui.tips.RIGHT.coop + trust: + click-type: SHIFT_LEFT + tooltip: commands.island.team.invite.gui.tips.SHIFT_LEFT.trust + \ No newline at end of file diff --git a/src/main/resources/panels/team_panel.yml b/src/main/resources/panels/team_panel.yml index e9ca5d19f..c34deb8d4 100644 --- a/src/main/resources/panels/team_panel.yml +++ b/src/main/resources/panels/team_panel.yml @@ -13,7 +13,7 @@ team_panel: border: # The border of each panel may be shown as a different item. # It can be used to provide a contrast to items in the panel. - icon: BLACK_STAINED_GLASS_PANE + icon: BLUE_STAINED_GLASS_PANE title: "&b&r" # Empty text # This tag indicates which rows in the panel must be shown. The panel will be sized vertically accordingly. This does not include the borders. # This can be a list and rows must be between 1 and 6, if used. @@ -61,6 +61,15 @@ team_panel: reject: click-type: SHIFT_RIGHT tooltip: commands.island.team.gui.tips.SHIFT_RIGHT.reject + 7: + # Invite button + data: + type: INVITE + name: commands.island.team.gui.buttons.invite + actions: + invite: + click-type: LEFT + tooltip: commands.island.team.gui.tips.LEFT.invite 2: 2: member_button 3: member_button From 5fcc203dcaed84caf0a63ddedfbe850c6b6e473d Mon Sep 17 00:00:00 2001 From: tastybento <tastybento@users.noreply.github.com> Date: Thu, 4 Jan 2024 21:56:20 +0900 Subject: [PATCH 13/22] Adds inviting to the GUI. --- .../island/team/IslandTeamCommand.java | 25 ++++- .../island/team/IslandTeamInviteCommand.java | 97 ++++++++++++++++--- src/main/resources/locales/en-US.yml | 2 + .../resources/panels/team_invite_panel.yml | 28 +++++- 4 files changed, 132 insertions(+), 20 deletions(-) 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 c7d00d979..6ea415f9e 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 @@ -21,7 +21,6 @@ import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; -import world.bentobox.bentobox.BentoBox; import world.bentobox.bentobox.api.commands.CompositeCommand; import world.bentobox.bentobox.api.events.IslandBaseEvent; import world.bentobox.bentobox.api.events.team.TeamEvent; @@ -80,6 +79,10 @@ public class IslandTeamCommand extends CompositeCommand { private IslandTeamInviteCommand inviteCommand; + private IslandTeamCoopCommand coopCommand; + + private IslandTeamTrustCommand trustCommand; + public IslandTeamCommand(CompositeCommand parent) { super(parent, "team"); inviteMap = new HashMap<>(); @@ -98,18 +101,18 @@ public void setup() { acceptCommand = new IslandTeamInviteAcceptCommand(this); rejectCommand = new IslandTeamInviteRejectCommand(this); if (RanksManager.getInstance().rankExists(RanksManager.COOP_RANK_REF)) { - new IslandTeamCoopCommand(this); + coopCommand = new IslandTeamCoopCommand(this); uncoopCommand = new IslandTeamUncoopCommand(this); } if (RanksManager.getInstance().rankExists(RanksManager.TRUSTED_RANK_REF)) { - new IslandTeamTrustCommand(this); + trustCommand = new IslandTeamTrustCommand(this); unTrustCommand = new IslandTeamUntrustCommand(this); } new IslandTeamPromoteCommand(this, "promote"); new IslandTeamPromoteCommand(this, "demote"); // Panels - getPlugin().saveResource("panels/team_panel.yml", true); + getPlugin().saveResource("panels/team_panel.yml", false); } @Override @@ -666,4 +669,18 @@ public Invite getInvite(UUID invitee) { public void removeInvite(@NonNull UUID invitee) { inviteMap.remove(invitee); } + + /** + * @return the coopCommand + */ + protected IslandTeamCoopCommand getCoopCommand() { + return coopCommand; + } + + /** + * @return the trustCommand + */ + protected IslandTeamTrustCommand getTrustCommand() { + return trustCommand; + } } 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 95cca395f..3b6f8d50c 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 @@ -8,7 +8,9 @@ import java.util.UUID; import org.bukkit.Material; +import org.bukkit.Sound; import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; import org.eclipse.jdt.annotation.Nullable; @@ -17,6 +19,7 @@ import world.bentobox.bentobox.api.events.IslandBaseEvent; import world.bentobox.bentobox.api.events.team.TeamEvent; import world.bentobox.bentobox.api.localization.TextVariables; +import world.bentobox.bentobox.api.panels.Panel; import world.bentobox.bentobox.api.panels.PanelItem; import world.bentobox.bentobox.api.panels.TemplatedPanel; import world.bentobox.bentobox.api.panels.builders.PanelItemBuilder; @@ -37,6 +40,8 @@ public class IslandTeamInviteCommand extends CompositeCommand { private @Nullable TemplateItem border; private @Nullable TemplateItem background; private User user; + private int page = 0; // This number by 35 + private static final int PER_PAGE = 35; public IslandTeamInviteCommand(IslandTeamCommand parent) { super(parent, "invite"); @@ -50,7 +55,7 @@ public void setup() { setDescription("commands.island.team.invite.description"); setConfigurableRankCommand(); // Panels - getPlugin().saveResource("panels/team_invite_panel.yml", true); + getPlugin().saveResource("panels/team_invite_panel.yml", false); } @@ -227,14 +232,13 @@ public void build(User user) { panelBuilder.user(user); panelBuilder.world(user.getWorld()); - panelBuilder.template("team_panel", new File(getPlugin().getDataFolder(), "panels")); + panelBuilder.template("team_invite_panel", new File(getPlugin().getDataFolder(), "panels")); panelBuilder.parameters("[name]", user.getName(), "[display_name]", user.getDisplayName()); panelBuilder.registerTypeBuilder("PROSPECT", this::createProspectButton); - //panelBuilder.registerTypeBuilder("INVITED", this::createInvitedButton); - //panelBuilder.registerTypeBuilder("RANK", this::createRankButton); - //panelBuilder.registerTypeBuilder("INVITE", this::createInviteButton); + panelBuilder.registerTypeBuilder("PREVIOUS", this::createPreviousButton); + panelBuilder.registerTypeBuilder("NEXT", this::createNextButton); border = panelBuilder.getPanelTemplate().border(); background = panelBuilder.getPanelTemplate().background(); // Register unknown type builder. @@ -242,6 +246,41 @@ public void build(User user) { } + private PanelItem createNextButton(ItemTemplateRecord template, TemplatedPanel.ItemSlot slot) { + long count = getWorld().getPlayers().stream().filter(player -> user.getPlayer().canSee(player)) + .filter(player -> !player.equals(user.getPlayer())).count(); + if (count > page * PER_PAGE) { + // We need to show a next button + return new PanelItemBuilder().name(user.getTranslation("protection.panel.next")).icon(Material.ARROW) + .clickHandler((panel, user, clickType, clickSlot) -> { + user.getPlayer().playSound(user.getLocation(), Sound.BLOCK_STONE_BUTTON_CLICK_ON, 1F, 1F); + page++; + build(user); + return true; + }).build(); + } + return getBlankBorder(); + } + + private PanelItem createPreviousButton(ItemTemplateRecord template, TemplatedPanel.ItemSlot slot) { + if (page > 0) { + // We need to show a next button + return new PanelItemBuilder().name(user.getTranslation("protection.panel.previous")).icon(Material.ARROW) + .clickHandler((panel, user, clickType, clickSlot) -> { + user.getPlayer().playSound(user.getLocation(), Sound.BLOCK_STONE_BUTTON_CLICK_ON, 1F, 1F); + page--; + build(user); + return true; + }).build(); + } + return getBlankBorder(); + } + + private PanelItem getBlankBorder() { + return new PanelItemBuilder().icon(Objects.requireNonNullElse(border.icon(), new ItemStack(Material.BARRIER))) + .name((Objects.requireNonNullElse(border.title(), ""))).build(); + } + /** * Create member button panel item. * @@ -255,20 +294,48 @@ private PanelItem createProspectButton(ItemTemplateRecord template, TemplatedPan if (island == null) { return this.getBlankBackground(); } - // TODO: THERE"S A BUG HERE - return user.getWorld().getPlayers().stream() - .filter(player -> !getIslands().inTeam(getWorld(), player.getUniqueId())).skip(slot.slot() - 1) - .limit(1L) - .findFirst().map(this::getProspect).orElse(this.getBlankBackground()); + if (page < 0) { + page = 0; + } + return getWorld().getPlayers().stream().filter(player -> user.getPlayer().canSee(player)) + .filter(player -> !player.equals(user.getPlayer())).skip(slot.slot() + page * PER_PAGE).findFirst() + .map(player -> getProspect(player, template)).orElse(this.getBlankBackground()); } - private PanelItem getProspect(Player player) { - return new PanelItemBuilder().icon(player.getName()).build(); + private PanelItem getProspect(Player player, ItemTemplateRecord template) { + // Check if the prospect has already been invited + if (this.itc.isInvited(player.getUniqueId()) + && user.getUniqueId().equals(this.itc.getInvite(player.getUniqueId()).getInviter())) { + return new PanelItemBuilder().icon(player.getName()).name(player.getDisplayName()) + .description(user.getTranslation("commands.island.team.invite.gui.button.already-invited")).build(); + } + List<String> desc = template.actions().stream().map(ar -> user + .getTranslation("commands.island.team.invite.gui.tips." + ar.clickType().name() + ".name") + + " " + user.getTranslation(ar.tooltip())).toList(); + return new PanelItemBuilder().icon(player.getName()).name(player.getDisplayName()).description(desc) + .clickHandler( + (panel, user, clickType, clickSlot) -> clickHandler(panel, user, clickType, clickSlot, player)) + .build(); } - private PanelItem getBlankBorder() { - return new PanelItemBuilder().icon(Objects.requireNonNullElse(border.icon(), new ItemStack(Material.BARRIER))) - .name((Objects.requireNonNullElse(border.title(), ""))).build(); + private boolean clickHandler(Panel panel, User user, ClickType clickType, int clickSlot, Player player) { + if (clickType.equals(ClickType.LEFT)) { + user.closeInventory(); + if (this.canExecute(user, this.getLabel(), List.of(player.getName()))) { + this.execute(user, getLabel(), List.of(player.getName())); + } + } else if (clickType.equals(ClickType.RIGHT)) { + user.closeInventory(); + if (this.itc.getCoopCommand().canExecute(user, this.getLabel(), List.of(player.getName()))) { + this.itc.getCoopCommand().execute(user, getLabel(), List.of(player.getName())); + } + } else if (clickType.equals(ClickType.SHIFT_LEFT)) { + user.closeInventory(); + if (this.itc.getTrustCommand().canExecute(user, this.getLabel(), List.of(player.getName()))) { + this.itc.getTrustCommand().execute(user, getLabel(), List.of(player.getName())); + } + } + return true; } private PanelItem getBlankBackground() { diff --git a/src/main/resources/locales/en-US.yml b/src/main/resources/locales/en-US.yml index 0014ef630..51e4ea18b 100644 --- a/src/main/resources/locales/en-US.yml +++ b/src/main/resources/locales/en-US.yml @@ -710,6 +710,8 @@ commands: gui: titles: team-invite-panel: "Invite Players" + button: + already-invited: "&c Invited already" tips: LEFT: name: "&b Left Click" diff --git a/src/main/resources/panels/team_invite_panel.yml b/src/main/resources/panels/team_invite_panel.yml index 722a0bd8b..e3c5b3326 100644 --- a/src/main/resources/panels/team_invite_panel.yml +++ b/src/main/resources/panels/team_invite_panel.yml @@ -1,5 +1,5 @@ # Name of panel used for indentification in the code - must be the same name as the filename. -team_panel: +team_invite_panel: # Title of the panel shown to the user. This is a reference and the reference will be translatable in the locale file title: commands.island.team.invite.gui.titles.team-invite-panel # The type of panel to show. Options are INVENTORY, HOPPER, DROPPER. INVENTORY is that standard chest inventory and @@ -21,6 +21,32 @@ team_panel: # The content section contains details of each item/button in the panel. The numbers indicate the rows and then then columns of each item. content: # Row number + 1: + 2: + data: + type: PREVIOUS + # Actions cover what happens if the button is clicked or the mouse is moved over it. There can be multiple actions possible for different + # click-types. + actions: + # Each action has an arbitrary descriptive name to define it. + view: + # The click-type is the same as the bukkit {@link org.bukkit.event.inventory.ClickType}. UNKNOWN is the default. + click-type: LEFT + # tooltip is a locale reference that will be translated for the user and shown when they hover over the button. + tooltip: commands.island.team.invite.gui.tips.previous + 8: + data: + type: NEXT + # Actions cover what happens if the button is clicked or the mouse is moved over it. There can be multiple actions possible for different + # click-types. + actions: + # Each action has an arbitrary descriptive name to define it. + view: + # The click-type is the same as the bukkit {@link org.bukkit.event.inventory.ClickType}. UNKNOWN is the default. + click-type: LEFT + # tooltip is a locale reference that will be translated for the user and shown when they hover over the button. + tooltip: commands.island.team.invite.gui.tips.next + 2: 2: prospect_button 3: prospect_button From 3702870095b0b8b662c94d2b0c41778eb9ecdbf1 Mon Sep 17 00:00:00 2001 From: tastybento <tastybento@users.noreply.github.com> Date: Fri, 5 Jan 2024 10:48:02 +0900 Subject: [PATCH 14/22] Fix tests --- .../island/team/IslandTeamCommand.java | 8 ++++++- .../island/team/IslandTeamCommandTest.java | 23 +++++-------------- .../team/IslandTeamInviteCommandTest.java | 18 +++++++++++++++ 3 files changed, 31 insertions(+), 18 deletions(-) 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 6ea415f9e..1b266f47a 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 @@ -116,7 +116,7 @@ public void setup() { } @Override - public boolean execute(User user, String label, List<String> args) { + public boolean canExecute(User user, String label, List<String> args) { this.user = user; // Player issuing the command must have an island island = getIslands().getPrimaryIsland(getWorld(), user.getUniqueId()); @@ -146,8 +146,14 @@ public boolean execute(User user, String label, List<String> args) { user.sendMessage("commands.island.team.invite.errors.island-is-full"); } } + return true; + } + + @Override + public boolean execute(User user, String label, List<String> args) { // Show members of island showMembers().forEach(user::sendRawMessage); + // Show the panel build(); return true; } 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 5ee5552fd..b0f360d80 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 @@ -31,7 +31,6 @@ import world.bentobox.bentobox.BentoBox; import world.bentobox.bentobox.api.commands.CompositeCommand; import world.bentobox.bentobox.api.commands.island.team.Invite.Type; -import world.bentobox.bentobox.api.localization.TextVariables; import world.bentobox.bentobox.api.user.User; import world.bentobox.bentobox.database.objects.Island; import world.bentobox.bentobox.managers.CommandsManager; @@ -149,33 +148,23 @@ public void testSetup() { } /** - * Test method for {@link world.bentobox.bentobox.api.commands.island.team.IslandTeamCommand#execute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. + * Test method for {@link world.bentobox.bentobox.api.commands.island.team.IslandTeamCommand#canExecute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. */ @Test - public void testExecuteUserStringListOfStringNoIsland() { + public void testCanExecuteUserStringListOfStringNoIsland() { when(im.getPrimaryIsland(world, uuid)).thenReturn(null); - assertFalse(tc.execute(user, "team", Collections.emptyList())); + assertFalse(tc.canExecute(user, "team", Collections.emptyList())); verify(user).sendMessage(eq("general.errors.no-island")); } /** - * Test method for - * {@link world.bentobox.bentobox.api.commands.island.team.IslandTeamCommand#execute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. - */ - @Test - public void testExecuteUserStringListOfStringIslandIsNotFull() { - assertTrue(tc.execute(user, "team", Collections.emptyList())); - verify(user).sendMessage(eq("commands.island.team.invite.you-can-invite"), eq(TextVariables.NUMBER), eq("3")); - } - - /** - * Test method for {@link world.bentobox.bentobox.api.commands.island.team.IslandTeamCommand#execute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. + * Test method for {@link world.bentobox.bentobox.api.commands.island.team.IslandTeamCommand#canExecute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. */ @Test - public void testExecuteUserStringListOfStringIslandIsFull() { + public void testCanExecuteUserStringListOfStringIslandIsFull() { // Max members when(im.getMaxMembers(eq(island), eq(RanksManager.MEMBER_RANK))).thenReturn(0); - assertTrue(tc.execute(user, "team", Collections.emptyList())); + assertTrue(tc.canExecute(user, "team", Collections.emptyList())); verify(user).sendMessage(eq("commands.island.team.invite.errors.island-is-full")); } 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 8fbe46b1c..e18155a47 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 @@ -11,6 +11,7 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import java.io.File; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -19,6 +20,10 @@ import org.bukkit.Bukkit; import org.bukkit.World; import org.bukkit.entity.Player; +import org.bukkit.event.inventory.InventoryType; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemFactory; +import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.plugin.PluginManager; import org.bukkit.scheduler.BukkitScheduler; import org.eclipse.jdt.annotation.NonNull; @@ -92,6 +97,10 @@ public void setUp() throws Exception { // Settings when(plugin.getSettings()).thenReturn(s); + // Data folder for panels + when(plugin.getDataFolder()) + .thenReturn(new File("src" + File.separator + "main" + File.separator + "resources")); + // Player & users PowerMockito.mockStatic(User.class); @@ -165,6 +174,15 @@ public void setUp() throws Exception { // Parent command when(ic.getTopLabel()).thenReturn("island"); + // Mock item factory (for itemstacks) + ItemFactory itemFactory = mock(ItemFactory.class); + ItemMeta bannerMeta = mock(ItemMeta.class); + when(itemFactory.getItemMeta(any())).thenReturn(bannerMeta); + when(Bukkit.getItemFactory()).thenReturn(itemFactory); + Inventory inventory = mock(Inventory.class); + when(Bukkit.createInventory(eq(null), anyInt(), any())).thenReturn(inventory); + when(Bukkit.createInventory(eq(null), any(InventoryType.class), any())).thenReturn(inventory); + // Command under test itl = new IslandTeamInviteCommand(ic); From 7392e036d933e198667e8253f29b1fbb79d7eb06 Mon Sep 17 00:00:00 2001 From: tastybento <tastybento@users.noreply.github.com> Date: Fri, 5 Jan 2024 11:27:59 +0900 Subject: [PATCH 15/22] Fixed minor bugs reported by SonarCloud --- .../island/team/IslandTeamCommand.java | 50 +++++++++---------- .../island/team/IslandTeamInviteCommand.java | 4 +- .../team/IslandTeamSetownerCommand.java | 3 +- 3 files changed, 27 insertions(+), 30 deletions(-) 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 1b266f47a..c63124629 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 @@ -9,6 +9,7 @@ import java.util.Locale; import java.util.Map; import java.util.Objects; +import java.util.Optional; import java.util.Set; import java.util.UUID; @@ -403,13 +404,9 @@ private PanelItem ownerView(ItemTemplateRecord template, ItemSlot slot) { if (slot.slot() > subOwnerCount + memberCount + trustedCount && slot.slot() < subOwnerCount + memberCount + trustedCount + coopCount + 1) { // Show coops - PanelItem item = getMemberButton(RanksManager.COOP_RANK, slot.slot(), template.actions()); - if (item != null) { - return item; - } - + return getMemberButton(RanksManager.COOP_RANK, slot.slot(), template.actions()); } - return new PanelItemBuilder().icon(Material.BLACK_STAINED_GLASS_PANE).name("&b&r").build(); + return this.getBlankBackground(); } @@ -426,8 +423,12 @@ private PanelItem getMemberButton(int targetRank, int slot, List<ActionRecords> return getMemberButton(RanksManager.OWNER_RANK, 1, actions); } String ref = RanksManager.getInstance().getRank(targetRank); - User member = island.getMemberSet(targetRank, false).stream().sorted().skip(slot - 1L).limit(1L) - .map(User::getInstance).findFirst().orElse(null); + Optional<User> opMember = island.getMemberSet(targetRank, false).stream().sorted().skip(slot - 1L).limit(1L) + .map(User::getInstance).findFirst(); + if (opMember.isEmpty()) { + return this.getBlankBackground(); + } + User member = opMember.get(); // Make button description depending on viewer List<String> desc = new ArrayList<>(); int userRank = Objects.requireNonNull(island).getRank(user); @@ -457,26 +458,21 @@ private PanelItem getMemberButton(int targetRank, int slot, List<ActionRecords> + " " + user.getTranslation(ar.tooltip())) .findFirst().ifPresent(desc::add); } - if (member != null) { - if (member.isOnline()) { - desc.add(0, user.getTranslation(ref)); - return new PanelItemBuilder().icon(member.getName()).name(member.getDisplayName()) - .description(desc) - .clickHandler((panel, user, clickType, i) -> clickListener(panel, user, clickType, i, member, - actions)) - .build(); - } else { - // Offline player - desc.add(0, user.getTranslation(ref)); - return new PanelItemBuilder().icon(member.getName()) - .name(offlinePlayerStatus(user, Bukkit.getOfflinePlayer(member.getUniqueId()))) - .description(desc) - .clickHandler((panel, user, clickType, i) -> clickListener(panel, user, clickType, i, member, - actions)) - .build(); - } + if (member.isOnline()) { + desc.add(0, user.getTranslation(ref)); + return new PanelItemBuilder().icon(member.getName()).name(member.getDisplayName()).description(desc) + .clickHandler( + (panel, user, clickType, i) -> clickListener(panel, user, clickType, i, member, actions)) + .build(); + } else { + // Offline player + desc.add(0, user.getTranslation(ref)); + return new PanelItemBuilder().icon(member.getName()) + .name(offlinePlayerStatus(user, Bukkit.getOfflinePlayer(member.getUniqueId()))).description(desc) + .clickHandler( + (panel, user, clickType, i) -> clickListener(panel, user, clickType, i, member, actions)) + .build(); } - return null; } private boolean clickListener(Panel panel, User clicker, ClickType clickType, int i, User member, 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 3b6f8d50c..33f63da70 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 @@ -40,8 +40,8 @@ public class IslandTeamInviteCommand extends CompositeCommand { private @Nullable TemplateItem border; private @Nullable TemplateItem background; private User user; - private int page = 0; // This number by 35 - private static final int PER_PAGE = 35; + private long page = 0; // This number by 35 + private static final long PER_PAGE = 35; public IslandTeamInviteCommand(IslandTeamCommand parent) { super(parent, "invite"); 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 0c792fe6b..24f10557b 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,7 @@ import java.util.Optional; import java.util.UUID; +import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; import world.bentobox.bentobox.api.commands.CompositeCommand; @@ -73,7 +74,7 @@ public boolean execute(User user, String label, List<String> args) { } - protected boolean setOwner(User user, @Nullable UUID targetUUID2) { + protected boolean setOwner(User user, @NonNull UUID targetUUID2) { // Fire event so add-ons can run commands, etc. Island island = getIslands().getPrimaryIsland(getWorld(), user.getUniqueId()); // Fire event so add-ons can run commands, etc. From 1a702bc74a7b4f68c57d88ba0981ecd9f0326c5d Mon Sep 17 00:00:00 2001 From: tastybento <tastybento@users.noreply.github.com> Date: Fri, 5 Jan 2024 13:21:09 +0900 Subject: [PATCH 16/22] Up Minecraft version and paper to 1.20.4 in POM --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 7ab9b80d2..ce7f409d7 100644 --- a/pom.xml +++ b/pom.xml @@ -73,10 +73,10 @@ <postgresql.version>42.2.18</postgresql.version> <hikaricp.version>5.0.1</hikaricp.version> <!-- More visible way to change dependency versions --> - <spigot.version>1.20.3-R0.1-SNAPSHOT</spigot.version> + <spigot.version>1.20.4-R0.1-SNAPSHOT</spigot.version> <!-- Might differ from the last Spigot release for short periods of time --> - <paper.version>1.20.2-R0.1-SNAPSHOT</paper.version> + <paper.version>1.20.4-R0.1-SNAPSHOT</paper.version> <bstats.version>3.0.0</bstats.version> <vault.version>1.7.1</vault.version> <placeholderapi.version>2.10.9</placeholderapi.version> From 4e3a8e84b0500bc3ae61659a58aafa2013b69214 Mon Sep 17 00:00:00 2001 From: tastybento <tastybento@users.noreply.github.com> Date: Fri, 5 Jan 2024 16:36:43 +0900 Subject: [PATCH 17/22] Added features based on Discord feedback. 1. added some lore to the invite button to explain the players shown are from the game world 2. removed the team state in chat 3. added a search to the invite panel --- .../island/team/IslandTeamCommand.java | 3 +- .../island/team/IslandTeamInviteCommand.java | 35 ++++++++++++++- .../team/conversations/InviteNamePrompt.java | 44 +++++++++++++++++++ .../api/panels/reader/ItemTemplateRecord.java | 34 +++++++++++--- src/main/resources/locales/en-US.yml | 39 +++++++++------- .../resources/panels/team_invite_panel.yml | 13 ++++++ 6 files changed, 142 insertions(+), 26 deletions(-) create mode 100644 src/main/java/world/bentobox/bentobox/api/commands/island/team/conversations/InviteNamePrompt.java 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 c63124629..6557f7d05 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 @@ -152,8 +152,6 @@ public boolean canExecute(User user, String label, List<String> args) { @Override public boolean execute(User user, String label, List<String> args) { - // Show members of island - showMembers().forEach(user::sendRawMessage); // Show the panel build(); return true; @@ -191,6 +189,7 @@ private PanelItem createInviteButton(ItemTemplateRecord template, TemplatedPanel PanelItemBuilder builder = new PanelItemBuilder(); builder.icon(Material.PLAYER_HEAD); builder.name(user.getTranslation("commands.island.team.gui.buttons.invite.name")); + builder.description(user.getTranslation("commands.island.team.gui.buttons.invite.description")); builder.clickHandler((panel, user, clickType, clickSlot) -> { if (clickType.equals(ClickType.LEFT)) { user.closeInventory(); 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 33f63da70..76ecb5cce 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 @@ -9,13 +9,16 @@ import org.bukkit.Material; import org.bukkit.Sound; +import org.bukkit.conversations.ConversationFactory; import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; import org.eclipse.jdt.annotation.Nullable; +import world.bentobox.bentobox.BentoBox; import world.bentobox.bentobox.api.commands.CompositeCommand; import world.bentobox.bentobox.api.commands.island.team.Invite.Type; +import world.bentobox.bentobox.api.commands.island.team.conversations.InviteNamePrompt; import world.bentobox.bentobox.api.events.IslandBaseEvent; import world.bentobox.bentobox.api.events.team.TeamEvent; import world.bentobox.bentobox.api.localization.TextVariables; @@ -239,6 +242,9 @@ public void build(User user) { panelBuilder.registerTypeBuilder("PROSPECT", this::createProspectButton); panelBuilder.registerTypeBuilder("PREVIOUS", this::createPreviousButton); panelBuilder.registerTypeBuilder("NEXT", this::createNextButton); + panelBuilder.registerTypeBuilder("SEARCH", this::createSearchButton); + + // Stash the backgrounds for later use border = panelBuilder.getPanelTemplate().border(); background = panelBuilder.getPanelTemplate().background(); // Register unknown type builder. @@ -246,12 +252,26 @@ public void build(User user) { } + private PanelItem createSearchButton(ItemTemplateRecord template, TemplatedPanel.ItemSlot slot) { + checkTemplate(template); + return new PanelItemBuilder().name(user.getTranslation(template.title())).icon(template.icon()) + .clickHandler((panel, user, clickType, clickSlot) -> { + user.closeInventory(); + new ConversationFactory(BentoBox.getInstance()).withLocalEcho(false).withTimeout(90) + .withModality(false) + .withFirstPrompt(new InviteNamePrompt(user, this)) + .buildConversation(user.getPlayer()).begin(); + return true; + }).build(); + } + private PanelItem createNextButton(ItemTemplateRecord template, TemplatedPanel.ItemSlot slot) { + checkTemplate(template); long count = getWorld().getPlayers().stream().filter(player -> user.getPlayer().canSee(player)) .filter(player -> !player.equals(user.getPlayer())).count(); if (count > page * PER_PAGE) { // We need to show a next button - return new PanelItemBuilder().name(user.getTranslation("protection.panel.next")).icon(Material.ARROW) + return new PanelItemBuilder().name(user.getTranslation(template.title())).icon(template.icon()) .clickHandler((panel, user, clickType, clickSlot) -> { user.getPlayer().playSound(user.getLocation(), Sound.BLOCK_STONE_BUTTON_CLICK_ON, 1F, 1F); page++; @@ -262,10 +282,21 @@ private PanelItem createNextButton(ItemTemplateRecord template, TemplatedPanel.I return getBlankBorder(); } + private void checkTemplate(ItemTemplateRecord template) { + if (template.icon() == null) { + getPlugin().logError("Icon in template is missing or unknown! " + template.toString()); + } + if (template.title() == null) { + getPlugin().logError("Title in template is missing! " + template.toString()); + } + + } + private PanelItem createPreviousButton(ItemTemplateRecord template, TemplatedPanel.ItemSlot slot) { + checkTemplate(template); if (page > 0) { // We need to show a next button - return new PanelItemBuilder().name(user.getTranslation("protection.panel.previous")).icon(Material.ARROW) + return new PanelItemBuilder().name(user.getTranslation(template.title())).icon(template.icon()) .clickHandler((panel, user, clickType, clickSlot) -> { user.getPlayer().playSound(user.getLocation(), Sound.BLOCK_STONE_BUTTON_CLICK_ON, 1F, 1F); page--; diff --git a/src/main/java/world/bentobox/bentobox/api/commands/island/team/conversations/InviteNamePrompt.java b/src/main/java/world/bentobox/bentobox/api/commands/island/team/conversations/InviteNamePrompt.java new file mode 100644 index 000000000..6517741db --- /dev/null +++ b/src/main/java/world/bentobox/bentobox/api/commands/island/team/conversations/InviteNamePrompt.java @@ -0,0 +1,44 @@ +package world.bentobox.bentobox.api.commands.island.team.conversations; + +import java.util.List; + +import org.bukkit.conversations.ConversationContext; +import org.bukkit.conversations.Prompt; +import org.bukkit.conversations.StringPrompt; +import org.eclipse.jdt.annotation.NonNull; + +import world.bentobox.bentobox.api.commands.island.team.IslandTeamInviteCommand; +import world.bentobox.bentobox.api.user.User; + +/** + * Invites a player by search + * @author tastybento + * + */ +public class InviteNamePrompt extends StringPrompt { + + @NonNull + private final User user; + @NonNull + private final IslandTeamInviteCommand itic; + + public InviteNamePrompt(@NonNull User user, IslandTeamInviteCommand islandTeamInviteCommand) { + this.user = user; + this.itic = islandTeamInviteCommand; + } + + @Override + @NonNull + public String getPromptText(@NonNull ConversationContext context) { + return user.getTranslation("commands.island.team.invite.gui.enter-name"); + } + + @Override + public Prompt acceptInput(@NonNull ConversationContext context, String input) { + if (itic.canExecute(user, itic.getLabel(), List.of(input))) { + itic.execute(user, itic.getLabel(), List.of(input)); + } + return Prompt.END_OF_CONVERSATION; + } + +} diff --git a/src/main/java/world/bentobox/bentobox/api/panels/reader/ItemTemplateRecord.java b/src/main/java/world/bentobox/bentobox/api/panels/reader/ItemTemplateRecord.java index ff7424f69..85b1ef2fd 100644 --- a/src/main/java/world/bentobox/bentobox/api/panels/reader/ItemTemplateRecord.java +++ b/src/main/java/world/bentobox/bentobox/api/panels/reader/ItemTemplateRecord.java @@ -27,8 +27,30 @@ * * @since 1.17.3 */ -public record ItemTemplateRecord(@Nullable ItemStack icon, @Nullable String title, @Nullable String description, - @NonNull List<ActionRecords> actions, @NonNull Map<String, Object> dataMap, +public record ItemTemplateRecord( + /** + * ItemStack of the Item + */ + @Nullable ItemStack icon, + /** + * Title of the item + */ + @Nullable String title, + /** + * Lore message of the item + */ + @Nullable String description, + /** + * List of Actions for a button + */ + @NonNull List<ActionRecords> actions, + /** + * DataMap that links additional objects for a button. + */ + @NonNull Map<String, Object> dataMap, + /** + * FallBack item if current one is not possible to generate. + */ @Nullable ItemTemplateRecord fallback) { /** @@ -75,12 +97,12 @@ public void addAction(ActionRecords actionData) { */ public record ActionRecords( /** - * the click type - */ + * the click type + */ ClickType clickType, /** - * the string that represents action type - */ + * the string that represents action type + */ String actionType, /** * the content of the action diff --git a/src/main/resources/locales/en-US.yml b/src/main/resources/locales/en-US.yml index 3cc79aa1d..f8b1d30c9 100644 --- a/src/main/resources/locales/en-US.yml +++ b/src/main/resources/locales/en-US.yml @@ -625,6 +625,10 @@ commands: invitation: "Invitation" invite: name: "Invite player" + description: | + &a Players must be in the + &a same world as you to be + &a shown in the list. tips: LEFT: name: "&b Left Click" @@ -708,22 +712,25 @@ commands: reject to reject' you-will-lose-your-island: '&c WARNING! You will lose your island if you accept!' gui: - titles: - team-invite-panel: "Invite Players" - button: - already-invited: "&c Invited already" - tips: - LEFT: - name: "&b Left Click" - invite: | - &a to invite a player - &a to join your team - RIGHT: - name: "&b Right Click" - coop: "&a to coop player" - SHIFT_LEFT: - name: "&b Shift Left Click" - trust: "&a to trust a player" + titles: + team-invite-panel: "Invite Players" + button: + already-invited: "&c Invited already" + search: "&a Search for a player" + enter-name: "&a Enter name:" + tips: + LEFT: + name: "&b Left Click" + search: "&a Enter the player's name" + invite: | + &a to invite a player + &a to join your team + RIGHT: + name: "&b Right Click" + coop: "&a to coop player" + SHIFT_LEFT: + name: "&b Shift Left Click" + trust: "&a to trust a player" errors: cannot-invite-self: '&c You cannot invite yourself!' cooldown: '&c You cannot invite that person for another [number] seconds.' diff --git a/src/main/resources/panels/team_invite_panel.yml b/src/main/resources/panels/team_invite_panel.yml index e3c5b3326..7c816d0e7 100644 --- a/src/main/resources/panels/team_invite_panel.yml +++ b/src/main/resources/panels/team_invite_panel.yml @@ -23,6 +23,8 @@ team_invite_panel: # Row number 1: 2: + title: "protection.panel.previous" + icon: ARROW data: type: PREVIOUS # Actions cover what happens if the button is clicked or the mouse is moved over it. There can be multiple actions possible for different @@ -34,7 +36,18 @@ team_invite_panel: click-type: LEFT # tooltip is a locale reference that will be translated for the user and shown when they hover over the button. tooltip: commands.island.team.invite.gui.tips.previous + 5: + title: "commands.island.team.invite.gui.button.search" + icon: PLAYER_HEAD + data: + type: SEARCH + actions: + search: + click-type: LEFT + tooltip: commands.island.team.invite.gui.tips.search 8: + title: "protection.panel.next" + icon: ARROW data: type: NEXT # Actions cover what happens if the button is clicked or the mouse is moved over it. There can be multiple actions possible for different From ee0ed2c38599e7e738a4d11f0e336e367947cdb3 Mon Sep 17 00:00:00 2001 From: tastybento <tastybento@users.noreply.github.com> Date: Fri, 5 Jan 2024 17:42:52 +0900 Subject: [PATCH 18/22] Added back button. Refactored some code and templates. --- .../island/team/IslandTeamCommand.java | 2 +- .../island/team/IslandTeamInviteCommand.java | 52 ++++++++----------- src/main/resources/locales/en-US.yml | 1 + .../resources/panels/team_invite_panel.yml | 16 +++++- .../team/IslandTeamInviteCommandTest.java | 6 +-- 5 files changed, 42 insertions(+), 35 deletions(-) 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 6557f7d05..24cdb911b 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 @@ -160,7 +160,7 @@ public boolean execute(User user, String label, List<String> args) { /** * This method builds this GUI. */ - private void build() { + void build() { // Start building panel. TemplatedPanelBuilder panelBuilder = new TemplatedPanelBuilder(); panelBuilder.user(user); 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 76ecb5cce..4154875cf 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 @@ -44,6 +44,7 @@ public class IslandTeamInviteCommand extends CompositeCommand { private @Nullable TemplateItem background; private User user; private long page = 0; // This number by 35 + private boolean inviteCmd; private static final long PER_PAGE = 35; public IslandTeamInviteCommand(IslandTeamCommand parent) { @@ -74,7 +75,9 @@ public boolean canExecute(User user, String label, List<String> args) { } if (args.size() != 1) { - return handleCommandWithNoArgs(user); + this.inviteCmd = true; + build(user); + return true; } Island island = islandsManager.getIsland(getWorld(), user); @@ -83,25 +86,6 @@ public boolean canExecute(User user, String label, List<String> args) { return checkRankAndInvitePlayer(user, island, rank, args.get(0)); } - private boolean handleCommandWithNoArgs(User user) { - UUID playerUUID = user.getUniqueId(); - Type inviteType = getInviteType(playerUUID); - - if (inviteType != null) { - // TODO: send to team command to present invite - String name = getPlayers().getName(playerUUID); - switch (inviteType) { - case COOP -> user.sendMessage("commands.island.team.invite.name-has-invited-you.coop", TextVariables.NAME, name); - case TRUST -> user.sendMessage("commands.island.team.invite.name-has-invited-you.trust", TextVariables.NAME, name); - default -> user.sendMessage("commands.island.team.invite.name-has-invited-you", TextVariables.NAME, name); - } - return true; - } - build(user); - showHelp(this, user); - return false; - } - private boolean checkRankAndInvitePlayer(User user, Island island, int rank, String playerName) { PlayersManager playersManager = getPlayers(); UUID playerUUID = user.getUniqueId(); @@ -151,14 +135,6 @@ private boolean checkRankAndInvitePlayer(User user, Island island, int rank, Str return true; } - private Type getInviteType(UUID playerUUID) { - if (itc.isInvited(playerUUID)) { - Invite invite = itc.getInvite(playerUUID); - return invite.getType(); - } - return null; - } - private boolean canInvitePlayer(User user, User invitedPlayer) { UUID playerUUID = user.getUniqueId(); if (!invitedPlayer.isOnline() || !user.getPlayer().canSee(invitedPlayer.getPlayer())) { @@ -228,7 +204,11 @@ public Optional<List<String>> tabComplete(User user, String alias, List<String> return Optional.of(Util.tabLimit(options, lastArg)); } - public void build(User user) { + /** + * Build the invite panel + * @param user use of the panel + */ + void build(User user) { this.user = user; // Start building panel. TemplatedPanelBuilder panelBuilder = new TemplatedPanelBuilder(); @@ -243,7 +223,7 @@ public void build(User user) { panelBuilder.registerTypeBuilder("PREVIOUS", this::createPreviousButton); panelBuilder.registerTypeBuilder("NEXT", this::createNextButton); panelBuilder.registerTypeBuilder("SEARCH", this::createSearchButton); - + panelBuilder.registerTypeBuilder("BACK", this::createBackButton); // Stash the backgrounds for later use border = panelBuilder.getPanelTemplate().border(); background = panelBuilder.getPanelTemplate().background(); @@ -252,6 +232,18 @@ public void build(User user) { } + private PanelItem createBackButton(ItemTemplateRecord template, TemplatedPanel.ItemSlot slot) { + checkTemplate(template); + return new PanelItemBuilder().name(user.getTranslation(template.title())).icon(template.icon()) + .clickHandler((panel, user, clickType, clickSlot) -> { + user.closeInventory(); + if (!inviteCmd) { + this.itc.build(); + } + return true; + }).build(); + } + private PanelItem createSearchButton(ItemTemplateRecord template, TemplatedPanel.ItemSlot slot) { checkTemplate(template); return new PanelItemBuilder().name(user.getTranslation(template.title())).icon(template.icon()) diff --git a/src/main/resources/locales/en-US.yml b/src/main/resources/locales/en-US.yml index f8b1d30c9..6fa23e7cc 100644 --- a/src/main/resources/locales/en-US.yml +++ b/src/main/resources/locales/en-US.yml @@ -722,6 +722,7 @@ commands: LEFT: name: "&b Left Click" search: "&a Enter the player's name" + back: "&a Back" invite: | &a to invite a player &a to join your team diff --git a/src/main/resources/panels/team_invite_panel.yml b/src/main/resources/panels/team_invite_panel.yml index 7c816d0e7..d082daa3d 100644 --- a/src/main/resources/panels/team_invite_panel.yml +++ b/src/main/resources/panels/team_invite_panel.yml @@ -59,7 +59,6 @@ team_invite_panel: click-type: LEFT # tooltip is a locale reference that will be translated for the user and shown when they hover over the button. tooltip: commands.island.team.invite.gui.tips.next - 2: 2: prospect_button 3: prospect_button @@ -100,6 +99,21 @@ team_invite_panel: 6: prospect_button 7: prospect_button 8: prospect_button + 9: + title: "commands.island.team.invite.gui.tips.LEFT.back" + icon: OAK_DOOR + data: + type: BACK + # Actions cover what happens if the button is clicked or the mouse is moved over it. There can be multiple actions possible for different + # click-types. + actions: + # Each action has an arbitrary descriptive name to define it. + back: + # The click-type is the same as the bukkit {@link org.bukkit.event.inventory.ClickType}. UNKNOWN is the default. + click-type: LEFT + # tooltip is a locale reference that will be translated for the user and shown when they hover over the button. + tooltip: commands.island.team.invite.gui.tips.LEFT.back + # This is where reusable buttons are defined. reusable: # This is the name of the button that is referenced 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 e18155a47..706a56cb7 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 @@ -238,9 +238,9 @@ public void testCanExecuteNoIsland() { */ @Test public void testCanExecuteNoTarget() { - assertFalse(itl.canExecute(user, itl.getLabel(), Collections.emptyList())); - // Show help - verify(user).sendMessage("commands.help.header", TextVariables.LABEL, "BSkyBlock"); + assertTrue(itl.canExecute(user, itl.getLabel(), Collections.emptyList())); + // Show panel + verify(p).openInventory(any(Inventory.class)); } /** From 803274b6cd397861cf6aa37ee000ef2972cbc028 Mon Sep 17 00:00:00 2001 From: tastybento <tastybento@users.noreply.github.com> Date: Sun, 7 Jan 2024 17:37:46 +0900 Subject: [PATCH 19/22] Fixed bugs with teams and uncoop untrust etc of Ops. --- .../world/bentobox/bentobox/BentoBox.java | 9 ++- .../island/team/IslandTeamCommand.java | 69 ++++++++++++++----- .../island/team/IslandTeamInviteCommand.java | 24 ++++++- .../island/team/IslandTeamKickCommand.java | 8 ++- .../island/team/IslandTeamLeaveCommand.java | 7 +- .../bentobox/database/objects/Island.java | 3 - .../team/IslandTeamKickCommandTest.java | 39 ++++++----- 7 files changed, 109 insertions(+), 50 deletions(-) diff --git a/src/main/java/world/bentobox/bentobox/BentoBox.java b/src/main/java/world/bentobox/bentobox/BentoBox.java index ee026484f..b70c19c87 100644 --- a/src/main/java/world/bentobox/bentobox/BentoBox.java +++ b/src/main/java/world/bentobox/bentobox/BentoBox.java @@ -1,5 +1,6 @@ package world.bentobox.bentobox; +import java.io.File; import java.util.List; import java.util.Optional; @@ -465,8 +466,12 @@ public boolean loadSettings() { } log("Saving default panels..."); - this.saveResource("panels/island_creation_panel.yml", false); - this.saveResource("panels/language_panel.yml", false); + if (!new File(getDataFolder() + File.separator + "panels", "island_creation_panel.yml").exists()) { + this.saveResource("panels/island_creation_panel.yml", false); + } + if (!new File(getDataFolder() + File.separator + "panels", "language_panel.yml").exists()) { + this.saveResource("panels/language_panel.yml", false); + } return true; } 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 24cdb911b..90120ba68 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 @@ -113,7 +113,9 @@ public void setup() { new IslandTeamPromoteCommand(this, "demote"); // Panels - getPlugin().saveResource("panels/team_panel.yml", false); + if (!new File(getPlugin().getDataFolder() + File.separator + "panels", "team_panel.yml").exists()) { + getPlugin().saveResource("panels/team_panel.yml", false); + } } @Override @@ -288,6 +290,8 @@ private PanelItem createInvitedButton(ItemTemplateRecord template, TemplatedPane .toList()); builder.clickHandler((panel, user, clickType, clickSlot) -> { if (clickType.equals(ClickType.SHIFT_LEFT) && user.hasPermission(this.acceptCommand.getPermission())) { + getPlugin().log("Invite accepted: " + user.getName() + " accepted " + invite.getType() + + " invite to island at " + island.getCenter()); // Accept switch (invite.getType()) { case COOP -> this.acceptCommand.acceptCoopInvite(user, invite); @@ -298,6 +302,8 @@ private PanelItem createInvitedButton(ItemTemplateRecord template, TemplatedPane } if (clickType.equals(ClickType.SHIFT_RIGHT) && user.hasPermission(this.rejectCommand.getPermission())) { // Reject + getPlugin().log("Invite rejected: " + user.getName() + " rejected " + invite.getType() + + " invite."); this.rejectCommand.execute(user, "", List.of()); user.closeInventory(); } @@ -474,34 +480,53 @@ private PanelItem getMemberButton(int targetRank, int slot, List<ActionRecords> } } - private boolean clickListener(Panel panel, User clicker, ClickType clickType, int i, User member, + private boolean clickListener(Panel panel, User clickingUser, ClickType clickType, int i, User target, List<ActionRecords> actions) { - int rank = Objects.requireNonNull(island).getRank(clicker); + int rank = Objects.requireNonNull(island).getRank(clickingUser); for (ItemTemplateRecord.ActionRecords action : actions) { - if (clickType == action.clickType() || action.clickType() == ClickType.UNKNOWN) { + if (clickType.equals(action.clickType())) { switch (action.actionType().toUpperCase(Locale.ENGLISH)) { case "KICK" -> { // Kick the player, or uncoop, or untrust - if (clicker.hasPermission(this.kickCommand.getPermission()) && !member.equals(clicker) + if (clickingUser.hasPermission(this.kickCommand.getPermission()) && !target.equals(clickingUser) && rank >= island.getRankCommand(this.getLabel() + " kick")) { - clicker.closeInventory(); - removePlayer(clicker, member); - clicker.getPlayer().playSound(clicker.getLocation(), Sound.BLOCK_GLASS_BREAK, 1F, 1F); + getPlugin().log("Kick: " + clickingUser.getName() + " kicked " + target.getName() + + " from island at " + island.getCenter()); + clickingUser.closeInventory(); + if (removePlayer(clickingUser, target)) { + clickingUser.getPlayer().playSound(clickingUser.getLocation(), Sound.BLOCK_GLASS_BREAK, 1F, + 1F); + getPlugin().log("Kick: success"); + } else { + getPlugin().log("Kick: failed"); + } } } case "SETOWNER" -> { // Make the player the leader of the island - if (clicker.hasPermission(this.setOwnerCommand.getPermission()) && !member.equals(clicker) - && clicker.getUniqueId().equals(island.getOwner())) { - clicker.closeInventory(); - this.setOwnerCommand.setOwner(clicker, member.getUniqueId()); + if (clickingUser.hasPermission(this.setOwnerCommand.getPermission()) && !target.equals(clickingUser) + && clickingUser.getUniqueId().equals(island.getOwner())) { + getPlugin().log("Set Owner: " + clickingUser.getName() + " trying to make " + target.getName() + + " owner of island at " + island.getCenter()); + clickingUser.closeInventory(); + if (this.setOwnerCommand.setOwner(clickingUser, target.getUniqueId())) { + getPlugin().log("Set Owner: success"); + } else { + getPlugin().log("Set Owner: failed"); + } } } case "LEAVE" -> { - if (clicker.hasPermission(this.leaveCommand.getPermission()) && member.equals(clicker) - && !clicker.getUniqueId().equals(island.getOwner())) { - clicker.closeInventory(); - leaveCommand.leave(clicker); + if (clickingUser.hasPermission(this.leaveCommand.getPermission()) && target.equals(clickingUser) + && !clickingUser.getUniqueId().equals(island.getOwner())) { + getPlugin().log("Leave: " + clickingUser.getName() + " trying to leave island at " + + island.getCenter()); + clickingUser.closeInventory(); + if (leaveCommand.leave(clickingUser)) { + getPlugin().log("Leave: success"); + } else { + getPlugin().log("Leave: failed"); + } } } } @@ -510,13 +535,19 @@ private boolean clickListener(Panel panel, User clicker, ClickType clickType, in return true; } - private void removePlayer(User clicker, User member) { + private boolean removePlayer(User clicker, User member) { // If member then kick, if coop, uncoop, if trusted, then untrust - switch (island.getRank(member)) { + return switch (island.getRank(member)) { case RanksManager.COOP_RANK -> this.uncoopCommand.unCoopCmd(user, member.getUniqueId()); case RanksManager.TRUSTED_RANK -> this.unTrustCommand.unTrustCmd(user, member.getUniqueId()); - default -> kickCommand.kick(clicker, member.getUniqueId()); + default -> { + if (kickCommand.canExecute(user, kickCommand.getLabel(), List.of(member.getName()))) { + yield kickCommand.execute(user, kickCommand.getLabel(), List.of(member.getName())); + } else { + yield false; + } } + }; } 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 4154875cf..7c0231848 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 @@ -59,7 +59,9 @@ public void setup() { setDescription("commands.island.team.invite.description"); setConfigurableRankCommand(); // Panels - getPlugin().saveResource("panels/team_invite_panel.yml", false); + if (!new File(getPlugin().getDataFolder() + File.separator + "panels", "team_invite_panel.yml").exists()) { + getPlugin().saveResource("panels/team_invite_panel.yml", false); + } } @@ -250,8 +252,7 @@ private PanelItem createSearchButton(ItemTemplateRecord template, TemplatedPanel .clickHandler((panel, user, clickType, clickSlot) -> { user.closeInventory(); new ConversationFactory(BentoBox.getInstance()).withLocalEcho(false).withTimeout(90) - .withModality(false) - .withFirstPrompt(new InviteNamePrompt(user, this)) + .withModality(false).withFirstPrompt(new InviteNamePrompt(user, this)) .buildConversation(user.getPlayer()).begin(); return true; }).build(); @@ -345,17 +346,34 @@ private boolean clickHandler(Panel panel, User user, ClickType clickType, int cl if (clickType.equals(ClickType.LEFT)) { user.closeInventory(); if (this.canExecute(user, this.getLabel(), List.of(player.getName()))) { + getPlugin().log("Invite sent to: " + player.getName() + " by " + user.getName() + " to join island in " + + getWorld().getName()); this.execute(user, getLabel(), List.of(player.getName())); + } else { + getPlugin().log("Invite failed: " + player.getName() + " by " + user.getName() + " to join island in " + + getWorld().getName()); } } else if (clickType.equals(ClickType.RIGHT)) { user.closeInventory(); if (this.itc.getCoopCommand().canExecute(user, this.getLabel(), List.of(player.getName()))) { + getPlugin().log("Coop: " + player.getName() + " cooped " + user.getName() + " to island in " + + getWorld().getName()); this.itc.getCoopCommand().execute(user, getLabel(), List.of(player.getName())); + } else { + getPlugin().log( + "Coop failed: " + player.getName() + "'s coop to " + user.getName() + " failed for island in " + + getWorld().getName()); } } else if (clickType.equals(ClickType.SHIFT_LEFT)) { user.closeInventory(); if (this.itc.getTrustCommand().canExecute(user, this.getLabel(), List.of(player.getName()))) { + getPlugin().log("Trust: " + player.getName() + " trusted " + user.getName() + " to island in " + + getWorld().getName()); this.itc.getTrustCommand().execute(user, getLabel(), List.of(player.getName())); + } else { + getPlugin().log("Trust failed: " + player.getName() + "'s trust failed for " + user.getName() + + " for island in " + + getWorld().getName()); } } return true; diff --git a/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamKickCommand.java b/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamKickCommand.java index 6024c7426..38989a433 100644 --- a/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamKickCommand.java +++ b/src/main/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamKickCommand.java @@ -35,7 +35,7 @@ public void setup() { } @Override - public boolean execute(User user, String label, List<String> args) { + public boolean canExecute(User user, String label, List<String> args) { if (!getIslands().inTeam(getWorld(), user.getUniqueId())) { user.sendMessage("general.errors.no-team"); return false; @@ -74,7 +74,13 @@ public boolean execute(User user, String label, List<String> args) { getPlayers().getName(targetUUID)); return false; } + return true; + } + @Override + public boolean execute(User user, String label, List<String> args) { + // Get target + UUID targetUUID = getPlayers().getUUID(args.get(0)); if (!getSettings().isKickConfirmation()) { kick(user, targetUUID); return true; 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 8e34ba1c9..882f19719 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 @@ -65,17 +65,17 @@ private void showResets(User user) { } - protected void leave(User user) { + protected boolean leave(User user) { Island island = getIslands().getIsland(getWorld(), user); if (island == null) { user.sendMessage("general.errors.no-island"); - return; + return false; } // Fire event IslandBaseEvent event = TeamEvent.builder().island(island).reason(TeamEvent.Reason.LEAVE) .involvedPlayer(user.getUniqueId()).build(); if (event.isCancelled()) { - return; + return false; } UUID ownerUUID = island.getOwner(); if (ownerUUID != null) { @@ -103,5 +103,6 @@ protected void leave(User user) { IslandEvent.builder().island(island).involvedPlayer(user.getUniqueId()).admin(false) .reason(IslandEvent.Reason.RANK_CHANGE).rankChange(island.getRank(user), RanksManager.VISITOR_RANK) .build(); + return true; } } \ No newline at end of file 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 528e5c433..09f79feb8 100644 --- a/src/main/java/world/bentobox/bentobox/database/objects/Island.java +++ b/src/main/java/world/bentobox/bentobox/database/objects/Island.java @@ -658,9 +658,6 @@ public int getRange() { * @return rank integer */ public int getRank(User user) { - if (user.isOp()) { - return RanksManager.ADMIN_RANK; - } return members.getOrDefault(user.getUniqueId(), RanksManager.VISITOR_RANK); } diff --git a/src/test/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamKickCommandTest.java b/src/test/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamKickCommandTest.java index dc017e017..a1cc1b546 100644 --- a/src/test/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamKickCommandTest.java +++ b/src/test/java/world/bentobox/bentobox/api/commands/island/team/IslandTeamKickCommandTest.java @@ -7,6 +7,7 @@ import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -188,18 +189,18 @@ public void setUp() throws Exception { } /** - * Test method for {@link IslandTeamKickCommand#execute(User, String, java.util.List)} + * Test method for {@link IslandTeamKickCommand#canExecute(User, String, java.util.List)} */ @Test public void testExecuteNoTeam() { when(im.inTeam(any(), eq(uuid))).thenReturn(false); IslandTeamKickCommand itl = new IslandTeamKickCommand(ic); - assertFalse(itl.execute(user, itl.getLabel(), Collections.emptyList())); + assertFalse(itl.canExecute(user, itl.getLabel(), Collections.emptyList())); verify(user).sendMessage(eq("general.errors.no-team")); } /** - * Test method for {@link IslandTeamKickCommand#execute(User, String, java.util.List)} + * Test method for {@link IslandTeamKickCommand#canExecute(User, String, java.util.List)} */ @Test public void testExecuteLowerTeamRank() { @@ -212,12 +213,12 @@ public void testExecuteLowerTeamRank() { when(island.getMemberSet()).thenReturn(ImmutableSet.of(notUUID)); IslandTeamKickCommand itl = new IslandTeamKickCommand(ic); - assertFalse(itl.execute(user, itl.getLabel(), Collections.singletonList("poslovitch"))); + assertFalse(itl.canExecute(user, itl.getLabel(), Collections.singletonList("poslovitch"))); verify(user).sendMessage(eq("commands.island.team.kick.cannot-kick-rank"), eq(TextVariables.NAME), eq("poslovitch")); } /** - * Test method for {@link IslandTeamKickCommand#execute(User, String, java.util.List)} + * Test method for {@link IslandTeamKickCommand#canExecute(User, String, java.util.List)} */ @Test public void testExecuteEqualTeamRank() { @@ -230,7 +231,7 @@ public void testExecuteEqualTeamRank() { when(island.getMemberSet()).thenReturn(ImmutableSet.of(notUUID)); IslandTeamKickCommand itl = new IslandTeamKickCommand(ic); - assertFalse(itl.execute(user, itl.getLabel(), Collections.singletonList("poslovitch"))); + assertFalse(itl.canExecute(user, itl.getLabel(), Collections.singletonList("poslovitch"))); verify(user).sendMessage(eq("commands.island.team.kick.cannot-kick-rank"), eq(TextVariables.NAME), eq("poslovitch")); } @@ -254,7 +255,7 @@ public void testExecuteLargerTeamRank() { } /** - * Test method for {@link IslandTeamKickCommand#execute(User, String, java.util.List)} + * Test method for {@link IslandTeamKickCommand#canExecute(User, String, java.util.List)} */ @Test public void testExecuteNoCommandRank() { @@ -262,61 +263,61 @@ public void testExecuteNoCommandRank() { when(island.getRank(user)).thenReturn(RanksManager.MEMBER_RANK); IslandTeamKickCommand itl = new IslandTeamKickCommand(ic); - assertFalse(itl.execute(user, itl.getLabel(), Collections.emptyList())); + assertFalse(itl.canExecute(user, itl.getLabel(), Collections.emptyList())); verify(user).sendMessage("general.errors.insufficient-rank", TextVariables.RANK, ""); } /** * Test method for - * {@link IslandTeamKickCommand#execute(User, String, java.util.List)} + * {@link IslandTeamKickCommand#canExecute(User, String, java.util.List)} */ @Test public void testExecuteNoTarget() { IslandTeamKickCommand itl = new IslandTeamKickCommand(ic); - assertFalse(itl.execute(user, itl.getLabel(), Collections.emptyList())); + assertFalse(itl.canExecute(user, itl.getLabel(), Collections.emptyList())); // Show help } /** * Test method for - * {@link IslandTeamKickCommand#execute(User, String, java.util.List)} + * {@link IslandTeamKickCommand#canExecute(User, String, java.util.List)} */ @Test public void testExecuteUnknownPlayer() { IslandTeamKickCommand itl = new IslandTeamKickCommand(ic); when(pm.getUUID(any())).thenReturn(null); - assertFalse(itl.execute(user, itl.getLabel(), Collections.singletonList("poslovitch"))); + assertFalse(itl.canExecute(user, itl.getLabel(), Collections.singletonList("poslovitch"))); verify(user).sendMessage("general.errors.unknown-player", "[name]", "poslovitch"); } /** * Test method for - * {@link IslandTeamKickCommand#execute(User, String, java.util.List)} + * {@link IslandTeamKickCommand#canExecute(User, String, java.util.List)} */ @Test public void testExecuteSamePlayer() { IslandTeamKickCommand itl = new IslandTeamKickCommand(ic); when(pm.getUUID(any())).thenReturn(uuid); - assertFalse(itl.execute(user, itl.getLabel(), Collections.singletonList("poslovitch"))); + assertFalse(itl.canExecute(user, itl.getLabel(), Collections.singletonList("poslovitch"))); verify(user).sendMessage(eq("commands.island.team.kick.cannot-kick")); } /** * Test method for - * {@link IslandTeamKickCommand#execute(User, String, java.util.List)} + * {@link IslandTeamKickCommand#canExecute(User, String, java.util.List)} */ @Test public void testExecuteDifferentPlayerNotInTeam() { IslandTeamKickCommand itl = new IslandTeamKickCommand(ic); when(pm.getUUID(any())).thenReturn(notUUID); // when(im.getMembers(any(), any())).thenReturn(Collections.emptySet()); - assertFalse(itl.execute(user, itl.getLabel(), Collections.singletonList("poslovitch"))); + assertFalse(itl.canExecute(user, itl.getLabel(), Collections.singletonList("poslovitch"))); verify(user).sendMessage(eq("general.errors.not-in-team")); } /** * Test method for - * {@link IslandTeamKickCommand#execute(User, String, java.util.List)} + * {@link IslandTeamKickCommand#canExecute(User, String, java.util.List)} */ @Test public void testExecuteDifferentPlayerNoRank() { @@ -324,7 +325,7 @@ public void testExecuteDifferentPlayerNoRank() { when(pm.getUUID(any())).thenReturn(notUUID); when(island.getRankCommand(anyString())).thenReturn(RanksManager.OWNER_RANK); when(island.getRank(any(User.class))).thenReturn(RanksManager.VISITOR_RANK); - assertFalse(itl.execute(user, itl.getLabel(), Collections.singletonList("poslovitch"))); + assertFalse(itl.canExecute(user, itl.getLabel(), Collections.singletonList("poslovitch"))); verify(user).sendMessage("general.errors.insufficient-rank", TextVariables.RANK, ""); } @@ -364,7 +365,7 @@ public void testExecuteNoConfirmationKeepInventory() { assertTrue(itl.execute(user, itl.getLabel(), Collections.singletonList("poslovitch"))); verify(im).removePlayer(any(World.class), eq(notUUID)); verify(user).sendMessage("commands.island.team.kick.success", TextVariables.NAME, "poslovitch", TextVariables.DISPLAY_NAME, "&Cposlovich"); - verify(target, Mockito.never()).getInventory(); + verify(target, never()).getInventory(); } From 256554e32bbf89cefc4fa043a933c7ea4f1b8765 Mon Sep 17 00:00:00 2001 From: tastybento <tastybento@users.noreply.github.com> Date: Mon, 8 Jan 2024 16:14:20 +0900 Subject: [PATCH 20/22] Return to name search GUI if name not found. --- .../api/commands/island/team/IslandTeamInviteCommand.java | 2 +- .../island/team/conversations/InviteNamePrompt.java | 8 +++++++- .../java/world/bentobox/bentobox/api/panels/Panel.java | 7 ++++--- .../bentobox/bentobox/api/panels/TemplatedPanel.java | 1 + 4 files changed, 13 insertions(+), 5 deletions(-) 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 7c0231848..439fdfaf7 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 @@ -210,7 +210,7 @@ public Optional<List<String>> tabComplete(User user, String alias, List<String> * Build the invite panel * @param user use of the panel */ - void build(User user) { + public void build(User user) { this.user = user; // Start building panel. TemplatedPanelBuilder panelBuilder = new TemplatedPanelBuilder(); diff --git a/src/main/java/world/bentobox/bentobox/api/commands/island/team/conversations/InviteNamePrompt.java b/src/main/java/world/bentobox/bentobox/api/commands/island/team/conversations/InviteNamePrompt.java index 6517741db..39ba15fb2 100644 --- a/src/main/java/world/bentobox/bentobox/api/commands/island/team/conversations/InviteNamePrompt.java +++ b/src/main/java/world/bentobox/bentobox/api/commands/island/team/conversations/InviteNamePrompt.java @@ -2,11 +2,13 @@ import java.util.List; +import org.bukkit.Bukkit; import org.bukkit.conversations.ConversationContext; import org.bukkit.conversations.Prompt; import org.bukkit.conversations.StringPrompt; import org.eclipse.jdt.annotation.NonNull; +import world.bentobox.bentobox.BentoBox; import world.bentobox.bentobox.api.commands.island.team.IslandTeamInviteCommand; import world.bentobox.bentobox.api.user.User; @@ -36,8 +38,12 @@ public String getPromptText(@NonNull ConversationContext context) { @Override public Prompt acceptInput(@NonNull ConversationContext context, String input) { if (itic.canExecute(user, itic.getLabel(), List.of(input))) { - itic.execute(user, itic.getLabel(), List.of(input)); + if (itic.execute(user, itic.getLabel(), List.of(input))) { + return Prompt.END_OF_CONVERSATION; + } } + // Return to the GUI but give a second for the error to show + Bukkit.getScheduler().runTaskLater(BentoBox.getInstance(), () -> itic.build(user), 20L); return Prompt.END_OF_CONVERSATION; } diff --git a/src/main/java/world/bentobox/bentobox/api/panels/Panel.java b/src/main/java/world/bentobox/bentobox/api/panels/Panel.java index 6ab674a55..06cd94c48 100644 --- a/src/main/java/world/bentobox/bentobox/api/panels/Panel.java +++ b/src/main/java/world/bentobox/bentobox/api/panels/Panel.java @@ -36,8 +36,8 @@ public class Panel implements HeadRequester, InventoryHolder { * <br> * The current list of inventories that cannot be created are:<br> * <blockquote> - * {@link Type#INVENTORY}, {@link Type#HOPPER} and - * {@link Type#DROPPER} + * {@link Type#INVENTORY}, {@link Type#HOPPER}, + * {@link Type#DROPPER}, {@link Type#ANVIL} * </blockquote> * * These relate to the Bukkit inventories with INVENTORY being the standard CHEST inventory. @@ -45,7 +45,7 @@ public class Panel implements HeadRequester, InventoryHolder { * @since 1.7.0 */ public enum Type { - INVENTORY, HOPPER, DROPPER + INVENTORY, HOPPER, DROPPER, ANVIL } public Panel() { @@ -90,6 +90,7 @@ protected void makePanel(String name, Map<Integer, PanelItem> items, int size, U case INVENTORY -> inventory = Bukkit.createInventory(null, fixSize(size), name); case HOPPER -> inventory = Bukkit.createInventory(null, InventoryType.HOPPER, name); case DROPPER -> inventory = Bukkit.createInventory(null, InventoryType.DROPPER, name); + case ANVIL -> inventory = Bukkit.createInventory(null, InventoryType.ANVIL, name); } // Fill the inventory and return diff --git a/src/main/java/world/bentobox/bentobox/api/panels/TemplatedPanel.java b/src/main/java/world/bentobox/bentobox/api/panels/TemplatedPanel.java index 866473e2d..6310fa144 100644 --- a/src/main/java/world/bentobox/bentobox/api/panels/TemplatedPanel.java +++ b/src/main/java/world/bentobox/bentobox/api/panels/TemplatedPanel.java @@ -61,6 +61,7 @@ private void generatePanel() { case INVENTORY -> this.populateInventoryPanel(new PanelItem[6][9]); case HOPPER -> this.populateInventoryPanel(new PanelItem[1][5]); case DROPPER -> this.populateInventoryPanel(new PanelItem[3][3]); + case ANVIL -> this.populateInventoryPanel(new PanelItem[4][9]); }; super.makePanel(this.user.getTranslation(this.panelTemplate.title(), this.parameters), items, From 3d3bd425057ad1dbecd0e6832920032e4c93ce59 Mon Sep 17 00:00:00 2001 From: tastybento <tastybento@users.noreply.github.com> Date: Mon, 8 Jan 2024 19:38:54 +0900 Subject: [PATCH 21/22] Added return to GUI for player search --- .../{conversations => }/InviteNamePrompt.java | 7 ++++-- .../island/team/IslandTeamInviteCommand.java | 24 +++++++++++++++---- src/main/resources/locales/en-US.yml | 3 +++ .../resources/panels/team_invite_panel.yml | 1 + 4 files changed, 29 insertions(+), 6 deletions(-) rename src/main/java/world/bentobox/bentobox/api/commands/island/team/{conversations => }/InviteNamePrompt.java (83%) diff --git a/src/main/java/world/bentobox/bentobox/api/commands/island/team/conversations/InviteNamePrompt.java b/src/main/java/world/bentobox/bentobox/api/commands/island/team/InviteNamePrompt.java similarity index 83% rename from src/main/java/world/bentobox/bentobox/api/commands/island/team/conversations/InviteNamePrompt.java rename to src/main/java/world/bentobox/bentobox/api/commands/island/team/InviteNamePrompt.java index 39ba15fb2..d9fde3cda 100644 --- a/src/main/java/world/bentobox/bentobox/api/commands/island/team/conversations/InviteNamePrompt.java +++ b/src/main/java/world/bentobox/bentobox/api/commands/island/team/InviteNamePrompt.java @@ -1,4 +1,4 @@ -package world.bentobox.bentobox.api.commands.island.team.conversations; +package world.bentobox.bentobox.api.commands.island.team; import java.util.List; @@ -9,7 +9,6 @@ import org.eclipse.jdt.annotation.NonNull; import world.bentobox.bentobox.BentoBox; -import world.bentobox.bentobox.api.commands.island.team.IslandTeamInviteCommand; import world.bentobox.bentobox.api.user.User; /** @@ -37,12 +36,16 @@ public String getPromptText(@NonNull ConversationContext context) { @Override public Prompt acceptInput(@NonNull ConversationContext context, String input) { + // TODO remove this and pass the options back to the GUI if (itic.canExecute(user, itic.getLabel(), List.of(input))) { if (itic.execute(user, itic.getLabel(), List.of(input))) { return Prompt.END_OF_CONVERSATION; } } + // Set the search item to what was entered + itic.setSearchName(input); // Return to the GUI but give a second for the error to show + // TODO: return the failed input and display the options in the GUI. Bukkit.getScheduler().runTaskLater(BentoBox.getInstance(), () -> itic.build(user), 20L); return Prompt.END_OF_CONVERSATION; } 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 439fdfaf7..c80c6df8b 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 @@ -18,7 +18,6 @@ import world.bentobox.bentobox.BentoBox; import world.bentobox.bentobox.api.commands.CompositeCommand; import world.bentobox.bentobox.api.commands.island.team.Invite.Type; -import world.bentobox.bentobox.api.commands.island.team.conversations.InviteNamePrompt; import world.bentobox.bentobox.api.events.IslandBaseEvent; import world.bentobox.bentobox.api.events.team.TeamEvent; import world.bentobox.bentobox.api.localization.TextVariables; @@ -46,6 +45,7 @@ public class IslandTeamInviteCommand extends CompositeCommand { private long page = 0; // This number by 35 private boolean inviteCmd; private static final long PER_PAGE = 35; + private String searchName = ""; public IslandTeamInviteCommand(IslandTeamCommand parent) { super(parent, "invite"); @@ -210,7 +210,7 @@ public Optional<List<String>> tabComplete(User user, String alias, List<String> * Build the invite panel * @param user use of the panel */ - public void build(User user) { + void build(User user) { this.user = user; // Start building panel. TemplatedPanelBuilder panelBuilder = new TemplatedPanelBuilder(); @@ -248,14 +248,21 @@ private PanelItem createBackButton(ItemTemplateRecord template, TemplatedPanel.I private PanelItem createSearchButton(ItemTemplateRecord template, TemplatedPanel.ItemSlot slot) { checkTemplate(template); - return new PanelItemBuilder().name(user.getTranslation(template.title())).icon(template.icon()) + PanelItemBuilder pib = new PanelItemBuilder().name(user.getTranslation(template.title())).icon(template.icon()) .clickHandler((panel, user, clickType, clickSlot) -> { user.closeInventory(); new ConversationFactory(BentoBox.getInstance()).withLocalEcho(false).withTimeout(90) .withModality(false).withFirstPrompt(new InviteNamePrompt(user, this)) .buildConversation(user.getPlayer()).begin(); return true; - }).build(); + }); + if (!this.searchName.isBlank()) { + pib.description(user.getTranslation(Objects + .requireNonNullElse(template.description(), + "commands.island.team.invite.gui.button.searching"), + TextVariables.NAME, searchName)); + } + return pib.build(); } private PanelItem createNextButton(ItemTemplateRecord template, TemplatedPanel.ItemSlot slot) { @@ -322,6 +329,8 @@ private PanelItem createProspectButton(ItemTemplateRecord template, TemplatedPan page = 0; } return getWorld().getPlayers().stream().filter(player -> user.getPlayer().canSee(player)) + .filter(player -> this.searchName.isBlank() ? true + : player.getName().toLowerCase().contains(searchName.toLowerCase())) .filter(player -> !player.equals(user.getPlayer())).skip(slot.slot() + page * PER_PAGE).findFirst() .map(player -> getProspect(player, template)).orElse(this.getBlankBackground()); } @@ -384,4 +393,11 @@ private PanelItem getBlankBackground() { .icon(Objects.requireNonNullElse(background.icon(), new ItemStack(Material.BARRIER))) .name((Objects.requireNonNullElse(background.title(), ""))).build(); } + + /** + * @param searchName the searchName to set + */ + void setSearchName(String searchName) { + this.searchName = searchName; + } } diff --git a/src/main/resources/locales/en-US.yml b/src/main/resources/locales/en-US.yml index 6fa23e7cc..2a0bb2db4 100644 --- a/src/main/resources/locales/en-US.yml +++ b/src/main/resources/locales/en-US.yml @@ -717,6 +717,9 @@ commands: button: already-invited: "&c Invited already" search: "&a Search for a player" + searching: | + &b Searching for + &c [name] enter-name: "&a Enter name:" tips: LEFT: diff --git a/src/main/resources/panels/team_invite_panel.yml b/src/main/resources/panels/team_invite_panel.yml index d082daa3d..7be5de6a0 100644 --- a/src/main/resources/panels/team_invite_panel.yml +++ b/src/main/resources/panels/team_invite_panel.yml @@ -38,6 +38,7 @@ team_invite_panel: tooltip: commands.island.team.invite.gui.tips.previous 5: title: "commands.island.team.invite.gui.button.search" + description: "commands.island.team.invite.gui.button.searching" icon: PLAYER_HEAD data: type: SEARCH From 2d2972c3e6583852cde76493945e0e51d7a04b5a Mon Sep 17 00:00:00 2001 From: tastybento <tastybento@users.noreply.github.com> Date: Mon, 8 Jan 2024 19:42:51 +0900 Subject: [PATCH 22/22] Use Path.of --- src/main/java/world/bentobox/bentobox/BentoBox.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/main/java/world/bentobox/bentobox/BentoBox.java b/src/main/java/world/bentobox/bentobox/BentoBox.java index b70c19c87..1ee3cfb1e 100644 --- a/src/main/java/world/bentobox/bentobox/BentoBox.java +++ b/src/main/java/world/bentobox/bentobox/BentoBox.java @@ -1,6 +1,7 @@ package world.bentobox.bentobox; -import java.io.File; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.List; import java.util.Optional; @@ -466,10 +467,13 @@ public boolean loadSettings() { } log("Saving default panels..."); - if (!new File(getDataFolder() + File.separator + "panels", "island_creation_panel.yml").exists()) { + if (!Files.exists(Path.of(this.getDataFolder().getPath(), "panels", "island_creation_panel.yml"))) { + log("Saving default island_creation_panel..."); this.saveResource("panels/island_creation_panel.yml", false); } - if (!new File(getDataFolder() + File.separator + "panels", "language_panel.yml").exists()) { + + if (!Files.exists(Path.of(this.getDataFolder().getPath(), "panels", "language_panel.yml"))) { + log("Saving default language_panel..."); this.saveResource("panels/language_panel.yml", false); } return true;