commit
49d05054d2
14
pom.xml
14
pom.xml
|
@ -88,7 +88,7 @@
|
||||||
<!-- Do not change unless you want different name for local builds. -->
|
<!-- Do not change unless you want different name for local builds. -->
|
||||||
<build.number>-LOCAL</build.number>
|
<build.number>-LOCAL</build.number>
|
||||||
<!-- This allows to change between versions. -->
|
<!-- This allows to change between versions. -->
|
||||||
<build.version>2.1.1</build.version>
|
<build.version>2.2.0</build.version>
|
||||||
<sonar.organization>bentobox-world</sonar.organization>
|
<sonar.organization>bentobox-world</sonar.organization>
|
||||||
<sonar.host.url>https://sonarcloud.io</sonar.host.url>
|
<sonar.host.url>https://sonarcloud.io</sonar.host.url>
|
||||||
<server.jars>${project.basedir}/lib</server.jars>
|
<server.jars>${project.basedir}/lib</server.jars>
|
||||||
|
@ -189,6 +189,12 @@
|
||||||
<id>MG-Dev Jenkins CI Maven Repository</id>
|
<id>MG-Dev Jenkins CI Maven Repository</id>
|
||||||
<url>https://ci.mg-dev.eu/plugin/repository/everything</url>
|
<url>https://ci.mg-dev.eu/plugin/repository/everything</url>
|
||||||
</repository>
|
</repository>
|
||||||
|
<!-- For MythicMobs -->
|
||||||
|
<repository>
|
||||||
|
<id>nexus</id>
|
||||||
|
<name>Lumine Releases</name>
|
||||||
|
<url>https://mvn.lumine.io/repository/maven-public/</url>
|
||||||
|
</repository>
|
||||||
</repositories>
|
</repositories>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@ -297,6 +303,12 @@
|
||||||
<version>${myworlds.version}</version>
|
<version>${myworlds.version}</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.lumine</groupId>
|
||||||
|
<artifactId>Mythic-Dist</artifactId>
|
||||||
|
<version>5.3.5</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
<!-- Shaded APIs -->
|
<!-- Shaded APIs -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.github.TheBusyBiscuit</groupId>
|
<groupId>com.github.TheBusyBiscuit</groupId>
|
||||||
|
|
|
@ -27,6 +27,7 @@ import world.bentobox.bentobox.database.DatabaseSetup;
|
||||||
import world.bentobox.bentobox.hooks.ItemsAdderHook;
|
import world.bentobox.bentobox.hooks.ItemsAdderHook;
|
||||||
import world.bentobox.bentobox.hooks.MultiverseCoreHook;
|
import world.bentobox.bentobox.hooks.MultiverseCoreHook;
|
||||||
import world.bentobox.bentobox.hooks.MyWorldsHook;
|
import world.bentobox.bentobox.hooks.MyWorldsHook;
|
||||||
|
import world.bentobox.bentobox.hooks.MythicMobsHook;
|
||||||
import world.bentobox.bentobox.hooks.SlimefunHook;
|
import world.bentobox.bentobox.hooks.SlimefunHook;
|
||||||
import world.bentobox.bentobox.hooks.VaultHook;
|
import world.bentobox.bentobox.hooks.VaultHook;
|
||||||
import world.bentobox.bentobox.hooks.placeholders.PlaceholderAPIHook;
|
import world.bentobox.bentobox.hooks.placeholders.PlaceholderAPIHook;
|
||||||
|
@ -185,6 +186,9 @@ public class BentoBox extends JavaPlugin implements Listener {
|
||||||
final long enableStart = System.currentTimeMillis();
|
final long enableStart = System.currentTimeMillis();
|
||||||
hooksManager.registerHook(new VaultHook());
|
hooksManager.registerHook(new VaultHook());
|
||||||
|
|
||||||
|
// MythicMobs
|
||||||
|
hooksManager.registerHook(new MythicMobsHook());
|
||||||
|
|
||||||
hooksManager.registerHook(new PlaceholderAPIHook());
|
hooksManager.registerHook(new PlaceholderAPIHook());
|
||||||
// Setup the Placeholders manager
|
// Setup the Placeholders manager
|
||||||
placeholdersManager = new PlaceholdersManager(this);
|
placeholdersManager = new PlaceholdersManager(this);
|
||||||
|
|
|
@ -82,7 +82,7 @@ public class AdminTeamDisbandCommand extends CompositeCommand {
|
||||||
|
|
||||||
private Map<String, Island> getIslandsXYZ(UUID target) {
|
private Map<String, Island> getIslandsXYZ(UUID target) {
|
||||||
return getIslands().getOwnedIslands(getWorld(), target).stream().filter(is -> is.getMemberSet().size() > 1) // Filter for teams
|
return getIslands().getOwnedIslands(getWorld(), target).stream().filter(is -> is.getMemberSet().size() > 1) // Filter for teams
|
||||||
.collect(Collectors.toMap(island -> Util.xyz(island.getCenter().toVector()), island -> island));
|
.collect(Collectors.toMap(is -> Util.xyz(is.getCenter().toVector()), is -> is));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,9 +1,17 @@
|
||||||
package world.bentobox.bentobox.api.commands.admin.team;
|
package world.bentobox.bentobox.api.commands.admin.team;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
|
|
||||||
|
import world.bentobox.bentobox.api.addons.GameModeAddon;
|
||||||
import world.bentobox.bentobox.api.commands.CompositeCommand;
|
import world.bentobox.bentobox.api.commands.CompositeCommand;
|
||||||
|
import world.bentobox.bentobox.api.commands.ConfirmableCommand;
|
||||||
import world.bentobox.bentobox.api.events.island.IslandEvent;
|
import world.bentobox.bentobox.api.events.island.IslandEvent;
|
||||||
import world.bentobox.bentobox.api.events.team.TeamEvent;
|
import world.bentobox.bentobox.api.events.team.TeamEvent;
|
||||||
import world.bentobox.bentobox.api.localization.TextVariables;
|
import world.bentobox.bentobox.api.localization.TextVariables;
|
||||||
|
@ -17,7 +25,11 @@ import world.bentobox.bentobox.util.Util;
|
||||||
*
|
*
|
||||||
* @author tastybento
|
* @author tastybento
|
||||||
*/
|
*/
|
||||||
public class AdminTeamSetownerCommand extends CompositeCommand {
|
public class AdminTeamSetownerCommand extends ConfirmableCommand {
|
||||||
|
|
||||||
|
private @Nullable UUID targetUUID;
|
||||||
|
private Island island;
|
||||||
|
private @Nullable UUID previousOwnerUUID;
|
||||||
|
|
||||||
public AdminTeamSetownerCommand(CompositeCommand parent) {
|
public AdminTeamSetownerCommand(CompositeCommand parent) {
|
||||||
super(parent, "setowner");
|
super(parent, "setowner");
|
||||||
|
@ -28,35 +40,50 @@ public class AdminTeamSetownerCommand extends CompositeCommand {
|
||||||
setPermission("mod.team.setowner");
|
setPermission("mod.team.setowner");
|
||||||
setParametersHelp("commands.admin.team.setowner.parameters");
|
setParametersHelp("commands.admin.team.setowner.parameters");
|
||||||
setDescription("commands.admin.team.setowner.description");
|
setDescription("commands.admin.team.setowner.description");
|
||||||
|
this.setOnlyPlayer(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean execute(User user, String label, List<String> args) {
|
public boolean canExecute(User user, String label, List<String> args) {
|
||||||
// If args are not right, show help
|
// If args are not right, show help
|
||||||
if (args.size() != 1) {
|
if (args.size() != 1) {
|
||||||
showHelp(this, user);
|
showHelp(this, user);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get target
|
// Get target
|
||||||
UUID targetUUID = Util.getUUID(args.get(0));
|
targetUUID = Util.getUUID(args.get(0));
|
||||||
if (targetUUID == null) {
|
if (targetUUID == null) {
|
||||||
user.sendMessage("general.errors.unknown-player", TextVariables.NAME, args.get(0));
|
user.sendMessage("general.errors.unknown-player", TextVariables.NAME, args.get(0));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!getIslands().inTeam(getWorld(), targetUUID)) {
|
// Check that user is on an island
|
||||||
user.sendMessage("general.errors.not-in-team");
|
Optional<Island> opIsland = getIslands().getIslandAt(user.getLocation());
|
||||||
|
if (opIsland.isEmpty()) {
|
||||||
|
user.sendMessage("commands.admin.team.setowner.must-be-on-island");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Island island = getIslands().getPrimaryIsland(getWorld(), targetUUID);
|
island = opIsland.get();
|
||||||
UUID previousOwnerUUID = island.getOwner();
|
previousOwnerUUID = island.getOwner();
|
||||||
if (targetUUID.equals(previousOwnerUUID)) {
|
if (targetUUID.equals(previousOwnerUUID)) {
|
||||||
user.sendMessage("commands.admin.team.setowner.already-owner", TextVariables.NAME, args.get(0));
|
user.sendMessage("commands.admin.team.setowner.already-owner", TextVariables.NAME, args.get(0));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// Get the User corresponding to the current owner
|
public boolean execute(User user, String label, List<String> args) {
|
||||||
|
Objects.requireNonNull(island);
|
||||||
|
Objects.requireNonNull(targetUUID);
|
||||||
|
|
||||||
|
this.askConfirmation(user, user.getTranslation("commands.admin.team.setowner.confirmation", TextVariables.NAME,
|
||||||
|
args.get(0), TextVariables.XYZ, Util.xyz(island.getCenter().toVector())), () -> changeOwner(user));
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void changeOwner(User user) {
|
||||||
User target = User.getInstance(targetUUID);
|
User target = User.getInstance(targetUUID);
|
||||||
|
|
||||||
// Fire event so add-ons know
|
// Fire event so add-ons know
|
||||||
// Call the setowner event
|
// Call the setowner event
|
||||||
TeamEvent.builder().island(island).reason(TeamEvent.Reason.SETOWNER).involvedPlayer(targetUUID).admin(true)
|
TeamEvent.builder().island(island).reason(TeamEvent.Reason.SETOWNER).involvedPlayer(targetUUID).admin(true)
|
||||||
|
@ -70,8 +97,20 @@ public class AdminTeamSetownerCommand extends CompositeCommand {
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
// Make new owner
|
// Make new owner
|
||||||
getIslands().setOwner(getWorld(), user, targetUUID);
|
getIslands().setOwner(user, targetUUID, island, RanksManager.MEMBER_RANK);
|
||||||
user.sendMessage("commands.admin.team.setowner.success", TextVariables.NAME, args.get(0));
|
user.sendMessage("commands.admin.team.setowner.success", TextVariables.NAME, target.getName());
|
||||||
|
|
||||||
|
// Report if this made player have more islands than expected
|
||||||
|
// Get how many islands this player has
|
||||||
|
int num = this.getIslands().getNumberOfConcurrentIslands(targetUUID, getWorld());
|
||||||
|
int max = target.getPermissionValue(
|
||||||
|
this.getIWM().getAddon(getWorld()).map(GameModeAddon::getPermissionPrefix).orElse("") + "island.number",
|
||||||
|
this.getIWM().getWorldSettings(getWorld()).getConcurrentIslands());
|
||||||
|
if (num > max) {
|
||||||
|
// You cannot make an island
|
||||||
|
user.sendMessage("commands.admin.team.setowner.extra-islands", TextVariables.NUMBER, String.valueOf(num),
|
||||||
|
"[max]", String.valueOf(max));
|
||||||
|
}
|
||||||
|
|
||||||
// Call the rank change event for the old island owner
|
// Call the rank change event for the old island owner
|
||||||
if (previousOwnerUUID != null) {
|
if (previousOwnerUUID != null) {
|
||||||
|
@ -80,6 +119,13 @@ public class AdminTeamSetownerCommand extends CompositeCommand {
|
||||||
.reason(IslandEvent.Reason.RANK_CHANGE)
|
.reason(IslandEvent.Reason.RANK_CHANGE)
|
||||||
.rankChange(RanksManager.OWNER_RANK, island.getRank(previousOwnerUUID)).build();
|
.rankChange(RanksManager.OWNER_RANK, island.getRank(previousOwnerUUID)).build();
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<List<String>> tabComplete(User user, String alias, List<String> args) {
|
||||||
|
String lastArg = !args.isEmpty() ? args.get(args.size() - 1) : "";
|
||||||
|
List<String> options = Bukkit.getOnlinePlayers().stream().map(Player::getName).toList();
|
||||||
|
return Optional.of(Util.tabLimit(options, lastArg));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,7 +53,7 @@ public class IslandSethomeCommand extends ConfirmableCommand {
|
||||||
|
|
||||||
// Check number of homes
|
// Check number of homes
|
||||||
|
|
||||||
int maxHomes = getIslands().getIslands(getWorld(), user).stream().mapToInt(getIslands()::getMaxHomes).sum();
|
int maxHomes = getIslands().getMaxHomes(island);
|
||||||
if (getIslands().getNumberOfHomesIfAdded(island, String.join(" ", args)) > maxHomes) {
|
if (getIslands().getNumberOfHomesIfAdded(island, String.join(" ", args)) > maxHomes) {
|
||||||
user.sendMessage("commands.island.sethome.too-many-homes", TextVariables.NUMBER, String.valueOf(maxHomes));
|
user.sendMessage("commands.island.sethome.too-many-homes", TextVariables.NUMBER, String.valueOf(maxHomes));
|
||||||
user.sendMessage("commands.island.sethome.homes-are");
|
user.sendMessage("commands.island.sethome.homes-are");
|
||||||
|
|
|
@ -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;
|
package world.bentobox.bentobox.api.commands.island.team;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.time.Duration;
|
|
||||||
import java.time.Instant;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
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.NonNull;
|
||||||
import org.eclipse.jdt.annotation.Nullable;
|
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.IslandBaseEvent;
|
||||||
import world.bentobox.bentobox.api.events.team.TeamEvent;
|
import world.bentobox.bentobox.api.events.team.TeamEvent;
|
||||||
import world.bentobox.bentobox.api.localization.TextVariables;
|
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.panels.reader.PanelTemplateRecord.TemplateItem;
|
||||||
import world.bentobox.bentobox.api.user.User;
|
import world.bentobox.bentobox.api.user.User;
|
||||||
import world.bentobox.bentobox.database.objects.Island;
|
import world.bentobox.bentobox.database.objects.Island;
|
||||||
import world.bentobox.bentobox.managers.RanksManager;
|
import world.bentobox.bentobox.managers.RanksManager;
|
||||||
import world.bentobox.bentobox.util.Util;
|
|
||||||
|
|
||||||
public class IslandTeamCommand extends CompositeCommand {
|
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.
|
* Invited list. Key is the invited party, value is the invite.
|
||||||
* @since 1.8.0
|
* @since 1.8.0
|
||||||
*/
|
*/
|
||||||
private final Map<UUID, Invite> inviteMap;
|
private final Map<UUID, Invite> inviteMap;
|
||||||
|
|
||||||
private User user;
|
|
||||||
|
|
||||||
private Island island;
|
|
||||||
|
|
||||||
private int rank = RanksManager.OWNER_RANK;
|
|
||||||
|
|
||||||
private IslandTeamKickCommand kickCommand;
|
private IslandTeamKickCommand kickCommand;
|
||||||
|
|
||||||
private IslandTeamLeaveCommand leaveCommand;
|
private IslandTeamLeaveCommand leaveCommand;
|
||||||
|
@ -120,13 +87,12 @@ public class IslandTeamCommand extends CompositeCommand {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canExecute(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
|
// 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 (island == null) {
|
||||||
if (isInvited(user.getUniqueId())) {
|
if (isInvited(user.getUniqueId())) {
|
||||||
// Player has an invite, so show the invite
|
// Player has an invite, so show the invite
|
||||||
build();
|
new IslandTeamGUI(getPlugin(), this, user, island).build();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
user.sendMessage("general.errors.no-island");
|
user.sendMessage("general.errors.no-island");
|
||||||
|
@ -155,510 +121,11 @@ public class IslandTeamCommand extends CompositeCommand {
|
||||||
@Override
|
@Override
|
||||||
public boolean execute(User user, String label, List<String> args) {
|
public boolean execute(User user, String label, List<String> args) {
|
||||||
// Show the panel
|
// Show the panel
|
||||||
build();
|
new IslandTeamGUI(getPlugin(), this, user, getIslands().getPrimaryIsland(getWorld(), user.getUniqueId()))
|
||||||
|
.build();
|
||||||
return true;
|
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())) {
|
|
||||||
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.execute(user, kickCommand.getLabel(), List.of(member.getName()));
|
|
||||||
} 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) {
|
private boolean fireEvent(User user, Island island) {
|
||||||
IslandBaseEvent e = TeamEvent.builder().island(island).reason(TeamEvent.Reason.INFO)
|
IslandBaseEvent e = TeamEvent.builder().island(island).reason(TeamEvent.Reason.INFO)
|
||||||
.involvedPlayer(user.getUniqueId()).build();
|
.involvedPlayer(user.getUniqueId()).build();
|
||||||
|
@ -730,4 +197,52 @@ public class IslandTeamCommand extends CompositeCommand {
|
||||||
protected IslandTeamTrustCommand getTrustCommand() {
|
protected IslandTeamTrustCommand getTrustCommand() {
|
||||||
return trustCommand;
|
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,567 @@
|
||||||
|
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.commands.island.team.Invite.Type;
|
||||||
|
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 static final String NAME = ".name";
|
||||||
|
|
||||||
|
private static final String TIPS = "commands.island.team.gui.tips.";
|
||||||
|
|
||||||
|
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().noneMatch(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
|
||||||
|
createDescription(builder);
|
||||||
|
createClickHandler(builder, template.actions());
|
||||||
|
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createClickHandler(PanelItemBuilder builder, @NonNull List<ActionRecords> actions) {
|
||||||
|
builder.clickHandler((panel, user, clickType, clickSlot) -> {
|
||||||
|
if (actions.stream().noneMatch(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;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createDescription(PanelItemBuilder builder) {
|
||||||
|
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"));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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());
|
||||||
|
if (invite == null) {
|
||||||
|
return this.getBlankBorder();
|
||||||
|
}
|
||||||
|
User inviter = User.getInstance(invite.getInviter());
|
||||||
|
String name = inviter.getName();
|
||||||
|
builder.icon(inviter.getName());
|
||||||
|
builder.name(user.getTranslation("commands.island.team.gui.buttons.invitation"));
|
||||||
|
createInviteDescription(builder, invite.getType(), name, template.actions());
|
||||||
|
createInviteClickHandler(builder, invite, template.actions());
|
||||||
|
} else {
|
||||||
|
return this.getBlankBorder();
|
||||||
|
}
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createInviteClickHandler(PanelItemBuilder builder, Invite invite, @NonNull List<ActionRecords> list) {
|
||||||
|
Type type = invite.getType();
|
||||||
|
builder.clickHandler((panel, user, clickType, clickSlot) -> {
|
||||||
|
if (list.stream().noneMatch(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 " + type);
|
||||||
|
// Accept
|
||||||
|
switch (type) {
|
||||||
|
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 " + type + " invite.");
|
||||||
|
parent.getRejectCommand().execute(user, "", List.of());
|
||||||
|
user.closeInventory();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createInviteDescription(PanelItemBuilder builder, Type type, String name,
|
||||||
|
@NonNull List<ActionRecords> list) {
|
||||||
|
builder.description(switch (type) {
|
||||||
|
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(list.stream()
|
||||||
|
.map(ar -> user.getTranslation(TIPS + ar.clickType().name() + NAME) + " "
|
||||||
|
+ user.getTranslation(ar.tooltip()))
|
||||||
|
.toList());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 is = plugin.getIslands().getPrimaryIsland(parent.getWorld(), user.getUniqueId());
|
||||||
|
if (is == 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 is = plugin.getIslands().getPrimaryIsland(parent.getWorld(), user.getUniqueId());
|
||||||
|
if (is == null) {
|
||||||
|
return this.getBlankBackground();
|
||||||
|
}
|
||||||
|
int minimumRank = RanksManager.getInstance().getRankUpValue(RanksManager.VISITOR_RANK); // Get the rank above Visitor.
|
||||||
|
Optional<User> opMember = is.getMemberSet(minimumRank).stream().map(User::getInstance)
|
||||||
|
.filter((User usr) -> rankView == RanksManager.OWNER_RANK || is.getRank(usr) == rankView) // If rankView is owner then show all ranks
|
||||||
|
.sorted(Comparator.comparingInt((User usr) -> is.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 = is.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(is).getRank(user);
|
||||||
|
// Add the tooltip for kicking
|
||||||
|
if (user.hasPermission(parent.getKickCommand().getPermission())
|
||||||
|
&& userRank >= is.getRankCommand(parent.getLabel() + " kick") && !user.equals(member)) {
|
||||||
|
actions.stream().filter(ar -> ar.actionType().equalsIgnoreCase("kick"))
|
||||||
|
.map(ar -> user.getTranslation(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(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(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(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().noneMatch(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" -> kickPlayer(clickingUser, target, rank);
|
||||||
|
case "SETOWNER" -> setOwner(clickingUser, target);
|
||||||
|
case "LEAVE" -> leave(clickingUser, target);
|
||||||
|
default -> {
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void leave(User clickingUser, User target) {
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setOwner(User clickingUser, User target) {
|
||||||
|
// 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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void kickPlayer(User clickingUser, User target, int rank) {
|
||||||
|
// 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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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(rank, island, onlineMembers));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> displayOnOffline(int rank, Island island, List<UUID> onlineMembers) {
|
||||||
|
List<String> message = new ArrayList<>();
|
||||||
|
for (UUID member : island.getMemberSet(rank, false)) {
|
||||||
|
message.add(getMemberStatus(member, onlineMembers.contains(member)));
|
||||||
|
|
||||||
|
}
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getMemberStatus(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(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(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.Optional;
|
||||||
import java.util.UUID;
|
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 org.eclipse.jdt.annotation.Nullable;
|
||||||
|
|
||||||
import world.bentobox.bentobox.BentoBox;
|
|
||||||
import world.bentobox.bentobox.api.commands.CompositeCommand;
|
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.Invite.Type;
|
||||||
import world.bentobox.bentobox.api.events.IslandBaseEvent;
|
import world.bentobox.bentobox.api.events.IslandBaseEvent;
|
||||||
import world.bentobox.bentobox.api.events.team.TeamEvent;
|
import world.bentobox.bentobox.api.events.team.TeamEvent;
|
||||||
import world.bentobox.bentobox.api.localization.TextVariables;
|
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.panels.reader.PanelTemplateRecord.TemplateItem;
|
||||||
import world.bentobox.bentobox.api.user.User;
|
import world.bentobox.bentobox.api.user.User;
|
||||||
import world.bentobox.bentobox.database.objects.Island;
|
import world.bentobox.bentobox.database.objects.Island;
|
||||||
|
@ -43,11 +28,6 @@ public class IslandTeamInviteCommand extends CompositeCommand {
|
||||||
private @Nullable User invitedPlayer;
|
private @Nullable User invitedPlayer;
|
||||||
private @Nullable TemplateItem border;
|
private @Nullable TemplateItem border;
|
||||||
private @Nullable TemplateItem background;
|
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) {
|
public IslandTeamInviteCommand(IslandTeamCommand parent) {
|
||||||
super(parent, "invite");
|
super(parent, "invite");
|
||||||
|
@ -77,14 +57,13 @@ public class IslandTeamInviteCommand extends CompositeCommand {
|
||||||
user.sendMessage("general.errors.no-island");
|
user.sendMessage("general.errors.no-island");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
Island island = islandsManager.getIsland(getWorld(), user);
|
||||||
|
|
||||||
if (args.size() != 1) {
|
if (args.size() != 1) {
|
||||||
this.inviteCmd = true;
|
new IslandTeamInviteGUI(itc, true, island).build(user);
|
||||||
build(user);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Island island = islandsManager.getIsland(getWorld(), user);
|
|
||||||
int rank = Objects.requireNonNull(island).getRank(user);
|
int rank = Objects.requireNonNull(island).getRank(user);
|
||||||
|
|
||||||
return checkRankAndInvitePlayer(user, island, rank, args.get(0));
|
return checkRankAndInvitePlayer(user, island, rank, args.get(0));
|
||||||
|
@ -208,204 +187,4 @@ public class IslandTeamInviteCommand extends CompositeCommand {
|
||||||
return Optional.of(Util.tabLimit(options, lastArg));
|
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,287 @@
|
||||||
|
package world.bentobox.bentobox.api.commands.island.team;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
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 = itc.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 is = plugin.getIslands().getPrimaryIsland(itc.getWorld(), user.getUniqueId());
|
||||||
|
if (is == null) {
|
||||||
|
return this.getBlankBackground();
|
||||||
|
}
|
||||||
|
if (page < 0) {
|
||||||
|
page = 0;
|
||||||
|
}
|
||||||
|
// Stream of all players that the user can see
|
||||||
|
Stream<Player> visiblePlayers = itc.getWorld().getPlayers().stream().filter(user.getPlayer()::canSee);
|
||||||
|
|
||||||
|
// Filter players based on searchName if it's not blank, and ensure they're not the user
|
||||||
|
Stream<Player> filteredPlayers = visiblePlayers
|
||||||
|
.filter(player -> this.searchName.isBlank()
|
||||||
|
|| player.getName().toLowerCase().contains(searchName.toLowerCase()))
|
||||||
|
.filter(player -> !player.equals(user.getPlayer()));
|
||||||
|
|
||||||
|
// Skipping to the correct pagination slot, then finding the first player
|
||||||
|
Optional<Player> playerOptional = filteredPlayers.skip(slot.slot() + page * PER_PAGE).findFirst();
|
||||||
|
|
||||||
|
// Map the player to a prospect or return a blank background if not found
|
||||||
|
return playerOptional.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(user, clickType, player,
|
||||||
|
template.actions()))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean clickHandler(User user, ClickType clickType, Player player, @NonNull List<ActionRecords> list) {
|
||||||
|
if (list.stream().noneMatch(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 "
|
||||||
|
+ itc.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 "
|
||||||
|
+ itc.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 "
|
||||||
|
+ itc.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 "
|
||||||
|
+ itc.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 "
|
||||||
|
+ itc.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 "
|
||||||
|
+ itc.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) {
|
||||||
|
if (itic.canExecute(user, itic.getLabel(), List.of(input))
|
||||||
|
&& 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -90,7 +90,10 @@ public class IslandTeamKickCommand extends ConfirmableCommand {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void kick(User user, UUID targetUUID) {
|
protected boolean kick(User user, UUID targetUUID) {
|
||||||
|
if (targetUUID == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
User target = User.getInstance(targetUUID);
|
User target = User.getInstance(targetUUID);
|
||||||
Island oldIsland = Objects.requireNonNull(getIslands().getIsland(getWorld(), targetUUID)); // Should never be
|
Island oldIsland = Objects.requireNonNull(getIslands().getIsland(getWorld(), targetUUID)); // Should never be
|
||||||
// null because of
|
// null because of
|
||||||
|
@ -99,7 +102,7 @@ public class IslandTeamKickCommand extends ConfirmableCommand {
|
||||||
IslandBaseEvent event = TeamEvent.builder().island(oldIsland).reason(TeamEvent.Reason.KICK)
|
IslandBaseEvent event = TeamEvent.builder().island(oldIsland).reason(TeamEvent.Reason.KICK)
|
||||||
.involvedPlayer(targetUUID).build();
|
.involvedPlayer(targetUUID).build();
|
||||||
if (event.isCancelled()) {
|
if (event.isCancelled()) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
target.sendMessage("commands.island.team.kick.player-kicked", TextVariables.GAMEMODE,
|
target.sendMessage("commands.island.team.kick.player-kicked", TextVariables.GAMEMODE,
|
||||||
getAddon().getDescription().getName(), TextVariables.NAME, user.getName(), TextVariables.DISPLAY_NAME,
|
getAddon().getDescription().getName(), TextVariables.NAME, user.getName(), TextVariables.DISPLAY_NAME,
|
||||||
|
@ -121,6 +124,7 @@ public class IslandTeamKickCommand extends ConfirmableCommand {
|
||||||
getParent().getSubCommand("invite").ifPresent(c -> c.setCooldown(oldIsland.getUniqueId(),
|
getParent().getSubCommand("invite").ifPresent(c -> c.setCooldown(oldIsland.getUniqueId(),
|
||||||
targetUUID.toString(), getSettings().getInviteCooldown() * 60));
|
targetUUID.toString(), getSettings().getInviteCooldown() * 60));
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -15,6 +15,9 @@ import world.bentobox.bentobox.database.objects.Island;
|
||||||
import world.bentobox.bentobox.managers.RanksManager;
|
import world.bentobox.bentobox.managers.RanksManager;
|
||||||
import world.bentobox.bentobox.util.Util;
|
import world.bentobox.bentobox.util.Util;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle promotion and demotion
|
||||||
|
*/
|
||||||
public class IslandTeamPromoteCommand extends CompositeCommand {
|
public class IslandTeamPromoteCommand extends CompositeCommand {
|
||||||
|
|
||||||
private User target;
|
private User target;
|
||||||
|
@ -45,7 +48,7 @@ public class IslandTeamPromoteCommand extends CompositeCommand {
|
||||||
showHelp(this, user);
|
showHelp(this, user);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
// Check if the user has a team
|
||||||
if (!getIslands().inTeam(getWorld(), user.getUniqueId())) {
|
if (!getIslands().inTeam(getWorld(), user.getUniqueId())) {
|
||||||
user.sendMessage("general.errors.no-team");
|
user.sendMessage("general.errors.no-team");
|
||||||
return false;
|
return false;
|
||||||
|
@ -65,6 +68,11 @@ public class IslandTeamPromoteCommand extends CompositeCommand {
|
||||||
user.sendMessage("general.errors.unknown-player", TextVariables.NAME, args.get(0));
|
user.sendMessage("general.errors.unknown-player", TextVariables.NAME, args.get(0));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
// Check that target is a member of this island
|
||||||
|
if (!island.getMemberSet().contains(target.getUniqueId())) {
|
||||||
|
user.sendMessage("commands.island.team.promote.errors.must-be-member");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
// Check if the user is not trying to promote/ demote himself
|
// Check if the user is not trying to promote/ demote himself
|
||||||
if (target.equals(user)) {
|
if (target.equals(user)) {
|
||||||
if (this.getLabel().equals("promote")) {
|
if (this.getLabel().equals("promote")) {
|
||||||
|
@ -100,7 +108,8 @@ public class IslandTeamPromoteCommand extends CompositeCommand {
|
||||||
if (this.getLabel().equals("promote")) {
|
if (this.getLabel().equals("promote")) {
|
||||||
int nextRank = RanksManager.getInstance().getRankUpValue(currentRank);
|
int nextRank = RanksManager.getInstance().getRankUpValue(currentRank);
|
||||||
// Stop short of owner
|
// Stop short of owner
|
||||||
if (nextRank != RanksManager.OWNER_RANK && nextRank > currentRank) {
|
if (nextRank < RanksManager.OWNER_RANK && currentRank >= RanksManager.MEMBER_RANK
|
||||||
|
&& nextRank > currentRank) {
|
||||||
island.setRank(target, nextRank);
|
island.setRank(target, nextRank);
|
||||||
String rankName = user.getTranslation(RanksManager.getInstance().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());
|
user.sendMessage("commands.island.team.promote.success", TextVariables.NAME, target.getName(), TextVariables.RANK, rankName, TextVariables.DISPLAY_NAME, target.getDisplayName());
|
||||||
|
|
|
@ -8,6 +8,7 @@ import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
|
@ -43,6 +44,7 @@ import world.bentobox.bentobox.api.user.User;
|
||||||
import world.bentobox.bentobox.blueprints.dataobjects.BlueprintBlock;
|
import world.bentobox.bentobox.blueprints.dataobjects.BlueprintBlock;
|
||||||
import world.bentobox.bentobox.blueprints.dataobjects.BlueprintCreatureSpawner;
|
import world.bentobox.bentobox.blueprints.dataobjects.BlueprintCreatureSpawner;
|
||||||
import world.bentobox.bentobox.blueprints.dataobjects.BlueprintEntity;
|
import world.bentobox.bentobox.blueprints.dataobjects.BlueprintEntity;
|
||||||
|
import world.bentobox.bentobox.hooks.MythicMobsHook;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The clipboard provides the holding spot for an active blueprint that is being
|
* The clipboard provides the holding spot for an active blueprint that is being
|
||||||
|
@ -67,6 +69,7 @@ public class BlueprintClipboard {
|
||||||
private final Map<Vector, BlueprintBlock> bpAttachable = new LinkedHashMap<>();
|
private final Map<Vector, BlueprintBlock> bpAttachable = new LinkedHashMap<>();
|
||||||
private final Map<Vector, BlueprintBlock> bpBlocks = new LinkedHashMap<>();
|
private final Map<Vector, BlueprintBlock> bpBlocks = new LinkedHashMap<>();
|
||||||
private final BentoBox plugin = BentoBox.getInstance();
|
private final BentoBox plugin = BentoBox.getInstance();
|
||||||
|
private Optional<MythicMobsHook> mmh;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a clipboard for blueprint
|
* Create a clipboard for blueprint
|
||||||
|
@ -74,9 +77,16 @@ public class BlueprintClipboard {
|
||||||
*/
|
*/
|
||||||
public BlueprintClipboard(@NonNull Blueprint blueprint) {
|
public BlueprintClipboard(@NonNull Blueprint blueprint) {
|
||||||
this.blueprint = blueprint;
|
this.blueprint = blueprint;
|
||||||
|
// MythicMobs
|
||||||
|
mmh = plugin.getHooks().getHook("MythicMobs").filter(MythicMobsHook.class::isInstance)
|
||||||
|
.map(MythicMobsHook.class::cast);
|
||||||
}
|
}
|
||||||
|
|
||||||
public BlueprintClipboard() { }
|
public BlueprintClipboard() {
|
||||||
|
// MythicMobs
|
||||||
|
mmh = plugin.getHooks().getHook("MythicMobs").filter(MythicMobsHook.class::isInstance)
|
||||||
|
.map(MythicMobsHook.class::cast);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copy the blocks between pos1 and pos2 into the clipboard for a user.
|
* Copy the blocks between pos1 and pos2 into the clipboard for a user.
|
||||||
|
@ -285,6 +295,7 @@ public class BlueprintClipboard {
|
||||||
List<BlueprintEntity> bpEnts = new ArrayList<>();
|
List<BlueprintEntity> bpEnts = new ArrayList<>();
|
||||||
for (LivingEntity entity: entities) {
|
for (LivingEntity entity: entities) {
|
||||||
BlueprintEntity bpe = new BlueprintEntity();
|
BlueprintEntity bpe = new BlueprintEntity();
|
||||||
|
|
||||||
bpe.setType(entity.getType());
|
bpe.setType(entity.getType());
|
||||||
bpe.setCustomName(entity.getCustomName());
|
bpe.setCustomName(entity.getCustomName());
|
||||||
if (entity instanceof Villager villager) {
|
if (entity instanceof Villager villager) {
|
||||||
|
@ -317,6 +328,10 @@ public class BlueprintClipboard {
|
||||||
if (entity instanceof Horse horse) {
|
if (entity instanceof Horse horse) {
|
||||||
bpe.setStyle(horse.getStyle());
|
bpe.setStyle(horse.getStyle());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mmh.filter(mm -> mm.isMythicMob(entity)).map(mm -> mm.getMythicMob(entity))
|
||||||
|
.ifPresent(bpe::setMythicMobsRecord);
|
||||||
|
|
||||||
bpEnts.add(bpe);
|
bpEnts.add(bpe);
|
||||||
}
|
}
|
||||||
return bpEnts;
|
return bpEnts;
|
||||||
|
|
|
@ -237,25 +237,7 @@ public class BlueprintPaster {
|
||||||
private void pasteBlocks(Bits bits, int count, Optional<User> owner, int pasteSpeed, boolean useNMS) {
|
private void pasteBlocks(Bits bits, int count, Optional<User> owner, int pasteSpeed, boolean useNMS) {
|
||||||
Iterator<Entry<Vector, BlueprintBlock>> it = pasteState.equals(PasteState.BLOCKS) ? bits.it : bits.it2;
|
Iterator<Entry<Vector, BlueprintBlock>> it = pasteState.equals(PasteState.BLOCKS) ? bits.it : bits.it2;
|
||||||
if (it.hasNext()) {
|
if (it.hasNext()) {
|
||||||
Map<Location, BlueprintBlock> blockMap = new HashMap<>();
|
pasteBlocksNow(it, count, pasteSpeed, useNMS);
|
||||||
// Paste blocks
|
|
||||||
while (count < pasteSpeed) {
|
|
||||||
if (!it.hasNext()) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Entry<Vector, BlueprintBlock> entry = it.next();
|
|
||||||
Location pasteTo = location.clone().add(entry.getKey());
|
|
||||||
// pos1 and pos2 update
|
|
||||||
updatePos(pasteTo);
|
|
||||||
|
|
||||||
BlueprintBlock block = entry.getValue();
|
|
||||||
blockMap.put(pasteTo, block);
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
if (!blockMap.isEmpty()) {
|
|
||||||
currentTask = useNMS ? paster.pasteBlocks(island, world, blockMap)
|
|
||||||
: fallback.pasteBlocks(island, world, blockMap);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (pasteState.equals(PasteState.BLOCKS)) {
|
if (pasteState.equals(PasteState.BLOCKS)) {
|
||||||
// Blocks done
|
// Blocks done
|
||||||
|
@ -272,6 +254,29 @@ public class BlueprintPaster {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void pasteBlocksNow(Iterator<Entry<Vector, BlueprintBlock>> it, int count, int pasteSpeed, boolean useNMS) {
|
||||||
|
Map<Location, BlueprintBlock> blockMap = new HashMap<>();
|
||||||
|
// Paste blocks
|
||||||
|
while (count < pasteSpeed) {
|
||||||
|
if (!it.hasNext()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Entry<Vector, BlueprintBlock> entry = it.next();
|
||||||
|
Location pasteTo = location.clone().add(entry.getKey());
|
||||||
|
// pos1 and pos2 update
|
||||||
|
updatePos(pasteTo);
|
||||||
|
|
||||||
|
BlueprintBlock block = entry.getValue();
|
||||||
|
blockMap.put(pasteTo, block);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
if (!blockMap.isEmpty()) {
|
||||||
|
currentTask = useNMS ? paster.pasteBlocks(island, world, blockMap)
|
||||||
|
: fallback.pasteBlocks(island, world, blockMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
private void loadChunk() {
|
private void loadChunk() {
|
||||||
long timer = System.currentTimeMillis();
|
long timer = System.currentTimeMillis();
|
||||||
pasteState = PasteState.CHUNK_LOADING;
|
pasteState = PasteState.CHUNK_LOADING;
|
||||||
|
|
|
@ -24,6 +24,19 @@ import com.google.gson.annotations.Expose;
|
||||||
*/
|
*/
|
||||||
public class BlueprintEntity {
|
public class BlueprintEntity {
|
||||||
|
|
||||||
|
public record MythicMobRecord(String type, String displayName, double level, float power, String stance) {
|
||||||
|
}
|
||||||
|
|
||||||
|
// GSON can serialize records, but the record class needs to be know in advance. So this breaks out the record entries
|
||||||
|
@Expose
|
||||||
|
String MMtype;
|
||||||
|
@Expose
|
||||||
|
Double MMLevel;
|
||||||
|
@Expose
|
||||||
|
String MMStance;
|
||||||
|
@Expose
|
||||||
|
Float MMpower;
|
||||||
|
|
||||||
@Expose
|
@Expose
|
||||||
private DyeColor color;
|
private DyeColor color;
|
||||||
@Expose
|
@Expose
|
||||||
|
@ -50,7 +63,6 @@ public class BlueprintEntity {
|
||||||
private Integer experience;
|
private Integer experience;
|
||||||
@Expose
|
@Expose
|
||||||
private Villager.Type villagerType;
|
private Villager.Type villagerType;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 1.8.0
|
* @since 1.8.0
|
||||||
|
@ -85,7 +97,6 @@ public class BlueprintEntity {
|
||||||
if (style != null && e instanceof Horse horse) {
|
if (style != null && e instanceof Horse horse) {
|
||||||
horse.setStyle(style);
|
horse.setStyle(style);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -270,5 +281,24 @@ public class BlueprintEntity {
|
||||||
public void setDomestication(Integer domestication) {
|
public void setDomestication(Integer domestication) {
|
||||||
this.domestication = domestication;
|
this.domestication = domestication;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the mythicMobsRecord
|
||||||
|
*/
|
||||||
|
public MythicMobRecord getMythicMobsRecord() {
|
||||||
|
return new MythicMobRecord(this.MMtype, this.getCustomName(), this.MMLevel, this.MMpower, this.MMStance);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param mmr the mythicMobsRecord to set
|
||||||
|
* @since 2.1.0
|
||||||
|
*/
|
||||||
|
public void setMythicMobsRecord(MythicMobRecord mmr) {
|
||||||
|
this.setCustomName(mmr.displayName());
|
||||||
|
this.MMtype = mmr.type();
|
||||||
|
this.MMLevel = mmr.level();
|
||||||
|
this.MMStance = mmr.stance();
|
||||||
|
this.MMpower = mmr.power();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,70 @@
|
||||||
|
package world.bentobox.bentobox.hooks;
|
||||||
|
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.entity.Entity;
|
||||||
|
|
||||||
|
import io.lumine.mythic.bukkit.BukkitAdapter;
|
||||||
|
import io.lumine.mythic.bukkit.MythicBukkit;
|
||||||
|
import io.lumine.mythic.core.mobs.ActiveMob;
|
||||||
|
import world.bentobox.bentobox.api.hooks.Hook;
|
||||||
|
import world.bentobox.bentobox.blueprints.dataobjects.BlueprintEntity.MythicMobRecord;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides implementation and interfacing to interact with MythicMobs.
|
||||||
|
*
|
||||||
|
* @author tastybento
|
||||||
|
* @since 2.2.0
|
||||||
|
*/
|
||||||
|
public class MythicMobsHook extends Hook {
|
||||||
|
|
||||||
|
public MythicMobsHook() {
|
||||||
|
super("MythicMobs", Material.CREEPER_HEAD);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isMythicMob(Entity bukkitEntity) {
|
||||||
|
return MythicBukkit.inst().getMobManager().isMythicMob(bukkitEntity);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MythicMobRecord getMythicMob(Entity bukkitEntity) {
|
||||||
|
ActiveMob mm = MythicBukkit.inst().getMobManager().getActiveMob(bukkitEntity.getUniqueId()).orElse(null);
|
||||||
|
if (mm != null) {
|
||||||
|
return new MythicMobRecord(mm.getMobType(), mm.getDisplayName(), mm.getLevel(),
|
||||||
|
mm.getPower(),
|
||||||
|
mm.getStance());
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hook() {
|
||||||
|
return true; // The hook process shouldn't fail
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getFailureCause() {
|
||||||
|
return null; // The hook process shouldn't fail
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Spawn a MythicMob
|
||||||
|
* @param mmr MythicMobRecord
|
||||||
|
* @param spawnLocation location
|
||||||
|
* @return true if spawn is successful
|
||||||
|
*/
|
||||||
|
public boolean spawnMythicMob(MythicMobRecord mmr, Location spawnLocation) {
|
||||||
|
return MythicBukkit.inst().getMobManager().getMythicMob(mmr.type()).map(mob -> {
|
||||||
|
// A delay is required before spawning, I assume because the blocks are pasted using NMS
|
||||||
|
Bukkit.getScheduler().runTaskLater(getPlugin(), () -> {
|
||||||
|
// spawns mob
|
||||||
|
ActiveMob activeMob = mob.spawn(BukkitAdapter.adapt(spawnLocation), mmr.level());
|
||||||
|
activeMob.setDisplayName(mmr.displayName());
|
||||||
|
activeMob.setPower(mmr.power());
|
||||||
|
activeMob.setStance(mmr.stance());
|
||||||
|
}, 40L);
|
||||||
|
return true;
|
||||||
|
}).orElse(false);
|
||||||
|
}
|
||||||
|
}
|
|
@ -28,7 +28,6 @@ import org.bukkit.inventory.BeaconInventory;
|
||||||
import org.bukkit.inventory.BrewerInventory;
|
import org.bukkit.inventory.BrewerInventory;
|
||||||
import org.bukkit.inventory.CartographyInventory;
|
import org.bukkit.inventory.CartographyInventory;
|
||||||
import org.bukkit.inventory.ChiseledBookshelfInventory;
|
import org.bukkit.inventory.ChiseledBookshelfInventory;
|
||||||
import org.bukkit.inventory.CraftingInventory;
|
|
||||||
import org.bukkit.inventory.DoubleChestInventory;
|
import org.bukkit.inventory.DoubleChestInventory;
|
||||||
import org.bukkit.inventory.EnchantingInventory;
|
import org.bukkit.inventory.EnchantingInventory;
|
||||||
import org.bukkit.inventory.FurnaceInventory;
|
import org.bukkit.inventory.FurnaceInventory;
|
||||||
|
@ -185,9 +184,6 @@ public class InventoryListener extends FlagListener
|
||||||
} else if (e.getInventory() instanceof ChiseledBookshelfInventory) {
|
} else if (e.getInventory() instanceof ChiseledBookshelfInventory) {
|
||||||
this.checkIsland(e, player, e.getInventory().getLocation(), Flags.BOOKSHELF);
|
this.checkIsland(e, player, e.getInventory().getLocation(), Flags.BOOKSHELF);
|
||||||
return true;
|
return true;
|
||||||
} else if (e.getInventory() instanceof CraftingInventory) {
|
|
||||||
this.checkIsland(e, player, e.getInventory().getLocation(), Flags.CRAFTING);
|
|
||||||
return true;
|
|
||||||
} else if (e.getInventory() instanceof DoubleChestInventory) {
|
} else if (e.getInventory() instanceof DoubleChestInventory) {
|
||||||
checkInvHolder(e.getInventory().getLocation(), e, player);
|
checkInvHolder(e.getInventory().getLocation(), e, player);
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -15,7 +15,7 @@ import world.bentobox.bentobox.lists.Flags;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Listener for {@link Flags#CROP_TRAMPLE, Flags#PRESSURE_PLATE, Flags#TURTLE_EGGS, Flags#BUTTON}
|
* Listener for {@link Flags#CROP_TRAMPLE}, {@link Flags#PRESSURE_PLATE}, {@link Flags#TURTLE_EGGS}, {@link Flags#BUTTON}
|
||||||
* @author tastybento
|
* @author tastybento
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -20,6 +20,7 @@ import world.bentobox.bentobox.api.flags.FlagListener;
|
||||||
import world.bentobox.bentobox.lists.Flags;
|
import world.bentobox.bentobox.lists.Flags;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Provides protection for placing blocks.
|
||||||
* @author tastybento
|
* @author tastybento
|
||||||
*/
|
*/
|
||||||
public class PlaceBlocksListener extends FlagListener
|
public class PlaceBlocksListener extends FlagListener
|
||||||
|
|
|
@ -674,7 +674,7 @@ public final class Flags {
|
||||||
/**
|
/**
|
||||||
* Crop Planting
|
* Crop Planting
|
||||||
* Controls who gets to plant crops on tilled soil.
|
* Controls who gets to plant crops on tilled soil.
|
||||||
* Listener is {@link PlaceBlockListener}
|
* Listener is {@link world.bentobox.bentobox.listeners.flags.protection.PlaceBlocksListener}
|
||||||
* @since 1.23.0
|
* @since 1.23.0
|
||||||
*/
|
*/
|
||||||
public static final Flag CROP_PLANTING = new Flag.Builder("CROP_PLANTING", Material.PUMPKIN_SEEDS).mode(Flag.Mode.BASIC).type(Type.PROTECTION).build();
|
public static final Flag CROP_PLANTING = new Flag.Builder("CROP_PLANTING", Material.PUMPKIN_SEEDS).mode(Flag.Mode.BASIC).type(Type.PROTECTION).build();
|
||||||
|
|
|
@ -214,8 +214,11 @@ public class BlueprintClipboardManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void unzipFiles(final ZipInputStream zipInputStream, final Path unzipFilePath) throws IOException {
|
private void unzipFiles(final ZipInputStream zipInputStream, final Path unzipFilePath) throws IOException {
|
||||||
if (!unzipFilePath.toFile().getCanonicalPath().startsWith(blueprintFolder.getCanonicalPath())) {
|
// Prevent directory traversal attacks by normalizing the path
|
||||||
throw new IOException("Entry is outside of the target directory");
|
if (!unzipFilePath.startsWith(blueprintFolder.getCanonicalFile().toPath().normalize())) {
|
||||||
|
throw new IOException(
|
||||||
|
"Blueprint file is trying to write outside of the target directory! Blocked attempt to write to "
|
||||||
|
+ unzipFilePath.toString());
|
||||||
}
|
}
|
||||||
try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(unzipFilePath.toFile().getCanonicalPath()))) {
|
try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(unzipFilePath.toFile().getCanonicalPath()))) {
|
||||||
byte[] bytesIn = new byte[1024];
|
byte[] bytesIn = new byte[1024];
|
||||||
|
|
|
@ -341,7 +341,7 @@ public class IslandsManager {
|
||||||
* Gets all the islands for this player in this world that this player owns.
|
* Gets all the islands for this player in this world that this player owns.
|
||||||
*
|
*
|
||||||
* @param world world to check
|
* @param world world to check
|
||||||
* @param uniqueId user's UUID
|
* @param user user
|
||||||
* @return List of islands or empty list if none found for user
|
* @return List of islands or empty list if none found for user
|
||||||
* @since 2.1.0
|
* @since 2.1.0
|
||||||
*/
|
*/
|
||||||
|
@ -1520,17 +1520,22 @@ public class IslandsManager {
|
||||||
/**
|
/**
|
||||||
* Sets this target as the owner for this island
|
* Sets this target as the owner for this island
|
||||||
*
|
*
|
||||||
* @param user previous owner
|
* @param user user making the change
|
||||||
* @param targetUUID new owner
|
* @param targetUUID new owner
|
||||||
* @param island island to register
|
* @param island island to register
|
||||||
* @param rank rank to which to set old owner.
|
* @param rank rank to which to set old owner.
|
||||||
*/
|
*/
|
||||||
public void setOwner(User user, UUID targetUUID, Island island, int rank) {
|
public void setOwner(User user, UUID targetUUID, Island island, int rank) {
|
||||||
islandCache.setOwner(island, targetUUID);
|
// Demote the old owner
|
||||||
// Set old owner as sub-owner on island.
|
if (rank >= RanksManager.OWNER_RANK) {
|
||||||
if (rank > RanksManager.VISITOR_RANK) {
|
plugin.logWarning("Setowner: previous owner's rank cannot be higher than SubOwner");
|
||||||
island.setRank(user, rank);
|
rank = RanksManager.SUB_OWNER_RANK;
|
||||||
}
|
}
|
||||||
|
if (rank > RanksManager.VISITOR_RANK && island.getOwner() != null) {
|
||||||
|
island.setRank(island.getOwner(), rank);
|
||||||
|
}
|
||||||
|
// Make the new owner
|
||||||
|
islandCache.setOwner(island, targetUUID);
|
||||||
|
|
||||||
user.sendMessage("commands.island.team.setowner.name-is-the-owner", "[name]",
|
user.sendMessage("commands.island.team.setowner.name-is-the-owner", "[name]",
|
||||||
plugin.getPlayers().getName(targetUUID));
|
plugin.getPlayers().getName(targetUUID));
|
||||||
|
|
|
@ -18,6 +18,7 @@ import org.eclipse.jdt.annotation.Nullable;
|
||||||
import world.bentobox.bentobox.BentoBox;
|
import world.bentobox.bentobox.BentoBox;
|
||||||
import world.bentobox.bentobox.api.flags.Flag;
|
import world.bentobox.bentobox.api.flags.Flag;
|
||||||
import world.bentobox.bentobox.database.objects.Island;
|
import world.bentobox.bentobox.database.objects.Island;
|
||||||
|
import world.bentobox.bentobox.managers.RanksManager;
|
||||||
import world.bentobox.bentobox.util.Util;
|
import world.bentobox.bentobox.util.Util;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -353,6 +354,7 @@ public class IslandCache {
|
||||||
if (newOwnerUUID != null) {
|
if (newOwnerUUID != null) {
|
||||||
islandsByUUID.computeIfAbsent(newOwnerUUID, k -> new HashSet<>()).add(island);
|
islandsByUUID.computeIfAbsent(newOwnerUUID, k -> new HashSet<>()).add(island);
|
||||||
}
|
}
|
||||||
|
island.setRank(newOwnerUUID, RanksManager.OWNER_RANK);
|
||||||
islandsByLocation.put(island.getCenter(), island);
|
islandsByLocation.put(island.getCenter(), island);
|
||||||
islandsById.put(island.getUniqueId(), island);
|
islandsById.put(island.getUniqueId(), island);
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,7 @@ import world.bentobox.bentobox.blueprints.dataobjects.BlueprintBlock;
|
||||||
import world.bentobox.bentobox.blueprints.dataobjects.BlueprintCreatureSpawner;
|
import world.bentobox.bentobox.blueprints.dataobjects.BlueprintCreatureSpawner;
|
||||||
import world.bentobox.bentobox.blueprints.dataobjects.BlueprintEntity;
|
import world.bentobox.bentobox.blueprints.dataobjects.BlueprintEntity;
|
||||||
import world.bentobox.bentobox.database.objects.Island;
|
import world.bentobox.bentobox.database.objects.Island;
|
||||||
|
import world.bentobox.bentobox.hooks.MythicMobsHook;
|
||||||
import world.bentobox.bentobox.nms.PasteHandler;
|
import world.bentobox.bentobox.nms.PasteHandler;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -172,29 +173,46 @@ public class DefaultPasteUtil {
|
||||||
public static CompletableFuture<Void> setEntity(Island island, Location location, List<BlueprintEntity> list) {
|
public static CompletableFuture<Void> setEntity(Island island, Location location, List<BlueprintEntity> list) {
|
||||||
World world = location.getWorld();
|
World world = location.getWorld();
|
||||||
assert world != null;
|
assert world != null;
|
||||||
return Util.getChunkAtAsync(location).thenRun(() -> list.stream().filter(k -> k.getType() != null).forEach(k -> {
|
return Util.getChunkAtAsync(location).thenRun(() -> list.stream().filter(k -> k.getType() != null)
|
||||||
LivingEntity e = (LivingEntity) location.getWorld().spawnEntity(location, k.getType());
|
.forEach(k -> spawnBlueprintEntity(k, location, island)));
|
||||||
if (k.getCustomName() != null) {
|
}
|
||||||
String customName = k.getCustomName();
|
|
||||||
|
|
||||||
if (island != null) {
|
/**
|
||||||
// Parse any placeholders in the entity's name, if the owner's connected (he should)
|
* Spawn an entity
|
||||||
Optional<Player> owner = Optional.ofNullable(island.getOwner())
|
* @param k the blueprint entity definition
|
||||||
.map(User::getInstance)
|
* @param location location
|
||||||
.map(User::getPlayer);
|
* @param island island
|
||||||
if (owner.isPresent()) {
|
* @return true if Bukkit entity spawned, false if MythicMob entity spawned
|
||||||
// Parse for the player's name first (in case placeholders might need it)
|
*/
|
||||||
customName = customName.replace(TextVariables.NAME, owner.get().getName());
|
static boolean spawnBlueprintEntity(BlueprintEntity k, Location location, Island island) {
|
||||||
// Now parse the placeholders
|
if (k.getMythicMobsRecord() != null && plugin.getHooks().getHook("MythicMobs")
|
||||||
customName = plugin.getPlaceholdersManager().replacePlaceholders(owner.get(), customName);
|
.filter(mmh -> mmh instanceof MythicMobsHook)
|
||||||
}
|
.map(mmh -> ((MythicMobsHook) mmh).spawnMythicMob(k.getMythicMobsRecord(), location))
|
||||||
|
.orElse(false)) {
|
||||||
|
// MythicMob has spawned.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
LivingEntity e = (LivingEntity) location.getWorld().spawnEntity(location, k.getType());
|
||||||
|
if (k.getCustomName() != null) {
|
||||||
|
String customName = k.getCustomName();
|
||||||
|
|
||||||
|
if (island != null) {
|
||||||
|
// Parse any placeholders in the entity's name, if the owner's connected (he should)
|
||||||
|
Optional<Player> owner = Optional.ofNullable(island.getOwner()).map(User::getInstance)
|
||||||
|
.map(User::getPlayer);
|
||||||
|
if (owner.isPresent()) {
|
||||||
|
// Parse for the player's name first (in case placeholders might need it)
|
||||||
|
customName = customName.replace(TextVariables.NAME, owner.get().getName());
|
||||||
|
// Now parse the placeholders
|
||||||
|
customName = plugin.getPlaceholdersManager().replacePlaceholders(owner.get(), customName);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actually set the custom name
|
|
||||||
e.setCustomName(customName);
|
|
||||||
}
|
}
|
||||||
k.configureEntity(e);
|
|
||||||
}));
|
// Actually set the custom name
|
||||||
|
e.setCustomName(customName);
|
||||||
|
}
|
||||||
|
k.configureEntity(e);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -144,7 +144,10 @@ commands:
|
||||||
parameters: <player>
|
parameters: <player>
|
||||||
description: transfers island ownership to the player
|
description: transfers island ownership to the player
|
||||||
already-owner: '&c [name] is already the owner of this island!'
|
already-owner: '&c [name] is already the owner of this island!'
|
||||||
|
must-be-on-island: '&c You must be on the island to set the owner'
|
||||||
|
confirmation: '&a Are you sure you want to set [name] to be the owner of the island at [xyz]?'
|
||||||
success: '&b [name]&a is now the owner of this island.'
|
success: '&b [name]&a is now the owner of this island.'
|
||||||
|
extra-islands: '&c Warning: this player now owns [number] islands. This is more than allowed by settings or perms: [max].'
|
||||||
range:
|
range:
|
||||||
description: admin island range command
|
description: admin island range command
|
||||||
invalid-value:
|
invalid-value:
|
||||||
|
@ -783,6 +786,7 @@ commands:
|
||||||
errors:
|
errors:
|
||||||
cant-demote-yourself: '&c You can''t demote yourself!'
|
cant-demote-yourself: '&c You can''t demote yourself!'
|
||||||
cant-demote: '&c You can''t demote higher ranks!'
|
cant-demote: '&c You can''t demote higher ranks!'
|
||||||
|
must-be-member: '&c Player must be an island member!'
|
||||||
failure: '&c Player cannot be demoted any further!'
|
failure: '&c Player cannot be demoted any further!'
|
||||||
success: '&a Demoted [name] to [rank]'
|
success: '&a Demoted [name] to [rank]'
|
||||||
promote:
|
promote:
|
||||||
|
@ -791,6 +795,7 @@ commands:
|
||||||
errors:
|
errors:
|
||||||
cant-promote-yourself: '&c You can''t promote yourself!'
|
cant-promote-yourself: '&c You can''t promote yourself!'
|
||||||
cant-promote: '&c You can''t promote above your rank!'
|
cant-promote: '&c You can''t promote above your rank!'
|
||||||
|
must-be-member: '&c Player must be an island member!'
|
||||||
failure: '&c Player cannot be promoted any further!'
|
failure: '&c Player cannot be promoted any further!'
|
||||||
success: '&a Promoted [name] to [rank]'
|
success: '&a Promoted [name] to [rank]'
|
||||||
setowner:
|
setowner:
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
name: BentoBox
|
name: BentoBox
|
||||||
main: world.bentobox.bentobox.BentoBox
|
main: world.bentobox.bentobox.BentoBox
|
||||||
version: ${project.version}${build.number}
|
version: ${project.version}${build.number}
|
||||||
api-version: "1.18"
|
api-version: "1.20"
|
||||||
|
|
||||||
authors: [tastybento, Poslovitch]
|
authors: [tastybento, Poslovitch]
|
||||||
contributors: ["The BentoBoxWorld Community"]
|
contributors: ["The BentoBoxWorld Community"]
|
||||||
|
@ -17,15 +17,13 @@ softdepend:
|
||||||
- Vault
|
- Vault
|
||||||
- PlaceholderAPI
|
- PlaceholderAPI
|
||||||
- dynmap
|
- dynmap
|
||||||
- WorldBorderAPI
|
|
||||||
- BsbMongo
|
- BsbMongo
|
||||||
- WorldGeneratorApi
|
|
||||||
- AdvancedChests
|
- AdvancedChests
|
||||||
- LangUtils
|
- LangUtils
|
||||||
- WildStacker
|
- WildStacker
|
||||||
- LuckPerms
|
- LuckPerms
|
||||||
- HolographicDisplays
|
|
||||||
- EconomyPlus
|
- EconomyPlus
|
||||||
|
- MythicMobs
|
||||||
|
|
||||||
libraries:
|
libraries:
|
||||||
- mysql:mysql-connector-java:${mysql.version}
|
- mysql:mysql-connector-java:${mysql.version}
|
||||||
|
|
|
@ -40,6 +40,7 @@ import world.bentobox.bentobox.api.user.User;
|
||||||
import world.bentobox.bentobox.blueprints.Blueprint;
|
import world.bentobox.bentobox.blueprints.Blueprint;
|
||||||
import world.bentobox.bentobox.managers.BlueprintsManager;
|
import world.bentobox.bentobox.managers.BlueprintsManager;
|
||||||
import world.bentobox.bentobox.managers.CommandsManager;
|
import world.bentobox.bentobox.managers.CommandsManager;
|
||||||
|
import world.bentobox.bentobox.managers.HooksManager;
|
||||||
import world.bentobox.bentobox.managers.LocalesManager;
|
import world.bentobox.bentobox.managers.LocalesManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -73,6 +74,11 @@ public class AdminBlueprintLoadCommandTest {
|
||||||
// Set up plugin
|
// Set up plugin
|
||||||
Whitebox.setInternalState(BentoBox.class, "instance", plugin);
|
Whitebox.setInternalState(BentoBox.class, "instance", plugin);
|
||||||
|
|
||||||
|
// Hooks
|
||||||
|
HooksManager hooksManager = mock(HooksManager.class);
|
||||||
|
when(hooksManager.getHook(anyString())).thenReturn(Optional.empty());
|
||||||
|
when(plugin.getHooks()).thenReturn(hooksManager);
|
||||||
|
|
||||||
// Blueprints Manager
|
// Blueprints Manager
|
||||||
when(plugin.getBlueprintsManager()).thenReturn(bm);
|
when(plugin.getBlueprintsManager()).thenReturn(bm);
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ import java.util.Comparator;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
|
@ -41,6 +42,7 @@ import world.bentobox.bentobox.blueprints.Blueprint;
|
||||||
import world.bentobox.bentobox.blueprints.BlueprintClipboard;
|
import world.bentobox.bentobox.blueprints.BlueprintClipboard;
|
||||||
import world.bentobox.bentobox.managers.BlueprintsManager;
|
import world.bentobox.bentobox.managers.BlueprintsManager;
|
||||||
import world.bentobox.bentobox.managers.CommandsManager;
|
import world.bentobox.bentobox.managers.CommandsManager;
|
||||||
|
import world.bentobox.bentobox.managers.HooksManager;
|
||||||
import world.bentobox.bentobox.managers.LocalesManager;
|
import world.bentobox.bentobox.managers.LocalesManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -58,7 +60,7 @@ public class AdminBlueprintSaveCommandTest {
|
||||||
private GameModeAddon addon;
|
private GameModeAddon addon;
|
||||||
@Mock
|
@Mock
|
||||||
private User user;
|
private User user;
|
||||||
private BlueprintClipboard clip = new BlueprintClipboard();
|
private BlueprintClipboard clip;
|
||||||
private UUID uuid = UUID.randomUUID();
|
private UUID uuid = UUID.randomUUID();
|
||||||
private File blueprintsFolder;
|
private File blueprintsFolder;
|
||||||
@Mock
|
@Mock
|
||||||
|
@ -72,6 +74,12 @@ public class AdminBlueprintSaveCommandTest {
|
||||||
// Set up plugin
|
// Set up plugin
|
||||||
BentoBox plugin = mock(BentoBox.class);
|
BentoBox plugin = mock(BentoBox.class);
|
||||||
Whitebox.setInternalState(BentoBox.class, "instance", plugin);
|
Whitebox.setInternalState(BentoBox.class, "instance", plugin);
|
||||||
|
// Hooks
|
||||||
|
HooksManager hooksManager = mock(HooksManager.class);
|
||||||
|
when(hooksManager.getHook(anyString())).thenReturn(Optional.empty());
|
||||||
|
when(plugin.getHooks()).thenReturn(hooksManager);
|
||||||
|
|
||||||
|
clip = new BlueprintClipboard();
|
||||||
|
|
||||||
// Blueprints Manager
|
// Blueprints Manager
|
||||||
when(plugin.getBlueprintsManager()).thenReturn(bm);
|
when(plugin.getBlueprintsManager()).thenReturn(bm);
|
||||||
|
@ -109,7 +117,6 @@ public class AdminBlueprintSaveCommandTest {
|
||||||
|
|
||||||
PowerMockito.mockStatic(Bukkit.class, Mockito.RETURNS_MOCKS);
|
PowerMockito.mockStatic(Bukkit.class, Mockito.RETURNS_MOCKS);
|
||||||
|
|
||||||
|
|
||||||
absc = new AdminBlueprintSaveCommand(ac);
|
absc = new AdminBlueprintSaveCommand(ac);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,38 +1,45 @@
|
||||||
package world.bentobox.bentobox.api.commands.admin.team;
|
package world.bentobox.bentobox.api.commands.admin.team;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyString;
|
||||||
import static org.mockito.ArgumentMatchers.eq;
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Optional;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Location;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.plugin.PluginManager;
|
import org.bukkit.plugin.PluginManager;
|
||||||
import org.bukkit.scheduler.BukkitScheduler;
|
import org.bukkit.scheduler.BukkitScheduler;
|
||||||
|
import org.bukkit.util.Vector;
|
||||||
|
import org.eclipse.jdt.annotation.NonNull;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.Mockito;
|
import org.mockito.Mockito;
|
||||||
|
import org.mockito.stubbing.Answer;
|
||||||
import org.powermock.api.mockito.PowerMockito;
|
import org.powermock.api.mockito.PowerMockito;
|
||||||
import org.powermock.core.classloader.annotations.PrepareForTest;
|
import org.powermock.core.classloader.annotations.PrepareForTest;
|
||||||
import org.powermock.modules.junit4.PowerMockRunner;
|
import org.powermock.modules.junit4.PowerMockRunner;
|
||||||
import org.powermock.reflect.Whitebox;
|
import org.powermock.reflect.Whitebox;
|
||||||
|
|
||||||
import world.bentobox.bentobox.BentoBox;
|
import world.bentobox.bentobox.BentoBox;
|
||||||
|
import world.bentobox.bentobox.Settings;
|
||||||
|
import world.bentobox.bentobox.TestWorldSettings;
|
||||||
import world.bentobox.bentobox.api.commands.CompositeCommand;
|
import world.bentobox.bentobox.api.commands.CompositeCommand;
|
||||||
|
import world.bentobox.bentobox.api.configuration.WorldSettings;
|
||||||
import world.bentobox.bentobox.api.localization.TextVariables;
|
import world.bentobox.bentobox.api.localization.TextVariables;
|
||||||
import world.bentobox.bentobox.api.user.User;
|
import world.bentobox.bentobox.api.user.User;
|
||||||
import world.bentobox.bentobox.database.objects.Island;
|
import world.bentobox.bentobox.database.objects.Island;
|
||||||
|
@ -40,6 +47,7 @@ import world.bentobox.bentobox.managers.CommandsManager;
|
||||||
import world.bentobox.bentobox.managers.IslandWorldManager;
|
import world.bentobox.bentobox.managers.IslandWorldManager;
|
||||||
import world.bentobox.bentobox.managers.IslandsManager;
|
import world.bentobox.bentobox.managers.IslandsManager;
|
||||||
import world.bentobox.bentobox.managers.LocalesManager;
|
import world.bentobox.bentobox.managers.LocalesManager;
|
||||||
|
import world.bentobox.bentobox.managers.PlaceholdersManager;
|
||||||
import world.bentobox.bentobox.managers.PlayersManager;
|
import world.bentobox.bentobox.managers.PlayersManager;
|
||||||
import world.bentobox.bentobox.util.Util;
|
import world.bentobox.bentobox.util.Util;
|
||||||
|
|
||||||
|
@ -53,16 +61,19 @@ public class AdminTeamSetownerCommandTest {
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private CompositeCommand ac;
|
private CompositeCommand ac;
|
||||||
private UUID uuid;
|
private UUID uuid = UUID.randomUUID();
|
||||||
@Mock
|
@Mock
|
||||||
private User user;
|
private User user;
|
||||||
@Mock
|
@Mock
|
||||||
private IslandsManager im;
|
private IslandsManager im;
|
||||||
@Mock
|
@Mock
|
||||||
private PlayersManager pm;
|
private PlayersManager pm;
|
||||||
private UUID notUUID;
|
private UUID notUUID = UUID.randomUUID();
|
||||||
@Mock
|
@Mock
|
||||||
private Island island;
|
private Island island;
|
||||||
|
private AdminTeamSetownerCommand itl;
|
||||||
|
@Mock
|
||||||
|
private @NonNull Location location;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
|
@ -73,35 +84,57 @@ public class AdminTeamSetownerCommandTest {
|
||||||
Whitebox.setInternalState(BentoBox.class, "instance", plugin);
|
Whitebox.setInternalState(BentoBox.class, "instance", plugin);
|
||||||
Util.setPlugin(plugin);
|
Util.setPlugin(plugin);
|
||||||
|
|
||||||
|
Settings settings = new Settings();
|
||||||
|
// Settings
|
||||||
|
when(plugin.getSettings()).thenReturn(settings);
|
||||||
|
|
||||||
// Command manager
|
// Command manager
|
||||||
CommandsManager cm = mock(CommandsManager.class);
|
CommandsManager cm = mock(CommandsManager.class);
|
||||||
when(plugin.getCommandsManager()).thenReturn(cm);
|
when(plugin.getCommandsManager()).thenReturn(cm);
|
||||||
|
|
||||||
// Player
|
// Player
|
||||||
Player p = mock(Player.class);
|
Player p = mock(Player.class);
|
||||||
|
when(p.getUniqueId()).thenReturn(uuid);
|
||||||
|
when(p.getName()).thenReturn("tastybento");
|
||||||
|
User.getInstance(p);
|
||||||
// Sometimes use Mockito.withSettings().verboseLogging()
|
// Sometimes use Mockito.withSettings().verboseLogging()
|
||||||
when(user.isOp()).thenReturn(false);
|
when(user.isOp()).thenReturn(false);
|
||||||
uuid = UUID.randomUUID();
|
|
||||||
notUUID = UUID.randomUUID();
|
|
||||||
while (notUUID.equals(uuid)) {
|
|
||||||
notUUID = UUID.randomUUID();
|
|
||||||
}
|
|
||||||
when(user.getUniqueId()).thenReturn(uuid);
|
when(user.getUniqueId()).thenReturn(uuid);
|
||||||
when(user.getPlayer()).thenReturn(p);
|
when(user.getPlayer()).thenReturn(p);
|
||||||
when(user.getName()).thenReturn("tastybento");
|
when(user.getName()).thenReturn("tastybento");
|
||||||
|
when(user.getTranslation(anyString()))
|
||||||
|
.thenAnswer((Answer<String>) invocation -> invocation.getArgument(0, String.class));
|
||||||
|
when(user.getTranslation(anyString(), anyString(), anyString(), anyString(), anyString()))
|
||||||
|
.thenAnswer((Answer<String>) invocation -> invocation.getArgument(0, String.class));
|
||||||
User.setPlugin(plugin);
|
User.setPlugin(plugin);
|
||||||
|
|
||||||
|
// Locales & Placeholders
|
||||||
|
LocalesManager lm = mock(LocalesManager.class);
|
||||||
|
when(lm.get(any(), any())).thenAnswer((Answer<String>) invocation -> invocation.getArgument(1, String.class));
|
||||||
|
PlaceholdersManager phm = mock(PlaceholdersManager.class);
|
||||||
|
when(plugin.getPlaceholdersManager()).thenReturn(phm);
|
||||||
|
when(phm.replacePlaceholders(any(), any()))
|
||||||
|
.thenAnswer((Answer<String>) invocation -> invocation.getArgument(1, String.class));
|
||||||
|
|
||||||
|
when(plugin.getLocalesManager()).thenReturn(lm);
|
||||||
|
|
||||||
// Parent command has no aliases
|
// Parent command has no aliases
|
||||||
when(ac.getSubCommandAliases()).thenReturn(new HashMap<>());
|
when(ac.getSubCommandAliases()).thenReturn(new HashMap<>());
|
||||||
|
|
||||||
// Island World Manager
|
// Island World Manager
|
||||||
IslandWorldManager iwm = mock(IslandWorldManager.class);
|
IslandWorldManager iwm = mock(IslandWorldManager.class);
|
||||||
when(plugin.getIWM()).thenReturn(iwm);
|
when(plugin.getIWM()).thenReturn(iwm);
|
||||||
|
@NonNull
|
||||||
|
WorldSettings worldSettings = new TestWorldSettings();
|
||||||
|
when(iwm.getWorldSettings(any())).thenReturn(worldSettings);
|
||||||
|
|
||||||
|
// Location
|
||||||
|
when(location.toVector()).thenReturn(new Vector(1, 2, 3));
|
||||||
// Player has island to begin with
|
// Player has island to begin with
|
||||||
when(im.hasIsland(any(), any(UUID.class))).thenReturn(true);
|
when(im.hasIsland(any(), any(UUID.class))).thenReturn(true);
|
||||||
when(im.hasIsland(any(), any(User.class))).thenReturn(true);
|
when(im.hasIsland(any(), any(User.class))).thenReturn(true);
|
||||||
when(island.getOwner()).thenReturn(uuid);
|
when(island.getOwner()).thenReturn(uuid);
|
||||||
|
when(island.getCenter()).thenReturn(location);
|
||||||
when(im.getPrimaryIsland(any(), any())).thenReturn(island);
|
when(im.getPrimaryIsland(any(), any())).thenReturn(island);
|
||||||
when(plugin.getIslands()).thenReturn(im);
|
when(plugin.getIslands()).thenReturn(im);
|
||||||
|
|
||||||
|
@ -115,15 +148,13 @@ public class AdminTeamSetownerCommandTest {
|
||||||
PowerMockito.mockStatic(Bukkit.class);
|
PowerMockito.mockStatic(Bukkit.class);
|
||||||
when(Bukkit.getScheduler()).thenReturn(sch);
|
when(Bukkit.getScheduler()).thenReturn(sch);
|
||||||
|
|
||||||
// Locales
|
|
||||||
LocalesManager lm = mock(LocalesManager.class);
|
|
||||||
when(lm.get(any(), any())).thenReturn("mock translation");
|
|
||||||
when(plugin.getLocalesManager()).thenReturn(lm);
|
|
||||||
|
|
||||||
// Plugin Manager
|
// Plugin Manager
|
||||||
PluginManager pim = mock(PluginManager.class);
|
PluginManager pim = mock(PluginManager.class);
|
||||||
when(Bukkit.getPluginManager()).thenReturn(pim);
|
when(Bukkit.getPluginManager()).thenReturn(pim);
|
||||||
|
|
||||||
|
// DUT
|
||||||
|
itl = new AdminTeamSetownerCommand(ac);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
|
@ -133,56 +164,45 @@ public class AdminTeamSetownerCommandTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test method for {@link AdminTeamSetownerCommand#execute(User, String, List)}.
|
* Test method for {@link AdminTeamSetownerCommand#canExecute(User, String, List)}.
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testExecuteNoTarget() {
|
public void testExecuteNoTarget() {
|
||||||
AdminTeamSetownerCommand itl = new AdminTeamSetownerCommand(ac);
|
assertFalse(itl.canExecute(user, itl.getLabel(), new ArrayList<>()));
|
||||||
assertFalse(itl.execute(user, itl.getLabel(), new ArrayList<>()));
|
|
||||||
// Show help
|
// Show help
|
||||||
|
verify(user).sendMessage("commands.help.header", TextVariables.LABEL, "commands.help.console");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test method for {@link AdminTeamSetownerCommand#execute(User, String, List)}.
|
* Test method for {@link AdminTeamSetownerCommand#setup()}
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testSetup() {
|
||||||
|
assertEquals("commands.admin.team.setowner.description", itl.getDescription());
|
||||||
|
assertEquals("commands.admin.team.setowner.parameters", itl.getParameters());
|
||||||
|
assertTrue(itl.isOnlyPlayer());
|
||||||
|
assertEquals("mod.team.setowner", itl.getPermission());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test method for {@link AdminTeamSetownerCommand#canExecute(User, String, List)}.
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testExecuteUnknownPlayer() {
|
public void testExecuteUnknownPlayer() {
|
||||||
AdminTeamSetownerCommand itl = new AdminTeamSetownerCommand(ac);
|
assertFalse(itl.canExecute(user, itl.getLabel(), List.of("tastybento")));
|
||||||
String[] name = { "tastybento" };
|
verify(user).sendMessage("general.errors.unknown-player", "[name]", "tastybento");
|
||||||
when(pm.getUUID(any())).thenReturn(null);
|
|
||||||
assertFalse(itl.execute(user, itl.getLabel(), Arrays.asList(name)));
|
|
||||||
verify(user).sendMessage("general.errors.unknown-player", "[name]", name[0]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test method for {@link AdminTeamSetownerCommand#execute(User, String, List)}.
|
* Test method for {@link AdminTeamSetownerCommand#canExecute(User, String, List)}.
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void testExecutePlayerNotInTeam() {
|
|
||||||
AdminTeamSetownerCommand itl = new AdminTeamSetownerCommand(ac);
|
|
||||||
String[] name = { "tastybento" };
|
|
||||||
when(pm.getUUID(any())).thenReturn(notUUID);
|
|
||||||
// when(im.getMembers(any(), any())).thenReturn(new HashSet<>());
|
|
||||||
assertFalse(itl.execute(user, itl.getLabel(), Arrays.asList(name)));
|
|
||||||
verify(user).sendMessage(eq("general.errors.not-in-team"));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test method for {@link AdminTeamSetownerCommand#execute(User, String, List)}.
|
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testExecuteMakeOwnerAlreadyOwner() {
|
public void testExecuteMakeOwnerAlreadyOwner() {
|
||||||
when(im.inTeam(any(), any())).thenReturn(true);
|
when(im.getIslandAt(any())).thenReturn(Optional.of(island));
|
||||||
Island is = mock(Island.class);
|
when(island.getOwner()).thenReturn(uuid);
|
||||||
when(im.getIsland(any(), any(UUID.class))).thenReturn(is);
|
when(Util.getUUID("tastybento")).thenReturn(uuid);
|
||||||
String[] name = {"tastybento"};
|
assertFalse(itl.canExecute(user, itl.getLabel(), List.of("tastybento")));
|
||||||
when(pm.getUUID(any())).thenReturn(notUUID);
|
verify(user).sendMessage("commands.admin.team.setowner.already-owner", TextVariables.NAME, "tastybento");
|
||||||
when(pm.getName(any())).thenReturn(name[0]);
|
|
||||||
when(island.getOwner()).thenReturn(notUUID);
|
|
||||||
|
|
||||||
AdminTeamSetownerCommand itl = new AdminTeamSetownerCommand(ac);
|
|
||||||
assertFalse(itl.execute(user, itl.getLabel(), Arrays.asList(name)));
|
|
||||||
verify(user).sendMessage("commands.admin.team.setowner.already-owner", TextVariables.NAME, name[0]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -190,28 +210,44 @@ public class AdminTeamSetownerCommandTest {
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testExecuteSuccess() {
|
public void testExecuteSuccess() {
|
||||||
// Player is a team member, not an owner
|
when(im.getIslandAt(any())).thenReturn(Optional.of(island));
|
||||||
when(im.hasIsland(any(), any(UUID.class))).thenReturn(false);
|
when(island.getOwner()).thenReturn(notUUID);
|
||||||
when(im.hasIsland(any(), any(User.class))).thenReturn(false);
|
when(Util.getUUID("tastybento")).thenReturn(uuid);
|
||||||
when(im.inTeam(any(), any())).thenReturn(true);
|
|
||||||
Island is = mock(Island.class);
|
|
||||||
when(im.getIsland(any(), any(UUID.class))).thenReturn(is);
|
|
||||||
String[] name = {"tastybento"};
|
|
||||||
when(pm.getUUID(any())).thenReturn(notUUID);
|
|
||||||
when(pm.getName(any())).thenReturn(name[0]);
|
|
||||||
// Owner
|
|
||||||
//when(im.getOwner(any(), eq(notUUID))).thenReturn(uuid);
|
|
||||||
when(pm.getName(eq(uuid))).thenReturn("owner");
|
|
||||||
// Members
|
|
||||||
Set<UUID> members = new HashSet<>();
|
|
||||||
members.add(uuid);
|
|
||||||
members.add(notUUID);
|
|
||||||
//when(im.getMembers(any(), any())).thenReturn(members);
|
|
||||||
|
|
||||||
AdminTeamSetownerCommand itl = new AdminTeamSetownerCommand(ac);
|
assertTrue(itl.canExecute(user, itl.getLabel(), List.of("tastybento")));
|
||||||
assertTrue(itl.execute(user, itl.getLabel(), Arrays.asList(name)));
|
assertTrue(itl.execute(user, itl.getLabel(), List.of("tastybento")));
|
||||||
// Add other verifications
|
// Add other verifications
|
||||||
verify(im).setOwner(any(), eq(user), eq(notUUID));
|
verify(user).getTranslation("commands.admin.team.setowner.confirmation", TextVariables.NAME, "tastybento",
|
||||||
verify(user).sendMessage("commands.admin.team.setowner.success", TextVariables.NAME, name[0]);
|
TextVariables.XYZ, "1,2,3");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test method for {@link AdminTeamSetownerCommand#changeOwner(User)}
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testChangeOwner() {
|
||||||
|
when(im.getIslandAt(any())).thenReturn(Optional.of(island));
|
||||||
|
when(island.getOwner()).thenReturn(notUUID);
|
||||||
|
when(Util.getUUID("tastybento")).thenReturn(uuid);
|
||||||
|
|
||||||
|
assertTrue(itl.canExecute(user, itl.getLabel(), List.of("tastybento")));
|
||||||
|
itl.changeOwner(user);
|
||||||
|
// Add other verifications
|
||||||
|
verify(user).sendMessage("commands.admin.team.setowner.success", TextVariables.NAME, "tastybento");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test method for {@link AdminTeamSetownerCommand#changeOwner(User)}
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testChangeOwnerNoOwner() {
|
||||||
|
when(im.getIslandAt(any())).thenReturn(Optional.of(island));
|
||||||
|
when(island.getOwner()).thenReturn(null);
|
||||||
|
when(Util.getUUID("tastybento")).thenReturn(uuid);
|
||||||
|
|
||||||
|
assertTrue(itl.canExecute(user, itl.getLabel(), List.of("tastybento")));
|
||||||
|
itl.changeOwner(user);
|
||||||
|
// Add other verifications
|
||||||
|
verify(user).sendMessage("commands.admin.team.setowner.success", TextVariables.NAME, "tastybento");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,7 @@ import world.bentobox.bentobox.BentoBox;
|
||||||
import world.bentobox.bentobox.Settings;
|
import world.bentobox.bentobox.Settings;
|
||||||
import world.bentobox.bentobox.api.commands.CompositeCommand;
|
import world.bentobox.bentobox.api.commands.CompositeCommand;
|
||||||
import world.bentobox.bentobox.api.configuration.WorldSettings;
|
import world.bentobox.bentobox.api.configuration.WorldSettings;
|
||||||
|
import world.bentobox.bentobox.api.localization.TextVariables;
|
||||||
import world.bentobox.bentobox.api.user.User;
|
import world.bentobox.bentobox.api.user.User;
|
||||||
import world.bentobox.bentobox.database.objects.Island;
|
import world.bentobox.bentobox.database.objects.Island;
|
||||||
import world.bentobox.bentobox.managers.CommandsManager;
|
import world.bentobox.bentobox.managers.CommandsManager;
|
||||||
|
@ -195,6 +196,20 @@ public class IslandSethomeCommandTest {
|
||||||
verify(user).sendMessage("commands.island.sethome.must-be-on-your-island");
|
verify(user).sendMessage("commands.island.sethome.must-be-on-your-island");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test method for
|
||||||
|
* {@link world.bentobox.bentobox.api.commands.island.IslandSethomeCommand#canExecute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testCanExecuteTooManyHomes() {
|
||||||
|
when(im.getMaxHomes(island)).thenReturn(10);
|
||||||
|
when(im.getNumberOfHomesIfAdded(eq(island), anyString())).thenReturn(11);
|
||||||
|
IslandSethomeCommand isc = new IslandSethomeCommand(ic);
|
||||||
|
assertFalse(isc.canExecute(user, "island", Collections.emptyList()));
|
||||||
|
verify(user).sendMessage("commands.island.sethome.too-many-homes", TextVariables.NUMBER, "10");
|
||||||
|
verify(user).sendMessage("commands.island.sethome.homes-are");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test method for
|
* Test method for
|
||||||
* {@link world.bentobox.bentobox.api.commands.island.IslandSethomeCommand#canExecute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}.
|
* {@link world.bentobox.bentobox.api.commands.island.IslandSethomeCommand#canExecute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}.
|
||||||
|
|
|
@ -132,6 +132,7 @@ public class IslandTeamInviteCommandTest extends RanksManagerBeforeClassTest {
|
||||||
// Parent command has no aliases
|
// Parent command has no aliases
|
||||||
when(ic.getSubCommandAliases()).thenReturn(new HashMap<>());
|
when(ic.getSubCommandAliases()).thenReturn(new HashMap<>());
|
||||||
when(ic.getWorld()).thenReturn(world);
|
when(ic.getWorld()).thenReturn(world);
|
||||||
|
when(ic.getPlugin()).thenReturn(plugin);
|
||||||
|
|
||||||
// Island
|
// Island
|
||||||
islandUUID = UUID.randomUUID();
|
islandUUID = UUID.randomUUID();
|
||||||
|
|
|
@ -102,6 +102,7 @@ public class IslandTeamPromoteCommandTest extends RanksManagerBeforeClassTest {
|
||||||
when(pm.getUser("target")).thenReturn(target);
|
when(pm.getUser("target")).thenReturn(target);
|
||||||
when(target.getName()).thenReturn("target");
|
when(target.getName()).thenReturn("target");
|
||||||
when(target.getDisplayName()).thenReturn("Target");
|
when(target.getDisplayName()).thenReturn("Target");
|
||||||
|
when(target.getUniqueId()).thenReturn(uuid);
|
||||||
|
|
||||||
// Managers
|
// Managers
|
||||||
when(plugin.getIslands()).thenReturn(im);
|
when(plugin.getIslands()).thenReturn(im);
|
||||||
|
|
|
@ -4,11 +4,14 @@ import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
import static org.junit.Assert.assertNull;
|
import static org.junit.Assert.assertNull;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyString;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.never;
|
import static org.mockito.Mockito.never;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
|
@ -29,6 +32,7 @@ import org.powermock.reflect.Whitebox;
|
||||||
|
|
||||||
import world.bentobox.bentobox.BentoBox;
|
import world.bentobox.bentobox.BentoBox;
|
||||||
import world.bentobox.bentobox.api.user.User;
|
import world.bentobox.bentobox.api.user.User;
|
||||||
|
import world.bentobox.bentobox.managers.HooksManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author tastybento
|
* @author tastybento
|
||||||
|
@ -56,6 +60,10 @@ public class BlueprintClipboardTest {
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
// Set up plugin
|
// Set up plugin
|
||||||
Whitebox.setInternalState(BentoBox.class, "instance", plugin);
|
Whitebox.setInternalState(BentoBox.class, "instance", plugin);
|
||||||
|
// Hooks
|
||||||
|
HooksManager hooksManager = mock(HooksManager.class);
|
||||||
|
when(hooksManager.getHook(anyString())).thenReturn(Optional.empty());
|
||||||
|
when(plugin.getHooks()).thenReturn(hooksManager);
|
||||||
|
|
||||||
// User
|
// User
|
||||||
when(user.getTranslation(Mockito.anyString())).thenAnswer((Answer<String>) invocation -> invocation.getArgument(0, String.class));
|
when(user.getTranslation(Mockito.anyString())).thenAnswer((Answer<String>) invocation -> invocation.getArgument(0, String.class));
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package world.bentobox.bentobox.blueprints.dataobjects;
|
package world.bentobox.bentobox.blueprints.dataobjects;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
@ -26,6 +27,8 @@ import org.mockito.Mock;
|
||||||
import org.mockito.Mockito;
|
import org.mockito.Mockito;
|
||||||
import org.powermock.modules.junit4.PowerMockRunner;
|
import org.powermock.modules.junit4.PowerMockRunner;
|
||||||
|
|
||||||
|
import world.bentobox.bentobox.blueprints.dataobjects.BlueprintEntity.MythicMobRecord;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author tastybento
|
* @author tastybento
|
||||||
*
|
*
|
||||||
|
@ -84,10 +87,10 @@ public class BlueprintEntityTest {
|
||||||
|
|
||||||
blueprint.configureEntity(villager);
|
blueprint.configureEntity(villager);
|
||||||
|
|
||||||
Assert.assertEquals(Profession.LIBRARIAN, villager.getProfession());
|
assertEquals(Profession.LIBRARIAN, villager.getProfession());
|
||||||
Assert.assertEquals(100, villager.getVillagerExperience());
|
assertEquals(100, villager.getVillagerExperience());
|
||||||
Assert.assertEquals(2, villager.getVillagerLevel());
|
assertEquals(2, villager.getVillagerLevel());
|
||||||
Assert.assertEquals(Villager.Type.PLAINS, villager.getVillagerType());
|
assertEquals(Villager.Type.PLAINS, villager.getVillagerType());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -99,7 +102,7 @@ public class BlueprintEntityTest {
|
||||||
|
|
||||||
blueprint.configureEntity(sheep);
|
blueprint.configureEntity(sheep);
|
||||||
|
|
||||||
Assert.assertEquals(DyeColor.BLUE, sheep.getColor());
|
assertEquals(DyeColor.BLUE, sheep.getColor());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -147,7 +150,7 @@ public class BlueprintEntityTest {
|
||||||
|
|
||||||
blueprint.configureEntity(horse);
|
blueprint.configureEntity(horse);
|
||||||
|
|
||||||
Assert.assertEquals(50, horse.getDomestication());
|
assertEquals(50, horse.getDomestication());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -159,7 +162,7 @@ public class BlueprintEntityTest {
|
||||||
|
|
||||||
blueprint.configureEntity(horse);
|
blueprint.configureEntity(horse);
|
||||||
|
|
||||||
Assert.assertEquals(Style.WHITE_DOTS, horse.getStyle());
|
assertEquals(Style.WHITE_DOTS, horse.getStyle());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -167,13 +170,13 @@ public class BlueprintEntityTest {
|
||||||
BlueprintEntity blueprint = new BlueprintEntity();
|
BlueprintEntity blueprint = new BlueprintEntity();
|
||||||
|
|
||||||
blueprint.setColor(DyeColor.RED);
|
blueprint.setColor(DyeColor.RED);
|
||||||
Assert.assertEquals(DyeColor.RED, blueprint.getColor());
|
assertEquals(DyeColor.RED, blueprint.getColor());
|
||||||
|
|
||||||
blueprint.setType(EntityType.CREEPER);
|
blueprint.setType(EntityType.CREEPER);
|
||||||
Assert.assertEquals(EntityType.CREEPER, blueprint.getType());
|
assertEquals(EntityType.CREEPER, blueprint.getType());
|
||||||
|
|
||||||
blueprint.setCustomName("My Entity");
|
blueprint.setCustomName("My Entity");
|
||||||
Assert.assertEquals("My Entity", blueprint.getCustomName());
|
assertEquals("My Entity", blueprint.getCustomName());
|
||||||
|
|
||||||
blueprint.setTamed(true);
|
blueprint.setTamed(true);
|
||||||
Assert.assertTrue(blueprint.getTamed());
|
Assert.assertTrue(blueprint.getTamed());
|
||||||
|
@ -185,27 +188,35 @@ public class BlueprintEntityTest {
|
||||||
Assert.assertFalse(blueprint.getAdult());
|
Assert.assertFalse(blueprint.getAdult());
|
||||||
|
|
||||||
blueprint.setDomestication(75);
|
blueprint.setDomestication(75);
|
||||||
Assert.assertEquals(75, blueprint.getDomestication().intValue());
|
assertEquals(75, blueprint.getDomestication().intValue());
|
||||||
|
|
||||||
Map<Integer, ItemStack> inventory = new HashMap<>();
|
Map<Integer, ItemStack> inventory = new HashMap<>();
|
||||||
inventory.put(1, new ItemStack(Material.DIAMOND));
|
inventory.put(1, new ItemStack(Material.DIAMOND));
|
||||||
blueprint.setInventory(inventory);
|
blueprint.setInventory(inventory);
|
||||||
Assert.assertEquals(inventory, blueprint.getInventory());
|
assertEquals(inventory, blueprint.getInventory());
|
||||||
|
|
||||||
blueprint.setStyle(Style.WHITE);
|
blueprint.setStyle(Style.WHITE);
|
||||||
Assert.assertEquals(Style.WHITE, blueprint.getStyle());
|
assertEquals(Style.WHITE, blueprint.getStyle());
|
||||||
|
|
||||||
blueprint.setLevel(5);
|
blueprint.setLevel(5);
|
||||||
Assert.assertEquals(5, blueprint.getLevel().intValue());
|
assertEquals(5, blueprint.getLevel().intValue());
|
||||||
|
|
||||||
blueprint.setProfession(Profession.FARMER);
|
blueprint.setProfession(Profession.FARMER);
|
||||||
Assert.assertEquals(Profession.FARMER, blueprint.getProfession());
|
assertEquals(Profession.FARMER, blueprint.getProfession());
|
||||||
|
|
||||||
blueprint.setExperience(500);
|
blueprint.setExperience(500);
|
||||||
Assert.assertEquals(500, blueprint.getExperience().intValue());
|
assertEquals(500, blueprint.getExperience().intValue());
|
||||||
|
|
||||||
blueprint.setVillagerType(Villager.Type.TAIGA);
|
blueprint.setVillagerType(Villager.Type.TAIGA);
|
||||||
Assert.assertEquals(Villager.Type.TAIGA, blueprint.getVillagerType());
|
assertEquals(Villager.Type.TAIGA, blueprint.getVillagerType());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMythicMobs() {
|
||||||
|
BlueprintEntity blueprint = new BlueprintEntity();
|
||||||
|
MythicMobRecord mmr = new MythicMobRecord("string", "string2", 10D, 1F, "string3");
|
||||||
|
blueprint.setMythicMobsRecord(mmr);
|
||||||
|
assertEquals(mmr, blueprint.getMythicMobsRecord());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,165 @@
|
||||||
|
package world.bentobox.bentobox.hooks;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyString;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.entity.Entity;
|
||||||
|
import org.bukkit.plugin.Plugin;
|
||||||
|
import org.bukkit.plugin.PluginManager;
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.Mockito;
|
||||||
|
import org.powermock.api.mockito.PowerMockito;
|
||||||
|
import org.powermock.core.classloader.annotations.PrepareForTest;
|
||||||
|
import org.powermock.modules.junit4.PowerMockRunner;
|
||||||
|
import org.powermock.reflect.Whitebox;
|
||||||
|
|
||||||
|
import io.lumine.mythic.api.mobs.MythicMob;
|
||||||
|
import io.lumine.mythic.bukkit.MythicBukkit;
|
||||||
|
import io.lumine.mythic.core.mobs.ActiveMob;
|
||||||
|
import io.lumine.mythic.core.mobs.MobExecutor;
|
||||||
|
import world.bentobox.bentobox.BentoBox;
|
||||||
|
import world.bentobox.bentobox.blueprints.dataobjects.BlueprintEntity.MythicMobRecord;
|
||||||
|
|
||||||
|
@RunWith(PowerMockRunner.class)
|
||||||
|
@PrepareForTest({ BentoBox.class, Bukkit.class, MythicBukkit.class })
|
||||||
|
public class MythicMobsHookTest {
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private BentoBox plugin;
|
||||||
|
@Mock
|
||||||
|
private PluginManager pim;
|
||||||
|
@Mock
|
||||||
|
private Plugin mythicMobs;
|
||||||
|
@Mock
|
||||||
|
private Location location;
|
||||||
|
@Mock
|
||||||
|
private World world;
|
||||||
|
// DUT
|
||||||
|
MythicMobsHook hook;
|
||||||
|
@Mock
|
||||||
|
private MythicBukkit mythicBukkit;
|
||||||
|
@Mock
|
||||||
|
private MobExecutor mm;
|
||||||
|
@Mock
|
||||||
|
private MythicMob mythicMob;
|
||||||
|
@Mock
|
||||||
|
private ActiveMob activeMob;
|
||||||
|
@Mock
|
||||||
|
private Entity entity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws java.lang.Exception
|
||||||
|
*/
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
// Set up plugin
|
||||||
|
plugin = mock(BentoBox.class);
|
||||||
|
Whitebox.setInternalState(BentoBox.class, "instance", plugin);
|
||||||
|
// Bukkit
|
||||||
|
PowerMockito.mockStatic(Bukkit.class, Mockito.RETURNS_MOCKS);
|
||||||
|
when(Bukkit.getPluginManager()).thenReturn(pim);
|
||||||
|
when(pim.getPlugin("MythicMobs")).thenReturn(mythicMobs);
|
||||||
|
// Location
|
||||||
|
when(world.getName()).thenReturn("bskyblock");
|
||||||
|
when(location.getWorld()).thenReturn(world);
|
||||||
|
// Entity
|
||||||
|
when(entity.getUniqueId()).thenReturn(UUID.randomUUID());
|
||||||
|
// MythicMobs
|
||||||
|
PowerMockito.mockStatic(MythicBukkit.class, Mockito.RETURNS_MOCKS);
|
||||||
|
when(MythicBukkit.inst()).thenReturn(mythicBukkit);
|
||||||
|
when(mythicBukkit.getMobManager()).thenReturn(mm);
|
||||||
|
when(mm.getMythicMob(anyString())).thenReturn(Optional.of(mythicMob));
|
||||||
|
when(activeMob.getDisplayName()).thenReturn("Minion");
|
||||||
|
when(activeMob.getMobType()).thenReturn("GIANT");
|
||||||
|
when(activeMob.getStance()).thenReturn("default");
|
||||||
|
when(activeMob.getLevel()).thenReturn(2.5D);
|
||||||
|
when(activeMob.getPower()).thenReturn(33.2F);
|
||||||
|
when(mm.getActiveMob(any())).thenReturn(Optional.of(activeMob));
|
||||||
|
|
||||||
|
hook = new MythicMobsHook();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws java.lang.Exception
|
||||||
|
*/
|
||||||
|
@After
|
||||||
|
public void tearDown() throws Exception {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test method for {@link world.bentobox.bentobox.hooks.MythicMobsHook#hook()}.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testHook() {
|
||||||
|
assertTrue(hook.hook());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test method for {@link world.bentobox.bentobox.hooks.MythicMobsHook#getFailureCause()}.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testGetFailureCause() {
|
||||||
|
assertNull(hook.getFailureCause());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test method for {@link world.bentobox.bentobox.hooks.MythicMobsHook#MythicMobsHook()}.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testMythicMobsHook() {
|
||||||
|
assertNotNull(hook);
|
||||||
|
assertEquals(Material.CREEPER_HEAD, hook.getIcon());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test method for {@link world.bentobox.bentobox.hooks.MythicMobsHook#isMythicMob(org.bukkit.entity.Entity)}.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testIsMythicMob() {
|
||||||
|
assertFalse(hook.isMythicMob(entity));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test method for {@link world.bentobox.bentobox.hooks.MythicMobsHook#getMythicMob(org.bukkit.entity.Entity)}.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testGetMythicMob() {
|
||||||
|
MythicMobRecord mmr = hook.getMythicMob(entity);
|
||||||
|
assertEquals("GIANT", mmr.type());
|
||||||
|
assertEquals("Minion", mmr.displayName());
|
||||||
|
assertEquals("default", mmr.stance());
|
||||||
|
assertEquals(2.5D, mmr.level(), 0D);
|
||||||
|
assertEquals(33.2F, mmr.power(), 0F);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test method for {@link world.bentobox.bentobox.hooks.MythicMobsHook#spawnMythicMob(world.bentobox.bentobox.blueprints.dataobjects.BlueprintEntity.MythicMobRecord, org.bukkit.Location)}.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testSpawnMythicMob() {
|
||||||
|
MythicMobRecord mmr = hook.getMythicMob(entity);
|
||||||
|
assertTrue(hook.spawnMythicMob(mmr, location));
|
||||||
|
verify(mm).getMythicMob("GIANT");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -4,6 +4,7 @@ import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyString;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
@ -16,6 +17,7 @@ import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.StandardOpenOption;
|
import java.nio.file.StandardOpenOption;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.zip.ZipEntry;
|
import java.util.zip.ZipEntry;
|
||||||
import java.util.zip.ZipOutputStream;
|
import java.util.zip.ZipOutputStream;
|
||||||
|
|
||||||
|
@ -33,6 +35,7 @@ import org.mockito.Mockito;
|
||||||
import org.powermock.api.mockito.PowerMockito;
|
import org.powermock.api.mockito.PowerMockito;
|
||||||
import org.powermock.core.classloader.annotations.PrepareForTest;
|
import org.powermock.core.classloader.annotations.PrepareForTest;
|
||||||
import org.powermock.modules.junit4.PowerMockRunner;
|
import org.powermock.modules.junit4.PowerMockRunner;
|
||||||
|
import org.powermock.reflect.Whitebox;
|
||||||
|
|
||||||
import world.bentobox.bentobox.BentoBox;
|
import world.bentobox.bentobox.BentoBox;
|
||||||
import world.bentobox.bentobox.api.user.User;
|
import world.bentobox.bentobox.api.user.User;
|
||||||
|
@ -128,13 +131,20 @@ public class BlueprintClipboardManagerTest {
|
||||||
blueprintFolder = new File("blueprints");
|
blueprintFolder = new File("blueprints");
|
||||||
// Clear any residual files
|
// Clear any residual files
|
||||||
tearDown();
|
tearDown();
|
||||||
|
// Set up plugin
|
||||||
|
BentoBox plugin = mock(BentoBox.class);
|
||||||
|
Whitebox.setInternalState(BentoBox.class, "instance", plugin);
|
||||||
|
// Hooks
|
||||||
|
HooksManager hooksManager = mock(HooksManager.class);
|
||||||
|
when(hooksManager.getHook(anyString())).thenReturn(Optional.empty());
|
||||||
|
when(plugin.getHooks()).thenReturn(hooksManager);
|
||||||
|
|
||||||
PowerMockito.mockStatic(Bukkit.class);
|
PowerMockito.mockStatic(Bukkit.class);
|
||||||
BlockData blockData = mock(BlockData.class);
|
BlockData blockData = mock(BlockData.class);
|
||||||
when(Bukkit.createBlockData(any(Material.class))).thenReturn(blockData);
|
when(Bukkit.createBlockData(any(Material.class))).thenReturn(blockData);
|
||||||
when(blockData.getAsString()).thenReturn("test123");
|
when(blockData.getAsString()).thenReturn("test123");
|
||||||
when(server.getBukkitVersion()).thenReturn("version");
|
when(server.getBukkitVersion()).thenReturn("version");
|
||||||
when(Bukkit.getServer()).thenReturn(server);
|
when(Bukkit.getServer()).thenReturn(server);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -268,7 +268,7 @@ public class NewIslandTest {
|
||||||
verify(builder, times(2)).build();
|
verify(builder, times(2)).build();
|
||||||
verify(bpb).getUniqueId();
|
verify(bpb).getUniqueId();
|
||||||
verify(ice).getBlueprintBundle();
|
verify(ice).getBlueprintBundle();
|
||||||
verify(pm).setDeaths(eq(world), eq(uuid), eq(0));
|
verify(pm).setDeaths(world, uuid, 0);
|
||||||
verify(im, never()).setHomeLocation(eq(user), any());
|
verify(im, never()).setHomeLocation(eq(user), any());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -281,13 +281,13 @@ public class NewIslandTest {
|
||||||
NewIsland.builder().addon(addon).name(NAME).player(user).reason(Reason.CREATE).build();
|
NewIsland.builder().addon(addon).name(NAME).player(user).reason(Reason.CREATE).build();
|
||||||
PowerMockito.mockStatic(Bukkit.class);
|
PowerMockito.mockStatic(Bukkit.class);
|
||||||
// Verifications
|
// Verifications
|
||||||
verify(im).save(eq(island));
|
verify(im).save(island);
|
||||||
verify(island).setFlagsDefaults();
|
verify(island).setFlagsDefaults();
|
||||||
verify(bpm).paste(eq(addon), eq(island), eq(NAME), any(Runnable.class), eq(true));
|
verify(bpm).paste(eq(addon), eq(island), eq(NAME), any(Runnable.class), eq(true));
|
||||||
verify(builder, times(2)).build();
|
verify(builder, times(2)).build();
|
||||||
verify(bpb).getUniqueId();
|
verify(bpb).getUniqueId();
|
||||||
verify(ice).getBlueprintBundle();
|
verify(ice).getBlueprintBundle();
|
||||||
verify(pm).setDeaths(eq(world), eq(uuid), eq(0));
|
verify(pm).setDeaths(world, uuid, 0);
|
||||||
verify(im, never()).setHomeLocation(eq(user), any());
|
verify(im, never()).setHomeLocation(eq(user), any());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -305,7 +305,7 @@ public class NewIslandTest {
|
||||||
verify(builder, times(2)).build();
|
verify(builder, times(2)).build();
|
||||||
verify(bpb).getUniqueId();
|
verify(bpb).getUniqueId();
|
||||||
verify(ice).getBlueprintBundle();
|
verify(ice).getBlueprintBundle();
|
||||||
verify(pm).setDeaths(eq(world), eq(uuid), eq(0));
|
verify(pm).setDeaths(world, uuid, 0);
|
||||||
verify(im, never()).setHomeLocation(eq(user), any());
|
verify(im, never()).setHomeLocation(eq(user), any());
|
||||||
verify(island).setProtectionRange(eq(20));
|
verify(island).setProtectionRange(eq(20));
|
||||||
verify(island).setReserved(eq(false));
|
verify(island).setReserved(eq(false));
|
||||||
|
@ -326,7 +326,7 @@ public class NewIslandTest {
|
||||||
verify(builder, times(2)).build();
|
verify(builder, times(2)).build();
|
||||||
verify(bpb).getUniqueId();
|
verify(bpb).getUniqueId();
|
||||||
verify(ice).getBlueprintBundle();
|
verify(ice).getBlueprintBundle();
|
||||||
verify(pm).setDeaths(eq(world), eq(uuid), eq(0));
|
verify(pm).setDeaths(world, uuid, 0);
|
||||||
verify(im, never()).setHomeLocation(eq(user), any());
|
verify(im, never()).setHomeLocation(eq(user), any());
|
||||||
verify(island).setProtectionRange(eq(20));
|
verify(island).setProtectionRange(eq(20));
|
||||||
//verify(plugin).logError("New island for user tastybento was not reserved!");
|
//verify(plugin).logError("New island for user tastybento was not reserved!");
|
||||||
|
@ -348,7 +348,7 @@ public class NewIslandTest {
|
||||||
verify(builder, times(2)).build();
|
verify(builder, times(2)).build();
|
||||||
verify(bpb).getUniqueId();
|
verify(bpb).getUniqueId();
|
||||||
verify(ice).getBlueprintBundle();
|
verify(ice).getBlueprintBundle();
|
||||||
verify(pm).setDeaths(eq(world), eq(uuid), eq(0));
|
verify(pm).setDeaths(world, uuid, 0);
|
||||||
verify(im, never()).setHomeLocation(eq(user), any());
|
verify(im, never()).setHomeLocation(eq(user), any());
|
||||||
verify(island).setProtectionRange(eq(20));
|
verify(island).setProtectionRange(eq(20));
|
||||||
verify(plugin).logError("New island for user tastybento was not reserved!");
|
verify(plugin).logError("New island for user tastybento was not reserved!");
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
package world.bentobox.bentobox.util;
|
package world.bentobox.bentobox.util;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.ArgumentMatchers.anyInt;
|
import static org.mockito.ArgumentMatchers.anyInt;
|
||||||
import static org.mockito.ArgumentMatchers.anyString;
|
import static org.mockito.ArgumentMatchers.anyString;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.never;
|
||||||
import static org.mockito.Mockito.times;
|
import static org.mockito.Mockito.times;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
@ -25,10 +28,13 @@ import org.bukkit.block.data.BlockData;
|
||||||
import org.bukkit.block.data.type.WallSign;
|
import org.bukkit.block.data.type.WallSign;
|
||||||
import org.bukkit.block.sign.Side;
|
import org.bukkit.block.sign.Side;
|
||||||
import org.bukkit.block.sign.SignSide;
|
import org.bukkit.block.sign.SignSide;
|
||||||
|
import org.bukkit.entity.EntityType;
|
||||||
|
import org.bukkit.entity.LivingEntity;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
|
import org.junit.Ignore;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.mockito.ArgumentCaptor;
|
import org.mockito.ArgumentCaptor;
|
||||||
|
@ -43,7 +49,11 @@ import world.bentobox.bentobox.api.addons.GameModeAddon;
|
||||||
import world.bentobox.bentobox.api.localization.TextVariables;
|
import world.bentobox.bentobox.api.localization.TextVariables;
|
||||||
import world.bentobox.bentobox.api.user.User;
|
import world.bentobox.bentobox.api.user.User;
|
||||||
import world.bentobox.bentobox.blueprints.dataobjects.BlueprintBlock;
|
import world.bentobox.bentobox.blueprints.dataobjects.BlueprintBlock;
|
||||||
|
import world.bentobox.bentobox.blueprints.dataobjects.BlueprintEntity;
|
||||||
|
import world.bentobox.bentobox.blueprints.dataobjects.BlueprintEntity.MythicMobRecord;
|
||||||
import world.bentobox.bentobox.database.objects.Island;
|
import world.bentobox.bentobox.database.objects.Island;
|
||||||
|
import world.bentobox.bentobox.hooks.MythicMobsHook;
|
||||||
|
import world.bentobox.bentobox.managers.HooksManager;
|
||||||
import world.bentobox.bentobox.managers.IslandWorldManager;
|
import world.bentobox.bentobox.managers.IslandWorldManager;
|
||||||
import world.bentobox.bentobox.managers.LocalesManager;
|
import world.bentobox.bentobox.managers.LocalesManager;
|
||||||
import world.bentobox.bentobox.managers.PlayersManager;
|
import world.bentobox.bentobox.managers.PlayersManager;
|
||||||
|
@ -79,10 +89,20 @@ public class DefaultPasteUtilTest {
|
||||||
@Mock(extraInterfaces = {org.bukkit.block.Sign.class})
|
@Mock(extraInterfaces = {org.bukkit.block.Sign.class})
|
||||||
BlockState sign;
|
BlockState sign;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private PlayersManager pm;
|
||||||
|
@Mock
|
||||||
|
private MythicMobsHook mythicMobsHook;
|
||||||
|
@Mock
|
||||||
|
private BlueprintEntity blueprintEntity;
|
||||||
|
@Mock
|
||||||
|
private Location location;
|
||||||
|
@Mock
|
||||||
|
private LivingEntity livingEntity;
|
||||||
@Mock
|
@Mock
|
||||||
private World world;
|
private World world;
|
||||||
@Mock
|
@Mock
|
||||||
private PlayersManager pm;
|
private HooksManager hooksManager;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -110,6 +130,11 @@ public class DefaultPasteUtilTest {
|
||||||
when(plugin.getLocalesManager()).thenReturn(localesManager);
|
when(plugin.getLocalesManager()).thenReturn(localesManager);
|
||||||
when(localesManager.getOrDefault(any(), anyString(), anyString())).thenReturn("translated");
|
when(localesManager.getOrDefault(any(), anyString(), anyString())).thenReturn("translated");
|
||||||
|
|
||||||
|
when(location.getWorld()).thenReturn(world);
|
||||||
|
// Hooks
|
||||||
|
when(hooksManager.getHook("MythicMobs")).thenReturn(Optional.of(mythicMobsHook));
|
||||||
|
when(plugin.getHooks()).thenReturn(hooksManager);
|
||||||
|
|
||||||
when(plugin.getPlayers()).thenReturn(pm);
|
when(plugin.getPlayers()).thenReturn(pm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,4 +213,32 @@ public class DefaultPasteUtilTest {
|
||||||
List<String> capturedLines = lineCaptor.getAllValues();
|
List<String> capturedLines = lineCaptor.getAllValues();
|
||||||
Assert.assertEquals(linesTranslated, capturedLines);
|
Assert.assertEquals(linesTranslated, capturedLines);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Ignore
|
||||||
|
@Test
|
||||||
|
public void testSpawnBlueprintEntity_WithMythicMobs() {
|
||||||
|
// Set up conditions to satisfy the mythic mobs spawning logic
|
||||||
|
MythicMobRecord mmr = new MythicMobRecord("string", "string2", 10D, 1F, "string3");
|
||||||
|
when(blueprintEntity.getMythicMobsRecord()).thenReturn(mmr);
|
||||||
|
when(mythicMobsHook.spawnMythicMob(mmr, location)).thenReturn(true);
|
||||||
|
// This test works fine if there is a System.out.println() in the code. I assume some optimization is being done in compilation
|
||||||
|
|
||||||
|
assertFalse(DefaultPasteUtil.spawnBlueprintEntity(blueprintEntity, location, island));
|
||||||
|
|
||||||
|
// Verify the mythic mob was spawned, and the method returned early
|
||||||
|
verify(mythicMobsHook).spawnMythicMob(mmr, location);
|
||||||
|
verify(world, never()).spawnEntity(any(Location.class), any(EntityType.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSpawnBlueprintEntity_WithoutMythicMobs() {
|
||||||
|
// Set up conditions where MythicMobs should not be spawned
|
||||||
|
when(hooksManager.getHook("MythicMobs")).thenReturn(Optional.empty());
|
||||||
|
|
||||||
|
assertTrue(DefaultPasteUtil.spawnBlueprintEntity(blueprintEntity, location, island));
|
||||||
|
|
||||||
|
// Verify a regular entity was spawned instead
|
||||||
|
verify(world).spawnEntity(location, blueprintEntity.getType());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue