mirror of
https://github.com/BentoBoxWorld/BentoBox.git
synced 2025-01-09 01:48:24 +01:00
Merge pull request #2324 from BentoBoxWorld/team_gui_rewrite
Team gui rewrite
This commit is contained in:
commit
4064c9a241
@ -1,53 +0,0 @@
|
||||
package world.bentobox.bentobox.api.commands.island.team;
|
||||
|
||||
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.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) {
|
||||
// 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;
|
||||
}
|
||||
|
||||
}
|
@ -1,24 +1,12 @@
|
||||
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.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
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.bukkit.inventory.ItemStack;
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
@ -26,40 +14,19 @@ 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.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;
|
||||
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;
|
||||
import world.bentobox.bentobox.util.Util;
|
||||
|
||||
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;
|
||||
|
||||
private int rank = RanksManager.OWNER_RANK;
|
||||
|
||||
private IslandTeamKickCommand kickCommand;
|
||||
|
||||
private IslandTeamLeaveCommand leaveCommand;
|
||||
@ -120,13 +87,12 @@ public class IslandTeamCommand extends CompositeCommand {
|
||||
|
||||
@Override
|
||||
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());
|
||||
Island island = getIslands().getPrimaryIsland(getWorld(), user.getUniqueId());
|
||||
if (island == null) {
|
||||
if (isInvited(user.getUniqueId())) {
|
||||
// Player has an invite, so show the invite
|
||||
build();
|
||||
new IslandTeamGUI(getPlugin(), this, user, island).build();
|
||||
return true;
|
||||
}
|
||||
user.sendMessage("general.errors.no-island");
|
||||
@ -155,511 +121,11 @@ public class IslandTeamCommand extends CompositeCommand {
|
||||
@Override
|
||||
public boolean execute(User user, String label, List<String> args) {
|
||||
// Show the panel
|
||||
build();
|
||||
new IslandTeamGUI(getPlugin(), this, user, getIslands().getPrimaryIsland(getWorld(), user.getUniqueId()))
|
||||
.build();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method builds this GUI.
|
||||
*/
|
||||
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("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();
|
||||
}
|
||||
|
||||
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.description(user.getTranslation("commands.island.team.gui.buttons.invite.description"));
|
||||
builder.clickHandler((panel, user, clickType, clickSlot) -> {
|
||||
if (!template.actions().stream().anyMatch(ar -> clickType.equals(ar.clickType()))) {
|
||||
// If the click type is not in the template, don't do anything
|
||||
return true;
|
||||
}
|
||||
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) {
|
||||
return this.getBlankBorder();
|
||||
}
|
||||
PanelItemBuilder builder = new PanelItemBuilder();
|
||||
builder.name(user.getTranslation("commands.island.team.gui.buttons.rank-filter.name"));
|
||||
builder.icon(Material.AMETHYST_SHARD);
|
||||
// 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) -> {
|
||||
if (!template.actions().stream().anyMatch(ar -> clickType.equals(ar.clickType()))) {
|
||||
// If the click type is not in the template, don't do anything
|
||||
return true;
|
||||
}
|
||||
if (clickType.equals(ClickType.LEFT)) {
|
||||
rank = RanksManager.getInstance().getRankDownValue(rank);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
// Update panel after click
|
||||
build();
|
||||
return true;
|
||||
});
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create invited button panel item.
|
||||
*
|
||||
* @param template the template
|
||||
* @param slot the slot
|
||||
* @return the panel item
|
||||
*/
|
||||
private PanelItem createInvitedButton(ItemTemplateRecord template, TemplatedPanel.ItemSlot slot) {
|
||||
PanelItemBuilder builder = new PanelItemBuilder();
|
||||
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(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,
|
||||
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 (!template.actions().stream().anyMatch(ar -> clickType.equals(ar.clickType()))) {
|
||||
// If the click type is not in the template, don't do anything
|
||||
return true;
|
||||
}
|
||||
if (clickType.equals(ClickType.SHIFT_LEFT) && user.hasPermission(this.acceptCommand.getPermission())) {
|
||||
getPlugin().log("Invite accepted: " + user.getName() + " accepted " + invite.getType());
|
||||
// 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) && user.hasPermission(this.rejectCommand.getPermission())) {
|
||||
// Reject
|
||||
getPlugin().log("Invite rejected: " + user.getName() + " rejected " + invite.getType()
|
||||
+ " invite.");
|
||||
this.rejectCommand.execute(user, "", List.of());
|
||||
user.closeInventory();
|
||||
}
|
||||
return true;
|
||||
});
|
||||
} else {
|
||||
return this.getBlankBorder();
|
||||
}
|
||||
return builder.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 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.
|
||||
*
|
||||
* @param template the template
|
||||
* @param slot the slot
|
||||
* @return the panel item
|
||||
*/
|
||||
private PanelItem createMemberButton(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();
|
||||
}
|
||||
return switch (rank) {
|
||||
case RanksManager.OWNER_RANK -> ownerView(template, slot);
|
||||
default -> getMemberButton(rank, slot.slot(), template.actions());
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 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, 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();
|
||||
long coopCount = island.getMemberSet(RanksManager.COOP_RANK, false).stream().count();
|
||||
long trustedCount = island.getMemberSet(RanksManager.TRUSTED_RANK, false).stream().count();
|
||||
|
||||
if (slot.slot() > 0 && slot.slot() < subOwnerCount + 1) {
|
||||
// Show sub owners
|
||||
PanelItem item = getMemberButton(RanksManager.SUB_OWNER_RANK, slot.slot(), template.actions());
|
||||
if (item != null) {
|
||||
return item;
|
||||
}
|
||||
|
||||
}
|
||||
if (slot.slot() > subOwnerCount && slot.slot() < subOwnerCount + memberCount + 1) {
|
||||
// Show members
|
||||
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, slot.slot(), template.actions());
|
||||
if (item != null) {
|
||||
return item;
|
||||
}
|
||||
|
||||
}
|
||||
if (slot.slot() > subOwnerCount + memberCount + trustedCount
|
||||
&& slot.slot() < subOwnerCount + memberCount + trustedCount + coopCount + 1) {
|
||||
// Show coops
|
||||
return getMemberButton(RanksManager.COOP_RANK, slot.slot(), template.actions());
|
||||
}
|
||||
return this.getBlankBackground();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 targetRank, int slot, List<ActionRecords> actions) {
|
||||
if (slot == 0 && island.getOwner() != null) {
|
||||
// Owner
|
||||
return getMemberButton(RanksManager.OWNER_RANK, 1, actions);
|
||||
}
|
||||
String ref = RanksManager.getInstance().getRank(targetRank);
|
||||
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);
|
||||
// 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() + ".name")
|
||||
+ " " + user.getTranslation(ar.tooltip()))
|
||||
.findFirst().ifPresent(desc::add);
|
||||
}
|
||||
// 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() + ".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.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();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean clickListener(Panel panel, User clickingUser, ClickType clickType, int i, User target,
|
||||
List<ActionRecords> actions) {
|
||||
if (!actions.stream().anyMatch(ar -> clickType.equals(ar.clickType()))) {
|
||||
// If the click type is not in the template, don't do anything
|
||||
return true;
|
||||
}
|
||||
int rank = Objects.requireNonNull(island).getRank(clickingUser);
|
||||
for (ItemTemplateRecord.ActionRecords action : actions) {
|
||||
if (clickType.equals(action.clickType())) {
|
||||
switch (action.actionType().toUpperCase(Locale.ENGLISH)) {
|
||||
case "KICK" -> {
|
||||
// Kick the player, or uncoop, or untrust
|
||||
if (clickingUser.hasPermission(this.kickCommand.getPermission()) && !target.equals(clickingUser)
|
||||
&& rank >= island.getRankCommand(this.getLabel() + " kick")) {
|
||||
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 (clickingUser.hasPermission(this.setOwnerCommand.getPermission()) && !target.equals(clickingUser)
|
||||
&& clickingUser.getUniqueId().equals(island.getOwner())
|
||||
&& island.getRank(target) >= RanksManager.MEMBER_RANK) {
|
||||
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 (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");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean removePlayer(User clicker, User member) {
|
||||
// If member then kick, if coop, uncoop, if trusted, then untrust
|
||||
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 -> {
|
||||
if (kickCommand.canExecute(user, kickCommand.getLabel(), List.of(member.getName()))) {
|
||||
yield kickCommand.kick(clicker, member.getUniqueId());
|
||||
} else {
|
||||
yield false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
private List<String> showMembers() {
|
||||
List<String> message = new ArrayList<>();
|
||||
// Gather online members
|
||||
long onlineMemberCount = island.getMemberSet(RanksManager.MEMBER_RANK).stream()
|
||||
.filter(uuid -> Util.getOnlinePlayerList(user).contains(Bukkit.getOfflinePlayer(uuid).getName()))
|
||||
.count();
|
||||
|
||||
// Show header:
|
||||
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(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) {
|
||||
Set<UUID> players = island.getMemberSet(rank, false);
|
||||
if (!players.isEmpty()) {
|
||||
if (rank == RanksManager.OWNER_RANK) {
|
||||
// Slightly special handling for the owner rank
|
||||
message.add(user.getTranslation("commands.island.team.info.rank-layout.owner", TextVariables.RANK,
|
||||
user.getTranslation(RanksManager.OWNER_RANK_REF)));
|
||||
} else {
|
||||
message.add(user.getTranslation("commands.island.team.info.rank-layout.generic", TextVariables.RANK,
|
||||
user.getTranslation(RanksManager.getInstance().getRank(rank)), TextVariables.NUMBER,
|
||||
String.valueOf(island.getMemberSet(rank, false).size())));
|
||||
}
|
||||
message.addAll(displayOnOffline(user, rank, island, onlineMembers));
|
||||
}
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
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)) {
|
||||
message.add(getMemberStatus(user, member, onlineMembers.contains(member)));
|
||||
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
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();
|
||||
|
||||
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"));
|
||||
}
|
||||
return lastSeen;
|
||||
}
|
||||
|
||||
private boolean fireEvent(User user, Island island) {
|
||||
IslandBaseEvent e = TeamEvent.builder().island(island).reason(TeamEvent.Reason.INFO)
|
||||
.involvedPlayer(user.getUniqueId()).build();
|
||||
@ -731,4 +197,52 @@ public class IslandTeamCommand extends CompositeCommand {
|
||||
protected IslandTeamTrustCommand getTrustCommand() {
|
||||
return trustCommand;
|
||||
}
|
||||
|
||||
public IslandTeamInviteCommand getInviteCommand() {
|
||||
return inviteCommand;
|
||||
}
|
||||
|
||||
public IslandTeamInviteAcceptCommand getAcceptCommand() {
|
||||
return acceptCommand;
|
||||
}
|
||||
|
||||
public IslandTeamInviteRejectCommand getRejectCommand() {
|
||||
return rejectCommand;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the kickCommand
|
||||
*/
|
||||
public IslandTeamKickCommand getKickCommand() {
|
||||
return kickCommand;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the leaveCommand
|
||||
*/
|
||||
public IslandTeamLeaveCommand getLeaveCommand() {
|
||||
return leaveCommand;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the setOwnerCommand
|
||||
*/
|
||||
public IslandTeamSetownerCommand getSetOwnerCommand() {
|
||||
return setOwnerCommand;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the uncoopCommand
|
||||
*/
|
||||
public IslandTeamUncoopCommand getUncoopCommand() {
|
||||
return uncoopCommand;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the unTrustCommand
|
||||
*/
|
||||
public IslandTeamUntrustCommand getUnTrustCommand() {
|
||||
return unTrustCommand;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,536 @@
|
||||
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.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
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.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.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;
|
||||
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;
|
||||
import world.bentobox.bentobox.util.Util;
|
||||
|
||||
public class IslandTeamGUI {
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
private final User user;
|
||||
|
||||
private final Island island;
|
||||
|
||||
private int rankView = RanksManager.OWNER_RANK;
|
||||
|
||||
private @Nullable TemplateItem border;
|
||||
|
||||
private @Nullable TemplateItem background;
|
||||
|
||||
private final IslandTeamCommand parent;
|
||||
|
||||
private final BentoBox plugin;
|
||||
|
||||
|
||||
/**
|
||||
* Displays the team management GUI
|
||||
* @param plugin BentoBox
|
||||
* @param parent IslandTeamCommand object
|
||||
* @param user user who is opening the GUI
|
||||
* @param island island that the GUI is managing
|
||||
*/
|
||||
public IslandTeamGUI(BentoBox plugin, IslandTeamCommand parent, User user, Island island) {
|
||||
this.parent = parent;
|
||||
this.plugin = plugin;
|
||||
this.user = user;
|
||||
this.island = island;
|
||||
// Panels
|
||||
if (!new File(plugin.getDataFolder() + File.separator + "panels", "team_panel.yml").exists()) {
|
||||
plugin.saveResource("panels/team_panel.yml", false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method builds this GUI.
|
||||
*/
|
||||
public void build() {
|
||||
// Start building panel.
|
||||
TemplatedPanelBuilder panelBuilder = new TemplatedPanelBuilder();
|
||||
panelBuilder.user(user);
|
||||
panelBuilder.world(user.getWorld());
|
||||
|
||||
panelBuilder.template("team_panel", new File(plugin.getDataFolder(), "panels"));
|
||||
|
||||
panelBuilder.parameters("[name]", user.getName(), "[display_name]", user.getDisplayName());
|
||||
|
||||
panelBuilder.registerTypeBuilder("STATUS", this::createStatusButton);
|
||||
panelBuilder.registerTypeBuilder("MEMBER", this::createMemberButton);
|
||||
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();
|
||||
}
|
||||
|
||||
private PanelItem createInviteButton(ItemTemplateRecord template, TemplatedPanel.ItemSlot slot) {
|
||||
if (island == null || !user.hasPermission(this.parent.getInviteCommand().getPermission())
|
||||
|| island.getRank(user) < island.getRankCommand(parent.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.description(user.getTranslation("commands.island.team.gui.buttons.invite.description"));
|
||||
builder.clickHandler((panel, user, clickType, clickSlot) -> {
|
||||
if (!template.actions().stream().anyMatch(ar -> clickType.equals(ar.clickType()))) {
|
||||
// If the click type is not in the template, don't do anything
|
||||
return true;
|
||||
}
|
||||
if (clickType.equals(ClickType.LEFT)) {
|
||||
user.closeInventory();
|
||||
new IslandTeamInviteGUI(parent, false, island).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) {
|
||||
return this.getBlankBorder();
|
||||
}
|
||||
PanelItemBuilder builder = new PanelItemBuilder();
|
||||
builder.name(user.getTranslation("commands.island.team.gui.buttons.rank-filter.name"));
|
||||
builder.icon(Material.AMETHYST_SHARD);
|
||||
// Create description
|
||||
RanksManager.getInstance().getRanks().forEach((reference, score) -> {
|
||||
if (rankView == 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 < rankView) {
|
||||
builder.description(user.getTranslation("protection.panel.flag-item.blocked-rank")
|
||||
+ user.getTranslation(reference));
|
||||
} else if (score <= RanksManager.OWNER_RANK && score > rankView) {
|
||||
builder.description(user.getTranslation("protection.panel.flag-item.blocked-rank")
|
||||
+ user.getTranslation(reference));
|
||||
} else if (score == rankView) {
|
||||
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) -> {
|
||||
if (!template.actions().stream().anyMatch(ar -> clickType.equals(ar.clickType()))) {
|
||||
// If the click type is not in the template, don't do anything
|
||||
return true;
|
||||
}
|
||||
if (clickType.equals(ClickType.LEFT)) {
|
||||
rankView = RanksManager.getInstance().getRankDownValue(rankView);
|
||||
if (rankView <= RanksManager.VISITOR_RANK) {
|
||||
rankView = 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)) {
|
||||
rankView = RanksManager.getInstance().getRankUpValue(rankView);
|
||||
if (rankView >= RanksManager.OWNER_RANK) {
|
||||
rankView = 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);
|
||||
}
|
||||
}
|
||||
|
||||
// Update panel after click
|
||||
build();
|
||||
return true;
|
||||
});
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create invited button panel item.
|
||||
*
|
||||
* @param template the template
|
||||
* @param slot the slot
|
||||
* @return the panel item
|
||||
*/
|
||||
private PanelItem createInvitedButton(ItemTemplateRecord template, TemplatedPanel.ItemSlot slot) {
|
||||
PanelItemBuilder builder = new PanelItemBuilder();
|
||||
if (parent.isInvited(user.getUniqueId()) && user.hasPermission(parent.getAcceptCommand().getPermission())) {
|
||||
Invite invite = parent.getInvite(user.getUniqueId());
|
||||
User inviter = User.getInstance(invite.getInviter());
|
||||
String name = inviter.getName();
|
||||
builder.icon(inviter.getName());
|
||||
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,
|
||||
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 (!template.actions().stream().anyMatch(ar -> clickType.equals(ar.clickType()))) {
|
||||
// If the click type is not in the template, don't do anything
|
||||
return true;
|
||||
}
|
||||
if (clickType.equals(ClickType.SHIFT_LEFT)
|
||||
&& user.hasPermission(parent.getAcceptCommand().getPermission())) {
|
||||
plugin.log("Invite accepted: " + user.getName() + " accepted " + invite.getType());
|
||||
// Accept
|
||||
switch (invite.getType()) {
|
||||
case COOP -> parent.getAcceptCommand().acceptCoopInvite(user, invite);
|
||||
case TRUST -> parent.getAcceptCommand().acceptTrustInvite(user, invite);
|
||||
default -> parent.getAcceptCommand().acceptTeamInvite(user, invite);
|
||||
}
|
||||
user.closeInventory();
|
||||
}
|
||||
if (clickType.equals(ClickType.SHIFT_RIGHT)
|
||||
&& user.hasPermission(parent.getRejectCommand().getPermission())) {
|
||||
// Reject
|
||||
plugin.log("Invite rejected: " + user.getName() + " rejected " + invite.getType()
|
||||
+ " invite.");
|
||||
parent.getRejectCommand().execute(user, "", List.of());
|
||||
user.closeInventory();
|
||||
}
|
||||
return true;
|
||||
});
|
||||
} else {
|
||||
return this.getBlankBorder();
|
||||
}
|
||||
return builder.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 = plugin.getIslands().getPrimaryIsland(parent.getWorld(), user.getUniqueId());
|
||||
if (island == null) {
|
||||
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.
|
||||
*
|
||||
* @param template the template
|
||||
* @param slot the slot
|
||||
* @return the panel item
|
||||
*/
|
||||
private PanelItem createMemberButton(ItemTemplateRecord template, TemplatedPanel.ItemSlot slot) {
|
||||
// Player issuing the command must have an island
|
||||
Island island = plugin.getIslands().getPrimaryIsland(parent.getWorld(), user.getUniqueId());
|
||||
if (island == null) {
|
||||
return this.getBlankBackground();
|
||||
}
|
||||
|
||||
Optional<User> opMember = island.getMemberSet().stream().map(User::getInstance)
|
||||
.filter((User usr) -> rankView == RanksManager.OWNER_RANK || island.getRank(usr) == rankView) // If rankView is owner then show all ranks
|
||||
.sorted(Comparator.comparingInt((User usr) -> island.getRank(usr)).reversed()) // Show owner on left, then descending ranks
|
||||
.skip(slot.slot()) // Get the head for this slot
|
||||
.limit(1L).findFirst(); // Get just one head
|
||||
if (opMember.isEmpty()) {
|
||||
return this.getBlankBackground();
|
||||
}
|
||||
User member = opMember.get();
|
||||
int rank = island.getRank(member);
|
||||
String rankRef = RanksManager.getInstance().getRank(rank);
|
||||
@NonNull
|
||||
List<ActionRecords> actions = template.actions();
|
||||
// Make button description depending on viewer
|
||||
List<String> desc = new ArrayList<>();
|
||||
int userRank = Objects.requireNonNull(island).getRank(user);
|
||||
// Add the tooltip for kicking
|
||||
if (user.hasPermission(parent.getKickCommand().getPermission())
|
||||
&& userRank >= island.getRankCommand(parent.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() + ".name")
|
||||
+ " " + user.getTranslation(ar.tooltip()))
|
||||
.findFirst().ifPresent(desc::add);
|
||||
}
|
||||
// Set Owner
|
||||
if (user.hasPermission(parent.getSetOwnerCommand().getPermission()) && !user.equals(member)
|
||||
&& userRank >= RanksManager.OWNER_RANK && rank >= 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() + ".name")
|
||||
+ " " + user.getTranslation(ar.tooltip()))
|
||||
.findFirst().ifPresent(desc::add);
|
||||
}
|
||||
// Leave
|
||||
if (user.hasPermission(parent.getLeaveCommand().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.isOnline()) {
|
||||
desc.add(0, user.getTranslation(rankRef));
|
||||
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(rankRef));
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Click listener
|
||||
* @param panel panel
|
||||
* @param clickingUser clicking user
|
||||
* @param clickType click type
|
||||
* @param i slot
|
||||
* @param target target user
|
||||
* @param actions actions
|
||||
* @return true if the inventory item should not be removed - always true
|
||||
*/
|
||||
private boolean clickListener(Panel panel, User clickingUser, ClickType clickType, int i, User target,
|
||||
List<ActionRecords> actions) {
|
||||
if (!actions.stream().anyMatch(ar -> clickType.equals(ar.clickType()))) {
|
||||
// If the click type is not in the template, don't do anything
|
||||
return true;
|
||||
}
|
||||
int rank = Objects.requireNonNull(island).getRank(clickingUser);
|
||||
for (ItemTemplateRecord.ActionRecords action : actions) {
|
||||
if (clickType.equals(action.clickType())) {
|
||||
switch (action.actionType().toUpperCase(Locale.ENGLISH)) {
|
||||
case "KICK" -> {
|
||||
// Kick the player, or uncoop, or untrust
|
||||
if (clickingUser.hasPermission(parent.getKickCommand().getPermission())
|
||||
&& !target.equals(clickingUser)
|
||||
&& rank >= island.getRankCommand(parent.getLabel() + " kick")) {
|
||||
plugin.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);
|
||||
plugin.log("Kick: success");
|
||||
} else {
|
||||
plugin.log("Kick: failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
case "SETOWNER" -> {
|
||||
// Make the player the leader of the island
|
||||
if (clickingUser.hasPermission(parent.getSetOwnerCommand().getPermission())
|
||||
&& !target.equals(clickingUser)
|
||||
&& clickingUser.getUniqueId().equals(island.getOwner())
|
||||
&& island.getRank(target) >= RanksManager.MEMBER_RANK) {
|
||||
plugin.log("Set Owner: " + clickingUser.getName() + " trying to make " + target.getName()
|
||||
+ " owner of island at " + island.getCenter());
|
||||
clickingUser.closeInventory();
|
||||
if (parent.getSetOwnerCommand().setOwner(clickingUser, target.getUniqueId())) {
|
||||
plugin.log("Set Owner: success");
|
||||
} else {
|
||||
plugin.log("Set Owner: failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
case "LEAVE" -> {
|
||||
if (clickingUser.hasPermission(parent.getLeaveCommand().getPermission())
|
||||
&& target.equals(clickingUser)
|
||||
&& !clickingUser.getUniqueId().equals(island.getOwner())) {
|
||||
plugin.log("Leave: " + clickingUser.getName() + " trying to leave island at "
|
||||
+ island.getCenter());
|
||||
clickingUser.closeInventory();
|
||||
if (parent.getLeaveCommand().leave(clickingUser)) {
|
||||
plugin.log("Leave: success");
|
||||
} else {
|
||||
plugin.log("Leave: failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean removePlayer(User clicker, User member) {
|
||||
// If member then kick, if coop, uncoop, if trusted, then untrust
|
||||
return switch (island.getRank(member)) {
|
||||
case RanksManager.COOP_RANK -> parent.getUncoopCommand().unCoopCmd(user, member.getUniqueId());
|
||||
case RanksManager.TRUSTED_RANK -> parent.getUnTrustCommand().unTrustCmd(user, member.getUniqueId());
|
||||
default -> {
|
||||
if (parent.getKickCommand().canExecute(user, parent.getKickCommand().getLabel(),
|
||||
List.of(member.getName()))) {
|
||||
yield parent.getKickCommand().kick(clicker, member.getUniqueId());
|
||||
} else {
|
||||
yield false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
private List<String> showMembers() {
|
||||
List<String> message = new ArrayList<>();
|
||||
// Gather online members
|
||||
long onlineMemberCount = island.getMemberSet(RanksManager.MEMBER_RANK).stream()
|
||||
.filter(uuid -> Util.getOnlinePlayerList(user).contains(Bukkit.getOfflinePlayer(uuid).getName()))
|
||||
.count();
|
||||
|
||||
// Show header:
|
||||
message.add(user.getTranslation("commands.island.team.info.header", "[max]",
|
||||
String.valueOf(plugin.getIslands().getMaxMembers(island, RanksManager.MEMBER_RANK)), "[total]",
|
||||
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) {
|
||||
Set<UUID> players = island.getMemberSet(rank, false);
|
||||
if (!players.isEmpty()) {
|
||||
if (rank == RanksManager.OWNER_RANK) {
|
||||
// Slightly special handling for the owner rank
|
||||
message.add(user.getTranslation("commands.island.team.info.rank-layout.owner", TextVariables.RANK,
|
||||
user.getTranslation(RanksManager.OWNER_RANK_REF)));
|
||||
} else {
|
||||
message.add(user.getTranslation("commands.island.team.info.rank-layout.generic", TextVariables.RANK,
|
||||
user.getTranslation(RanksManager.getInstance().getRank(rank)), TextVariables.NUMBER,
|
||||
String.valueOf(island.getMemberSet(rank, false).size())));
|
||||
}
|
||||
message.addAll(displayOnOffline(user, rank, island, onlineMembers));
|
||||
}
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
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)) {
|
||||
message.add(getMemberStatus(user, member, onlineMembers.contains(member)));
|
||||
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
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();
|
||||
|
||||
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"));
|
||||
}
|
||||
return lastSeen;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -7,28 +7,13 @@ import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
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.NonNull;
|
||||
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.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;
|
||||
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;
|
||||
@ -43,11 +28,6 @@ public class IslandTeamInviteCommand extends CompositeCommand {
|
||||
private @Nullable User invitedPlayer;
|
||||
private @Nullable TemplateItem border;
|
||||
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;
|
||||
private String searchName = "";
|
||||
|
||||
public IslandTeamInviteCommand(IslandTeamCommand parent) {
|
||||
super(parent, "invite");
|
||||
@ -77,14 +57,13 @@ public class IslandTeamInviteCommand extends CompositeCommand {
|
||||
user.sendMessage("general.errors.no-island");
|
||||
return false;
|
||||
}
|
||||
Island island = islandsManager.getIsland(getWorld(), user);
|
||||
|
||||
if (args.size() != 1) {
|
||||
this.inviteCmd = true;
|
||||
build(user);
|
||||
new IslandTeamInviteGUI(itc, true, island).build(user);
|
||||
return true;
|
||||
}
|
||||
|
||||
Island island = islandsManager.getIsland(getWorld(), user);
|
||||
int rank = Objects.requireNonNull(island).getRank(user);
|
||||
|
||||
return checkRankAndInvitePlayer(user, island, rank, args.get(0));
|
||||
@ -208,204 +187,4 @@ public class IslandTeamInviteCommand extends CompositeCommand {
|
||||
return Optional.of(Util.tabLimit(options, lastArg));
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the invite panel
|
||||
* @param user use of the panel
|
||||
*/
|
||||
void build(User user) {
|
||||
this.user = user;
|
||||
// Start building panel.
|
||||
TemplatedPanelBuilder panelBuilder = new TemplatedPanelBuilder();
|
||||
panelBuilder.user(user);
|
||||
panelBuilder.world(user.getWorld());
|
||||
|
||||
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("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();
|
||||
// Register unknown type builder.
|
||||
panelBuilder.build();
|
||||
|
||||
}
|
||||
|
||||
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);
|
||||
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;
|
||||
});
|
||||
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) {
|
||||
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(template.title())).icon(template.icon())
|
||||
.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 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(template.title())).icon(template.icon())
|
||||
.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.
|
||||
*
|
||||
* @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();
|
||||
}
|
||||
if (page < 0) {
|
||||
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());
|
||||
}
|
||||
|
||||
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,
|
||||
template.actions()))
|
||||
.build();
|
||||
}
|
||||
|
||||
private boolean clickHandler(Panel panel, User user, ClickType clickType, int clickSlot, Player player,
|
||||
@NonNull List<ActionRecords> list) {
|
||||
if (!list.stream().anyMatch(ar -> clickType.equals(ar.clickType()))) {
|
||||
// If the click type is not in the template, don't do anything
|
||||
return true;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
private PanelItem getBlankBackground() {
|
||||
return new PanelItemBuilder()
|
||||
.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;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,279 @@
|
||||
package world.bentobox.bentobox.api.commands.island.team;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.conversations.ConversationContext;
|
||||
import org.bukkit.conversations.ConversationFactory;
|
||||
import org.bukkit.conversations.Prompt;
|
||||
import org.bukkit.conversations.StringPrompt;
|
||||
import org.bukkit.entity.Player;
|
||||
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.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;
|
||||
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;
|
||||
|
||||
public class IslandTeamInviteGUI {
|
||||
|
||||
private final IslandTeamInviteCommand itic;
|
||||
private final IslandTeamCommand itc;
|
||||
private @Nullable TemplateItem border;
|
||||
private @Nullable TemplateItem background;
|
||||
private User user;
|
||||
private long page = 0; // This number by 35
|
||||
private final boolean inviteCmd;
|
||||
private static final long PER_PAGE = 35;
|
||||
private String searchName = "";
|
||||
private final BentoBox plugin;
|
||||
private final Island island;
|
||||
|
||||
public IslandTeamInviteGUI(IslandTeamCommand itc, boolean invitedCmd, Island island) {
|
||||
this.island = island;
|
||||
this.plugin = itc.getPlugin();
|
||||
this.inviteCmd = invitedCmd;
|
||||
itic = itc.getInviteCommand();
|
||||
this.itc = itc;
|
||||
// Panels
|
||||
if (!new File(plugin.getDataFolder() + File.separator + "panels", "team_invite_panel.yml")
|
||||
.exists()) {
|
||||
plugin.saveResource("panels/team_invite_panel.yml", false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the invite panel
|
||||
* @param user use of the panel
|
||||
*/
|
||||
void build(User user) {
|
||||
this.user = user;
|
||||
// Start building panel.
|
||||
TemplatedPanelBuilder panelBuilder = new TemplatedPanelBuilder();
|
||||
panelBuilder.user(user);
|
||||
panelBuilder.world(user.getWorld());
|
||||
|
||||
panelBuilder.template("team_invite_panel", new File(plugin.getDataFolder(), "panels"));
|
||||
|
||||
panelBuilder.parameters("[name]", user.getName(), "[display_name]", user.getDisplayName());
|
||||
|
||||
panelBuilder.registerTypeBuilder("PROSPECT", this::createProspectButton);
|
||||
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();
|
||||
// Register unknown type builder.
|
||||
panelBuilder.build();
|
||||
|
||||
}
|
||||
|
||||
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) {
|
||||
new IslandTeamGUI(plugin, itc, user, island).build();
|
||||
}
|
||||
return true;
|
||||
}).build();
|
||||
}
|
||||
|
||||
private PanelItem createSearchButton(ItemTemplateRecord template, TemplatedPanel.ItemSlot slot) {
|
||||
checkTemplate(template);
|
||||
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())
|
||||
.buildConversation(user.getPlayer()).begin();
|
||||
return true;
|
||||
});
|
||||
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) {
|
||||
checkTemplate(template);
|
||||
long count = itic.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(template.title())).icon(template.icon())
|
||||
.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 void checkTemplate(ItemTemplateRecord template) {
|
||||
if (template.icon() == null) {
|
||||
plugin.logError("Icon in template is missing or unknown! " + template.toString());
|
||||
}
|
||||
if (template.title() == null) {
|
||||
plugin.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(template.title())).icon(template.icon())
|
||||
.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.
|
||||
*
|
||||
* @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 = plugin.getIslands().getPrimaryIsland(itic.getWorld(), user.getUniqueId());
|
||||
if (island == null) {
|
||||
return this.getBlankBackground();
|
||||
}
|
||||
if (page < 0) {
|
||||
page = 0;
|
||||
}
|
||||
return itic.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());
|
||||
}
|
||||
|
||||
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,
|
||||
template.actions()))
|
||||
.build();
|
||||
}
|
||||
|
||||
private boolean clickHandler(Panel panel, User user, ClickType clickType, int clickSlot, Player player,
|
||||
@NonNull List<ActionRecords> list) {
|
||||
if (!list.stream().anyMatch(ar -> clickType.equals(ar.clickType()))) {
|
||||
// If the click type is not in the template, don't do anything
|
||||
return true;
|
||||
}
|
||||
if (clickType.equals(ClickType.LEFT)) {
|
||||
user.closeInventory();
|
||||
if (itic.canExecute(user, itic.getLabel(), List.of(player.getName()))) {
|
||||
plugin.log("Invite sent to: " + player.getName() + " by " + user.getName() + " to join island in "
|
||||
+ itic.getWorld().getName());
|
||||
itic.execute(user, itic.getLabel(), List.of(player.getName()));
|
||||
} else {
|
||||
plugin.log("Invite failed: " + player.getName() + " by " + user.getName() + " to join island in "
|
||||
+ itic.getWorld().getName());
|
||||
}
|
||||
} else if (clickType.equals(ClickType.RIGHT)) {
|
||||
user.closeInventory();
|
||||
if (this.itc.getCoopCommand().canExecute(user, itic.getLabel(), List.of(player.getName()))) {
|
||||
plugin.log("Coop: " + player.getName() + " cooped " + user.getName() + " to island in "
|
||||
+ itic.getWorld().getName());
|
||||
this.itc.getCoopCommand().execute(user, itic.getLabel(), List.of(player.getName()));
|
||||
} else {
|
||||
plugin.log(
|
||||
"Coop failed: " + player.getName() + "'s coop to " + user.getName() + " failed for island in "
|
||||
+ itic.getWorld().getName());
|
||||
}
|
||||
} else if (clickType.equals(ClickType.SHIFT_LEFT)) {
|
||||
user.closeInventory();
|
||||
if (this.itc.getTrustCommand().canExecute(user, itic.getLabel(), List.of(player.getName()))) {
|
||||
plugin.log("Trust: " + player.getName() + " trusted " + user.getName() + " to island in "
|
||||
+ itic.getWorld().getName());
|
||||
this.itc.getTrustCommand().execute(user, itic.getLabel(), List.of(player.getName()));
|
||||
} else {
|
||||
plugin.log("Trust failed: " + player.getName() + "'s trust failed for " + user.getName()
|
||||
+ " for island in "
|
||||
+ itic.getWorld().getName());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private PanelItem getBlankBackground() {
|
||||
return new PanelItemBuilder()
|
||||
.icon(Objects.requireNonNullElse(background.icon(), new ItemStack(Material.BARRIER)))
|
||||
.name((Objects.requireNonNullElse(background.title(), ""))).build();
|
||||
}
|
||||
|
||||
class InviteNamePrompt extends StringPrompt {
|
||||
|
||||
@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) {
|
||||
// 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
|
||||
searchName = 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(), () -> build(user), 20L);
|
||||
return Prompt.END_OF_CONVERSATION;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -102,6 +102,7 @@ public class IslandTeamPromoteCommandTest extends RanksManagerBeforeClassTest {
|
||||
when(pm.getUser("target")).thenReturn(target);
|
||||
when(target.getName()).thenReturn("target");
|
||||
when(target.getDisplayName()).thenReturn("Target");
|
||||
when(target.getUniqueId()).thenReturn(uuid);
|
||||
|
||||
// Managers
|
||||
when(plugin.getIslands()).thenReturn(im);
|
||||
|
Loading…
Reference in New Issue
Block a user