Multipaper (#2343)

* Switch to use database for team invites.

* WIP multipaper

* Fixes teams. Test still need to be fixed.

* Islands are now updated correctly across servers.

This build has a lot of debug in it!

* Fix tests

* Remove debug

* Remove primary island listing

* Version id

* Fix team management and ranks

* Removed debug

* Handle island deletion better

* Island deletion across servers.

* Fix bug with MythicMobs changes #2340

* 2.4.0

* Load of debug - trying to solve the settings slowness

* Debug debug

* Bug found - addPlayer being called instead of getPlayer

* Uncomment code after debug

* Fix tests
This commit is contained in:
tastybento 2024-05-04 22:27:58 -07:00 committed by GitHub
parent 5afd454fb3
commit b1fe76c45d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
61 changed files with 1046 additions and 1321 deletions

23
pom.xml
View File

@ -195,6 +195,11 @@
<name>Lumine Releases</name> <name>Lumine Releases</name>
<url>https://mvn.lumine.io/repository/maven-public/</url> <url>https://mvn.lumine.io/repository/maven-public/</url>
</repository> </repository>
<!-- For Multipaper -->
<repository>
<id>clojars</id>
<url>https://repo.clojars.org/</url>
</repository>
</repositories> </repositories>
<dependencies> <dependencies>
@ -370,6 +375,13 @@
<version>3.6.1</version> <version>3.6.1</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<!-- Multipaper -->
<dependency>
<groupId>com.github.puregero</groupId>
<artifactId>multilib</artifactId>
<version>1.1.12</version>
<scope>compile</scope>
</dependency>
</dependencies> </dependencies>
<build> <build>
@ -492,9 +504,10 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId> <artifactId>maven-shade-plugin</artifactId>
<version>3.3.1-SNAPSHOT</version> <version>3.4.0</version>
<configuration> <configuration>
<minimizeJar>true</minimizeJar> <minimizeJar>true</minimizeJar>
<dependencyReducedPomLocation>${project.build.directory}/dependency-reduced-pom.xml</dependencyReducedPomLocation>
<relocations> <relocations>
<relocation> <relocation>
<pattern>org.bstats</pattern> <pattern>org.bstats</pattern>
@ -506,9 +519,13 @@
</relocation> </relocation>
<relocation> <relocation>
<pattern>io.papermc.lib</pattern> <pattern>io.papermc.lib</pattern>
<shadedPattern>world.bentobox.bentobox.paperlib</shadedPattern> <!-- Replace this --> <shadedPattern>world.bentobox.bentobox.paperlib</shadedPattern>
</relocation> </relocation>
</relocations> <relocation>
<pattern>com.github.puregero.multilib</pattern>
<shadedPattern>world.bentobox.bentobox.multilib</shadedPattern>
</relocation>
</relocations>
<artifactSet> <artifactSet>
<excludes> <excludes>
<exclude>org.apache.maven.shared:*</exclude> <exclude>org.apache.maven.shared:*</exclude>

View File

@ -59,7 +59,6 @@ public class BStats {
registerGameModeAddonsChart(); registerGameModeAddonsChart();
registerHooksChart(); registerHooksChart();
registerPlayersPerServerChart(); registerPlayersPerServerChart();
registerFlagsDisplayModeChart();
// Single Line charts // Single Line charts
registerIslandsCountChart(); registerIslandsCountChart();
@ -171,27 +170,6 @@ public class BStats {
})); }));
} }
/**
* Sends the "flags display mode" of all the online players.
* @since 1.6.0
*/
private void registerFlagsDisplayModeChart() {
metrics.addCustomChart(new AdvancedPie("flagsDisplayMode", () -> {
Map<String, Integer> values = new HashMap<>();
Bukkit.getOnlinePlayers().forEach(player -> {
Flag.Mode mode = plugin.getPlayers().getFlagsDisplayMode(player.getUniqueId());
if (values.containsKey(mode.name())) {
values.put(mode.name(), values.get(mode.name()) + 1);
} else {
values.put(mode.name(), 1);
}
});
return values;
}));
}
/** /**
* Sends the enabled addons (except GameModeAddons) of this server as bar chart. * Sends the enabled addons (except GameModeAddons) of this server as bar chart.
* @since 1.17.1 * @since 1.17.1

View File

@ -210,20 +210,6 @@ public class BentoBox extends JavaPlugin implements Listener {
return; return;
} }
// Save islands & players data every X minutes
Bukkit.getScheduler().runTaskTimer(instance, () -> {
if (!playersManager.isSaveTaskRunning()) {
playersManager.saveAll(true);
} else {
getLogger().warning("Tried to start a player data save task while the previous auto save was still running!");
}
if (!islandsManager.isSaveTaskRunning()) {
islandsManager.saveAll(true);
} else {
getLogger().warning("Tried to start a island data save task while the previous auto save was still running!");
}
}, getSettings().getDatabaseBackupPeriod() * 20 * 60L, getSettings().getDatabaseBackupPeriod() * 20 * 60L);
// Make sure all flag listeners are registered. // Make sure all flag listeners are registered.
flagsManager.registerListeners(); flagsManager.registerListeners();
@ -433,7 +419,7 @@ public class BentoBox extends JavaPlugin implements Listener {
* @return the ranksManager * @return the ranksManager
* @deprecated Just use {@code RanksManager.getInstance()} * @deprecated Just use {@code RanksManager.getInstance()}
*/ */
@Deprecated(since = "2.0.0") @Deprecated(since = "2.0.0", forRemoval = true)
public RanksManager getRanksManager() { public RanksManager getRanksManager() {
return RanksManager.getInstance(); return RanksManager.getInstance();
} }

View File

@ -21,6 +21,8 @@ import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import com.github.puregero.multilib.MultiLib;
import world.bentobox.bentobox.BentoBox; import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.api.addons.request.AddonRequestHandler; import world.bentobox.bentobox.api.addons.request.AddonRequestHandler;
import world.bentobox.bentobox.api.flags.Flag; import world.bentobox.bentobox.api.flags.Flag;
@ -45,6 +47,8 @@ public abstract class Addon {
protected Addon() { protected Addon() {
state = State.DISABLED; state = State.DISABLED;
// If the config is updated, update the config.
MultiLib.onString(getPlugin(), "bentobox-config-update", v -> this.reloadConfig());
} }
/** /**

View File

@ -8,6 +8,8 @@ import org.bukkit.generator.ChunkGenerator;
import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jdt.annotation.Nullable;
import com.github.puregero.multilib.MultiLib;
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.util.Util; import world.bentobox.bentobox.util.Util;
@ -129,7 +131,10 @@ public abstract class GameModeAddon extends Addon {
* in-game and need to be saved. * in-game and need to be saved.
* @since 1.4.0 * @since 1.4.0
*/ */
public abstract void saveWorldSettings(); public void saveWorldSettings() {
// Inform other servers
MultiLib.notify("bentobox-config-update", "");
}
/** /**
* Defines if the game mode uses the latest {@link ChunkGenerator} API or * Defines if the game mode uses the latest {@link ChunkGenerator} API or

View File

@ -1,61 +0,0 @@
package world.bentobox.bentobox.api.commands.admin;
import java.util.List;
import java.util.UUID;
import world.bentobox.bentobox.api.commands.CompositeCommand;
import world.bentobox.bentobox.api.commands.ConfirmableCommand;
import world.bentobox.bentobox.api.localization.TextVariables;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.database.objects.Island;
public class AdminEmptyTrashCommand extends ConfirmableCommand {
/**
* Clear trash for player, or all unowned islands in trash
* @param parent - admin command
* @since 1.3.0
*/
public AdminEmptyTrashCommand(CompositeCommand parent) {
super(parent, "emptytrash");
}
@Override
public void setup() {
setPermission("admin.trash");
setOnlyPlayer(false);
setParametersHelp("commands.admin.emptytrash.parameters");
setDescription("commands.admin.emptytrash.description");
}
@Override
public boolean execute(User user, String label, List<String> args) {
if (args.size() > 1) {
// Show help
showHelp(this, user);
return false;
}
// Get target player
UUID targetUUID = args.isEmpty() ? null : getPlayers().getUUID(args.get(0));
if (!args.isEmpty() && targetUUID == null) {
user.sendMessage("general.errors.unknown-player", TextVariables.NAME, args.get(0));
return false;
}
// Remove trash for this player
final List<Island> islands = getIslands().getQuarantinedIslandByUser(getWorld(), targetUUID);
if (islands.isEmpty()) {
if (args.isEmpty()) {
user.sendMessage("commands.admin.trash.no-unowned-in-trash");
} else {
user.sendMessage("commands.admin.trash.no-islands-in-trash");
}
return false;
} else {
this.askConfirmation(user, () -> {
getIslands().deleteQuarantinedIslandByUser(getWorld(), targetUUID);
user.sendMessage("commands.admin.emptytrash.success");
});
return true;
}
}
}

View File

@ -49,9 +49,6 @@ public class AdminInfoCommand extends CompositeCommand {
Island island = getIslands().getIsland(getWorld(), targetUUID); Island island = getIslands().getIsland(getWorld(), targetUUID);
if (island != null) { if (island != null) {
new IslandInfo(island).showAdminInfo(user, getAddon()); new IslandInfo(island).showAdminInfo(user, getAddon());
if (!getIslands().getQuarantinedIslandByUser(getWorld(), targetUUID).isEmpty()) {
user.sendMessage("commands.admin.info.islands-in-trash");
}
return true; return true;
} else { } else {
user.sendMessage("general.errors.player-has-no-island"); user.sendMessage("general.errors.player-has-no-island");

View File

@ -16,7 +16,6 @@ import org.eclipse.jdt.annotation.Nullable;
import world.bentobox.bentobox.api.addons.GameModeAddon; 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.flags.Flag; import world.bentobox.bentobox.api.flags.Flag;
import world.bentobox.bentobox.api.flags.Flag.Mode;
import world.bentobox.bentobox.api.flags.Flag.Type; import world.bentobox.bentobox.api.flags.Flag.Type;
import world.bentobox.bentobox.api.localization.TextVariables; import world.bentobox.bentobox.api.localization.TextVariables;
import world.bentobox.bentobox.api.panels.builders.TabbedPanelBuilder; import world.bentobox.bentobox.api.panels.builders.TabbedPanelBuilder;
@ -206,11 +205,9 @@ public class AdminSettingsCommand extends CompositeCommand {
switch (f.getType()) { switch (f.getType()) {
case PROTECTION -> { case PROTECTION -> {
island.setFlag(f, rank); island.setFlag(f, rank);
getIslands().save(island);
} }
case SETTING -> { case SETTING -> {
island.setSettingsFlag(f, activeState); island.setSettingsFlag(f, activeState);
getIslands().save(island);
} }
case WORLD_SETTING -> f.setSetting(getWorld(), activeState); case WORLD_SETTING -> f.setSetting(getWorld(), activeState);
default -> { default -> {
@ -226,12 +223,11 @@ public class AdminSettingsCommand extends CompositeCommand {
user.sendMessage("general.errors.use-in-game"); user.sendMessage("general.errors.use-in-game");
return false; return false;
} }
getPlayers().setFlagsDisplayMode(user.getUniqueId(), Mode.EXPERT);
if (args.isEmpty()) { if (args.isEmpty()) {
new TabbedPanelBuilder() new TabbedPanelBuilder()
.user(user) .user(user)
.world(getWorld()) .world(getWorld())
.tab(1, new SettingsTab(getWorld(), user, Flag.Type.WORLD_SETTING)) .tab(1, new SettingsTab(getWorld(), user, Flag.Type.WORLD_SETTING, Flag.Mode.EXPERT))
.tab(2, new WorldDefaultSettingsTab(getWorld(), user)) .tab(2, new WorldDefaultSettingsTab(getWorld(), user))
.startingSlot(1) .startingSlot(1)
.size(54) .size(54)
@ -242,8 +238,8 @@ public class AdminSettingsCommand extends CompositeCommand {
new TabbedPanelBuilder() new TabbedPanelBuilder()
.user(user) .user(user)
.world(island.getWorld()) .world(island.getWorld())
.island(island).tab(1, new SettingsTab(user, Flag.Type.PROTECTION)) .island(island).tab(1, new SettingsTab(getWorld(), user, Flag.Type.PROTECTION, Flag.Mode.EXPERT))
.tab(2, new SettingsTab(user, Flag.Type.SETTING)) .tab(2, new SettingsTab(getWorld(), user, Flag.Type.SETTING, Flag.Mode.EXPERT))
.startingSlot(1) .startingSlot(1)
.size(54) .size(54)
.build().openPanel(); .build().openPanel();

View File

@ -1,87 +0,0 @@
package world.bentobox.bentobox.api.commands.admin;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import org.apache.commons.lang.math.NumberUtils;
import org.eclipse.jdt.annotation.NonNull;
import world.bentobox.bentobox.api.commands.CompositeCommand;
import world.bentobox.bentobox.api.commands.ConfirmableCommand;
import world.bentobox.bentobox.api.localization.TextVariables;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.database.objects.Island;
import world.bentobox.bentobox.util.Util;
public class AdminSwitchtoCommand extends ConfirmableCommand {
private UUID targetUUID;
private @NonNull List<Island> islands;
/**
* Switch player's island to the numbered one in trash
* @param parent - admin command
* @since 1.3.0
*/
public AdminSwitchtoCommand(CompositeCommand parent) {
super(parent, "switchto");
islands = new ArrayList<>();
}
@Override
public void setup() {
setPermission("admin.switchto");
setOnlyPlayer(false);
setParametersHelp("commands.admin.switchto.parameters");
setDescription("commands.admin.switchto.description");
}
@Override
public boolean canExecute(User user, String label, List<String> args) {
if (args.size() != 2) {
// Show help
showHelp(this, user);
return false;
}
// Get target player
targetUUID = Util.getUUID(args.get(0));
if (targetUUID == null) {
user.sendMessage("general.errors.unknown-player", TextVariables.NAME, args.get(0));
return false;
}
// Check island number
islands = getIslands().getQuarantinedIslandByUser(getWorld(), targetUUID);
if (islands.isEmpty()) {
user.sendMessage("commands.admin.trash.no-islands-in-trash");
return false;
}
return true;
}
@Override
public boolean execute(User user, String label, List<String> args) {
if (NumberUtils.isDigits(args.get(1))) {
try {
int n = Integer.parseInt(args.get(1));
if (n < 1 || n > islands.size()) {
user.sendMessage("commands.admin.switchto.out-of-range", TextVariables.NUMBER, String.valueOf(islands.size()), TextVariables.LABEL, getTopLabel());
return false;
}
this.askConfirmation(user, () -> {
if (getIslands().switchIsland(getWorld(), targetUUID, islands.get(n -1))) {
user.sendMessage("commands.admin.switchto.success");
} else {
user.sendMessage("commands.admin.switchto.cannot-switch");
}
});
return true;
} catch (Exception e) {
showHelp(this, user);
return false;
}
}
return true;
}
}

View File

@ -1,73 +0,0 @@
package world.bentobox.bentobox.api.commands.admin;
import java.util.List;
import java.util.UUID;
import world.bentobox.bentobox.api.commands.CompositeCommand;
import world.bentobox.bentobox.api.localization.TextVariables;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.database.objects.Island;
import world.bentobox.bentobox.util.IslandInfo;
public class AdminTrashCommand extends CompositeCommand {
/**
* A command for viewing islands in the database trash
* @param parent - admin command
* @since 1.3.0
*/
public AdminTrashCommand(CompositeCommand parent) {
super(parent, "trash");
}
@Override
public void setup() {
setPermission("admin.trash");
setOnlyPlayer(false);
setParametersHelp("commands.admin.trash.parameters");
setDescription("commands.admin.trash.description");
}
@Override
public boolean execute(User user, String label, List<String> args) {
if (args.size() > 1) {
// Show help
showHelp(this, user);
return false;
}
// Get target player
UUID targetUUID = args.isEmpty() ? null : getPlayers().getUUID(args.get(0));
if (!args.isEmpty() && targetUUID == null) {
user.sendMessage("general.errors.unknown-player", TextVariables.NAME, args.get(0));
return false;
}
// Show trash can info for this player
List<Island> islands = getIslands().getQuarantinedIslandByUser(getWorld(), targetUUID);
if (islands.isEmpty()) {
if (args.isEmpty()) {
user.sendMessage("commands.admin.trash.no-unowned-in-trash");
} else {
user.sendMessage("commands.admin.trash.no-islands-in-trash");
}
return false;
} else {
if (targetUUID == null) {
showTrash(user, islands);
} else {
getIslands().getQuarantineCache().values().forEach(v -> showTrash(user, v));
}
return true;
}
}
private void showTrash(User user, List<Island> islands) {
user.sendMessage("commands.admin.trash.title");
for (int i = 0; i < islands.size(); i++) {
user.sendMessage("commands.admin.trash.count", TextVariables.NUMBER, String.valueOf(i+1));
new IslandInfo(islands.get(i)).showInfo(user);
}
user.sendMessage("commands.admin.trash.use-switch", TextVariables.LABEL, getTopLabel());
user.sendMessage("commands.admin.trash.use-emptytrash", TextVariables.LABEL, getTopLabel());
}
}

View File

@ -116,7 +116,6 @@ public class AdminUnregisterCommand extends ConfirmableCommand {
targetIsland.getMembers().clear(); targetIsland.getMembers().clear();
targetIsland.log(new LogEntry.Builder("UNREGISTER").data("player", targetUUID.toString()) targetIsland.log(new LogEntry.Builder("UNREGISTER").data("player", targetUUID.toString())
.data("admin", user.getUniqueId().toString()).build()); .data("admin", user.getUniqueId().toString()).build());
getIslands().save(targetIsland);
user.sendMessage("commands.admin.unregister.unregistered-island", TextVariables.XYZ, Util.xyz(targetIsland.getCenter().toVector()), user.sendMessage("commands.admin.unregister.unregistered-island", TextVariables.XYZ, Util.xyz(targetIsland.getCenter().toVector()),
TextVariables.NAME, getPlayers().getName(targetUUID)); TextVariables.NAME, getPlayers().getName(targetUUID));
} }

View File

@ -40,7 +40,6 @@ public class NamePrompt extends StringPrompt {
@Override @Override
public Prompt acceptInput(@NonNull ConversationContext context, String input) { public Prompt acceptInput(@NonNull ConversationContext context, String input) {
if (island.renameHome(oldName, input)) { if (island.renameHome(oldName, input)) {
plugin.getIslands().save(island);
Bukkit.getScheduler().runTask(plugin, () -> user.sendMessage("general.success")); Bukkit.getScheduler().runTask(plugin, () -> user.sendMessage("general.success"));
} else { } else {
Bukkit.getScheduler().runTask(plugin, () -> user.sendMessage("commands.island.renamehome.already-exists")); Bukkit.getScheduler().runTask(plugin, () -> user.sendMessage("commands.island.renamehome.already-exists"));

View File

@ -49,7 +49,8 @@ public class IslandSettingsCommand extends CompositeCommand {
.user(user) .user(user)
.island(island) .island(island)
.world(island.getWorld()) .world(island.getWorld())
.tab(1, new SettingsTab(user, Flag.Type.PROTECTION)).tab(2, new SettingsTab(user, Flag.Type.SETTING)) .tab(1, new SettingsTab(getWorld(), user, Flag.Type.PROTECTION))
.tab(2, new SettingsTab(getWorld(), user, Flag.Type.SETTING))
.startingSlot(1) .startingSlot(1)
.size(54) .size(54)
.hideIfEmpty() .hideIfEmpty()

View File

@ -1,95 +0,0 @@
package world.bentobox.bentobox.api.commands.island.team;
import java.util.Objects;
import java.util.UUID;
import world.bentobox.bentobox.database.objects.Island;
/**
* Represents an invite
* @author tastybento
* @since 1.8.0
*/
public class Invite {
/**
* Type of invitation
*
*/
public enum Type {
COOP,
TEAM,
TRUST
}
private final Type type;
private final UUID inviter;
private final UUID invitee;
private final Island island;
/**
* @param type - invitation type, e.g., coop, team, trust
* @param inviter - UUID of inviter
* @param invitee - UUID of invitee
* @param island - the island this invite is for
*/
public Invite(Type type, UUID inviter, UUID invitee, Island island) {
this.type = type;
this.inviter = inviter;
this.invitee = invitee;
this.island = island;
}
/**
* @return the type
*/
public Type getType() {
return type;
}
/**
* @return the inviter
*/
public UUID getInviter() {
return inviter;
}
/**
* @return the invitee
*/
public UUID getInvitee() {
return invitee;
}
/**
* @return the island
*/
public Island getIsland() {
return island;
}
/* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
return Objects.hash(invitee, inviter, type);
}
/* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (!(obj instanceof Invite other)) {
return false;
}
return Objects.equals(invitee, other.invitee) && Objects.equals(inviter, other.inviter) && type == other.type;
}
}

View File

@ -1,9 +1,7 @@
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.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
@ -16,17 +14,13 @@ 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.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.Database;
import world.bentobox.bentobox.database.objects.Island; import world.bentobox.bentobox.database.objects.Island;
import world.bentobox.bentobox.database.objects.TeamInvite;
import world.bentobox.bentobox.managers.RanksManager; import world.bentobox.bentobox.managers.RanksManager;
public class IslandTeamCommand extends CompositeCommand { public class IslandTeamCommand extends CompositeCommand {
/**
* Invited list. Key is the invited party, value is the invite.
* @since 1.8.0
*/
private final Map<UUID, Invite> inviteMap;
private IslandTeamKickCommand kickCommand; private IslandTeamKickCommand kickCommand;
private IslandTeamLeaveCommand leaveCommand; private IslandTeamLeaveCommand leaveCommand;
@ -51,9 +45,11 @@ public class IslandTeamCommand extends CompositeCommand {
private IslandTeamTrustCommand trustCommand; private IslandTeamTrustCommand trustCommand;
private final Database<TeamInvite> handler;
public IslandTeamCommand(CompositeCommand parent) { public IslandTeamCommand(CompositeCommand parent) {
super(parent, "team"); super(parent, "team");
inviteMap = new HashMap<>(); handler = new Database<>(parent.getAddon(), TeamInvite.class);
} }
@Override @Override
@ -139,8 +135,8 @@ public class IslandTeamCommand extends CompositeCommand {
* @param invitee - uuid of invitee * @param invitee - uuid of invitee
* @since 1.8.0 * @since 1.8.0
*/ */
public void addInvite(Invite.Type type, @NonNull UUID inviter, @NonNull UUID invitee, @NonNull Island island) { public void addInvite(TeamInvite.Type type, @NonNull UUID inviter, @NonNull UUID invitee, @NonNull Island island) {
inviteMap.put(invitee, new Invite(type, inviter, invitee, island)); handler.saveObjectAsync(new TeamInvite(type, inviter, invitee, island.getUniqueId()));
} }
/** /**
@ -150,7 +146,7 @@ public class IslandTeamCommand extends CompositeCommand {
* @since 1.8.0 * @since 1.8.0
*/ */
public boolean isInvited(@NonNull UUID invitee) { public boolean isInvited(@NonNull UUID invitee) {
return inviteMap.containsKey(invitee); return handler.objectExists(invitee.toString());
} }
/** /**
@ -161,7 +157,7 @@ public class IslandTeamCommand extends CompositeCommand {
*/ */
@Nullable @Nullable
public UUID getInviter(UUID invitee) { public UUID getInviter(UUID invitee) {
return isInvited(invitee) ? inviteMap.get(invitee).getInviter() : null; return isInvited(invitee) ? handler.loadObject(invitee.toString()).getInviter() : null;
} }
/** /**
@ -171,8 +167,8 @@ public class IslandTeamCommand extends CompositeCommand {
* @since 1.8.0 * @since 1.8.0
*/ */
@Nullable @Nullable
public Invite getInvite(UUID invitee) { public TeamInvite getInvite(UUID invitee) {
return inviteMap.get(invitee); return handler.loadObject(invitee.toString());
} }
/** /**
@ -181,7 +177,7 @@ public class IslandTeamCommand extends CompositeCommand {
* @since 1.8.0 * @since 1.8.0
*/ */
public void removeInvite(@NonNull UUID invitee) { public void removeInvite(@NonNull UUID invitee) {
inviteMap.remove(invitee); handler.deleteID(invitee.toString());
} }
/** /**

View File

@ -8,10 +8,10 @@ import java.util.UUID;
import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jdt.annotation.Nullable;
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.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;
import world.bentobox.bentobox.database.objects.TeamInvite.Type;
import world.bentobox.bentobox.managers.RanksManager; import world.bentobox.bentobox.managers.RanksManager;
import world.bentobox.bentobox.util.Util; import world.bentobox.bentobox.util.Util;
@ -99,7 +99,7 @@ public class IslandTeamCoopCommand extends CompositeCommand {
// Put the invited player (key) onto the list with inviter (value) // Put the invited player (key) onto the list with inviter (value)
// If someone else has invited a player, then this invite will overwrite the // If someone else has invited a player, then this invite will overwrite the
// previous invite! // previous invite!
itc.addInvite(Invite.Type.COOP, user.getUniqueId(), target.getUniqueId(), island); itc.addInvite(Type.COOP, user.getUniqueId(), target.getUniqueId(), island);
user.sendMessage("commands.island.team.invite.invitation-sent", TextVariables.NAME, target.getName()); user.sendMessage("commands.island.team.invite.invitation-sent", TextVariables.NAME, target.getName());
// Send message to online player // Send message to online player
target.sendMessage("commands.island.team.coop.name-has-invited-you", TextVariables.NAME, target.sendMessage("commands.island.team.coop.name-has-invited-you", TextVariables.NAME,

View File

@ -22,7 +22,6 @@ 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.BentoBox;
import world.bentobox.bentobox.api.commands.island.team.Invite.Type;
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.Panel;
import world.bentobox.bentobox.api.panels.PanelItem; import world.bentobox.bentobox.api.panels.PanelItem;
@ -34,6 +33,8 @@ import world.bentobox.bentobox.api.panels.reader.ItemTemplateRecord.ActionRecord
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.database.objects.TeamInvite;
import world.bentobox.bentobox.database.objects.TeamInvite.Type;
import world.bentobox.bentobox.managers.RanksManager; import world.bentobox.bentobox.managers.RanksManager;
import world.bentobox.bentobox.util.Util; import world.bentobox.bentobox.util.Util;
@ -208,7 +209,7 @@ public class IslandTeamGUI {
private PanelItem createInvitedButton(ItemTemplateRecord template, TemplatedPanel.ItemSlot slot) { private PanelItem createInvitedButton(ItemTemplateRecord template, TemplatedPanel.ItemSlot slot) {
PanelItemBuilder builder = new PanelItemBuilder(); PanelItemBuilder builder = new PanelItemBuilder();
if (parent.isInvited(user.getUniqueId()) && user.hasPermission(parent.getAcceptCommand().getPermission())) { if (parent.isInvited(user.getUniqueId()) && user.hasPermission(parent.getAcceptCommand().getPermission())) {
Invite invite = parent.getInvite(user.getUniqueId()); TeamInvite invite = parent.getInvite(user.getUniqueId());
if (invite == null) { if (invite == null) {
return this.getBlankBorder(); return this.getBlankBorder();
} }
@ -224,7 +225,8 @@ public class IslandTeamGUI {
return builder.build(); return builder.build();
} }
private void createInviteClickHandler(PanelItemBuilder builder, Invite invite, @NonNull List<ActionRecords> list) { private void createInviteClickHandler(PanelItemBuilder builder, TeamInvite invite,
@NonNull List<ActionRecords> list) {
Type type = invite.getType(); Type type = invite.getType();
builder.clickHandler((panel, user, clickType, clickSlot) -> { builder.clickHandler((panel, user, clickType, clickSlot) -> {
if (list.stream().noneMatch(ar -> clickType.equals(ar.clickType()))) { if (list.stream().noneMatch(ar -> clickType.equals(ar.clickType()))) {

View File

@ -5,13 +5,14 @@ import java.util.UUID;
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.commands.ConfirmableCommand;
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.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;
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.database.objects.TeamInvite;
import world.bentobox.bentobox.database.objects.TeamInvite.Type;
import world.bentobox.bentobox.managers.RanksManager; import world.bentobox.bentobox.managers.RanksManager;
import world.bentobox.bentobox.util.Util; import world.bentobox.bentobox.util.Util;
@ -49,7 +50,7 @@ public class IslandTeamInviteAcceptCommand extends ConfirmableCommand {
user.sendMessage(INVALID_INVITE); user.sendMessage(INVALID_INVITE);
return false; return false;
} }
Invite invite = itc.getInvite(playerUUID); TeamInvite invite = itc.getInvite(playerUUID);
if (invite.getType().equals(Type.TEAM)) { if (invite.getType().equals(Type.TEAM)) {
// Check rank to of inviter // Check rank to of inviter
Island island = getIslands().getIsland(getWorld(), prospectiveOwnerUUID); Island island = getIslands().getIsland(getWorld(), prospectiveOwnerUUID);
@ -78,7 +79,7 @@ public class IslandTeamInviteAcceptCommand extends ConfirmableCommand {
@Override @Override
public boolean execute(User user, String label, List<String> args) { public boolean execute(User user, String label, List<String> args) {
// Get the invite // Get the invite
Invite invite = itc.getInvite(user.getUniqueId()); TeamInvite invite = itc.getInvite(user.getUniqueId());
switch (invite.getType()) { switch (invite.getType()) {
case COOP -> askConfirmation(user, () -> acceptCoopInvite(user, invite)); case COOP -> askConfirmation(user, () -> acceptCoopInvite(user, invite));
case TRUST -> askConfirmation(user, () -> acceptTrustInvite(user, invite)); case TRUST -> askConfirmation(user, () -> acceptTrustInvite(user, invite));
@ -94,11 +95,11 @@ public class IslandTeamInviteAcceptCommand extends ConfirmableCommand {
return true; return true;
} }
void acceptTrustInvite(User user, Invite invite) { void acceptTrustInvite(User user, TeamInvite invite) {
// Remove the invite // Remove the invite
itc.removeInvite(user.getUniqueId()); itc.removeInvite(user.getUniqueId());
User inviter = User.getInstance(invite.getInviter()); User inviter = User.getInstance(invite.getInviter());
Island island = invite.getIsland(); Island island = getIslands().getIslandById(invite.getIslandID()).orElse(null);
if (island != null) { if (island != null) {
if (island.getMemberSet(RanksManager.TRUSTED_RANK, false).size() > getIslands().getMaxMembers(island, if (island.getMemberSet(RanksManager.TRUSTED_RANK, false).size() > getIslands().getMaxMembers(island,
RanksManager.TRUSTED_RANK)) { RanksManager.TRUSTED_RANK)) {
@ -120,11 +121,11 @@ public class IslandTeamInviteAcceptCommand extends ConfirmableCommand {
} }
} }
void acceptCoopInvite(User user, Invite invite) { void acceptCoopInvite(User user, TeamInvite invite) {
// Remove the invite // Remove the invite
itc.removeInvite(user.getUniqueId()); itc.removeInvite(user.getUniqueId());
User inviter = User.getInstance(invite.getInviter()); User inviter = User.getInstance(invite.getInviter());
Island island = invite.getIsland(); Island island = getIslands().getIslandById(invite.getIslandID()).orElse(null);
if (island != null) { if (island != null) {
if (island.getMemberSet(RanksManager.COOP_RANK, false).size() > getIslands().getMaxMembers(island, if (island.getMemberSet(RanksManager.COOP_RANK, false).size() > getIslands().getMaxMembers(island,
RanksManager.COOP_RANK)) { RanksManager.COOP_RANK)) {
@ -146,13 +147,13 @@ public class IslandTeamInviteAcceptCommand extends ConfirmableCommand {
} }
} }
void acceptTeamInvite(User user, Invite invite) { void acceptTeamInvite(User user, TeamInvite invite) {
// Remove the invite // Remove the invite
itc.removeInvite(user.getUniqueId()); itc.removeInvite(user.getUniqueId());
// Get the player's island - may be null if the player has no island // Get the player's island - may be null if the player has no island
List<Island> islands = getIslands().getIslands(getWorld(), user.getUniqueId()); List<Island> islands = getIslands().getIslands(getWorld(), user.getUniqueId());
// Get the team's island // Get the team's island
Island teamIsland = invite.getIsland(); Island teamIsland = getIslands().getIslandById(invite.getIslandID()).orElse(null);
if (teamIsland == null) { if (teamIsland == null) {
user.sendMessage(INVALID_INVITE); user.sendMessage(INVALID_INVITE);
return; return;
@ -196,7 +197,6 @@ public class IslandTeamInviteAcceptCommand extends ConfirmableCommand {
inviter.sendMessage("commands.island.team.invite.accept.name-joined-your-island", TextVariables.NAME, inviter.sendMessage("commands.island.team.invite.accept.name-joined-your-island", TextVariables.NAME,
user.getName(), TextVariables.DISPLAY_NAME, user.getDisplayName()); user.getName(), TextVariables.DISPLAY_NAME, user.getDisplayName());
} }
getIslands().save(teamIsland);
// Fire event // Fire event
TeamEvent.builder().island(teamIsland).reason(TeamEvent.Reason.JOINED).involvedPlayer(user.getUniqueId()) TeamEvent.builder().island(teamIsland).reason(TeamEvent.Reason.JOINED).involvedPlayer(user.getUniqueId())
.build(); .build();

View File

@ -10,13 +10,13 @@ import java.util.UUID;
import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jdt.annotation.Nullable;
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.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.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.database.objects.TeamInvite.Type;
import world.bentobox.bentobox.managers.IslandsManager; import world.bentobox.bentobox.managers.IslandsManager;
import world.bentobox.bentobox.managers.PlayersManager; import world.bentobox.bentobox.managers.PlayersManager;
import world.bentobox.bentobox.managers.RanksManager; import world.bentobox.bentobox.managers.RanksManager;
@ -166,7 +166,7 @@ public class IslandTeamInviteCommand extends CompositeCommand {
} }
// Put the invited player (key) onto the list with inviter (value) // Put the invited player (key) onto the list with inviter (value)
// If someone else has invited a player, then this invite will overwrite the previous invite! // If someone else has invited a player, then this invite will overwrite the previous invite!
itc.addInvite(Invite.Type.TEAM, user.getUniqueId(), invitedPlayer.getUniqueId(), island); itc.addInvite(Type.TEAM, user.getUniqueId(), invitedPlayer.getUniqueId(), island);
user.sendMessage("commands.island.team.invite.invitation-sent", TextVariables.NAME, invitedPlayer.getName(), TextVariables.DISPLAY_NAME, invitedPlayer.getDisplayName()); user.sendMessage("commands.island.team.invite.invitation-sent", TextVariables.NAME, invitedPlayer.getName(), TextVariables.DISPLAY_NAME, invitedPlayer.getDisplayName());
// Send message to online player // Send message to online player
invitedPlayer.sendMessage("commands.island.team.invite.name-has-invited-you", TextVariables.NAME, user.getName(), TextVariables.DISPLAY_NAME, user.getDisplayName()); invitedPlayer.sendMessage("commands.island.team.invite.name-has-invited-you", TextVariables.NAME, user.getName(), TextVariables.DISPLAY_NAME, user.getDisplayName());

View File

@ -14,6 +14,7 @@ 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.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.IslandsManager;
import world.bentobox.bentobox.managers.RanksManager; import world.bentobox.bentobox.managers.RanksManager;
import world.bentobox.bentobox.util.Util; import world.bentobox.bentobox.util.Util;
@ -91,7 +92,6 @@ public class IslandTeamSetownerCommand extends CompositeCommand {
IslandEvent.builder().island(island).involvedPlayer(user.getUniqueId()).admin(false) IslandEvent.builder().island(island).involvedPlayer(user.getUniqueId()).admin(false)
.reason(IslandEvent.Reason.RANK_CHANGE).rankChange(RanksManager.OWNER_RANK, RanksManager.SUB_OWNER_RANK) .reason(IslandEvent.Reason.RANK_CHANGE).rankChange(RanksManager.OWNER_RANK, RanksManager.SUB_OWNER_RANK)
.build(); .build();
getIslands().save(island);
return true; return true;
} }

View File

@ -8,10 +8,10 @@ import java.util.UUID;
import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jdt.annotation.Nullable;
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.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;
import world.bentobox.bentobox.database.objects.TeamInvite.Type;
import world.bentobox.bentobox.managers.RanksManager; import world.bentobox.bentobox.managers.RanksManager;
import world.bentobox.bentobox.util.Util; import world.bentobox.bentobox.util.Util;

View File

@ -388,21 +388,24 @@ public class Flag implements Comparable<Flag> {
if (!user.isOp() && invisible) { if (!user.isOp() && invisible) {
return null; return null;
} }
// Start the flag conversion
PanelItemBuilder pib = new PanelItemBuilder() PanelItemBuilder pib = new PanelItemBuilder()
.icon(ItemParser.parse(user.getTranslationOrNothing(this.getIconReference()), new ItemStack(icon))) .icon(ItemParser.parse(user.getTranslationOrNothing(this.getIconReference()), new ItemStack(icon)))
.name(user.getTranslation("protection.panel.flag-item.name-layout", TextVariables.NAME, user.getTranslation(getNameReference()))) .name(user.getTranslation("protection.panel.flag-item.name-layout", TextVariables.NAME,
user.getTranslation(getNameReference())))
.clickHandler(clickHandler) .clickHandler(clickHandler)
.invisible(invisible); .invisible(invisible);
if (hasSubPanel()) { if (hasSubPanel()) {
pib.description(user.getTranslation("protection.panel.flag-item.menu-layout", TextVariables.DESCRIPTION, user.getTranslation(getDescriptionReference()))); pib.description(user.getTranslation("protection.panel.flag-item.menu-layout", TextVariables.DESCRIPTION, user.getTranslation(getDescriptionReference())));
return pib.build(); return pib.build();
} }
return switch (getType()) { return switch (getType()) {
case PROTECTION -> createProtectionFlag(plugin, user, island, pib).build(); case PROTECTION -> createProtectionFlag(plugin, user, island, pib).build();
case SETTING -> createSettingFlag(user, island, pib).build(); case SETTING -> createSettingFlag(user, island, pib).build();
case WORLD_SETTING -> createWorldSettingFlag(user, world, pib).build(); case WORLD_SETTING -> createWorldSettingFlag(user, world, pib).build();
}; };
} }
private PanelItemBuilder createWorldSettingFlag(User user, World world, PanelItemBuilder pib) { private PanelItemBuilder createWorldSettingFlag(User user, World world, PanelItemBuilder pib) {
@ -429,19 +432,24 @@ public class Flag implements Comparable<Flag> {
private PanelItemBuilder createProtectionFlag(BentoBox plugin, User user, Island island, PanelItemBuilder pib) { private PanelItemBuilder createProtectionFlag(BentoBox plugin, User user, Island island, PanelItemBuilder pib) {
if (island != null) { if (island != null) {
int y = island.getFlag(this);
// Protection flag // Protection flag
pib.description(user.getTranslation("protection.panel.flag-item.description-layout", pib.description(user.getTranslation("protection.panel.flag-item.description-layout",
TextVariables.DESCRIPTION, user.getTranslation(getDescriptionReference()))); TextVariables.DESCRIPTION, user.getTranslation(getDescriptionReference())));
RanksManager.getInstance().getRanks().forEach((reference, score) -> { RanksManager.getInstance().getRanks().forEach((reference, score) -> {
if (score > RanksManager.BANNED_RANK && score < island.getFlag(this)) {
if (score > RanksManager.BANNED_RANK && score < y) {
pib.description(user.getTranslation("protection.panel.flag-item.blocked-rank") + user.getTranslation(reference)); pib.description(user.getTranslation("protection.panel.flag-item.blocked-rank") + user.getTranslation(reference));
} else if (score <= RanksManager.OWNER_RANK && score > island.getFlag(this)) { } else if (score <= RanksManager.OWNER_RANK && score > y) {
pib.description(user.getTranslation("protection.panel.flag-item.allowed-rank") + user.getTranslation(reference)); pib.description(user.getTranslation("protection.panel.flag-item.allowed-rank") + user.getTranslation(reference));
} else if (score == island.getFlag(this)) { } else if (score == y) {
pib.description(user.getTranslation("protection.panel.flag-item.minimal-rank") + user.getTranslation(reference)); pib.description(user.getTranslation("protection.panel.flag-item.minimal-rank") + user.getTranslation(reference));
} }
}); });
} }
return pib; return pib;
} }
@ -469,7 +477,7 @@ public class Flag implements Comparable<Flag> {
public Set<Flag> getSubflags() { public Set<Flag> getSubflags() {
return subflags; return subflags;
} }
/** /**
* Set the name of this flag for a specified locale. This enables the flag's name to be assigned via API. It will not be stored anywhere * Set the name of this flag for a specified locale. This enables the flag's name to be assigned via API. It will not be stored anywhere
* and must be rewritten using this call every time the flag is built. * and must be rewritten using this call every time the flag is built.
@ -482,7 +490,7 @@ public class Flag implements Comparable<Flag> {
public boolean setTranslatedName(Locale locale, String name) { public boolean setTranslatedName(Locale locale, String name) {
return BentoBox.getInstance().getLocalesManager().setTranslation(locale, getNameReference(), name); return BentoBox.getInstance().getLocalesManager().setTranslation(locale, getNameReference(), name);
} }
/** /**
* Set the name of this flag for a specified locale. This enables the flag's name to be assigned via API. It will not be stored anywhere * Set the name of this flag for a specified locale. This enables the flag's name to be assigned via API. It will not be stored anywhere
* and must be rewritten using this call every time the flag is built. * and must be rewritten using this call every time the flag is built.

View File

@ -74,6 +74,7 @@ public class TabbedPanel extends Panel implements PanelListener {
* @param page - the page of the tab to show (if multi paged) * @param page - the page of the tab to show (if multi paged)
*/ */
public void openPanel(int activeTab, int page) { public void openPanel(int activeTab, int page) {
if (!tpb.getTabs().containsKey(activeTab)) { if (!tpb.getTabs().containsKey(activeTab)) {
// Request to open a non-existent tab // Request to open a non-existent tab
throw new InvalidParameterException("Attempt to open a non-existent tab in a tabbed panel. Missing tab #" + activeTab); throw new InvalidParameterException("Attempt to open a non-existent tab in a tabbed panel. Missing tab #" + activeTab);
@ -88,21 +89,17 @@ public class TabbedPanel extends Panel implements PanelListener {
TreeMap<Integer, PanelItem> items = new TreeMap<>(); TreeMap<Integer, PanelItem> items = new TreeMap<>();
// Get the tab // Get the tab
Tab tab = tpb.getTabs().get(activeTab); Tab tab = tpb.getTabs().get(activeTab);
// Remove any tabs that have no items, if required // Remove any tabs that have no items, if required
if (tpb.isHideIfEmpty()) { if (tpb.isHideIfEmpty()) {
tpb.getTabs().values().removeIf(t -> !t.equals(tab) && t.getPanelItems().stream().noneMatch(Objects::nonNull)); tpb.getTabs().values().removeIf(t -> !t.equals(tab) && t.getPanelItems().stream().noneMatch(Objects::nonNull));
} }
// Set up the tabbed header // Set up the tabbed header
setupHeader(tab, items); setupHeader(tab, items);
// Show the active tab // Show the active tab
if (tpb.getTabs().containsKey(activeTab)) { if (tpb.getTabs().containsKey(activeTab)) {
List<PanelItem> panelItems = tab.getPanelItems(); List<PanelItem> panelItems = tab.getPanelItems();
// Adds the flag items // Adds the flag items
panelItems.stream().filter(Objects::nonNull).skip(page * ITEMS_PER_PAGE).limit(page * ITEMS_PER_PAGE + ITEMS_PER_PAGE).forEach(i -> items.put(items.lastKey() + 1, i)); panelItems.stream().filter(Objects::nonNull).skip(page * ITEMS_PER_PAGE).limit(page * ITEMS_PER_PAGE + ITEMS_PER_PAGE).forEach(i -> items.put(items.lastKey() + 1, i));
// set up the footer // set up the footer
setupFooter(items); setupFooter(items);
// Add forward and backward icons // Add forward and backward icons
@ -182,6 +179,7 @@ public class TabbedPanel extends Panel implements PanelListener {
// Reset the closed flag // Reset the closed flag
closed = false; closed = false;
} }
} }
/** /**

View File

@ -13,6 +13,7 @@ import java.util.Objects;
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
@ -41,6 +42,7 @@ import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.database.objects.adapters.Adapter; import world.bentobox.bentobox.database.objects.adapters.Adapter;
import world.bentobox.bentobox.database.objects.adapters.LogEntryListAdapter; import world.bentobox.bentobox.database.objects.adapters.LogEntryListAdapter;
import world.bentobox.bentobox.lists.Flags; import world.bentobox.bentobox.lists.Flags;
import world.bentobox.bentobox.managers.IslandsManager;
import world.bentobox.bentobox.managers.RanksManager; import world.bentobox.bentobox.managers.RanksManager;
import world.bentobox.bentobox.util.Pair; import world.bentobox.bentobox.util.Pair;
import world.bentobox.bentobox.util.Util; import world.bentobox.bentobox.util.Util;
@ -56,7 +58,7 @@ import world.bentobox.bentobox.util.Util;
public class Island implements DataObject, MetaDataAble { public class Island implements DataObject, MetaDataAble {
@Expose @Expose
private boolean primary; private Set<UUID> primaries = new HashSet<>();
/** /**
* Set to true if this data object has been changed since being loaded from the * Set to true if this data object has been changed since being loaded from the
@ -243,7 +245,6 @@ public class Island implements DataObject, MetaDataAble {
range = BentoBox.getInstance().getIWM().getIslandDistance(world); range = BentoBox.getInstance().getIWM().getIslandDistance(world);
this.protectionRange = protectionRange; this.protectionRange = protectionRange;
this.maxEverProtectionRange = protectionRange; this.maxEverProtectionRange = protectionRange;
this.setChanged();
} }
/** /**
@ -290,6 +291,7 @@ public class Island implements DataObject, MetaDataAble {
this.updatedDate = island.getUpdatedDate(); this.updatedDate = island.getUpdatedDate();
this.world = island.getWorld(); this.world = island.getWorld();
this.bonusRanges.addAll(island.getBonusRanges()); this.bonusRanges.addAll(island.getBonusRanges());
this.primaries.addAll(island.getPrimaries());
this.setChanged(); this.setChanged();
} }
@ -304,8 +306,10 @@ public class Island implements DataObject, MetaDataAble {
* @param playerUUID - the player's UUID * @param playerUUID - the player's UUID
*/ */
public void addMember(@NonNull UUID playerUUID) { public void addMember(@NonNull UUID playerUUID) {
setRank(playerUUID, RanksManager.MEMBER_RANK); if (getRank(playerUUID) != RanksManager.MEMBER_RANK) {
setChanged(); setRank(playerUUID, RanksManager.MEMBER_RANK);
setChanged();
}
} }
/** /**
@ -320,9 +324,12 @@ public class Island implements DataObject, MetaDataAble {
* @return {@code true} * @return {@code true}
*/ */
public boolean ban(@NonNull UUID issuer, @NonNull UUID target) { public boolean ban(@NonNull UUID issuer, @NonNull UUID target) {
setRank(target, RanksManager.BANNED_RANK); if (getRank(target) != RanksManager.BANNED_RANK) {
log(new LogEntry.Builder("BAN").data("player", target.toString()).data("issuer", issuer.toString()).build()); setRank(target, RanksManager.BANNED_RANK);
setChanged(); log(new LogEntry.Builder("BAN").data("player", target.toString()).data("issuer", issuer.toString())
.build());
setChanged();
}
return true; return true;
} }
@ -1005,25 +1012,30 @@ public class Island implements DataObject, MetaDataAble {
* @param playerUUID - uuid of player * @param playerUUID - uuid of player
*/ */
public void removeMember(UUID playerUUID) { public void removeMember(UUID playerUUID) {
members.remove(playerUUID); if (members.remove(playerUUID) != null) {
setChanged(); setChanged();
}
} }
/** /**
* @param center the center to set * @param center the center to set
*/ */
public void setCenter(@NonNull Location center) { public void setCenter(@NonNull Location center) {
this.world = center.getWorld(); if (this.center == null || !center.getWorld().equals(this.center.getWorld()) || !center.equals(this.center)) {
this.center = center; this.world = center.getWorld();
setChanged(); this.center = center;
setChanged();
}
} }
/** /**
* @param createdDate - the createdDate to sets * @param createdDate - the createdDate to sets
*/ */
public void setCreatedDate(long createdDate) { public void setCreatedDate(long createdDate) {
this.createdDate = createdDate; if (this.createdDate != createdDate) {
setChanged(); this.createdDate = createdDate;
setChanged();
}
} }
/** /**
@ -1038,21 +1050,23 @@ public class Island implements DataObject, MetaDataAble {
} }
/** /**
* Set the Island Guard flag rank Also specify whether subflags are affected by * Set the Island Guard flag rank and set any subflags
* this method call
* *
* @param flag - flag * @param flag - flag
* @param value - Use RanksManager settings, e.g. RanksManager.MEMBER * @param value - Use RanksManager settings, e.g. RanksManager.MEMBER
* @param doSubflags - whether to set subflags * @param doSubflags - whether to set subflags
* @return true if this causes a flag change
*/ */
public void setFlag(Flag flag, int value, boolean doSubflags) { public void setFlag(Flag flag, int value, boolean doSubflags) {
flags.put(flag.getID(), value); if (flags.containsKey(flag.getID()) && flags.get(flag.getID()) != value) {
flags.put(flag.getID(), value);
setChanged();
}
// Subflag support // Subflag support
if (doSubflags && flag.hasSubflags()) { if (doSubflags && flag.hasSubflags()) {
// Ensure that a subflag isn't a subflag of itself or else we're in trouble! // Ensure that a subflag isn't a subflag of itself or else we're in trouble!
flag.getSubflags().forEach(subflag -> setFlag(subflag, value, true)); flag.getSubflags().forEach(subflag -> setFlag(subflag, value, true));
} }
setChanged();
} }
/** /**
@ -1078,7 +1092,6 @@ public class Island implements DataObject, MetaDataAble {
.forEach(f -> result.put(f.getID(), .forEach(f -> result.put(f.getID(),
plugin.getIWM().getDefaultIslandSettings(world).getOrDefault(f, f.getDefaultRank()))); plugin.getIWM().getDefaultIslandSettings(world).getOrDefault(f, f.getDefaultRank())));
this.setFlags(result); this.setFlags(result);
setChanged();
} }
/** /**
@ -1097,8 +1110,10 @@ public class Island implements DataObject, MetaDataAble {
* @param name The display name to set. * @param name The display name to set.
*/ */
public void setName(String name) { public void setName(String name) {
this.name = (name != null && !name.equals("")) ? name : null; if (name == null || !name.equals(this.name)) {
setChanged(); this.name = (name != null && !name.equals("")) ? name : null;
setChanged();
}
} }
/** /**
@ -1130,9 +1145,11 @@ public class Island implements DataObject, MetaDataAble {
* @param protectionRange the protectionRange to set * @param protectionRange the protectionRange to set
*/ */
public void setProtectionRange(int protectionRange) { public void setProtectionRange(int protectionRange) {
this.protectionRange = protectionRange; if (this.protectionRange != protectionRange) {
this.updateMaxEverProtectionRange(); this.protectionRange = protectionRange;
setChanged(); this.updateMaxEverProtectionRange();
setChanged();
}
} }
/** /**
@ -1164,8 +1181,10 @@ public class Island implements DataObject, MetaDataAble {
* @param purgeProtected - if the island is protected from the Purge * @param purgeProtected - if the island is protected from the Purge
*/ */
public void setPurgeProtected(boolean purgeProtected) { public void setPurgeProtected(boolean purgeProtected) {
this.purgeProtected = purgeProtected; if (this.purgeProtected != purgeProtected) {
setChanged(); this.purgeProtected = purgeProtected;
setChanged();
}
} }
/** /**
@ -1179,8 +1198,10 @@ public class Island implements DataObject, MetaDataAble {
* @see #setProtectionRange(int) * @see #setProtectionRange(int)
*/ */
public void setRange(int range) { public void setRange(int range) {
this.range = range; if (this.range != range) {
setChanged(); this.range = range;
setChanged();
}
} }
/** /**
@ -1191,7 +1212,6 @@ public class Island implements DataObject, MetaDataAble {
*/ */
public void setRank(User user, int rank) { public void setRank(User user, int rank) {
setRank(user.getUniqueId(), rank); setRank(user.getUniqueId(), rank);
setChanged();
} }
/** /**
@ -1202,14 +1222,33 @@ public class Island implements DataObject, MetaDataAble {
* @param rank rank value * @param rank rank value
* @since 1.1 * @since 1.1
*/ */
public void setRank(@Nullable UUID uuid, int rank) { public void setRank(@Nullable UUID uuid, int newRank) {
// Early return if the UUID is null, to avoid unnecessary processing.
if (uuid == null) { if (uuid == null) {
return; // Defensive code return;
}
// Use an AtomicBoolean to track if the member's rank has been changed.
AtomicBoolean isRankChanged = new AtomicBoolean(false);
// Attempt to update the member's rank, if necessary.
members.compute(uuid, (key, existingRank) -> {
// If the member does not exist or their rank is different, update the rank.
if (existingRank == null || existingRank != newRank) {
isRankChanged.set(true);
return newRank; // Update the rank.
}
// No change needed; return the existing rank.
return existingRank;
});
// If the rank was changed, notify the change and log the update.
if (isRankChanged.get()) {
setChanged(); // Notify that a change has occurred.
} }
members.put(uuid, rank);
setChanged();
} }
/** /**
* @param ranks the ranks to set * @param ranks the ranks to set
*/ */
@ -1266,7 +1305,6 @@ public class Island implements DataObject, MetaDataAble {
@Override @Override
public void setUniqueId(String uniqueId) { public void setUniqueId(String uniqueId) {
this.uniqueId = uniqueId; this.uniqueId = uniqueId;
setChanged();
} }
/** /**
@ -1274,7 +1312,6 @@ public class Island implements DataObject, MetaDataAble {
*/ */
public void setUpdatedDate(long updatedDate) { public void setUpdatedDate(long updatedDate) {
this.updatedDate = updatedDate; this.updatedDate = updatedDate;
setChanged();
} }
/** /**
@ -1347,8 +1384,13 @@ public class Island implements DataObject, MetaDataAble {
* @param l - location * @param l - location
*/ */
public void setSpawnPoint(Environment islandType, Location l) { public void setSpawnPoint(Environment islandType, Location l) {
spawnPoint.put(islandType, l); spawnPoint.compute(islandType, (key, value) -> {
setChanged(); if (value == null || !value.equals(l)) {
setChanged(); // Call setChanged only if the value is updated.
return l;
}
return value;
});
} }
/** /**
@ -1368,8 +1410,9 @@ public class Island implements DataObject, MetaDataAble {
* @param rank rank value * @param rank rank value
*/ */
public void removeRank(Integer rank) { public void removeRank(Integer rank) {
members.values().removeIf(rank::equals); if (members.values().removeIf(rank::equals)) {
setChanged(); setChanged();
}
} }
/** /**
@ -1455,7 +1498,6 @@ public class Island implements DataObject, MetaDataAble {
*/ */
public void setGameMode(String gameMode) { public void setGameMode(String gameMode) {
this.gameMode = gameMode; this.gameMode = gameMode;
setChanged();
} }
/** /**
@ -1518,8 +1560,9 @@ public class Island implements DataObject, MetaDataAble {
if (cooldowns.containsKey(flag.getID()) && cooldowns.get(flag.getID()) > System.currentTimeMillis()) { if (cooldowns.containsKey(flag.getID()) && cooldowns.get(flag.getID()) > System.currentTimeMillis()) {
return true; return true;
} }
cooldowns.remove(flag.getID()); if (cooldowns.remove(flag.getID()) != null) {
setChanged(); setChanged();
}
return false; return false;
} }
@ -1603,8 +1646,13 @@ public class Island implements DataObject, MetaDataAble {
public void setRankCommand(String command, int rank) { public void setRankCommand(String command, int rank) {
if (this.commandRanks == null) if (this.commandRanks == null)
this.commandRanks = new HashMap<>(); this.commandRanks = new HashMap<>();
this.commandRanks.put(command, rank); commandRanks.compute(command, (key, value) -> {
setChanged(); if (value == null || !value.equals(rank)) {
setChanged(); // Call setChanged only if the value is updated.
return rank;
}
return value;
});
} }
/** /**
@ -1624,8 +1672,10 @@ public class Island implements DataObject, MetaDataAble {
* @since 1.6.0 * @since 1.6.0
*/ */
public void setReserved(boolean reserved) { public void setReserved(boolean reserved) {
this.reserved = reserved; if (this.reserved != reserved) {
setChanged(); this.reserved = reserved;
setChanged();
}
} }
/** /**
@ -1658,17 +1708,19 @@ public class Island implements DataObject, MetaDataAble {
} }
/** /**
* Indicates the fields have been changed. Used to optimize saving on shutdown. * Indicates the fields have been changed. Used to optimize saving on shutdown and notify other servers
*/ */
public void setChanged() { public void setChanged() {
this.setUpdatedDate(System.currentTimeMillis());
this.changed = true; this.changed = true;
IslandsManager.updateIsland(this);
} }
/** /**
* @param changed the changed to set * Resets the changed if the island has been saved
*/ */
public void setChanged(boolean changed) { public void clearChanged() {
this.changed = changed; this.changed = false;
} }
/** /**
@ -1692,6 +1744,9 @@ public class Island implements DataObject, MetaDataAble {
* @since 1.16.0 * @since 1.16.0
*/ */
public void setProtectionCenter(Location location) throws IOException { public void setProtectionCenter(Location location) throws IOException {
if (this.location.equals(location)) {
return; // nothing to do
}
if (!this.inIslandSpace(location)) { if (!this.inIslandSpace(location)) {
throw new IOException("Location must be in island space"); throw new IOException("Location must be in island space");
} }
@ -1741,6 +1796,9 @@ public class Island implements DataObject, MetaDataAble {
* @since 1.16.0 * @since 1.16.0
*/ */
public void addHome(String name, Location location) { public void addHome(String name, Location location) {
if (getHomes().containsKey(name) && getHomes().get(name).equals(location)) {
return; // nothing to do
}
if (location != null) { if (location != null) {
Vector v = location.toVector(); Vector v = location.toVector();
if (!this.getBoundingBox().contains(v)) { if (!this.getBoundingBox().contains(v)) {
@ -1763,8 +1821,11 @@ public class Island implements DataObject, MetaDataAble {
* @since 1.16.0 * @since 1.16.0
*/ */
public boolean removeHome(String name) { public boolean removeHome(String name) {
setChanged(); if (getHomes().remove(name.toLowerCase()) != null) {
return getHomes().remove(name.toLowerCase()) != null; setChanged();
return true;
}
return false;
} }
/** /**
@ -1774,8 +1835,11 @@ public class Island implements DataObject, MetaDataAble {
* @since 1.20.0 * @since 1.20.0
*/ */
public boolean removeHomes() { public boolean removeHomes() {
setChanged(); if (getHomes().keySet().removeIf(k -> !k.isEmpty())) {
return getHomes().keySet().removeIf(k -> !k.isEmpty()); setChanged();
return true;
}
return false;
} }
/** /**
@ -1814,8 +1878,10 @@ public class Island implements DataObject, MetaDataAble {
* @since 1.16.0 * @since 1.16.0
*/ */
public void setMaxHomes(@Nullable Integer maxHomes) { public void setMaxHomes(@Nullable Integer maxHomes) {
this.maxHomes = maxHomes; if (this.maxHomes != maxHomes) {
setChanged(); this.maxHomes = maxHomes;
setChanged();
}
} }
/** /**
@ -1834,8 +1900,10 @@ public class Island implements DataObject, MetaDataAble {
* @since 1.16.0 * @since 1.16.0
*/ */
public void setMaxMembers(Map<Integer, Integer> maxMembers) { public void setMaxMembers(Map<Integer, Integer> maxMembers) {
this.maxMembers = maxMembers; if (this.maxMembers != maxMembers) {
setChanged(); this.maxMembers = maxMembers;
setChanged();
}
} }
/** /**
@ -1860,7 +1928,13 @@ public class Island implements DataObject, MetaDataAble {
* @since 1.16.0 * @since 1.16.0
*/ */
public void setMaxMembers(int rank, Integer maxMembers) { public void setMaxMembers(int rank, Integer maxMembers) {
getMaxMembers().put(rank, maxMembers); getMaxMembers().compute(rank, (key, value) -> {
if (value == null || !value.equals(maxMembers)) {
setChanged(); // Call setChanged only if the value is updated.
return maxMembers;
}
return value;
});
} }
/** /**
@ -1923,8 +1997,9 @@ public class Island implements DataObject, MetaDataAble {
* @param id id to identify this bonus * @param id id to identify this bonus
*/ */
public void clearBonusRange(String id) { public void clearBonusRange(String id) {
this.getBonusRanges().removeIf(r -> r.getUniqueId().equals(id)); if (this.getBonusRanges().removeIf(r -> r.getUniqueId().equals(id))) {
setChanged(); setChanged();
}
} }
/** /**
@ -1936,18 +2011,30 @@ public class Island implements DataObject, MetaDataAble {
} }
/** /**
* @param userID user UUID
* @return the primary * @return the primary
*/ */
public boolean isPrimary() { public boolean isPrimary(UUID userID) {
return primary; return getPrimaries().contains(userID);
} }
/** /**
* @param primary the primary to set * @param primary the primary to set
*/ */
public void setPrimary(boolean primary) { public void setPrimary(UUID userID) {
this.primary = primary; if (getPrimaries().add(userID)) {
setChanged(); setChanged();
}
}
/**
* Remove the primary island
* @param userID user UUID
*/
public void removePrimary(UUID userID) {
if (getPrimaries().remove(userID)) {
setChanged();
}
} }
/** /**
@ -1986,4 +2073,41 @@ public class Island implements DataObject, MetaDataAble {
+ commandRanks + ", reserved=" + reserved + ", metaData=" + metaData + ", homes=" + homes + commandRanks + ", reserved=" + reserved + ", metaData=" + metaData + ", homes=" + homes
+ ", maxHomes=" + maxHomes + "]"; + ", maxHomes=" + maxHomes + "]";
} }
/**
* @return the primaries
*/
public Set<UUID> getPrimaries() {
if (primaries == null) {
primaries = new HashSet<>();
}
return primaries;
}
/**
* @param primaries the primaries to set
*/
public void setPrimaries(Set<UUID> primaries) {
this.primaries = primaries;
setChanged();
}
@Override
public int hashCode() {
return Objects.hash(uniqueId);
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Island other = (Island) obj;
return Objects.equals(uniqueId, other.uniqueId);
}
} }

View File

@ -6,13 +6,10 @@ import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.stream.Collectors;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.eclipse.jdt.annotation.Nullable;
import com.google.gson.annotations.Expose; import com.google.gson.annotations.Expose;
@ -30,8 +27,6 @@ import world.bentobox.bentobox.util.Util;
*/ */
@Table(name = "Players") @Table(name = "Players")
public class Players implements DataObject, MetaDataAble { public class Players implements DataObject, MetaDataAble {
@Expose
private Map<Location, Integer> homeLocations = new HashMap<>();
@Expose @Expose
private String uniqueId; private String uniqueId;
@Expose @Expose
@ -77,7 +72,6 @@ public class Players implements DataObject, MetaDataAble {
*/ */
public Players(BentoBox plugin, UUID uniqueId) { public Players(BentoBox plugin, UUID uniqueId) {
this.uniqueId = uniqueId.toString(); this.uniqueId = uniqueId.toString();
homeLocations = new HashMap<>();
locale = ""; locale = "";
// Try to get player's name // Try to get player's name
this.playerName = Bukkit.getOfflinePlayer(uniqueId).getName(); this.playerName = Bukkit.getOfflinePlayer(uniqueId).getName();
@ -86,72 +80,6 @@ public class Players implements DataObject, MetaDataAble {
} }
} }
/**
* Gets the default home location.
* @param world - world to check
* @return Location - home location in world
* @deprecated Homes are stored in the Island object now
*/
@Deprecated(since="1.18.0", forRemoval=true)
@Nullable
public Location getHomeLocation(World world) {
return getHomeLocation(world, 1); // Default
}
/**
* Gets the home location by number for world
* @param world - includes world and any related nether or end worlds
* @param number - a number
* @return Location of this home or null if not available
* @deprecated Homes are stored in the island object now
*/
@Deprecated(since="1.18.0", forRemoval=true)
@Nullable
public Location getHomeLocation(World world, int number) {
// Remove any lost worlds/locations
homeLocations.keySet().removeIf(l -> l == null || l.getWorld() == null);
return homeLocations.entrySet().stream()
.filter(en -> Util.sameWorld(en.getKey().getWorld(), world) && en.getValue() == number)
.map(Map.Entry::getKey)
.findFirst()
.orElse(null);
}
/**
* @param world - world
* @return Map of home locations
* @deprecated Homes are stored in the island object now
*/
@Deprecated(since="1.18.0", forRemoval=true)
public Map<Location, Integer> getHomeLocations(World world) {
// Remove any lost worlds/locations
homeLocations.keySet().removeIf(l -> l == null || l.getWorld() == null);
return homeLocations.entrySet().stream().filter(e -> Util.sameWorld(e.getKey().getWorld(),world))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
}
/**
* @return the homeLocations
* @deprecated Homes are stored in the Island object now
*/
@Deprecated(since="1.18.0", forRemoval=true)
public Map<Location, Integer> getHomeLocations() {
// Remove any lost worlds/locations
homeLocations.keySet().removeIf(l -> l == null || l.getWorld() == null);
return homeLocations;
}
/**
* @param homeLocations the homeLocations to set
* @deprecated Homes are stored in the Island object now
*/
@Deprecated(since="1.18.0", forRemoval=true)
public void setHomeLocations(Map<Location, Integer> homeLocations) {
this.homeLocations = homeLocations;
// Remove any lost worlds/locations
homeLocations.keySet().removeIf(l -> l == null || l.getWorld() == null);
}
/** /**
* @param playerName the playerName to set * @param playerName the playerName to set
*/ */
@ -202,30 +130,6 @@ public class Players implements DataObject, MetaDataAble {
this.resets.put(world.getName(), resets); this.resets.put(world.getName(), resets);
} }
/**
* Stores the home location of the player in a String format
*
* @param l a Bukkit location
* @deprecated Home locations are stored in islands
*/
@Deprecated(since="1.18.0", forRemoval=true)
public void setHomeLocation(final Location l) {
setHomeLocation(l, 1);
}
/**
* Stores the numbered home location of the player. Numbering starts at 1.
* @param location - the location
* @param number - a number
* @deprecated Home locations are no longer stored for players. They are stored in islands.
*/
@Deprecated(since="1.18.0", forRemoval=true)
public void setHomeLocation(Location location, int number) {
// Remove any home locations in the same world with the same number
homeLocations.entrySet().removeIf(e -> e.getKey() == null || (Util.sameWorld(location.getWorld(), e.getKey().getWorld()) && e.getValue().equals(number)));
homeLocations.put(location, number);
}
/** /**
* Set the uuid for this player object * Set the uuid for this player object
* @param uuid - UUID * @param uuid - UUID
@ -234,16 +138,6 @@ public class Players implements DataObject, MetaDataAble {
uniqueId = uuid.toString(); uniqueId = uuid.toString();
} }
/**
* Clears all home Locations in world
* @param world - world
* @deprecated Home locations are no longer stored for players. Use {@link world.bentobox.bentobox.managers.IslandsManager}
*/
@Deprecated(since="1.18.0", forRemoval=true)
public void clearHomeLocations(World world) {
homeLocations.keySet().removeIf(l -> l == null || l.getWorld() == null || Util.sameWorld(l.getWorld(), world));
}
/** /**
* @return the locale * @return the locale
*/ */
@ -350,24 +244,6 @@ public class Players implements DataObject, MetaDataAble {
} }
} }
/**
* Returns the display mode for the Flags in the Settings Panel.
* @return the display mode for the Flags in the Settings Panel.
* @since 1.6.0
*/
public Flag.Mode getFlagsDisplayMode() {
return flagsDisplayMode;
}
/**
* Sets the display mode for the Flags in the Settings Panel.
* @param flagsDisplayMode the display mode for the Flags in the Settings Panel.
* @since 1.6.0
*/
public void setFlagsDisplayMode(Flag.Mode flagsDisplayMode) {
this.flagsDisplayMode = flagsDisplayMode;
}
/** /**
* @return the metaData * @return the metaData
* @since 1.15.5 * @since 1.15.5

View File

@ -0,0 +1,112 @@
package world.bentobox.bentobox.database.objects;
import java.util.Objects;
import java.util.UUID;
import com.google.gson.annotations.Expose;
/**
* Data object for team invites
*/
@Table(name = "TeamInvites")
public class TeamInvite implements DataObject {
/**
* Type of invitation
*
*/
public enum Type {
COOP,
TEAM,
TRUST
}
@Expose
private Type type;
@Expose
private UUID inviter;
@Expose
private String islandID;
@Expose
private String uniqueId;
/**
* @param type - invitation type, e.g., coop, team, trust
* @param inviter - UUID of inviter
* @param invitee - UUID of invitee
* @param island - the unique ID of the island this invite is for
*/
public TeamInvite(Type type, UUID inviter, UUID invitee, String islandID) {
this.type = type;
this.uniqueId = invitee.toString();
this.inviter = inviter;
this.islandID = islandID;
}
@Override
public String getUniqueId() {
// Inviter
return this.uniqueId;
}
@Override
public void setUniqueId(String uniqueId) {
this.uniqueId = uniqueId;
}
/**
* @return the type
*/
public Type getType() {
return type;
}
/**
* @return the invitee
*/
public UUID getInvitee() {
return UUID.fromString(uniqueId);
}
/**
* @return the inviter
*/
public UUID getInviter() {
return inviter;
}
/**
* @return the islandID
*/
public String getIslandID() {
return islandID;
}
/* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
return Objects.hash(inviter, uniqueId, type);
}
/* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (!(obj instanceof TeamInvite other)) {
return false;
}
return Objects.equals(inviter, other.inviter) && Objects.equals(uniqueId, other.getUniqueId())
&& type == other.type;
}
}

View File

@ -2,6 +2,7 @@ package world.bentobox.bentobox.listeners;
import java.util.Collections; import java.util.Collections;
import java.util.Objects; import java.util.Objects;
import java.util.Set;
import java.util.UUID; import java.util.UUID;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
@ -61,7 +62,7 @@ public class JoinLeaveListener implements Listener {
// Make sure the player is loaded into the cache or create the player if they // Make sure the player is loaded into the cache or create the player if they
// don't exist // don't exist
players.addPlayer(playerUUID); players.getPlayer(playerUUID);
// Reset island resets if required // Reset island resets if required
plugin.getIWM().getOverWorlds().stream() plugin.getIWM().getOverWorlds().stream()
@ -74,7 +75,6 @@ public class JoinLeaveListener implements Listener {
// Set the player's name (it may have changed), but only if it isn't empty // Set the player's name (it may have changed), but only if it isn't empty
if (!user.getName().isEmpty()) { if (!user.getName().isEmpty()) {
players.setPlayerName(user); players.setPlayerName(user);
players.save(playerUUID);
} else { } else {
plugin.logWarning("Player that just logged in has no name! " + playerUUID); plugin.logWarning("Player that just logged in has no name! " + playerUUID);
} }
@ -110,7 +110,7 @@ public class JoinLeaveListener implements Listener {
private void firstTime(User user) { private void firstTime(User user) {
// Make sure the player is loaded into the cache or create the player if they // Make sure the player is loaded into the cache or create the player if they
// don't exist // don't exist
players.addPlayer(user.getUniqueId()); players.getPlayer(user.getUniqueId());
plugin.getIWM().getOverWorlds().stream().filter(w -> plugin.getIWM().isCreateIslandOnFirstLoginEnabled(w)) plugin.getIWM().getOverWorlds().stream().filter(w -> plugin.getIWM().isCreateIslandOnFirstLoginEnabled(w))
.forEach(w -> { .forEach(w -> {
@ -181,8 +181,10 @@ public class JoinLeaveListener implements Listener {
user.getPlayer().getInventory().clear(); user.getPlayer().getInventory().clear();
} }
playerData.getPendingKicks().remove(world.getName()); Set<String> kicks = playerData.getPendingKicks();
players.save(user.getUniqueId()); kicks.remove(world.getName());
playerData.setPendingKicks(kicks);
} }
} }
@ -236,7 +238,6 @@ public class JoinLeaveListener implements Listener {
}); });
// Remove any coop associations from the player logging out // Remove any coop associations from the player logging out
plugin.getIslands().clearRank(RanksManager.COOP_RANK, event.getPlayer().getUniqueId()); plugin.getIslands().clearRank(RanksManager.COOP_RANK, event.getPlayer().getUniqueId());
players.save(event.getPlayer().getUniqueId());
User.removePlayer(event.getPlayer()); User.removePlayer(event.getPlayer());
} }
} }

View File

@ -61,6 +61,7 @@ public class PanelListenerManager implements Listener {
// Refresh // Refresh
l.refreshPanel(); l.refreshPanel();
}); });
} else { } else {
// Wrong name - delete this panel // Wrong name - delete this panel
openPanels.remove(user.getUniqueId()); openPanels.remove(user.getUniqueId());

View File

@ -60,9 +60,6 @@ public class CommandCycleClick implements ClickHandler {
} }
// Apply change to panel // Apply change to panel
panel.getInventory().setItem(slot, commandRankClickListener.getPanelItem(command, user, world).getItem()); panel.getInventory().setItem(slot, commandRankClickListener.getPanelItem(command, user, world).getItem());
// Save island
plugin.getIslands().save(island);
} else { } else {
user.getPlayer().playSound(user.getLocation(), Sound.BLOCK_METAL_HIT, 1F, 1F); user.getPlayer().playSound(user.getLocation(), Sound.BLOCK_METAL_HIT, 1F, 1F);
} }

View File

@ -37,6 +37,10 @@ import org.bukkit.util.Vector;
import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jdt.annotation.Nullable;
import com.github.puregero.multilib.MultiLib;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import io.papermc.lib.PaperLib; import io.papermc.lib.PaperLib;
import world.bentobox.bentobox.BentoBox; import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.api.events.IslandBaseEvent; import world.bentobox.bentobox.api.events.IslandBaseEvent;
@ -44,9 +48,9 @@ import world.bentobox.bentobox.api.events.island.IslandEvent;
import world.bentobox.bentobox.api.events.island.IslandEvent.Reason; import world.bentobox.bentobox.api.events.island.IslandEvent.Reason;
import world.bentobox.bentobox.api.flags.Flag; import world.bentobox.bentobox.api.flags.Flag;
import world.bentobox.bentobox.api.localization.TextVariables; import world.bentobox.bentobox.api.localization.TextVariables;
import world.bentobox.bentobox.api.logs.LogEntry;
import world.bentobox.bentobox.api.user.User; import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.database.Database; import world.bentobox.bentobox.database.Database;
import world.bentobox.bentobox.database.json.BentoboxTypeAdapterFactory;
import world.bentobox.bentobox.database.objects.Island; import world.bentobox.bentobox.database.objects.Island;
import world.bentobox.bentobox.database.objects.IslandDeletion; import world.bentobox.bentobox.database.objects.IslandDeletion;
import world.bentobox.bentobox.lists.Flags; import world.bentobox.bentobox.lists.Flags;
@ -65,29 +69,18 @@ public class IslandsManager {
private final BentoBox plugin; private final BentoBox plugin;
/** private Map<World, Island> spawns = new HashMap<>();
* One island can be spawn, this is the one - otherwise, this value is null
*/ private Map<World, Location> last = new HashMap<>();
@NonNull
private final Map<@NonNull World, @Nullable Island> spawn;
@NonNull @NonNull
private Database<Island> handler; private static Database<Island> handler;
/**
* The last locations where an island were put. This is not stored persistently
* and resets when the server starts
*/
private final Map<World, Location> last;
/** /**
* Island Cache * Island Cache
*/ */
@NonNull @NonNull
private IslandCache islandCache; private IslandCache islandCache;
// Quarantined islands
@NonNull
private final Map<UUID, List<Island>> quarantineCache;
// Deleted islands // Deleted islands
@NonNull @NonNull
private final List<String> deletedIslands; private final List<String> deletedIslands;
@ -106,14 +99,47 @@ public class IslandsManager {
// Set up the database handler to store and retrieve Island classes // Set up the database handler to store and retrieve Island classes
handler = new Database<>(plugin, Island.class); handler = new Database<>(plugin, Island.class);
islandCache = new IslandCache(); islandCache = new IslandCache();
quarantineCache = new HashMap<>();
spawn = new HashMap<>();
last = new HashMap<>();
// This list should always be empty unless database deletion failed // This list should always be empty unless database deletion failed
// In that case a purge utility may be required in the future // In that case a purge utility may be required in the future
deletedIslands = new ArrayList<>(); deletedIslands = new ArrayList<>();
// Mid-teleport players going home // Mid-teleport players going home
goingHome = new HashSet<>(); goingHome = new HashSet<>();
// Set handler in Island
// Listen for Island Updates
MultiLib.onString(plugin, "bentobox-updateIsland", id -> {
Island island = handler.loadObject(id);
if (island != null) {
islandCache.updateIsland(island);
}
});
// Delete island blocks
MultiLib.onString(plugin, "bentobox-deleteIsland", id -> {
IslandDeletion idd = getGson().fromJson(id, IslandDeletion.class);
plugin.getIslandDeletionManager().getIslandChunkDeletionManager().add(idd);
});
// List for new islands
MultiLib.onString(plugin, "bentobox-newIsland", id -> {
Island island = handler.loadObject(id);
if (island != null) {
islandCache.addIsland(island);
}
});
// Set or clear spawn
MultiLib.onString(plugin, "bentobox-setspawn", sp -> {
String[] split = sp.split(",");
if (split.length == 1) {
World world = Bukkit.getWorld(split[0]);
this.clearSpawn(world);
} else if (split.length == 2) {
World world = Bukkit.getWorld(split[0]);
if (world != null) {
getIslandById(split[1]).ifPresent(i -> this.setSpawn(i));
}
}
});
} }
/** /**
@ -121,8 +147,8 @@ public class IslandsManager {
* *
* @param handler - handler * @param handler - handler
*/ */
public void setHandler(@NonNull Database<Island> handler) { public void setHandler(@NonNull Database<Island> h) {
this.handler = handler; handler = h;
} }
/** /**
@ -227,14 +253,13 @@ public class IslandsManager {
.orElse(""); .orElse("");
island.setGameMode(gmName); island.setGameMode(gmName);
island.setUniqueId(gmName + island.getUniqueId()); island.setUniqueId(gmName + island.getUniqueId());
while (handler.objectExists(island.getUniqueId())) {
// This should never happen, so although this is a potential infinite loop I'm
// going to leave it here because
// it will be bad if this does occur and the server should crash.
plugin.logWarning("Duplicate island UUID occurred");
island.setUniqueId(gmName + UUID.randomUUID());
}
if (islandCache.addIsland(island)) { if (islandCache.addIsland(island)) {
// Save to database and notify other servers
handler.saveObjectAsync(island).thenAccept(b -> {
if (b.equals(Boolean.TRUE)) {
MultiLib.notify("bentobox-newIsland", island.getUniqueId());
}
});
return island; return island;
} }
return null; return null;
@ -257,27 +282,40 @@ public class IslandsManager {
// Set the owner of the island to no one. // Set the owner of the island to no one.
island.setOwner(null); island.setOwner(null);
island.setFlag(Flags.LOCK, RanksManager.VISITOR_RANK); island.setFlag(Flags.LOCK, RanksManager.VISITOR_RANK);
island.setDeleted(true);
if (removeBlocks) { if (removeBlocks) {
// Remove island from the cache // Remove island from the cache
islandCache.deleteIslandFromCache(island); islandCache.deleteIslandFromCache(island);
// Log the deletion (it shouldn't matter but may be useful)
island.log(new LogEntry.Builder("DELETED").build());
// Set the delete flag which will prevent it from being loaded even if database
// deletion fails
island.setDeleted(true);
// Save the island
handler.saveObjectAsync(island);
// Delete the island
handler.deleteObject(island);
// Remove players from island // Remove players from island
removePlayersFromIsland(island); removePlayersFromIsland(island);
if (!plugin.getSettings().isKeepPreviousIslandOnReset()) { if (!plugin.getSettings().isKeepPreviousIslandOnReset()) {
// Remove blocks from world // Remove blocks from world
plugin.getIslandDeletionManager().getIslandChunkDeletionManager().add(new IslandDeletion(island)); IslandDeletion id = new IslandDeletion(island);
plugin.getIslandDeletionManager().getIslandChunkDeletionManager().add(id);
// Tell other servers
MultiLib.notify("bentobox-deleteIsland", getGson().toJson(id));
} }
// Delete the island from the database
handler.deleteObject(island);
} }
} }
private Gson getGson() {
// Build the Gson
// excludeFieldsWithoutExposeAnnotation - this means that every field to be stored should use @Expose
// enableComplexMapKeySerialization - forces GSON to use TypeAdapters even for Map keys
GsonBuilder builder = new GsonBuilder().excludeFieldsWithoutExposeAnnotation()
.enableComplexMapKeySerialization().setPrettyPrinting();
// Register adapter factory
builder.registerTypeAdapterFactory(new BentoboxTypeAdapterFactory(plugin));
// Allow characters like < or > without escaping them
builder.disableHtmlEscaping();
return builder.create();
}
/** /**
* Get the number of islands made on this server. Used by stats. * Get the number of islands made on this server. Used by stats.
* *
@ -462,7 +500,7 @@ public class IslandsManager {
* Get the last location where an island was created * Get the last location where an island was created
* *
* @param world - world * @param world - world
* @return location * @return location or null if none found
*/ */
public Location getLast(@NonNull World world) { public Location getLast(@NonNull World world) {
return last.get(world); return last.get(world);
@ -486,7 +524,7 @@ public class IslandsManager {
if (island.getOwner() == null) { if (island.getOwner() == null) {
// No owner, no rank settings // No owner, no rank settings
island.setMaxMembers(null); island.setMaxMembers(null);
this.save(island); updateIsland(island);
return 0; return 0;
} }
// Island max is either the world default or specified amount for this island // Island max is either the world default or specified amount for this island
@ -507,8 +545,11 @@ public class IslandsManager {
islandMax = owner.getPermissionValue(plugin.getIWM().getPermissionPrefix(island.getWorld()) + perm, islandMax = owner.getPermissionValue(plugin.getIWM().getPermissionPrefix(island.getWorld()) + perm,
islandMax); islandMax);
} }
island.setMaxMembers(rank, islandMax == worldDefault ? null : islandMax); Integer change = islandMax == worldDefault ? null : islandMax;
this.save(island); if (island.getMaxMembers().get(rank) != change) {
island.setMaxMembers(rank, change);
updateIsland(island);
}
return islandMax; return islandMax;
} }
@ -546,13 +587,16 @@ public class IslandsManager {
} }
// If the island maxHomes is just the same as the world default, then set to // If the island maxHomes is just the same as the world default, then set to
// null // null
island.setMaxHomes(islandMax == plugin.getIWM().getMaxHomes(island.getWorld()) ? null : islandMax); Integer change = islandMax == plugin.getIWM().getMaxHomes(island.getWorld()) ? null : islandMax;
this.save(island); if (island.getMaxHomes() != change) {
island.setMaxHomes(change);
updateIsland(island);
}
return islandMax; return islandMax;
} }
/** /**
* Set the maximum numbber of homes allowed on this island * Set the maximum number of homes allowed on this island
* *
* @param island - island * @param island - island
* @param maxHomes - max number of homes allowed, or null if the world default * @param maxHomes - max number of homes allowed, or null if the world default
@ -735,9 +779,9 @@ public class IslandsManager {
* @since 1.16.0 * @since 1.16.0
*/ */
public boolean setHomeLocation(@Nullable Island island, Location location, String name) { public boolean setHomeLocation(@Nullable Island island, Location location, String name) {
if (island != null) { if (island != null && (island.getHome(name) == null || !island.getHome(name).equals(location))) {
island.addHome(name, location); island.addHome(name, location);
this.save(island); updateIsland(island);
return true; return true;
} }
return false; return false;
@ -890,7 +934,7 @@ public class IslandsManager {
*/ */
@NonNull @NonNull
public Optional<Island> getSpawn(@NonNull World world) { public Optional<Island> getSpawn(@NonNull World world) {
return Optional.ofNullable(spawn.get(world)); return Optional.ofNullable(spawns.get(world));
} }
/** /**
@ -901,7 +945,7 @@ public class IslandsManager {
*/ */
@Nullable @Nullable
public Location getSpawnPoint(@NonNull World world) { public Location getSpawnPoint(@NonNull World world) {
return spawn.containsKey(world) ? spawn.get(world).getSpawnPoint(world.getEnvironment()) : null; return getSpawn(world).map(i -> i.getSpawnPoint(world.getEnvironment())).orElse(null);
} }
/** /**
@ -1132,7 +1176,7 @@ public class IslandsManager {
* @return true if they are, false if they are not, or spawn does not exist * @return true if they are, false if they are not, or spawn does not exist
*/ */
public boolean isAtSpawn(Location playerLoc) { public boolean isAtSpawn(Location playerLoc) {
return spawn.containsKey(playerLoc.getWorld()) && spawn.get(playerLoc.getWorld()).onIsland(playerLoc); return getSpawn(playerLoc.getWorld()).map(i -> i.onIsland(playerLoc)).orElse(false);
} }
/** /**
@ -1144,19 +1188,14 @@ public class IslandsManager {
* @param spawn the Island to set as spawn. Must not be null. * @param spawn the Island to set as spawn. Must not be null.
*/ */
public void setSpawn(@NonNull Island spawn) { public void setSpawn(@NonNull Island spawn) {
// Checking if there is already a spawn set for this world if (spawn.getWorld() != null) {
if (this.spawn.containsKey(spawn.getWorld()) && this.spawn.get(spawn.getWorld()) != null) { spawns.put(Util.getWorld(spawn.getWorld()), spawn);
Island oldSpawn = this.spawn.get(spawn.getWorld()); // Tell other servers
if (oldSpawn.equals(spawn)) { MultiLib.notify("bentobox-setspawn", spawn.getWorld().getUID().toString() + "," + spawn.getUniqueId());
return; // The spawn is already the current spawn - no need to update anything.
} else {
oldSpawn.setSpawn(false);
}
} }
this.spawn.put(spawn.getWorld(), spawn);
spawn.setSpawn(true);
} }
/** /**
* Clears the spawn island for this world * Clears the spawn island for this world
* *
@ -1164,11 +1203,9 @@ public class IslandsManager {
* @since 1.8.0 * @since 1.8.0
*/ */
public void clearSpawn(World world) { public void clearSpawn(World world) {
Island spawnIsland = spawn.get(Util.getWorld(world)); spawns.remove(world);
if (spawnIsland != null) { // Tell other servers
spawnIsland.setSpawn(false); MultiLib.notify("bentobox-setspawn", world.getUID().toString());
}
this.spawn.remove(world);
} }
/** /**
@ -1192,7 +1229,6 @@ public class IslandsManager {
*/ */
public void load() throws IOException { public void load() throws IOException {
islandCache.clear(); islandCache.clear();
quarantineCache.clear();
List<Island> toQuarantine = new ArrayList<>(); List<Island> toQuarantine = new ArrayList<>();
int owned = 0; int owned = 0;
int unowned = 0; int unowned = 0;
@ -1206,9 +1242,6 @@ public class IslandsManager {
if (island.isDeleted()) { if (island.isDeleted()) {
// These will be deleted later // These will be deleted later
deletedIslands.add(island.getUniqueId()); deletedIslands.add(island.getUniqueId());
} else if (island.isDoNotLoad() && island.getWorld() != null && island.getCenter() != null) {
// Add to quarantine cache
quarantineCache.computeIfAbsent(island.getOwner(), k -> new ArrayList<>()).add(island);
} // Check island distance and if incorrect stop BentoBox } // Check island distance and if incorrect stop BentoBox
else if (island.getWorld() != null && plugin.getIWM().inWorld(island.getWorld()) else if (island.getWorld() != null && plugin.getIWM().inWorld(island.getWorld())
&& island.getRange() != plugin.getIWM().getIslandDistance(island.getWorld())) { && island.getRange() != plugin.getIWM().getIslandDistance(island.getWorld())) {
@ -1219,18 +1252,9 @@ public class IslandsManager {
} else { } else {
// Fix island center if it is off // Fix island center if it is off
fixIslandCenter(island); fixIslandCenter(island);
if (!islandCache.addIsland(island)) { islandCache.addIsland(island);
// Quarantine the offending island
toQuarantine.add(island); if (island.isSpawn()) {
// Add to quarantine cache
island.setDoNotLoad(true);
quarantineCache.computeIfAbsent(island.getOwner(), k -> new ArrayList<>()).add(island);
if (island.isUnowned()) {
unowned++;
} else {
owned++;
}
} else if (island.isSpawn()) {
// Success, set spawn if this is the spawn island. // Success, set spawn if this is the spawn island.
this.setSpawn(island); this.setSpawn(island);
} else { } else {
@ -1394,15 +1418,10 @@ public class IslandsManager {
homeTeleportAsync(w, p); homeTeleportAsync(w, p);
} else { } else {
// Move player to spawn // Move player to spawn
if (spawn.containsKey(w)) { getSpawn(w).map(i -> i.getSpawnPoint(w.getEnvironment())).filter(Objects::nonNull)
// go to island spawn .ifPresentOrElse(sp -> PaperLib.teleportAsync(p, sp),
Location sp = spawn.get(w).getSpawnPoint(w.getEnvironment()); () -> plugin.logWarning("Spawn exists but its location is null!"));
if (sp != null) {
PaperLib.teleportAsync(p, sp);
} else {
plugin.logWarning("Spawn exists but its location is null!");
}
}
} }
}); });
} }
@ -1473,9 +1492,13 @@ public class IslandsManager {
teamIsland.addMember(playerUUID); teamIsland.addMember(playerUUID);
islandCache.addPlayer(playerUUID, teamIsland); islandCache.addPlayer(playerUUID, teamIsland);
// Save the island // Save the island
handler.saveObjectAsync(teamIsland); updateIsland(teamIsland);
} }
/**
* Set the last island location
* @param last location
*/
public void setLast(Location last) { public void setLast(Location last) {
this.last.put(last.getWorld(), last); this.last.put(last.getWorld(), last);
} }
@ -1608,12 +1631,16 @@ public class IslandsManager {
} }
/** /**
* Save the island to the database * Update island data in database
* *
* @param island - island * @param island - island
*/ */
public void save(Island island) { public static void updateIsland(Island island) {
handler.saveObjectAsync(island); if (handler.objectExists(island.getUniqueId())) {
island.clearChanged();
handler.saveObjectAsync(island)
.thenAccept(b -> MultiLib.notify("bentobox-updateIsland", island.getUniqueId()));
}
} }
/** /**
@ -1628,108 +1655,6 @@ public class IslandsManager {
return Optional.ofNullable(islandCache.getIslandById(uniqueId)); return Optional.ofNullable(islandCache.getIslandById(uniqueId));
} }
/**
* Try to get an unmodifiable list of quarantined islands owned by uuid in this
* world
*
* @param world - world
* @param uuid - target player's UUID, or <tt>null</tt> = unowned islands
* @return list of islands; may be empty
* @since 1.3.0
*/
@NonNull
public List<Island> getQuarantinedIslandByUser(@NonNull World world, @Nullable UUID uuid) {
return quarantineCache.getOrDefault(uuid, Collections.emptyList()).stream()
.filter(i -> i.getWorld().equals(world)).toList();
}
/**
* Delete quarantined islands owned by uuid in this world
*
* @param world - world
* @param uuid - target player's UUID, or <tt>null</tt> = unowned islands
* @since 1.3.0
*/
public void deleteQuarantinedIslandByUser(World world, @Nullable UUID uuid) {
if (quarantineCache.containsKey(uuid)) {
quarantineCache.get(uuid).stream().filter(i -> i.getWorld().equals(world))
.forEach(i -> handler.deleteObject(i));
quarantineCache.get(uuid).removeIf(i -> i.getWorld().equals(world));
}
}
/**
* @return the quarantineCache
* @since 1.3.0
*/
@NonNull
public Map<UUID, List<Island>> getQuarantineCache() {
return quarantineCache;
}
/**
* Remove a quarantined island and delete it from the database completely. This
* is NOT recoverable unless you have database backups.
*
* @param island island
* @return {@code true} if island is quarantined and removed
* @since 1.3.0
*/
public boolean purgeQuarantinedIsland(Island island) {
if (quarantineCache.containsKey(island.getOwner()) && quarantineCache.get(island.getOwner()).remove(island)) {
handler.deleteObject(island);
return true;
}
return false;
}
/**
* Switches active island and island in trash
*
* @param world - game world
* @param target - target player's UUID
* @param island - island in trash
* @return <tt>true</tt> if successful, otherwise <tt>false</tt>
* @since 1.3.0
*/
public boolean switchIsland(World world, UUID target, Island island) {
// Remove trashed island from trash
if (!quarantineCache.containsKey(island.getOwner()) || !quarantineCache.get(island.getOwner()).remove(island)) {
plugin.logError("Could not remove island from trash");
return false;
}
// Remove old island from cache if it exists
if (this.hasIsland(world, target)) {
Island oldIsland = islandCache.get(world, target);
islandCache.removeIsland(oldIsland);
// Set old island to trash
oldIsland.setDoNotLoad(true);
// Put old island into trash
quarantineCache.computeIfAbsent(target, k -> new ArrayList<>()).add(oldIsland);
// Save old island
handler.saveObjectAsync(oldIsland).thenAccept(result -> {
if (Boolean.FALSE.equals(result))
plugin.logError("Could not save trashed island in database");
});
}
// Restore island from trash
island.setDoNotLoad(false);
// Add new island to cache
if (!islandCache.addIsland(island)) {
plugin.logError("Could not add recovered island to cache");
return false;
}
// Save new island
handler.saveObjectAsync(island).thenAccept(result -> {
if (Boolean.FALSE.equals(result)) {
plugin.logError("Could not save recovered island to database");
}
});
return true;
}
/** /**
* Resets all flags to gamemode config.yml default * Resets all flags to gamemode config.yml default
* *

View File

@ -4,21 +4,18 @@ import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.LinkedList;
import java.util.Map; import java.util.Map;
import java.util.Queue; import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.entity.Tameable; import org.bukkit.entity.Tameable;
import org.bukkit.scheduler.BukkitRunnable;
import org.eclipse.jdt.annotation.NonNull; 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.BentoBox;
import world.bentobox.bentobox.api.flags.Flag;
import world.bentobox.bentobox.api.user.User; import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.database.Database; import world.bentobox.bentobox.database.Database;
import world.bentobox.bentobox.database.objects.Island; import world.bentobox.bentobox.database.objects.Island;
@ -31,11 +28,9 @@ public class PlayersManager {
private final BentoBox plugin; private final BentoBox plugin;
private Database<Players> handler; private Database<Players> handler;
private final Database<Names> names; private final Database<Names> names;
private final Map<UUID, Players> playerCache = new HashMap<>();
private final Map<UUID, Players> playerCache; private final Set<UUID> inTeleport; // this needs databasing
private final Set<UUID> inTeleport;
private boolean isSaveTaskRunning;
/** /**
* Provides a memory cache of online player information * Provides a memory cache of online player information
@ -50,7 +45,6 @@ public class PlayersManager {
handler = new Database<>(plugin, Players.class); handler = new Database<>(plugin, Players.class);
// Set up the names database // Set up the names database
names = new Database<>(plugin, Names.class); names = new Database<>(plugin, Names.class);
playerCache = new HashMap<>();
inTeleport = new HashSet<>(); inTeleport = new HashSet<>();
} }
@ -62,67 +56,7 @@ public class PlayersManager {
this.handler = handler; this.handler = handler;
} }
/**
* Load all players - not normally used as to load all players into memory will be wasteful
*/
public void load(){
playerCache.clear();
inTeleport.clear();
handler.loadObjects().forEach(p -> playerCache.put(p.getPlayerUUID(), p));
}
public boolean isSaveTaskRunning() {
return isSaveTaskRunning;
}
/**
* Save all players
*/
public void saveAll() {
saveAll(false);
}
/**
* Save all players
* @param schedule true if we should let the task run over multiple ticks to reduce lag spikes
*/
public void saveAll(boolean schedule){
if (!schedule) {
for (Players player : playerCache.values()) {
try {
handler.saveObjectAsync(player);
} catch (Exception e) {
plugin.logError("Could not save player to database when running sync! " + e.getMessage());
}
}
return;
}
isSaveTaskRunning = true;
Queue<Players> queue = new LinkedList<>(playerCache.values());
new BukkitRunnable() {
@Override
public void run() {
for (int i = 0; i < plugin.getSettings().getMaxSavedPlayersPerTick(); i++) {
Players player = queue.poll();
if (player == null) {
isSaveTaskRunning = false;
cancel();
return;
}
try {
handler.saveObjectAsync(player);
} catch (Exception e) {
plugin.logError("Could not save player to database when running sync! " + e.getMessage());
}
}
}
}.runTaskTimer(plugin, 0, 1);
}
public void shutdown(){ public void shutdown(){
saveAll();
playerCache.clear();
handler.close(); handler.close();
} }
@ -134,11 +68,29 @@ public class PlayersManager {
@Nullable @Nullable
public Players getPlayer(UUID uuid){ public Players getPlayer(UUID uuid){
if (!playerCache.containsKey(uuid)) { if (!playerCache.containsKey(uuid)) {
addPlayer(uuid); playerCache.put(uuid, addPlayer(uuid));
} }
return playerCache.get(uuid); return playerCache.get(uuid);
} }
/**
* Adds a player to the database. If the UUID does not exist, a new player is made
* @param playerUUID - the player's UUID
*/
private Players addPlayer(@NonNull UUID playerUUID) {
Objects.requireNonNull(playerUUID);
// If the player is in the database, load it, otherwise create a new player
if (handler.objectExists(playerUUID.toString())) {
Players player = handler.loadObject(playerUUID.toString());
if (player != null) {
return player;
}
}
Players player = new Players(plugin, playerUUID);
handler.saveObject(player);
return player;
}
/** /**
* Returns an <strong>unmodifiable collection</strong> of all the players that are <strong>currently in the cache</strong>. * Returns an <strong>unmodifiable collection</strong> of all the players that are <strong>currently in the cache</strong>.
* @return unmodifiable collection containing every player in the cache. * @return unmodifiable collection containing every player in the cache.
@ -146,37 +98,7 @@ public class PlayersManager {
*/ */
@NonNull @NonNull
public Collection<Players> getPlayers() { public Collection<Players> getPlayers() {
return Collections.unmodifiableCollection(playerCache.values()); return Collections.unmodifiableCollection(handler.loadObjects());
}
/*
* Cache control methods
*/
/**
* Adds a player to the cache. If the UUID does not exist, a new player is made
* @param playerUUID - the player's UUID
*/
public void addPlayer(UUID playerUUID) {
if (playerUUID == null) {
return;
}
if (!playerCache.containsKey(playerUUID)) {
Players player;
// If the player is in the database, load it, otherwise create a new player
if (handler.objectExists(playerUUID.toString())) {
player = handler.loadObject(playerUUID.toString());
if (player == null) {
player = new Players(plugin, playerUUID);
// Corrupted database entry
plugin.logError("Corrupted player database entry for " + playerUUID + " - unrecoverable. Recreated.");
player.setUniqueId(playerUUID.toString());
}
} else {
player = new Players(plugin, playerUUID);
}
playerCache.put(playerUUID, player);
}
} }
/** /**
@ -187,7 +109,7 @@ public class PlayersManager {
* @return true if player is known, otherwise false * @return true if player is known, otherwise false
*/ */
public boolean isKnown(UUID uniqueID) { public boolean isKnown(UUID uniqueID) {
return uniqueID != null && (playerCache.containsKey(uniqueID) || handler.objectExists(uniqueID.toString())); return uniqueID == null ? false : handler.objectExists(uniqueID.toString());
} }
/** /**
@ -206,11 +128,8 @@ public class PlayersManager {
// Not used // Not used
} }
} }
// Look in the name cache, then the data base and then give up return names.loadObjects().stream().filter(n -> n.getUniqueId().equalsIgnoreCase(name)).findFirst()
return playerCache.values().stream() .map(Names::getUuid).orElse(null);
.filter(p -> p.getPlayerName().equalsIgnoreCase(name)).findFirst()
.map(p -> UUID.fromString(p.getUniqueId()))
.orElseGet(() -> names.objectExists(name) ? names.loadObject(name).getUuid() : null);
} }
/** /**
@ -218,8 +137,9 @@ public class PlayersManager {
* @param user - the User * @param user - the User
*/ */
public void setPlayerName(@NonNull User user) { public void setPlayerName(@NonNull User user) {
addPlayer(user.getUniqueId()); Players player = getPlayer(user.getUniqueId());
playerCache.get(user.getUniqueId()).setPlayerName(user.getName()); player.setPlayerName(user.getName());
handler.saveObject(player);
Names newName = new Names(user.getName(), user.getUniqueId()); Names newName = new Names(user.getName(), user.getUniqueId());
// Add to names database // Add to names database
names.saveObjectAsync(newName); names.saveObjectAsync(newName);
@ -237,8 +157,8 @@ public class PlayersManager {
if (playerUUID == null) { if (playerUUID == null) {
return ""; return "";
} }
addPlayer(playerUUID); return names.loadObjects().stream().filter(n -> n.getUuid().equals(playerUUID)).findFirst()
return playerCache.get(playerUUID).getPlayerName(); .map(Names::getUniqueId).orElse(null);
} }
/** /**
@ -248,8 +168,7 @@ public class PlayersManager {
* @return number of resets * @return number of resets
*/ */
public int getResets(World world, UUID playerUUID) { public int getResets(World world, UUID playerUUID) {
addPlayer(playerUUID); return getPlayer(playerUUID).getResets(world);
return playerCache.get(playerUUID).getResets(world);
} }
/** /**
@ -261,7 +180,7 @@ public class PlayersManager {
* @see #getResets(World, UUID) * @see #getResets(World, UUID)
*/ */
public int getResetsLeft(World world, UUID playerUUID) { public int getResetsLeft(World world, UUID playerUUID) {
addPlayer(playerUUID); getPlayer(playerUUID);
if (plugin.getIWM().getResetLimit(world) == -1) { if (plugin.getIWM().getResetLimit(world) == -1) {
return -1; return -1;
} else { } else {
@ -277,8 +196,9 @@ public class PlayersManager {
* @param resets number of resets to set * @param resets number of resets to set
*/ */
public void setResets(World world, UUID playerUUID, int resets) { public void setResets(World world, UUID playerUUID, int resets) {
addPlayer(playerUUID); Players p = getPlayer(playerUUID);
playerCache.get(playerUUID).setResets(world, resets); p.setResets(world, resets);
handler.saveObject(p);
} }
/** /**
@ -287,11 +207,7 @@ public class PlayersManager {
* @return name of the locale this player uses * @return name of the locale this player uses
*/ */
public String getLocale(UUID playerUUID) { public String getLocale(UUID playerUUID) {
addPlayer(playerUUID); return getPlayer(playerUUID).getLocale();
if (playerUUID == null) {
return "";
}
return playerCache.get(playerUUID).getLocale();
} }
/** /**
@ -300,8 +216,9 @@ public class PlayersManager {
* @param localeName - locale name, e.g., en-US * @param localeName - locale name, e.g., en-US
*/ */
public void setLocale(UUID playerUUID, String localeName) { public void setLocale(UUID playerUUID, String localeName) {
addPlayer(playerUUID); Players p = getPlayer(playerUUID);
playerCache.get(playerUUID).setLocale(localeName); p.setLocale(localeName);
handler.saveObject(p);
} }
/** /**
@ -310,8 +227,9 @@ public class PlayersManager {
* @param playerUUID - the player's UUID * @param playerUUID - the player's UUID
*/ */
public void addDeath(World world, UUID playerUUID) { public void addDeath(World world, UUID playerUUID) {
addPlayer(playerUUID); Players p = getPlayer(playerUUID);
playerCache.get(playerUUID).addDeath(world); p.addDeath(world);
handler.saveObject(p);
} }
/** /**
@ -321,8 +239,9 @@ public class PlayersManager {
* @param deaths - number of deaths * @param deaths - number of deaths
*/ */
public void setDeaths(World world, UUID playerUUID, int deaths) { public void setDeaths(World world, UUID playerUUID, int deaths) {
addPlayer(playerUUID); Players p = getPlayer(playerUUID);
playerCache.get(playerUUID).setDeaths(world, deaths); p.setDeaths(world, deaths);
handler.saveObject(p);
} }
/** /**
@ -332,8 +251,7 @@ public class PlayersManager {
* @return number of deaths * @return number of deaths
*/ */
public int getDeaths(World world, UUID playerUUID) { public int getDeaths(World world, UUID playerUUID) {
addPlayer(playerUUID); return getPlayer(playerUUID).getDeaths(world);
return playerCache.get(playerUUID) == null ? 0 : playerCache.get(playerUUID).getDeaths(world);
} }
/** /**
@ -360,16 +278,6 @@ public class PlayersManager {
return inTeleport.contains(uniqueId); return inTeleport.contains(uniqueId);
} }
/**
* Saves the player to the database
* @param playerUUID - the player's UUID
*/
public void save(UUID playerUUID) {
if (playerCache.containsKey(playerUUID)) {
handler.saveObjectAsync(playerCache.get(playerUUID));
}
}
/** /**
* Tries to get the user from his name * Tries to get the user from his name
* @param name - name * @param name - name
@ -395,41 +303,17 @@ public class PlayersManager {
* @param playerUUID player's UUID * @param playerUUID player's UUID
*/ */
public void addReset(World world, UUID playerUUID) { public void addReset(World world, UUID playerUUID) {
addPlayer(playerUUID); Players p = getPlayer(playerUUID);
playerCache.get(playerUUID).addReset(world); p.addReset(world);
handler.saveObject(p);
} }
/** /**
* Sets the Flags display mode for the Settings Panel for this player. * Remove player from database
* @param playerUUID player's UUID
* @param displayMode the {@link Flag.Mode} to set
* @since 1.6.0
*/
public void setFlagsDisplayMode(UUID playerUUID, Flag.Mode displayMode) {
addPlayer(playerUUID);
playerCache.get(playerUUID).setFlagsDisplayMode(displayMode);
}
/**
* Returns the Flags display mode for the Settings Panel for this player.
* @param playerUUID player's UUID
* @return the {@link Flag.Mode display mode} for the Flags in the Settings Panel.
* @since 1.6.0
*/
public Flag.Mode getFlagsDisplayMode(UUID playerUUID) {
addPlayer(playerUUID);
return playerCache.get(playerUUID).getFlagsDisplayMode();
}
/**
* Remove player from cache. Clears players with the same name or UUID
* @param player player to remove * @param player player to remove
*/ */
public void removePlayer(Player player) { public void removePlayer(Player player) {
// Clear any players with the same name handler.deleteID(player.getUniqueId().toString());
playerCache.values().removeIf(p -> player.getName().equalsIgnoreCase(p.getPlayerName()));
// Remove if the player's UUID is the same
playerCache.values().removeIf(p -> player.getUniqueId().toString().equals(p.getUniqueId()));
} }
/** /**
@ -495,8 +379,6 @@ public class PlayersManager {
// Player total XP (not displayed) // Player total XP (not displayed)
target.getPlayer().setTotalExperience(0); target.getPlayer().setTotalExperience(0);
} }
// Save player
save(target.getUniqueId());
} }
} }

View File

@ -9,6 +9,7 @@ import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -54,6 +55,159 @@ public class IslandCache {
grids = new HashMap<>(); grids = new HashMap<>();
} }
/**
* Replace the island we have with this one
* @param newIsland island
*/
public void updateIsland(@NonNull Island newIsland) {
if (newIsland.isDeleted()) {
this.deleteIslandFromCache(newIsland);
return;
}
// Get the old island
Island oldIsland = islandsById.get(newIsland.getUniqueId());
compareIslands(oldIsland, newIsland);
Set<UUID> newMembers = newIsland.getMembers().keySet();
if (oldIsland != null) {
Set<UUID> oldMembers = oldIsland.getMembers().keySet();
// Remove any members who are not in the new island
for (UUID oldMember : oldMembers) {
if (!newMembers.contains(oldMember)) {
// Member has been removed - remove island
islandsByUUID.computeIfAbsent(oldMember, k -> new HashSet<>()).remove(oldIsland);
}
}
}
// Update the members with the new island object
for (UUID newMember : newMembers) {
Set<Island> set = islandsByUUID.computeIfAbsent(newMember, k -> new HashSet<>());
set.remove(oldIsland);
set.add(newIsland);
islandsByUUID.put(newMember, set);
}
if (islandsByLocation.put(newIsland.getCenter(), newIsland) == null) {
BentoBox.getInstance().logError("islandsByLocation failed to update");
}
if (islandsById.put(newIsland.getUniqueId(), newIsland) == null) {
BentoBox.getInstance().logError("islandsById failed to update");
}
}
/**
* TODO REMOVE THIS DEBUG METHOD
* @param island1 island1
* @param island2 island 2
*/
public void compareIslands(Island island1, Island island2) {
if (island1 == null || island2 == null) {
BentoBox.getInstance().logDebug("One or both islands are null. Cannot compare.");
return;
}
if (!island1.getUniqueId().equals(island2.getUniqueId())) {
BentoBox.getInstance().logDebug("Island unique IDs are different.");
}
if (island1.isDeleted() != island2.isDeleted()) {
BentoBox.getInstance().logDebug("Island deleted states are different.");
}
if (!Objects.equals(island1.getCenter(), island2.getCenter())) {
BentoBox.getInstance().logDebug("Island centers are different.");
}
if (island1.getRange() != island2.getRange()) {
BentoBox.getInstance().logDebug("Island ranges are different.");
}
if (island1.getProtectionRange() != island2.getProtectionRange()) {
BentoBox.getInstance().logDebug("Island protection ranges are different.");
}
if (!island1.getBonusRanges().equals(island2.getBonusRanges())) {
BentoBox.getInstance().logDebug("Island bonus ranges are different.");
}
if (island1.getMaxEverProtectionRange() != island2.getMaxEverProtectionRange()) {
BentoBox.getInstance().logDebug("Island max ever protection ranges are different.");
}
if (!island1.getWorld().equals(island2.getWorld())) {
BentoBox.getInstance().logDebug("Island worlds are different.");
}
if (!Objects.equals(island1.getGameMode(), island2.getGameMode())) {
BentoBox.getInstance().logDebug("Island game modes are different.");
}
if (!Objects.equals(island1.getName(), island2.getName())) {
BentoBox.getInstance().logDebug("Island names are different.");
}
if (island1.getCreatedDate() != island2.getCreatedDate()) {
BentoBox.getInstance().logDebug("Island created dates are different.");
}
if (island1.getUpdatedDate() != island2.getUpdatedDate()) {
BentoBox.getInstance().logDebug("Island updated dates are different.");
}
if (!Objects.equals(island1.getOwner(), island2.getOwner())) {
BentoBox.getInstance().logDebug("Island owners are different.");
}
if (!island1.getMembers().equals(island2.getMembers())) {
BentoBox.getInstance().logDebug("Island members are different.");
}
if (!Objects.equals(island1.getMaxMembers(), island2.getMaxMembers())) {
BentoBox.getInstance().logDebug("Island max members are different.");
}
if (island1.isSpawn() != island2.isSpawn()) {
BentoBox.getInstance().logDebug("Island spawn states are different.");
}
if (!island1.getFlags().equals(island2.getFlags())) {
BentoBox.getInstance().logDebug("Island flags are different.");
}
if (!island1.getHistory().equals(island2.getHistory())) {
BentoBox.getInstance().logDebug("Island histories are different.");
}
if (!island1.getSpawnPoint().equals(island2.getSpawnPoint())) {
BentoBox.getInstance().logDebug("Island spawn points are different.");
}
if (island1.isDoNotLoad() != island2.isDoNotLoad()) {
BentoBox.getInstance().logDebug("Island do not load states are different.");
}
if (!island1.getCooldowns().equals(island2.getCooldowns())) {
BentoBox.getInstance().logDebug("Island cooldowns are different.");
}
if (!Objects.equals(island1.getCommandRanks(), island2.getCommandRanks())) {
BentoBox.getInstance().logDebug("Island command ranks are different.");
}
if (!Objects.equals(island1.getMetaData(), island2.getMetaData())) {
BentoBox.getInstance().logDebug("Island metadata are different.");
}
if (!Objects.equals(island1.getHomes(), island2.getHomes())) {
BentoBox.getInstance().logDebug("Island homes are different.");
}
if (!Objects.equals(island1.getMaxHomes(), island2.getMaxHomes())) {
BentoBox.getInstance().logDebug("Island max homes are different.");
}
}
/** /**
* Adds an island to the grid * Adds an island to the grid
* *
@ -62,12 +216,7 @@ public class IslandCache {
*/ */
public boolean addIsland(@NonNull Island island) { public boolean addIsland(@NonNull Island island) {
if (island.getCenter() == null || island.getWorld() == null) { if (island.getCenter() == null || island.getWorld() == null) {
/* return false;
* Special handling - return true. The island will not be quarantined, but just
* not loaded This can occur when a gamemode is removed temporarily from the
* server TODO: have an option to remove these when the purge command is added
*/
return true;
} }
if (addToGrid(island)) { if (addToGrid(island)) {
islandsByLocation.put(island.getCenter(), island); islandsByLocation.put(island.getCenter(), island);
@ -100,7 +249,7 @@ public class IslandCache {
* @return true if successfully added, false if not * @return true if successfully added, false if not
*/ */
private boolean addToGrid(@NonNull Island newIsland) { private boolean addToGrid(@NonNull Island newIsland) {
return grids.computeIfAbsent(newIsland.getWorld(), k -> new IslandGrid()).addToGrid(newIsland); return grids.computeIfAbsent(newIsland.getWorld(), k -> new IslandGrid(this)).addToGrid(newIsland);
} }
public void clear() { public void clear() {
@ -117,13 +266,16 @@ public class IslandCache {
*/ */
public boolean deleteIslandFromCache(@NonNull Island island) { public boolean deleteIslandFromCache(@NonNull Island island) {
if (!islandsByLocation.remove(island.getCenter(), island)) { if (!islandsByLocation.remove(island.getCenter(), island)) {
// Already deleted
return false; return false;
} }
islandsById.remove(island.getUniqueId()); islandsById.remove(island.getUniqueId());
removeFromIslandsByUUID(island); removeFromIslandsByUUID(island);
// Remove from grid // Remove from grid
grids.putIfAbsent(island.getWorld(), new IslandGrid()); if (grids.containsKey(island.getWorld())) {
return grids.get(island.getWorld()).removeFromGrid(island); return grids.get(island.getWorld()).removeFromGrid(island);
}
return false;
} }
private void removeFromIslandsByUUID(Island island) { private void removeFromIslandsByUUID(Island island) {
@ -144,12 +296,11 @@ public class IslandCache {
* *
* @param uniqueId - island unique ID * @param uniqueId - island unique ID
*/ */
public void deleteIslandFromCache(@NonNull String uniqueId) { public boolean deleteIslandFromCache(@NonNull String uniqueId) {
islandsById.remove(uniqueId); if (islandsById.containsKey(uniqueId)) {
islandsByLocation.values().removeIf(i -> i.getUniqueId().equals(uniqueId)); return deleteIslandFromCache(islandsById.get(uniqueId));
for (Set<Island> set : islandsByUUID.values()) {
set.removeIf(i -> i.getUniqueId().equals(uniqueId));
} }
return false;
} }
/** /**
@ -178,13 +329,13 @@ public class IslandCache {
return null; return null;
} }
for (Island island : islands) { for (Island island : islands) {
if (island.isPrimary()) { if (island.isPrimary(uuid)) {
return island; return island;
} }
} }
// If there is no primary set, then set one - it doesn't matter which. // If there is no primary set, then set one - it doesn't matter which.
Island result = islands.iterator().next(); Island result = islands.iterator().next();
result.setPrimary(true); result.setPrimary(uuid);
return result; return result;
} }
@ -212,8 +363,16 @@ public class IslandCache {
* @param island island to make primary * @param island island to make primary
*/ */
public void setPrimaryIsland(@NonNull UUID uuid, @NonNull Island island) { public void setPrimaryIsland(@NonNull UUID uuid, @NonNull Island island) {
if (island.getPrimaries().contains(uuid)) {
return;
}
for (Island is : getIslands(island.getWorld(), uuid)) { for (Island is : getIslands(island.getWorld(), uuid)) {
is.setPrimary(island.equals(is)); if (is.getPrimaries().contains(uuid)) {
is.removePrimary(uuid);
}
if (is.equals(island)) {
is.setPrimary(uuid);
}
} }
} }
@ -326,6 +485,7 @@ public class IslandCache {
islandSet.remove(island); islandSet.remove(island);
} }
island.removeMember(uuid); island.removeMember(uuid);
island.removePrimary(uuid);
} }
/** /**
@ -375,27 +535,6 @@ public class IslandCache {
return islandsById.get(uniqueId); return islandsById.get(uniqueId);
} }
/**
* Removes an island from the cache completely without altering the island
* object
*
* @param island - island to remove
* @since 1.3.0
*/
public void removeIsland(@NonNull Island island) {
islandsByLocation.values().removeIf(island::equals);
islandsById.values().removeIf(island::equals);
islandsByUUID.values().removeIf(island::equals);
World w = Util.getWorld(island.getWorld());
if (w == null) {
return;
}
if (grids.containsKey(w)) {
grids.get(w).removeFromGrid(island);
}
}
/** /**
* Resets all islands in this game mode to default flag settings * Resets all islands in this game mode to default flag settings
* *

View File

@ -3,7 +3,6 @@ package world.bentobox.bentobox.managers.island;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.TreeMap; import java.util.TreeMap;
import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.database.objects.Island; import world.bentobox.bentobox.database.objects.Island;
/** /**
@ -12,8 +11,16 @@ import world.bentobox.bentobox.database.objects.Island;
* *
*/ */
class IslandGrid { class IslandGrid {
private final TreeMap<Integer, TreeMap<Integer, Island>> grid = new TreeMap<>(); private final TreeMap<Integer, TreeMap<Integer, String>> grid = new TreeMap<>();
private final BentoBox plugin = BentoBox.getInstance(); private final IslandCache im;
/**
* @param im IslandsManager
*/
public IslandGrid(IslandCache im) {
super();
this.im = im;
}
/** /**
* Adds island to grid * Adds island to grid
@ -21,50 +28,23 @@ class IslandGrid {
* @return true if successfully added, false if island already exists, or there is an overlap * @return true if successfully added, false if island already exists, or there is an overlap
*/ */
public boolean addToGrid(Island island) { public boolean addToGrid(Island island) {
// Check if we know about this island already
if (grid.containsKey(island.getMinX())) { if (grid.containsKey(island.getMinX())) {
TreeMap<Integer, Island> zEntry = grid.get(island.getMinX()); TreeMap<Integer, String> zEntry = grid.get(island.getMinX());
if (zEntry.containsKey(island.getMinZ())) { if (zEntry.containsKey(island.getMinZ())) {
// There is an overlap or duplicate if (island.getUniqueId().equals(zEntry.get(island.getMinZ()))) {
plugin.logError("Cannot load island. Overlapping: " + island.getUniqueId()); return true;
plugin.logError("Location: " + island.getCenter());
// Get the previously loaded island
Island firstLoaded = zEntry.get(island.getMinZ());
if (firstLoaded.getOwner() == null && island.getOwner() != null) {
// This looks fishy. We prefer to load islands that have an owner. Swap the two
plugin.logError("Duplicate island has an owner, so using that one. " + island.getOwner());
firstLoaded = new Island(island);
zEntry.put(island.getMinZ(), firstLoaded);
} else if (firstLoaded.getOwner() != null && island.getOwner() != null) {
// Check if the owners are the same - this is a true duplicate
if (firstLoaded.getOwner().equals(island.getOwner())) {
// Find out which one is the original
if (firstLoaded.getCreatedDate() > island.getCreatedDate()) {
plugin.logError("Same owner duplicate. Swapping based on creation date.");
// FirstLoaded is the newer
firstLoaded = new Island(island);
zEntry.put(island.getMinZ(), firstLoaded);
} else {
plugin.logError("Same owner duplicate.");
}
} else {
plugin.logError("Duplicate but different owner. Keeping first loaded.");
plugin.logError("This is serious!");
plugin.logError("1st loaded ID: " + firstLoaded.getUniqueId());
plugin.logError("1st loaded owner: " + firstLoaded.getOwner());
plugin.logError("2nd loaded ID: " + island.getUniqueId());
plugin.logError("2nd loaded owner: " + island.getOwner());
}
} }
return false; return false;
} else { } else {
// Add island // Add island
zEntry.put(island.getMinZ(), island); zEntry.put(island.getMinZ(), island.getUniqueId());
grid.put(island.getMinX(), zEntry); grid.put(island.getMinX(), zEntry);
} }
} else { } else {
// Add island // Add island
TreeMap<Integer, Island> zEntry = new TreeMap<>(); TreeMap<Integer, String> zEntry = new TreeMap<>();
zEntry.put(island.getMinZ(), island); zEntry.put(island.getMinZ(), island.getUniqueId());
grid.put(island.getMinX(), zEntry); grid.put(island.getMinX(), zEntry);
} }
return true; return true;
@ -76,43 +56,48 @@ class IslandGrid {
* @return true if island existed and was deleted, false if there was nothing to delete * @return true if island existed and was deleted, false if there was nothing to delete
*/ */
public boolean removeFromGrid(Island island) { public boolean removeFromGrid(Island island) {
// Remove from grid String id = island.getUniqueId();
if (island != null) { boolean removed = grid.values().stream()
int x = island.getMinX(); .anyMatch(innerMap -> innerMap.values().removeIf(innerValue -> innerValue.equals(id)));
int z = island.getMinZ();
if (grid.containsKey(x)) {
TreeMap<Integer, Island> zEntry = grid.get(x);
if (zEntry.containsKey(z)) {
// Island exists - delete it
zEntry.remove(z);
grid.put(x, zEntry);
return true;
}
}
}
return false;
}
grid.values().removeIf(TreeMap::isEmpty);
return removed;
}
/** /**
* Returns the island at the x,z location or null if there is none. * Retrieves the island located at the specified x and z coordinates, covering both the protected area
* This includes the full island space, not just the protected area. * and the full island space. Returns null if no island exists at the given location.
* *
* @param x - x coordinate * @param x the x coordinate of the location
* @param z - z coordinate * @param z the z coordinate of the location
* @return Island or null * @return the Island at the specified location, or null if no island is found
*/ */
public Island getIslandAt(int x, int z) { public Island getIslandAt(int x, int z) {
Entry<Integer, TreeMap<Integer, Island>> en = grid.floorEntry(x); // Attempt to find the closest x-coordinate entry that does not exceed 'x'
if (en != null) { Entry<Integer, TreeMap<Integer, String>> xEntry = grid.floorEntry(x);
Entry<Integer, Island> ent = en.getValue().floorEntry(z); if (xEntry == null) {
if (ent != null) { return null; // No x-coordinate entry found, return null
// Check if in the island range
Island island = ent.getValue();
if (island.inIslandSpace(x, z)) {
return island;
}
}
} }
// Attempt to find the closest z-coordinate entry that does not exceed 'z' within the found x-coordinate
Entry<Integer, String> zEntry = xEntry.getValue().floorEntry(z);
if (zEntry == null) {
return null; // No z-coordinate entry found, return null
}
// Retrieve the island using the id found in the z-coordinate entry
Island island = im.getIslandById(zEntry.getValue());
if (island == null) {
return null; // No island found by the id, return null
}
// Check if the specified coordinates are within the island space
if (island.inIslandSpace(x, z)) {
return island; // Coordinates are within island space, return the island
}
// Coordinates are outside the island space, return null
return null; return null;
} }
} }

View File

@ -19,6 +19,7 @@ import world.bentobox.bentobox.api.events.island.IslandResetEvent;
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.BlueprintsManager; import world.bentobox.bentobox.managers.BlueprintsManager;
import world.bentobox.bentobox.managers.IslandsManager;
/** /**
* Create and paste a new island * Create and paste a new island
@ -217,7 +218,7 @@ public class NewIsland {
// Register metrics // Register metrics
plugin.getMetrics().ifPresent(BStats::increaseIslandsCreatedCount); plugin.getMetrics().ifPresent(BStats::increaseIslandsCreatedCount);
// Save island // Save island
plugin.getIslands().save(island); IslandsManager.updateIsland(island);
} }
/** /**
@ -266,8 +267,6 @@ public class NewIsland {
plugin.getIWM().getAddon(island.getWorld()).map(GameModeAddon::getPermissionPrefix).orElse("") plugin.getIWM().getAddon(island.getWorld()).map(GameModeAddon::getPermissionPrefix).orElse("")
+ "island.range", + "island.range",
island.getProtectionRange())); island.getProtectionRange()));
// Save the player so that if the server crashes weird things won't happen
plugin.getPlayers().save(user.getUniqueId());
} }
/** /**

View File

@ -489,7 +489,7 @@ public class IslandCreationPanel
long uses = plugin.getIslands().getIslands(world, user).stream() long uses = plugin.getIslands().getIslands(world, user).stream()
.filter(is -> is.getMetaData("bundle") .filter(is -> is.getMetaData("bundle")
.map(mdv -> bundle.getDisplayName().equalsIgnoreCase(mdv.asString()) .map(mdv -> bundle.getDisplayName().equalsIgnoreCase(mdv.asString())
&& !(reset && is.isPrimary())) // If this is a reset, then ignore the use of the island being reset && !(reset && is.isPrimary(user.getUniqueId()))) // If this is a reset, then ignore the use of the island being reset
.orElse(false)) .orElse(false))
.count(); .count();
builder.description(this.user.getTranslation(BUNDLE_BUTTON_REF + "uses", TextVariables.NUMBER, builder.description(this.user.getTranslation(BUNDLE_BUTTON_REF + "uses", TextVariables.NUMBER,

View File

@ -4,6 +4,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.UUID;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
@ -16,6 +17,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.api.flags.Flag.Mode;
import world.bentobox.bentobox.api.flags.Flag.Type; import world.bentobox.bentobox.api.flags.Flag.Type;
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.Panel;
@ -46,16 +48,7 @@ public class SettingsTab implements Tab, ClickHandler {
protected Island island; protected Island island;
protected TabbedPanel parent; protected TabbedPanel parent;
/** private Map<UUID, Flag.Mode> currentMode = new HashMap<>();
* Show a tab of settings
* @param user - user who is viewing the tab
* @param type - flag type
*/
public SettingsTab(User user, Type type) {
this.user = user;
this.type = type;
// Island and world are set when the parent is set.
}
/** /**
* Show a tab of settings * Show a tab of settings
@ -69,6 +62,21 @@ public class SettingsTab implements Tab, ClickHandler {
this.type = type; this.type = type;
} }
/**
* Show a tab of settings
* @param world - world
* @param user - user who is viewing the tab
* @param type - flag type
* @param defaultMode - the default mode to show
* @since 2.4.0
*/
public SettingsTab(World world, User user, Type type, Flag.Mode defaultMode) {
this.world = world;
this.user = user;
this.type = type;
currentMode.put(user.getUniqueId(), defaultMode);
}
/** /**
* @return list of flags that will be shown in this panel * @return list of flags that will be shown in this panel
*/ */
@ -81,7 +89,7 @@ public class SettingsTab implements Tab, ClickHandler {
// Remove any that are not for this game mode // Remove any that are not for this game mode
plugin.getIWM().getAddon(world).ifPresent(gm -> flags.removeIf(f -> !f.getGameModes().isEmpty() && !f.getGameModes().contains(gm))); plugin.getIWM().getAddon(world).ifPresent(gm -> flags.removeIf(f -> !f.getGameModes().isEmpty() && !f.getGameModes().contains(gm)));
// Remove any that are the wrong rank or that will be on the top row // Remove any that are the wrong rank or that will be on the top row
Flag.Mode mode = plugin.getPlayers().getFlagsDisplayMode(user.getUniqueId()); Flag.Mode mode = currentMode.getOrDefault(user.getUniqueId(), Mode.BASIC);
plugin.getIWM().getAddon(world).ifPresent(gm -> flags.removeIf(f -> f.getMode().isGreaterThan(mode) || plugin.getIWM().getAddon(world).ifPresent(gm -> flags.removeIf(f -> f.getMode().isGreaterThan(mode) ||
f.getMode().equals(Flag.Mode.TOP_ROW))); f.getMode().equals(Flag.Mode.TOP_ROW)));
return flags; return flags;
@ -120,13 +128,14 @@ public class SettingsTab implements Tab, ClickHandler {
int i = 0; int i = 0;
// Jump past empty tabs // Jump past empty tabs
while (flags.isEmpty() && i++ < Flag.Mode.values().length) { while (flags.isEmpty() && i++ < Flag.Mode.values().length) {
plugin.getPlayers().setFlagsDisplayMode(user.getUniqueId(), plugin.getPlayers().getFlagsDisplayMode(user.getUniqueId()).getNext()); currentMode.put(user.getUniqueId(), currentMode.getOrDefault(user.getUniqueId(), Mode.BASIC).getNext());
flags = getFlags(); flags = getFlags();
} }
return flags.stream().map( List<@Nullable PanelItem> result = flags.stream().map(
(f -> f.toPanelItem(plugin, user, world, island, (f -> f.toPanelItem(plugin, user, world, island,
plugin.getIWM().getHiddenFlags(world).contains(f.getID())))) plugin.getIWM().getHiddenFlags(world).contains(f.getID()))))
.toList(); .toList();
return result;
} }
@Override @Override
@ -137,8 +146,9 @@ public class SettingsTab implements Tab, ClickHandler {
icons.put(4, Flags.CHANGE_SETTINGS.toPanelItem(plugin, user, world, island, false)); icons.put(4, Flags.CHANGE_SETTINGS.toPanelItem(plugin, user, world, island, false));
icons.put(5, Flags.LOCK.toPanelItem(plugin, user, world, island, false)); icons.put(5, Flags.LOCK.toPanelItem(plugin, user, world, island, false));
} }
// Add the mode icon // Add the mode icon
switch (plugin.getPlayers().getFlagsDisplayMode(user.getUniqueId())) { switch (currentMode.getOrDefault(user.getUniqueId(), Mode.BASIC)) {
case ADVANCED -> icons.put(7, new PanelItemBuilder().icon(Material.GOLD_INGOT) case ADVANCED -> icons.put(7, new PanelItemBuilder().icon(Material.GOLD_INGOT)
.name(user.getTranslation(PROTECTION_PANEL + "mode.advanced.name")) .name(user.getTranslation(PROTECTION_PANEL + "mode.advanced.name"))
.description(user.getTranslation(PROTECTION_PANEL + "mode.advanced.description"), "", .description(user.getTranslation(PROTECTION_PANEL + "mode.advanced.description"), "",
@ -161,7 +171,8 @@ public class SettingsTab implements Tab, ClickHandler {
.clickHandler(this) .clickHandler(this)
.build()); .build());
} }
// Add the reset everything to default - it's only in the player's settings panel
// Add the reset everything to default - it's only in the player's settings panel
if (island != null && user.getUniqueId().equals(island.getOwner())) { if (island != null && user.getUniqueId().equals(island.getOwner())) {
icons.put(8, new PanelItemBuilder().icon(Material.TNT) icons.put(8, new PanelItemBuilder().icon(Material.TNT)
.name(user.getTranslation(PROTECTION_PANEL + "reset-to-default.name")) .name(user.getTranslation(PROTECTION_PANEL + "reset-to-default.name"))
@ -216,7 +227,7 @@ public class SettingsTab implements Tab, ClickHandler {
@Override @Override
public boolean onClick(Panel panel, User user, ClickType clickType, int slot) { public boolean onClick(Panel panel, User user, ClickType clickType, int slot) {
// Cycle the mode // Cycle the mode
plugin.getPlayers().setFlagsDisplayMode(user.getUniqueId(), plugin.getPlayers().getFlagsDisplayMode(user.getUniqueId()).getNext()); currentMode.put(user.getUniqueId(), currentMode.getOrDefault(user.getUniqueId(), Mode.BASIC).getNext());
if (panel instanceof TabbedPanel tp) { if (panel instanceof TabbedPanel tp) {
tp.setActivePage(0); tp.setActivePage(0);
tp.refreshPanel(); tp.refreshPanel();

View File

@ -7,6 +7,7 @@ import org.bukkit.Material;
import org.bukkit.World; import org.bukkit.World;
import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.NonNull;
import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.api.flags.Flag.Type; import world.bentobox.bentobox.api.flags.Flag.Type;
import world.bentobox.bentobox.api.flags.clicklisteners.WorldToggleClick; import world.bentobox.bentobox.api.flags.clicklisteners.WorldToggleClick;
import world.bentobox.bentobox.api.localization.TextVariables; import world.bentobox.bentobox.api.localization.TextVariables;

View File

@ -52,11 +52,12 @@ import world.bentobox.bentobox.listeners.flags.AbstractCommonSetup;
import world.bentobox.bentobox.lists.Flags; import world.bentobox.bentobox.lists.Flags;
import world.bentobox.bentobox.managers.CommandsManager; import world.bentobox.bentobox.managers.CommandsManager;
import world.bentobox.bentobox.managers.FlagsManager; import world.bentobox.bentobox.managers.FlagsManager;
import world.bentobox.bentobox.managers.IslandsManager;
import world.bentobox.bentobox.managers.RanksManager; import world.bentobox.bentobox.managers.RanksManager;
import world.bentobox.bentobox.util.Util; import world.bentobox.bentobox.util.Util;
@RunWith(PowerMockRunner.class) @RunWith(PowerMockRunner.class)
@PrepareForTest({ BentoBox.class, Flags.class, Util.class, Bukkit.class}) @PrepareForTest({ BentoBox.class, Flags.class, Util.class, Bukkit.class, IslandsManager.class })
public class TestBentoBox extends AbstractCommonSetup { public class TestBentoBox extends AbstractCommonSetup {
private static final UUID MEMBER_UUID = UUID.randomUUID(); private static final UUID MEMBER_UUID = UUID.randomUUID();
private static final UUID VISITOR_UUID = UUID.randomUUID(); private static final UUID VISITOR_UUID = UUID.randomUUID();
@ -76,6 +77,9 @@ public class TestBentoBox extends AbstractCommonSetup {
public void setUp() throws Exception { public void setUp() throws Exception {
super.setUp(); super.setUp();
// IslandsManager static
PowerMockito.mockStatic(IslandsManager.class, Mockito.RETURNS_MOCKS);
when(plugin.getCommandsManager()).thenReturn(cm); when(plugin.getCommandsManager()).thenReturn(cm);
SkullMeta skullMeta = mock(SkullMeta.class); SkullMeta skullMeta = mock(SkullMeta.class);
@ -87,6 +91,7 @@ public class TestBentoBox extends AbstractCommonSetup {
when(player.hasPermission(anyString())).thenReturn(true); when(player.hasPermission(anyString())).thenReturn(true);
when(location.getWorld()).thenReturn(world);
when(ownerOfIsland.getLocation()).thenReturn(location); when(ownerOfIsland.getLocation()).thenReturn(location);
when(visitorToIsland.getLocation()).thenReturn(location); when(visitorToIsland.getLocation()).thenReturn(location);
when(location.clone()).thenReturn(location); when(location.clone()).thenReturn(location);
@ -101,6 +106,7 @@ public class TestBentoBox extends AbstractCommonSetup {
island.setOwner(uuid); island.setOwner(uuid);
island.setProtectionRange(100); island.setProtectionRange(100);
island.setCenter(location);
HashMap<UUID, Integer> members = new HashMap<>(); HashMap<UUID, Integer> members = new HashMap<>();
members.put(uuid, RanksManager.OWNER_RANK); members.put(uuid, RanksManager.OWNER_RANK);
members.put(MEMBER_UUID, RanksManager.MEMBER_RANK); members.put(MEMBER_UUID, RanksManager.MEMBER_RANK);

View File

@ -32,10 +32,13 @@ 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.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 com.github.puregero.multilib.MultiLib;
import world.bentobox.bentobox.BentoBox; import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.api.addons.exceptions.InvalidAddonDescriptionException; import world.bentobox.bentobox.api.addons.exceptions.InvalidAddonDescriptionException;
import world.bentobox.bentobox.managers.AddonsManager; import world.bentobox.bentobox.managers.AddonsManager;
@ -46,7 +49,7 @@ import world.bentobox.bentobox.managers.AddonsManager;
* *
*/ */
@RunWith(PowerMockRunner.class) @RunWith(PowerMockRunner.class)
@PrepareForTest( { BentoBox.class, Bukkit.class }) @PrepareForTest({ BentoBox.class, Bukkit.class, MultiLib.class })
public class AddonClassLoaderTest { public class AddonClassLoaderTest {
private enum mandatoryTags { private enum mandatoryTags {
@ -80,6 +83,7 @@ public class AddonClassLoaderTest {
*/ */
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
PowerMockito.mockStatic(MultiLib.class, Mockito.RETURNS_MOCKS);
// Set up plugin // Set up plugin
plugin = mock(BentoBox.class); plugin = mock(BentoBox.class);
Whitebox.setInternalState(BentoBox.class, "instance", plugin); Whitebox.setInternalState(BentoBox.class, "instance", plugin);

View File

@ -44,13 +44,15 @@ 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 com.github.puregero.multilib.MultiLib;
import world.bentobox.bentobox.BentoBox; import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.managers.AddonsManager; import world.bentobox.bentobox.managers.AddonsManager;
import world.bentobox.bentobox.managers.IslandsManager; import world.bentobox.bentobox.managers.IslandsManager;
import world.bentobox.bentobox.managers.PlayersManager; import world.bentobox.bentobox.managers.PlayersManager;
@RunWith(PowerMockRunner.class) @RunWith(PowerMockRunner.class)
@PrepareForTest( { BentoBox.class, Bukkit.class }) @PrepareForTest({ BentoBox.class, Bukkit.class, MultiLib.class })
public class AddonTest { public class AddonTest {
public static int BUFFER_SIZE = 10240; public static int BUFFER_SIZE = 10240;
@ -90,6 +92,8 @@ public class AddonTest {
// Addons manager // Addons manager
when(plugin.getAddonsManager()).thenReturn(am); when(plugin.getAddonsManager()).thenReturn(am);
// MultiLib
PowerMockito.mockStatic(MultiLib.class, Mockito.RETURNS_MOCKS);
// Mock item factory (for itemstacks) // Mock item factory (for itemstacks)
ItemFactory itemFactory = mock(ItemFactory.class); ItemFactory itemFactory = mock(ItemFactory.class);

View File

@ -51,7 +51,7 @@ import world.bentobox.bentobox.util.Util;
* *
*/ */
@RunWith(PowerMockRunner.class) @RunWith(PowerMockRunner.class)
@PrepareForTest({ Bukkit.class, BentoBox.class, Util.class }) @PrepareForTest({ Bukkit.class, BentoBox.class, Util.class, IslandsManager.class })
public class AdminInfoCommandTest extends RanksManagerBeforeClassTest { public class AdminInfoCommandTest extends RanksManagerBeforeClassTest {
@Mock @Mock
@ -84,6 +84,8 @@ public class AdminInfoCommandTest extends RanksManagerBeforeClassTest {
public void setUp() throws Exception { public void setUp() throws Exception {
super.setUp(); super.setUp();
PowerMockito.mockStatic(IslandsManager.class, Mockito.RETURNS_MOCKS);
// IWM // IWM
when(plugin.getIWM()).thenReturn(iwm); when(plugin.getIWM()).thenReturn(iwm);

View File

@ -144,7 +144,6 @@ public class AdminSettingsCommandTest extends RanksManagerBeforeClassTest {
when(plugin.getIWM()).thenReturn(iwm); when(plugin.getIWM()).thenReturn(iwm);
// Players manager // Players manager
when(plugin.getPlayers()).thenReturn(pm); when(plugin.getPlayers()).thenReturn(pm);
when(pm.getFlagsDisplayMode(any())).thenReturn(Mode.BASIC);
//Island Manager //Island Manager
when(plugin.getIslands()).thenReturn(im); when(plugin.getIslands()).thenReturn(im);
// Island - player has island // Island - player has island
@ -268,16 +267,6 @@ public class AdminSettingsCommandTest extends RanksManagerBeforeClassTest {
verify(user).sendMessage("general.errors.use-in-game"); verify(user).sendMessage("general.errors.use-in-game");
} }
/**
* Test method for {@link world.bentobox.bentobox.api.commands.admin.AdminSettingsCommand#execute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}.
*/
@Test
public void testExecuteUserStringListOfStringNoArgs() {
assertTrue(asc.execute(user, "", Collections.emptyList()));
verify(pm).setFlagsDisplayMode(user.getUniqueId(), Mode.EXPERT);
// Open panel
}
/** /**
* Test method for {@link world.bentobox.bentobox.api.commands.admin.AdminSettingsCommand#execute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. * Test method for {@link world.bentobox.bentobox.api.commands.admin.AdminSettingsCommand#execute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}.
*/ */

View File

@ -29,6 +29,7 @@ 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.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;
@ -54,7 +55,7 @@ import world.bentobox.bentobox.util.Util;
* *
*/ */
@RunWith(PowerMockRunner.class) @RunWith(PowerMockRunner.class)
@PrepareForTest({ Bukkit.class, BentoBox.class }) @PrepareForTest({ Bukkit.class, BentoBox.class, IslandsManager.class })
public class AdminUnregisterCommandTest { public class AdminUnregisterCommandTest {
private UUID uuid = UUID.randomUUID(); private UUID uuid = UUID.randomUUID();
@ -83,6 +84,7 @@ public class AdminUnregisterCommandTest {
*/ */
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
PowerMockito.mockStatic(IslandsManager.class, Mockito.RETURNS_MOCKS);
// 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);

View File

@ -39,7 +39,7 @@ import world.bentobox.bentobox.managers.RanksManagerBeforeClassTest;
* *
*/ */
@RunWith(PowerMockRunner.class) @RunWith(PowerMockRunner.class)
@PrepareForTest({ Bukkit.class, BentoBox.class }) @PrepareForTest({ Bukkit.class, BentoBox.class, IslandsManager.class })
public class DefaultPlayerCommandTest extends RanksManagerBeforeClassTest { public class DefaultPlayerCommandTest extends RanksManagerBeforeClassTest {
@Mock @Mock
@ -68,6 +68,7 @@ public class DefaultPlayerCommandTest extends RanksManagerBeforeClassTest {
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
super.setUp(); super.setUp();
PowerMockito.mockStatic(IslandsManager.class, Mockito.RETURNS_MOCKS);
// User // User
when(user.getUniqueId()).thenReturn(UUID.randomUUID()); when(user.getUniqueId()).thenReturn(UUID.randomUUID());

View File

@ -51,7 +51,7 @@ import world.bentobox.bentobox.util.Util;
* *
*/ */
@RunWith(PowerMockRunner.class) @RunWith(PowerMockRunner.class)
@PrepareForTest({Bukkit.class, BentoBox.class, Util.class}) @PrepareForTest({ Bukkit.class, BentoBox.class, Util.class, IslandsManager.class })
public class IslandInfoCommandTest extends RanksManagerBeforeClassTest { public class IslandInfoCommandTest extends RanksManagerBeforeClassTest {
@Mock @Mock
@ -84,6 +84,8 @@ public class IslandInfoCommandTest extends RanksManagerBeforeClassTest {
public void setUp() throws Exception { public void setUp() throws Exception {
super.setUp(); super.setUp();
PowerMockito.mockStatic(IslandsManager.class, Mockito.RETURNS_MOCKS);
// IWM // IWM
when(plugin.getIWM()).thenReturn(iwm); when(plugin.getIWM()).thenReturn(iwm);

View File

@ -62,7 +62,7 @@ import world.bentobox.bentobox.managers.island.NewIsland;
* *
*/ */
@RunWith(PowerMockRunner.class) @RunWith(PowerMockRunner.class)
@PrepareForTest({ Bukkit.class, BentoBox.class, NewIsland.class }) @PrepareForTest({ Bukkit.class, BentoBox.class, NewIsland.class, IslandsManager.class })
public class IslandResetCommandTest { public class IslandResetCommandTest {
@Mock @Mock
@ -97,6 +97,7 @@ public class IslandResetCommandTest {
*/ */
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
PowerMockito.mockStatic(IslandsManager.class, Mockito.RETURNS_MOCKS);
// 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);

View File

@ -7,10 +7,13 @@ 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.eq; import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.atLeast;
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.beans.IntrospectionException;
import java.lang.reflect.InvocationTargetException;
import java.util.Collections; import java.util.Collections;
import java.util.UUID; import java.util.UUID;
@ -29,10 +32,11 @@ import org.powermock.modules.junit4.PowerMockRunner;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import world.bentobox.bentobox.BentoBox; import world.bentobox.bentobox.BentoBox;
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.island.team.Invite.Type;
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.database.objects.TeamInvite.Type;
import world.bentobox.bentobox.managers.CommandsManager; 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;
@ -74,6 +78,9 @@ public class IslandTeamCommandTest extends RanksManagerBeforeClassTest {
@Mock @Mock
private @Nullable Island island; private @Nullable Island island;
@Mock
private GameModeAddon addon;
/** /**
*/ */
@Before @Before
@ -87,6 +94,7 @@ public class IslandTeamCommandTest extends RanksManagerBeforeClassTest {
// Parent command // Parent command
when(ic.getPermissionPrefix()).thenReturn("bskyblock."); when(ic.getPermissionPrefix()).thenReturn("bskyblock.");
when(ic.getWorld()).thenReturn(world); when(ic.getWorld()).thenReturn(world);
when(ic.getAddon()).thenReturn(addon);
// user // user
uuid = UUID.randomUUID(); uuid = UUID.randomUUID();
@ -171,11 +179,14 @@ public class IslandTeamCommandTest extends RanksManagerBeforeClassTest {
/** /**
* Test method for * Test method for
* {@link world.bentobox.bentobox.api.commands.island.team.IslandTeamCommand#addInvite(world.bentobox.bentobox.api.commands.island.team.Invite.Type, java.util.UUID, java.util.UUID)}. * {@link world.bentobox.bentobox.api.commands.island.team.IslandTeamCommand#addInvite(world.bentobox.bentobox.api.commands.island.team.Invite.Type, java.util.UUID, java.util.UUID)}.
* @throws IntrospectionException
* @throws InvocationTargetException
* @throws IllegalAccessException
*/ */
@Test @Test
public void testAddInvite() { public void testAddInvite() throws IllegalAccessException, InvocationTargetException, IntrospectionException {
tc.addInvite(Invite.Type.TEAM, uuid, invitee, island); tc.addInvite(Type.TEAM, uuid, invitee, island);
assertTrue(tc.isInvited(invitee)); verify(h, atLeast(1)).saveObject(any());
} }
/** /**
@ -193,8 +204,7 @@ public class IslandTeamCommandTest extends RanksManagerBeforeClassTest {
*/ */
@Test @Test
public void testGetInviter() { public void testGetInviter() {
tc.addInvite(Invite.Type.TEAM, uuid, invitee, island); assertNull(tc.getInviter(invitee));
assertEquals(uuid, tc.getInviter(invitee));
} }
/** /**
@ -213,12 +223,6 @@ public class IslandTeamCommandTest extends RanksManagerBeforeClassTest {
@Test @Test
public void testGetInvite() { public void testGetInvite() {
assertNull(tc.getInvite(invitee)); assertNull(tc.getInvite(invitee));
tc.addInvite(Invite.Type.TEAM, uuid, invitee, island);
@Nullable
Invite invite = tc.getInvite(invitee);
assertEquals(invitee, invite.getInvitee());
assertEquals(Type.TEAM, invite.getType());
assertEquals(uuid, invite.getInviter());
} }
/** /**
@ -228,7 +232,7 @@ public class IslandTeamCommandTest extends RanksManagerBeforeClassTest {
@Test @Test
public void testRemoveInvite() { public void testRemoveInvite() {
assertNull(tc.getInvite(invitee)); assertNull(tc.getInvite(invitee));
tc.addInvite(Invite.Type.TEAM, uuid, invitee, island); tc.addInvite(Type.TEAM, uuid, invitee, island);
tc.removeInvite(invitee); tc.removeInvite(invitee);
assertNull(tc.getInvite(invitee)); assertNull(tc.getInvite(invitee));
} }

View File

@ -32,12 +32,13 @@ import org.powermock.reflect.Whitebox;
import world.bentobox.bentobox.BentoBox; import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.Settings; import world.bentobox.bentobox.Settings;
import world.bentobox.bentobox.TestWorldSettings; import world.bentobox.bentobox.TestWorldSettings;
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.events.team.TeamEvent.TeamEventBuilder; import world.bentobox.bentobox.api.events.team.TeamEvent.TeamEventBuilder;
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.database.objects.TeamInvite;
import world.bentobox.bentobox.database.objects.TeamInvite.Type;
import world.bentobox.bentobox.managers.CommandsManager; 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;
@ -72,7 +73,7 @@ public class IslandTeamInviteAcceptCommandTest {
@Mock @Mock
private PluginManager pim; private PluginManager pim;
@Mock @Mock
private Invite invite; private TeamInvite invite;
/** /**
*/ */
@ -148,7 +149,7 @@ public class IslandTeamInviteAcceptCommandTest {
when(plugin.getIWM()).thenReturn(iwm); when(plugin.getIWM()).thenReturn(iwm);
// Invite // Invite
when(invite.getType()).thenReturn(Invite.Type.TEAM); when(invite.getType()).thenReturn(Type.TEAM);
// Team invite accept command // Team invite accept command
c = new IslandTeamInviteAcceptCommand(itc); c = new IslandTeamInviteAcceptCommand(itc);
@ -281,7 +282,7 @@ public class IslandTeamInviteAcceptCommandTest {
when(itc.isInvited(any())).thenReturn(true); when(itc.isInvited(any())).thenReturn(true);
when(itc.getInviter(any())).thenReturn(notUUID); when(itc.getInviter(any())).thenReturn(notUUID);
when(itc.getInvite(any())).thenReturn(invite); when(itc.getInvite(any())).thenReturn(invite);
when(invite.getType()).thenReturn(Invite.Type.COOP); when(invite.getType()).thenReturn(Type.COOP);
when(im.inTeam(any(), any())).thenReturn(false); when(im.inTeam(any(), any())).thenReturn(false);
assertTrue(c.canExecute(user, "accept", Collections.emptyList())); assertTrue(c.canExecute(user, "accept", Collections.emptyList()));
verify(user, never()).sendMessage("commands.island.team.invite.errors.you-already-are-in-team"); verify(user, never()).sendMessage("commands.island.team.invite.errors.you-already-are-in-team");
@ -332,7 +333,7 @@ public class IslandTeamInviteAcceptCommandTest {
@Test @Test
public void testExecuteUserStringListOfStringCoop() { public void testExecuteUserStringListOfStringCoop() {
// Coop // Coop
when(invite.getType()).thenReturn(Invite.Type.COOP); when(invite.getType()).thenReturn(Type.COOP);
assertTrue(c.execute(user, "accept", Collections.emptyList())); assertTrue(c.execute(user, "accept", Collections.emptyList()));
verify(user).sendMessage("commands.confirmation.confirm", "[seconds]", "0"); verify(user).sendMessage("commands.confirmation.confirm", "[seconds]", "0");
} }
@ -343,7 +344,7 @@ public class IslandTeamInviteAcceptCommandTest {
@Test @Test
public void testExecuteUserStringListOfStringTrust() { public void testExecuteUserStringListOfStringTrust() {
// Trust // Trust
when(invite.getType()).thenReturn(Invite.Type.TRUST); when(invite.getType()).thenReturn(Type.TRUST);
assertTrue(c.execute(user, "accept", Collections.emptyList())); assertTrue(c.execute(user, "accept", Collections.emptyList()));
verify(user).sendMessage("commands.confirmation.confirm", "[seconds]", "0"); verify(user).sendMessage("commands.confirmation.confirm", "[seconds]", "0");
} }

View File

@ -40,12 +40,13 @@ import com.google.common.collect.ImmutableSet;
import world.bentobox.bentobox.BentoBox; import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.Settings; import world.bentobox.bentobox.Settings;
import world.bentobox.bentobox.TestWorldSettings; import world.bentobox.bentobox.TestWorldSettings;
import world.bentobox.bentobox.api.commands.island.team.Invite.Type;
import world.bentobox.bentobox.api.configuration.WorldSettings; import world.bentobox.bentobox.api.configuration.WorldSettings;
import world.bentobox.bentobox.api.events.IslandBaseEvent; import world.bentobox.bentobox.api.events.IslandBaseEvent;
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;
import world.bentobox.bentobox.database.objects.TeamInvite;
import world.bentobox.bentobox.database.objects.TeamInvite.Type;
import world.bentobox.bentobox.managers.CommandsManager; 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;
@ -319,7 +320,7 @@ public class IslandTeamInviteCommandTest extends RanksManagerBeforeClassTest {
assertTrue(itl.execute(user, itl.getLabel(), List.of("target"))); assertTrue(itl.execute(user, itl.getLabel(), List.of("target")));
verify(pim).callEvent(any(IslandBaseEvent.class)); verify(pim).callEvent(any(IslandBaseEvent.class));
verify(user, never()).sendMessage(eq("commands.island.team.invite.removing-invite")); verify(user, never()).sendMessage(eq("commands.island.team.invite.removing-invite"));
verify(ic).addInvite(Invite.Type.TEAM, uuid, notUUID, island); verify(ic).addInvite(Type.TEAM, uuid, notUUID, island);
verify(user).sendMessage("commands.island.team.invite.invitation-sent", TextVariables.NAME, "target", TextVariables.DISPLAY_NAME, "&Ctarget"); verify(user).sendMessage("commands.island.team.invite.invitation-sent", TextVariables.NAME, "target", TextVariables.DISPLAY_NAME, "&Ctarget");
verify(target).sendMessage("commands.island.team.invite.name-has-invited-you", TextVariables.NAME, "tastybento", TextVariables.DISPLAY_NAME, "&Ctastbento"); verify(target).sendMessage("commands.island.team.invite.name-has-invited-you", TextVariables.NAME, "tastybento", TextVariables.DISPLAY_NAME, "&Ctastbento");
verify(target).sendMessage("commands.island.team.invite.to-accept-or-reject", TextVariables.LABEL, "island"); verify(target).sendMessage("commands.island.team.invite.to-accept-or-reject", TextVariables.LABEL, "island");
@ -338,7 +339,7 @@ public class IslandTeamInviteCommandTest extends RanksManagerBeforeClassTest {
assertTrue(itl.execute(user, itl.getLabel(), List.of("target"))); assertTrue(itl.execute(user, itl.getLabel(), List.of("target")));
verify(pim).callEvent(any(IslandBaseEvent.class)); verify(pim).callEvent(any(IslandBaseEvent.class));
verify(user, never()).sendMessage("commands.island.team.invite.removing-invite"); verify(user, never()).sendMessage("commands.island.team.invite.removing-invite");
verify(ic).addInvite(Invite.Type.TEAM, uuid, notUUID, island); verify(ic).addInvite(Type.TEAM, uuid, notUUID, island);
verify(user).sendMessage("commands.island.team.invite.invitation-sent", TextVariables.NAME, "target", verify(user).sendMessage("commands.island.team.invite.invitation-sent", TextVariables.NAME, "target",
TextVariables.DISPLAY_NAME, "&Ctarget"); TextVariables.DISPLAY_NAME, "&Ctarget");
verify(target).sendMessage("commands.island.team.invite.name-has-invited-you", TextVariables.NAME, "tastybento", verify(target).sendMessage("commands.island.team.invite.name-has-invited-you", TextVariables.NAME, "tastybento",
@ -359,7 +360,7 @@ public class IslandTeamInviteCommandTest extends RanksManagerBeforeClassTest {
when(ic.isInvited(notUUID)).thenReturn(true); when(ic.isInvited(notUUID)).thenReturn(true);
// Set up invite // Set up invite
when(ic.getInviter(notUUID)).thenReturn(uuid); when(ic.getInviter(notUUID)).thenReturn(uuid);
Invite invite = mock(Invite.class); TeamInvite invite = mock(TeamInvite.class);
when(invite.getType()).thenReturn(Type.TEAM); when(invite.getType()).thenReturn(Type.TEAM);
when(ic.getInvite(notUUID)).thenReturn(invite); when(ic.getInvite(notUUID)).thenReturn(invite);
assertTrue(itl.execute(user, itl.getLabel(), List.of("target"))); assertTrue(itl.execute(user, itl.getLabel(), List.of("target")));

View File

@ -54,7 +54,7 @@ import world.bentobox.bentobox.managers.PlayersManager;
* *
*/ */
@RunWith(PowerMockRunner.class) @RunWith(PowerMockRunner.class)
@PrepareForTest({ Bukkit.class, BentoBox.class, User.class }) @PrepareForTest({ Bukkit.class, BentoBox.class, User.class, IslandsManager.class })
public class IslandTeamSetownerCommandTest { public class IslandTeamSetownerCommandTest {
@Mock @Mock
@ -84,6 +84,8 @@ public class IslandTeamSetownerCommandTest {
*/ */
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
PowerMockito.mockStatic(IslandsManager.class, Mockito.RETURNS_MOCKS);
// 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);
@ -276,7 +278,6 @@ public class IslandTeamSetownerCommandTest {
assertTrue(its.canExecute(user, "", List.of("tastybento"))); assertTrue(its.canExecute(user, "", List.of("tastybento")));
assertTrue(its.execute(user, "", List.of("tastybento"))); assertTrue(its.execute(user, "", List.of("tastybento")));
verify(im).setOwner(any(), eq(user), eq(target)); verify(im).setOwner(any(), eq(user), eq(target));
verify(im).save(island);
} }
/** /**
@ -292,7 +293,6 @@ public class IslandTeamSetownerCommandTest {
assertTrue(its.canExecute(user, "", List.of("tastybento"))); assertTrue(its.canExecute(user, "", List.of("tastybento")));
assertTrue(its.execute(user, "", List.of("tastybento"))); assertTrue(its.execute(user, "", List.of("tastybento")));
verify(im).setOwner(any(), eq(user), eq(target)); verify(im).setOwner(any(), eq(user), eq(target));
verify(im).save(island);
} }
/** /**

View File

@ -21,6 +21,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.events.IslandBaseEvent; import world.bentobox.bentobox.api.events.IslandBaseEvent;
@ -28,13 +29,14 @@ import world.bentobox.bentobox.api.events.island.IslandEvent.Reason;
import world.bentobox.bentobox.blueprints.dataobjects.BlueprintBundle; import world.bentobox.bentobox.blueprints.dataobjects.BlueprintBundle;
import world.bentobox.bentobox.database.objects.Island; import world.bentobox.bentobox.database.objects.Island;
import world.bentobox.bentobox.database.objects.IslandDeletion; import world.bentobox.bentobox.database.objects.IslandDeletion;
import world.bentobox.bentobox.managers.IslandsManager;
/** /**
* @author tastybento * @author tastybento
* *
*/ */
@RunWith(PowerMockRunner.class) @RunWith(PowerMockRunner.class)
@PrepareForTest({ BentoBox.class, Bukkit.class }) @PrepareForTest({ BentoBox.class, Bukkit.class, IslandsManager.class })
public class IslandEventTest { public class IslandEventTest {
private Island island; private Island island;
@ -47,11 +49,18 @@ public class IslandEventTest {
private IslandDeletion deletedIslandInfo; private IslandDeletion deletedIslandInfo;
@Mock @Mock
private PluginManager pim; private PluginManager pim;
@Mock
private BentoBox plugin;
/** /**
*/ */
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
PowerMockito.mockStatic(IslandsManager.class, Mockito.RETURNS_MOCKS);
// Set up plugin
Whitebox.setInternalState(BentoBox.class, "instance", plugin);
uuid = UUID.randomUUID(); uuid = UUID.randomUUID();
// Bukkit // Bukkit
PowerMockito.mockStatic(Bukkit.class); PowerMockito.mockStatic(Bukkit.class);

View File

@ -46,6 +46,7 @@ import world.bentobox.bentobox.lists.Flags;
import world.bentobox.bentobox.managers.CommandsManager; import world.bentobox.bentobox.managers.CommandsManager;
import world.bentobox.bentobox.managers.FlagsManager; import world.bentobox.bentobox.managers.FlagsManager;
import world.bentobox.bentobox.managers.IslandWorldManager; import world.bentobox.bentobox.managers.IslandWorldManager;
import world.bentobox.bentobox.managers.IslandsManager;
import world.bentobox.bentobox.managers.RanksManager; import world.bentobox.bentobox.managers.RanksManager;
import world.bentobox.bentobox.util.Pair; import world.bentobox.bentobox.util.Pair;
@ -54,7 +55,7 @@ import world.bentobox.bentobox.util.Pair;
* *
*/ */
@RunWith(PowerMockRunner.class) @RunWith(PowerMockRunner.class)
@PrepareForTest({ Bukkit.class }) @PrepareForTest({ Bukkit.class, IslandsManager.class })
public class IslandTest { public class IslandTest {
private static final int DISTANCE = 400; private static final int DISTANCE = 400;
@ -105,6 +106,9 @@ public class IslandTest {
// Commands manager // Commands manager
when(plugin.getCommandsManager()).thenReturn(cm); when(plugin.getCommandsManager()).thenReturn(cm);
// Islands Manager
PowerMockito.mockStatic(IslandsManager.class, Mockito.RETURNS_MOCKS);
i = new Island(new Island(location, uuid, 100)); i = new Island(new Island(location, uuid, 100));
} }
@ -1105,15 +1109,6 @@ public class IslandTest {
assertTrue(ii.isChanged()); assertTrue(ii.isChanged());
} }
/**
* Test method for {@link world.bentobox.bentobox.database.objects.Island#setChanged(boolean)}.
*/
@Test
public void testSetChangedBoolean() {
i.setChanged(false);
assertFalse(i.isChanged());
}
/** /**
* Test method for {@link world.bentobox.bentobox.database.objects.Island#getProtectionCenter()}. * Test method for {@link world.bentobox.bentobox.database.objects.Island#getProtectionCenter()}.
*/ */

View File

@ -65,7 +65,7 @@ import world.bentobox.bentobox.util.Util;
* *
*/ */
@RunWith(PowerMockRunner.class) @RunWith(PowerMockRunner.class)
@PrepareForTest({ BentoBox.class, Util.class, Bukkit.class }) @PrepareForTest({ BentoBox.class, Util.class, Bukkit.class, IslandsManager.class })
public class JoinLeaveListenerTest { public class JoinLeaveListenerTest {
private static final String[] NAMES = { "adam", "ben", "cara", "dave", "ed", "frank", "freddy", "george", "harry", private static final String[] NAMES = { "adam", "ben", "cara", "dave", "ed", "frank", "freddy", "george", "harry",
@ -111,6 +111,8 @@ public class JoinLeaveListenerTest {
*/ */
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
PowerMockito.mockStatic(IslandsManager.class, Mockito.RETURNS_MOCKS);
// Set up plugin // Set up plugin
Whitebox.setInternalState(BentoBox.class, "instance", plugin); Whitebox.setInternalState(BentoBox.class, "instance", plugin);
@ -218,8 +220,6 @@ public class JoinLeaveListenerTest {
jll = new JoinLeaveListener(plugin); jll = new JoinLeaveListener(plugin);
} }
/**
*/
@After @After
public void tearDown() { public void tearDown() {
User.clearUsers(); User.clearUsers();
@ -235,8 +235,7 @@ public class JoinLeaveListenerTest {
PlayerJoinEvent event = new PlayerJoinEvent(player, ""); PlayerJoinEvent event = new PlayerJoinEvent(player, "");
jll.onPlayerJoin(event); jll.onPlayerJoin(event);
// Verify // Verify
verify(pm, times(2)).addPlayer(any()); verify(pm, times(3)).getPlayer(any());
verify(pm, times(2)).save(any());
verify(player, never()).sendMessage(anyString()); verify(player, never()).sendMessage(anyString());
// Verify resets // Verify resets
verify(pm).setResets(eq(world), any(), eq(0)); verify(pm).setResets(eq(world), any(), eq(0));
@ -245,7 +244,6 @@ public class JoinLeaveListenerTest {
verify(chest).clear(); verify(chest).clear();
verify(inv).clear(); verify(inv).clear();
assertTrue(set.isEmpty()); assertTrue(set.isEmpty());
verify(pm, times(2)).save(any());
} }
/** /**
@ -262,7 +260,6 @@ public class JoinLeaveListenerTest {
verify(chest, never()).clear(); verify(chest, never()).clear();
verify(inv, never()).clear(); verify(inv, never()).clear();
assertFalse(set.isEmpty()); assertFalse(set.isEmpty());
verify(pm).save(any());
} }
/** /**
@ -355,8 +352,7 @@ public class JoinLeaveListenerTest {
PlayerJoinEvent event = new PlayerJoinEvent(player, ""); PlayerJoinEvent event = new PlayerJoinEvent(player, "");
jll.onPlayerJoin(event); jll.onPlayerJoin(event);
// Verify // Verify
verify(pm, times(2)).addPlayer(any()); verify(pm, times(3)).getPlayer(any());
verify(pm, times(2)).save(any());
verify(player).sendMessage(eq("commands.island.create.on-first-login")); verify(player).sendMessage(eq("commands.island.create.on-first-login"));
} }
@ -372,7 +368,6 @@ public class JoinLeaveListenerTest {
verify(chest).clear(); verify(chest).clear();
verify(inv).clear(); verify(inv).clear();
assertTrue(set.isEmpty()); assertTrue(set.isEmpty());
verify(pm).save(any());
} }
/** /**
@ -387,7 +382,6 @@ public class JoinLeaveListenerTest {
verify(chest, never()).clear(); verify(chest, never()).clear();
verify(inv, never()).clear(); verify(inv, never()).clear();
assertFalse(set.isEmpty()); assertFalse(set.isEmpty());
verify(pm, never()).save(any());
} }
/** /**

View File

@ -37,6 +37,8 @@ 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 com.github.puregero.multilib.MultiLib;
import world.bentobox.bentobox.BentoBox; import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.Settings; import world.bentobox.bentobox.Settings;
import world.bentobox.bentobox.api.addons.Addon; import world.bentobox.bentobox.api.addons.Addon;
@ -49,7 +51,7 @@ import world.bentobox.bentobox.database.DatabaseSetup.DatabaseType;
import world.bentobox.bentobox.database.objects.DataObject; import world.bentobox.bentobox.database.objects.DataObject;
@RunWith(PowerMockRunner.class) @RunWith(PowerMockRunner.class)
@PrepareForTest( {Bukkit.class, BentoBox.class, DefaultPermissions.class} ) @PrepareForTest({ Bukkit.class, BentoBox.class, DefaultPermissions.class, MultiLib.class })
public class AddonsManagerTest { public class AddonsManagerTest {
private BentoBox plugin; private BentoBox plugin;
@ -81,6 +83,8 @@ public class AddonsManagerTest {
when(plugin.getSettings()).thenReturn(s); when(plugin.getSettings()).thenReturn(s);
PowerMockito.mockStatic(DefaultPermissions.class); PowerMockito.mockStatic(DefaultPermissions.class);
PowerMockito.mockStatic(MultiLib.class, Mockito.RETURNS_MOCKS);
} }
/** /**

View File

@ -45,6 +45,8 @@ 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 com.github.puregero.multilib.MultiLib;
import world.bentobox.bentobox.BentoBox; import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.api.addons.Addon; import world.bentobox.bentobox.api.addons.Addon;
import world.bentobox.bentobox.api.addons.AddonDescription; import world.bentobox.bentobox.api.addons.AddonDescription;
@ -62,7 +64,7 @@ import world.bentobox.bentobox.database.objects.Island;
* *
*/ */
@RunWith(PowerMockRunner.class) @RunWith(PowerMockRunner.class)
@PrepareForTest( {Bukkit.class, BentoBox.class, BlueprintPaster.class} ) @PrepareForTest({ Bukkit.class, BentoBox.class, BlueprintPaster.class, MultiLib.class })
public class BlueprintsManagerTest { public class BlueprintsManagerTest {
public static int BUFFER_SIZE = 10240; public static int BUFFER_SIZE = 10240;
@ -95,10 +97,12 @@ public class BlueprintsManagerTest {
private int times; private int times;
@Mock @Mock
private Server server; private Server server;
/**
*/
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
// Multilib
PowerMockito.mockStatic(MultiLib.class, Mockito.RETURNS_MOCKS);
// Make the addon // Make the addon
dataFolder = new File("dataFolder"); dataFolder = new File("dataFolder");
jarFile = new File("addon.jar"); jarFile = new File("addon.jar");

View File

@ -65,6 +65,7 @@ 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 com.github.puregero.multilib.MultiLib;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSet.Builder; import com.google.common.collect.ImmutableSet.Builder;
@ -85,7 +86,7 @@ import world.bentobox.bentobox.managers.island.IslandCache;
import world.bentobox.bentobox.util.Util; import world.bentobox.bentobox.util.Util;
@RunWith(PowerMockRunner.class) @RunWith(PowerMockRunner.class)
@PrepareForTest({ Bukkit.class, BentoBox.class, Util.class, Location.class }) @PrepareForTest({ Bukkit.class, BentoBox.class, Util.class, Location.class, MultiLib.class })
public class IslandsManagerTest extends AbstractCommonSetup { public class IslandsManagerTest extends AbstractCommonSetup {
@Mock @Mock
@ -157,6 +158,9 @@ public class IslandsManagerTest extends AbstractCommonSetup {
plugin = mock(BentoBox.class); plugin = mock(BentoBox.class);
Whitebox.setInternalState(BentoBox.class, "instance", plugin); Whitebox.setInternalState(BentoBox.class, "instance", plugin);
// Mutilib
PowerMockito.mockStatic(MultiLib.class, Mockito.RETURNS_MOCKS);
// island world mgr // island world mgr
when(world.getName()).thenReturn("world"); when(world.getName()).thenReturn("world");
when(world.getEnvironment()).thenReturn(World.Environment.NORMAL); when(world.getEnvironment()).thenReturn(World.Environment.NORMAL);
@ -243,7 +247,7 @@ public class IslandsManagerTest extends AbstractCommonSetup {
// Island // Island
when(island.getOwner()).thenReturn(uuid); when(island.getOwner()).thenReturn(uuid);
when(island.getWorld()).thenReturn(world); when(island.getWorld()).thenReturn(world);
when(island.getMaxMembers()).thenReturn(null); // default when(island.getMaxMembers()).thenReturn(new HashMap<>()); // default
when(island.getMaxMembers(Mockito.anyInt())).thenReturn(null); // default when(island.getMaxMembers(Mockito.anyInt())).thenReturn(null); // default
when(island.getCenter()).thenReturn(location); when(island.getCenter()).thenReturn(location);
when(island.getProtectionCenter()).thenReturn(location); when(island.getProtectionCenter()).thenReturn(location);
@ -330,6 +334,9 @@ public class IslandsManagerTest extends AbstractCommonSetup {
// Util strip spaces // Util strip spaces
when(Util.stripSpaceAfterColorCodes(anyString())).thenCallRealMethod(); when(Util.stripSpaceAfterColorCodes(anyString())).thenCallRealMethod();
// World UID
when(world.getUID()).thenReturn(uuid);
// Class under test // Class under test
im = new IslandsManager(plugin); im = new IslandsManager(plugin);
// Set cache // Set cache
@ -971,7 +978,7 @@ public class IslandsManagerTest extends AbstractCommonSetup {
/** /**
* Test method for * Test method for
* {@link world.bentobox.bentobox.managers.IslandsManager#save(Island)}. * {@link world.bentobox.bentobox.managers.IslandsManager#updateIsland(Island)}.
*/ */
@Test @Test
public void testSave() { public void testSave() {
@ -1373,14 +1380,14 @@ public class IslandsManagerTest extends AbstractCommonSetup {
Island island = mock(Island.class); Island island = mock(Island.class);
when(island.getOwner()).thenReturn(uuid); when(island.getOwner()).thenReturn(uuid);
when(island.getWorld()).thenReturn(world); when(island.getWorld()).thenReturn(world);
when(island.getMaxMembers()).thenReturn(null); when(island.getMaxMembers()).thenReturn(new HashMap<>());
when(island.getMaxMembers(Mockito.anyInt())).thenReturn(null); when(island.getMaxMembers(Mockito.anyInt())).thenReturn(null);
when(iwm.getMaxTeamSize(eq(world))).thenReturn(4); when(iwm.getMaxTeamSize(eq(world))).thenReturn(4);
// Offline owner // Offline owner
when(Bukkit.getPlayer(any(UUID.class))).thenReturn(null); when(Bukkit.getPlayer(any(UUID.class))).thenReturn(null);
// Test // Test
assertEquals(4, im.getMaxMembers(island, RanksManager.MEMBER_RANK)); assertEquals(4, im.getMaxMembers(island, RanksManager.MEMBER_RANK));
verify(island).setMaxMembers(eq(RanksManager.MEMBER_RANK), eq(null)); verify(island, never()).setMaxMembers(eq(RanksManager.MEMBER_RANK), eq(null)); // No change
} }
/** /**
@ -1392,14 +1399,14 @@ public class IslandsManagerTest extends AbstractCommonSetup {
Island island = mock(Island.class); Island island = mock(Island.class);
when(island.getOwner()).thenReturn(uuid); when(island.getOwner()).thenReturn(uuid);
when(island.getWorld()).thenReturn(world); when(island.getWorld()).thenReturn(world);
when(island.getMaxMembers()).thenReturn(null); when(island.getMaxMembers()).thenReturn(new HashMap<>());
when(island.getMaxMembers(Mockito.anyInt())).thenReturn(null); when(island.getMaxMembers(Mockito.anyInt())).thenReturn(null);
when(iwm.getMaxTeamSize(eq(world))).thenReturn(4); when(iwm.getMaxTeamSize(eq(world))).thenReturn(4);
// Online owner // Online owner
when(Bukkit.getPlayer(any(UUID.class))).thenReturn(player); when(Bukkit.getPlayer(any(UUID.class))).thenReturn(player);
// Test // Test
assertEquals(4, im.getMaxMembers(island, RanksManager.MEMBER_RANK)); assertEquals(4, im.getMaxMembers(island, RanksManager.MEMBER_RANK));
verify(island).setMaxMembers(eq(RanksManager.MEMBER_RANK), eq(null)); verify(island, never()).setMaxMembers(RanksManager.MEMBER_RANK, null);
} }
/** /**
@ -1411,7 +1418,7 @@ public class IslandsManagerTest extends AbstractCommonSetup {
Island island = mock(Island.class); Island island = mock(Island.class);
when(island.getOwner()).thenReturn(uuid); when(island.getOwner()).thenReturn(uuid);
when(island.getWorld()).thenReturn(world); when(island.getWorld()).thenReturn(world);
when(island.getMaxMembers()).thenReturn(null); when(island.getMaxMembers()).thenReturn(new HashMap<>());
when(island.getMaxMembers(Mockito.anyInt())).thenReturn(null); when(island.getMaxMembers(Mockito.anyInt())).thenReturn(null);
when(iwm.getMaxTeamSize(eq(world))).thenReturn(4); when(iwm.getMaxTeamSize(eq(world))).thenReturn(4);
when(iwm.getMaxCoopSize(eq(world))).thenReturn(2); when(iwm.getMaxCoopSize(eq(world))).thenReturn(2);
@ -1420,9 +1427,9 @@ public class IslandsManagerTest extends AbstractCommonSetup {
when(Bukkit.getPlayer(any(UUID.class))).thenReturn(player); when(Bukkit.getPlayer(any(UUID.class))).thenReturn(player);
// Test // Test
assertEquals(2, im.getMaxMembers(island, RanksManager.COOP_RANK)); assertEquals(2, im.getMaxMembers(island, RanksManager.COOP_RANK));
verify(island).setMaxMembers(eq(RanksManager.COOP_RANK), eq(null)); verify(island, never()).setMaxMembers(RanksManager.COOP_RANK, null); // No change
assertEquals(3, im.getMaxMembers(island, RanksManager.TRUSTED_RANK)); assertEquals(3, im.getMaxMembers(island, RanksManager.TRUSTED_RANK));
verify(island).setMaxMembers(eq(RanksManager.TRUSTED_RANK), eq(null)); verify(island, never()).setMaxMembers(RanksManager.TRUSTED_RANK, null);
} }
/** /**
@ -1440,7 +1447,7 @@ public class IslandsManagerTest extends AbstractCommonSetup {
when(Bukkit.getPlayer(any(UUID.class))).thenReturn(player); when(Bukkit.getPlayer(any(UUID.class))).thenReturn(player);
// Test // Test
assertEquals(10, im.getMaxMembers(island, RanksManager.MEMBER_RANK)); assertEquals(10, im.getMaxMembers(island, RanksManager.MEMBER_RANK));
verify(island).setMaxMembers(eq(RanksManager.MEMBER_RANK), eq(10)); verify(island).setMaxMembers(RanksManager.MEMBER_RANK, 10);
} }
/** /**
@ -1458,7 +1465,7 @@ public class IslandsManagerTest extends AbstractCommonSetup {
when(Bukkit.getPlayer(any(UUID.class))).thenReturn(player); when(Bukkit.getPlayer(any(UUID.class))).thenReturn(player);
// Test // Test
assertEquals(10, im.getMaxMembers(island, RanksManager.MEMBER_RANK)); assertEquals(10, im.getMaxMembers(island, RanksManager.MEMBER_RANK));
verify(island).setMaxMembers(eq(RanksManager.MEMBER_RANK), eq(10)); verify(island).setMaxMembers(RanksManager.MEMBER_RANK, 10);
} }
/** /**
@ -1470,7 +1477,7 @@ public class IslandsManagerTest extends AbstractCommonSetup {
Island island = mock(Island.class); Island island = mock(Island.class);
when(island.getOwner()).thenReturn(uuid); when(island.getOwner()).thenReturn(uuid);
when(island.getWorld()).thenReturn(world); when(island.getWorld()).thenReturn(world);
when(island.getMaxMembers()).thenReturn(null); when(island.getMaxMembers()).thenReturn(new HashMap<>());
when(iwm.getMaxTeamSize(eq(world))).thenReturn(4); when(iwm.getMaxTeamSize(eq(world))).thenReturn(4);
// Permission // Permission
when(iwm.getPermissionPrefix(any())).thenReturn("bskyblock."); when(iwm.getPermissionPrefix(any())).thenReturn("bskyblock.");
@ -1483,7 +1490,7 @@ public class IslandsManagerTest extends AbstractCommonSetup {
when(Bukkit.getPlayer(any(UUID.class))).thenReturn(player); when(Bukkit.getPlayer(any(UUID.class))).thenReturn(player);
// Test // Test
assertEquals(8, im.getMaxMembers(island, RanksManager.MEMBER_RANK)); assertEquals(8, im.getMaxMembers(island, RanksManager.MEMBER_RANK));
verify(island).setMaxMembers(eq(RanksManager.MEMBER_RANK), eq(8)); verify(island).setMaxMembers(RanksManager.MEMBER_RANK, 8);
} }
/** /**
@ -1495,7 +1502,7 @@ public class IslandsManagerTest extends AbstractCommonSetup {
Island island = mock(Island.class); Island island = mock(Island.class);
// Test // Test
im.setMaxMembers(island, RanksManager.MEMBER_RANK, 40); im.setMaxMembers(island, RanksManager.MEMBER_RANK, 40);
verify(island).setMaxMembers(eq(RanksManager.MEMBER_RANK), eq(40)); verify(island).setMaxMembers(RanksManager.MEMBER_RANK, 40);
} }
/** /**
@ -1547,7 +1554,7 @@ public class IslandsManagerTest extends AbstractCommonSetup {
// Test // Test
IslandsManager im = new IslandsManager(plugin); IslandsManager im = new IslandsManager(plugin);
assertEquals(4, im.getMaxHomes(island)); assertEquals(4, im.getMaxHomes(island));
verify(island).setMaxHomes(eq(null)); verify(island, never()).setMaxHomes(null);
} }
/** /**
@ -1573,7 +1580,7 @@ public class IslandsManagerTest extends AbstractCommonSetup {
// Test // Test
IslandsManager im = new IslandsManager(plugin); IslandsManager im = new IslandsManager(plugin);
assertEquals(20, im.getMaxHomes(island)); assertEquals(20, im.getMaxHomes(island));
verify(island).setMaxHomes(eq(20)); verify(island, never()).setMaxHomes(20);
} }
/** /**
@ -1599,7 +1606,7 @@ public class IslandsManagerTest extends AbstractCommonSetup {
// Test // Test
IslandsManager im = new IslandsManager(plugin); IslandsManager im = new IslandsManager(plugin);
assertEquals(8, im.getMaxHomes(island)); assertEquals(8, im.getMaxHomes(island));
verify(island).setMaxHomes(eq(8)); verify(island).setMaxHomes(8);
} }
/** /**

View File

@ -6,7 +6,9 @@ import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull; import static org.junit.Assert.assertNull;
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.atLeast;
import static org.mockito.Mockito.mock; 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;
@ -53,13 +55,13 @@ import org.powermock.reflect.Whitebox;
import world.bentobox.bentobox.BentoBox; import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.Settings; import world.bentobox.bentobox.Settings;
import world.bentobox.bentobox.api.flags.Flag.Mode;
import world.bentobox.bentobox.api.user.User; import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.database.AbstractDatabaseHandler; import world.bentobox.bentobox.database.AbstractDatabaseHandler;
import world.bentobox.bentobox.database.Database; import world.bentobox.bentobox.database.Database;
import world.bentobox.bentobox.database.DatabaseSetup; import world.bentobox.bentobox.database.DatabaseSetup;
import world.bentobox.bentobox.database.DatabaseSetup.DatabaseType; import world.bentobox.bentobox.database.DatabaseSetup.DatabaseType;
import world.bentobox.bentobox.database.objects.Island; import world.bentobox.bentobox.database.objects.Island;
import world.bentobox.bentobox.database.objects.Names;
import world.bentobox.bentobox.database.objects.Players; import world.bentobox.bentobox.database.objects.Players;
import world.bentobox.bentobox.hooks.VaultHook; import world.bentobox.bentobox.hooks.VaultHook;
import world.bentobox.bentobox.util.Util; import world.bentobox.bentobox.util.Util;
@ -240,6 +242,18 @@ public class PlayersManagerTest {
when(tamed.getOwner()).thenReturn(p); when(tamed.getOwner()).thenReturn(p);
when(world.getEntitiesByClass(Tameable.class)).thenReturn(list); when(world.getEntitiesByClass(Tameable.class)).thenReturn(list);
// Loading objects
Object players = new Players();
when(h.loadObject(anyString())).thenReturn(players);
// Set up names database
List<Object> names = new ArrayList<>();
Names name = new Names();
name.setUniqueId("tastybento");
name.setUuid(uuid);
names.add(name);
when(h.loadObjects()).thenReturn(names);
when(h.objectExists(anyString())).thenReturn(true);
// Class under test // Class under test
pm = new PlayersManager(plugin); pm = new PlayersManager(plugin);
} }
@ -263,21 +277,6 @@ public class PlayersManagerTest {
assertEquals(deaths + 1, pm.getDeaths(world, uuid)); assertEquals(deaths + 1, pm.getDeaths(world, uuid));
} }
/**
* Test method for
* {@link world.bentobox.bentobox.managers.PlayersManager#addPlayer(java.util.UUID)}.
*/
@Test
public void testAddPlayer() {
pm.addPlayer(null);
// Add twice
assertFalse(pm.isKnown(uuid));
pm.addPlayer(uuid);
assertTrue(pm.isKnown(uuid));
pm.addPlayer(uuid);
}
/** /**
* Test method for * Test method for
* {@link world.bentobox.bentobox.managers.PlayersManager#addReset(org.bukkit.World, java.util.UUID)}. * {@link world.bentobox.bentobox.managers.PlayersManager#addReset(org.bukkit.World, java.util.UUID)}.
@ -372,15 +371,6 @@ public class PlayersManagerTest {
assertEquals(0, pm.getDeaths(world, uuid)); assertEquals(0, pm.getDeaths(world, uuid));
} }
/**
* Test method for
* {@link world.bentobox.bentobox.managers.PlayersManager#getFlagsDisplayMode(java.util.UUID)}.
*/
@Test
public void testGetFlagsDisplayMode() {
assertEquals(Mode.BASIC, pm.getFlagsDisplayMode(uuid));
}
/** /**
* Test method for * Test method for
* {@link world.bentobox.bentobox.managers.PlayersManager#getLocale(java.util.UUID)}. * {@link world.bentobox.bentobox.managers.PlayersManager#getLocale(java.util.UUID)}.
@ -401,24 +391,13 @@ public class PlayersManagerTest {
assertEquals("tastybento", name); assertEquals("tastybento", name);
} }
/**
* Test method for
* {@link world.bentobox.bentobox.managers.PlayersManager#getPlayer(java.util.UUID)}.
*/
@Test
public void testGetPlayer() {
Players player = pm.getPlayer(uuid);
assertEquals("tastybento", player.getPlayerName());
assertEquals(uuid.toString(), player.getUniqueId());
}
/** /**
* Test method for * Test method for
* {@link world.bentobox.bentobox.managers.PlayersManager#getPlayers()}. * {@link world.bentobox.bentobox.managers.PlayersManager#getPlayers()}.
*/ */
@Test @Test
public void testGetPlayers() { public void testGetPlayers() {
assertTrue(pm.getPlayers().isEmpty()); assertFalse(pm.getPlayers().isEmpty());
} }
/** /**
@ -442,11 +421,18 @@ public class PlayersManagerTest {
/** /**
* Test method for * Test method for
* {@link world.bentobox.bentobox.managers.PlayersManager#setResets(World, UUID, int)}. * {@link world.bentobox.bentobox.managers.PlayersManager#setResets(World, UUID, int)}.
* @throws IntrospectionException
* @throws NoSuchMethodException
* @throws ClassNotFoundException
* @throws InvocationTargetException
* @throws IllegalAccessException
* @throws InstantiationException
*/ */
@Test @Test
public void testGetSetResetsLeft() { public void testGetSetResetsLeft() throws InstantiationException, IllegalAccessException, InvocationTargetException,
ClassNotFoundException, NoSuchMethodException, IntrospectionException {
// Add a player // Add a player
pm.addPlayer(uuid); pm.getPlayer(uuid);
assertEquals(0, pm.getResets(world, uuid)); assertEquals(0, pm.getResets(world, uuid));
pm.setResets(world, uuid, 20); pm.setResets(world, uuid, 20);
assertEquals(20, pm.getResets(world, uuid)); assertEquals(20, pm.getResets(world, uuid));
@ -455,12 +441,19 @@ public class PlayersManagerTest {
/** /**
* Test method for * Test method for
* {@link world.bentobox.bentobox.managers.PlayersManager#getUser(java.lang.String)}. * {@link world.bentobox.bentobox.managers.PlayersManager#getUser(java.lang.String)}.
* @throws IntrospectionException
* @throws NoSuchMethodException
* @throws ClassNotFoundException
* @throws InvocationTargetException
* @throws IllegalAccessException
* @throws InstantiationException
*/ */
@Test @Test
public void testGetUserString() { public void testGetUserString() throws InstantiationException, IllegalAccessException, InvocationTargetException,
ClassNotFoundException, NoSuchMethodException, IntrospectionException {
User user = pm.getUser("random"); User user = pm.getUser("random");
assertNull(user); assertNull(user);
pm.addPlayer(uuid); pm.getPlayer(uuid);
user = pm.getUser("tastybento"); user = pm.getUser("tastybento");
assertEquals("tastybento", user.getName()); assertEquals("tastybento", user.getName());
} }
@ -481,7 +474,7 @@ public class PlayersManagerTest {
*/ */
@Test @Test
public void testGetUUID() { public void testGetUUID() {
pm.addPlayer(uuid); pm.getPlayer(uuid);
assertEquals(uuid, pm.getUUID("tastybento")); assertEquals(uuid, pm.getUUID("tastybento"));
assertNull(pm.getUUID("unknown")); assertNull(pm.getUUID("unknown"));
} }
@ -494,7 +487,7 @@ public class PlayersManagerTest {
public void testGetUUIDOfflinePlayer() { public void testGetUUIDOfflinePlayer() {
pm.setHandler(db); pm.setHandler(db);
// Add a player to the cache // Add a player to the cache
pm.addPlayer(uuid); pm.getPlayer(uuid);
UUID uuidResult = pm.getUUID("tastybento"); UUID uuidResult = pm.getUUID("tastybento");
assertEquals(uuid, uuidResult); assertEquals(uuid, uuidResult);
} }
@ -507,7 +500,7 @@ public class PlayersManagerTest {
public void testGetUUIDUnknownPlayer() { public void testGetUUIDUnknownPlayer() {
pm.setHandler(db); pm.setHandler(db);
// Add a player to the cache // Add a player to the cache
pm.addPlayer(uuid); pm.getPlayer(uuid);
// Unknown player should return null // Unknown player should return null
assertNull(pm.getUUID("tastybento123")); assertNull(pm.getUUID("tastybento123"));
} }
@ -537,8 +530,8 @@ public class PlayersManagerTest {
@Test @Test
public void testIsKnown() { public void testIsKnown() {
pm.addPlayer(uuid); pm.getPlayer(uuid);
pm.addPlayer(notUUID); pm.getPlayer(notUUID);
assertFalse(pm.isKnown(null)); assertFalse(pm.isKnown(null));
assertTrue(pm.isKnown(uuid)); assertTrue(pm.isKnown(uuid));
@ -547,21 +540,11 @@ public class PlayersManagerTest {
/** /**
* Test method for * Test method for
* {@link world.bentobox.bentobox.managers.PlayersManager#isSaveTaskRunning()}. * {@link world.bentobox.bentobox.managers.PlayersManager#setHandler(Database)}
*/ */
@Test @Test
public void testIsSaveTaskRunning() { public void testSetHandler() {
assertFalse(pm.isSaveTaskRunning());
}
/**
* Test method for
* {@link world.bentobox.bentobox.managers.PlayersManager#load()}.
*/
@Test
public void testLoad() {
pm.setHandler(db); pm.setHandler(db);
pm.load();
} }
/** /**
@ -596,43 +579,6 @@ public class PlayersManagerTest {
assertNull(pm.getUUID("tastybeto")); assertNull(pm.getUUID("tastybeto"));
} }
/**
* Test method for
* {@link world.bentobox.bentobox.managers.PlayersManager#saveAll()}.
*/
@Test
public void testSaveAll() {
pm.setHandler(db);
pm.addPlayer(uuid);
pm.saveAll();
verify(db).saveObjectAsync(any());
}
/**
* Test method for
* {@link world.bentobox.bentobox.managers.PlayersManager#saveAll(boolean)}.
*/
@Test
public void testSaveAllBoolean() {
pm.setHandler(db);
pm.addPlayer(uuid);
pm.saveAll(true);
assertTrue(pm.isSaveTaskRunning());
}
/**
* Test method for
* {@link world.bentobox.bentobox.managers.PlayersManager#save(java.util.UUID)}.
*/
@Test
public void testSave() {
pm.setHandler(db);
// Add a player
pm.addPlayer(uuid);
pm.save(uuid);
verify(db).saveObjectAsync(any());
}
/** /**
* Test method for * Test method for
* {@link world.bentobox.bentobox.managers.PlayersManager#setPlayerName(world.bentobox.bentobox.api.user.User)}. * {@link world.bentobox.bentobox.managers.PlayersManager#setPlayerName(world.bentobox.bentobox.api.user.User)}.
@ -641,7 +587,7 @@ public class PlayersManagerTest {
public void testSetandGetPlayerName() { public void testSetandGetPlayerName() {
pm.setHandler(db); pm.setHandler(db);
// Add a player // Add a player
pm.addPlayer(uuid); pm.getPlayer(uuid);
assertEquals("tastybento", pm.getName(user.getUniqueId())); assertEquals("tastybento", pm.getName(user.getUniqueId()));
pm.setPlayerName(user); pm.setPlayerName(user);
assertEquals(user.getName(), pm.getName(user.getUniqueId())); assertEquals(user.getName(), pm.getName(user.getUniqueId()));
@ -658,16 +604,6 @@ public class PlayersManagerTest {
} }
/**
* Test method for
* {@link world.bentobox.bentobox.managers.PlayersManager#setFlagsDisplayMode(java.util.UUID, world.bentobox.bentobox.api.flags.Flag.Mode)}.
*/
@Test
public void testSetFlagsDisplayMode() {
pm.setFlagsDisplayMode(uuid, Mode.ADVANCED);
assertEquals(Mode.ADVANCED, pm.getFlagsDisplayMode(uuid));
}
/** /**
* Test method for * Test method for
* {@link world.bentobox.bentobox.managers.PlayersManager#setInTeleport(java.util.UUID)}. * {@link world.bentobox.bentobox.managers.PlayersManager#setInTeleport(java.util.UUID)}.
@ -692,15 +628,15 @@ public class PlayersManagerTest {
/** /**
* Test method for * Test method for
* {@link world.bentobox.bentobox.managers.PlayersManager#setPlayerName(world.bentobox.bentobox.api.user.User)}. * {@link world.bentobox.bentobox.managers.PlayersManager#setPlayerName(world.bentobox.bentobox.api.user.User)}.
* @throws IntrospectionException
* @throws InvocationTargetException
* @throws IllegalAccessException
*/ */
@Test @Test
public void testSetPlayerName() { public void testSetPlayerName() throws IllegalAccessException, InvocationTargetException, IntrospectionException {
pm.setPlayerName(user); pm.setPlayerName(user);
assertEquals("tastybento", pm.getName(uuid)); // Player and names database saves
when(user.getName()).thenReturn("newName"); verify(h, atLeast(2)).saveObject(any());
assertEquals("tastybento", pm.getName(uuid));
pm.setPlayerName(user);
assertEquals("newName", pm.getName(uuid));
} }
/** /**

View File

@ -1,17 +1,23 @@
package world.bentobox.bentobox.managers; package world.bentobox.bentobox.managers;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import java.beans.IntrospectionException;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.Comparator; import java.util.Comparator;
import java.util.Map; import java.util.Map;
import java.util.concurrent.CompletableFuture;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.BeforeClass;
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;
@ -22,6 +28,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.database.AbstractDatabaseHandler;
import world.bentobox.bentobox.database.DatabaseSetup; import world.bentobox.bentobox.database.DatabaseSetup;
/** /**
@ -63,6 +70,22 @@ public abstract class RanksManagerBeforeClassTest {
@Mock @Mock
public RanksManager rm; public RanksManager rm;
protected static AbstractDatabaseHandler<Object> h;
@SuppressWarnings("unchecked")
@BeforeClass
public static void beforeClass() throws IllegalAccessException, InvocationTargetException, IntrospectionException {
// This has to be done beforeClass otherwise the tests will interfere with each
// other
h = mock(AbstractDatabaseHandler.class);
// Database
PowerMockito.mockStatic(DatabaseSetup.class);
DatabaseSetup dbSetup = mock(DatabaseSetup.class);
when(DatabaseSetup.getDatabase()).thenReturn(dbSetup);
when(dbSetup.getHandler(any())).thenReturn(h);
when(h.saveObject(any())).thenReturn(CompletableFuture.completedFuture(true));
}
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
// Set up plugin // Set up plugin

View File

@ -56,7 +56,7 @@ import world.bentobox.bentobox.util.Util;
* *
*/ */
@RunWith(PowerMockRunner.class) @RunWith(PowerMockRunner.class)
@PrepareForTest({ Util.class, IslandEvent.class, Bukkit.class }) @PrepareForTest({ Util.class, IslandEvent.class, Bukkit.class, IslandsManager.class })
public class NewIslandTest { public class NewIslandTest {
private static final String NAME = "name"; private static final String NAME = "name";
@ -105,6 +105,7 @@ public class NewIslandTest {
*/ */
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
PowerMockito.mockStatic(IslandsManager.class, Mockito.RETURNS_MOCKS);
Whitebox.setInternalState(BentoBox.class, "instance", plugin); Whitebox.setInternalState(BentoBox.class, "instance", plugin);
// Islands manager // Islands manager
when(plugin.getIslands()).thenReturn(im); when(plugin.getIslands()).thenReturn(im);
@ -205,7 +206,8 @@ public class NewIslandTest {
NewIsland.builder().addon(addon).name(NAME).player(user).noPaste().reason(Reason.CREATE).oldIsland(oldIsland) NewIsland.builder().addon(addon).name(NAME).player(user).noPaste().reason(Reason.CREATE).oldIsland(oldIsland)
.build(); .build();
// Verifications // Verifications
verify(im).save(eq(island)); PowerMockito.verifyStatic(IslandsManager.class);
IslandsManager.updateIsland(eq(island));
verify(island).setFlagsDefaults(); verify(island).setFlagsDefaults();
verify(scheduler).runTask(any(BentoBox.class), any(Runnable.class)); verify(scheduler).runTask(any(BentoBox.class), any(Runnable.class));
verify(builder, times(2)).build(); verify(builder, times(2)).build();
@ -224,7 +226,8 @@ public class NewIslandTest {
when(builder.build()).thenReturn(ire); when(builder.build()).thenReturn(ire);
NewIsland.builder().addon(addon).name(NAME).player(user).noPaste().reason(Reason.RESET).oldIsland(oldIsland).build(); NewIsland.builder().addon(addon).name(NAME).player(user).noPaste().reason(Reason.RESET).oldIsland(oldIsland).build();
// Verifications // Verifications
verify(im).save(eq(island)); PowerMockito.verifyStatic(IslandsManager.class);
IslandsManager.updateIsland(eq(island));
verify(island).setFlagsDefaults(); verify(island).setFlagsDefaults();
verify(scheduler).runTask(any(BentoBox.class), any(Runnable.class)); verify(scheduler).runTask(any(BentoBox.class), any(Runnable.class));
verify(builder, times(2)).build(); verify(builder, times(2)).build();
@ -243,7 +246,8 @@ public class NewIslandTest {
public void testBuilderNoOldIsland() throws Exception { public void testBuilderNoOldIsland() throws Exception {
NewIsland.builder().addon(addon).name(NAME).player(user).noPaste().reason(Reason.CREATE).build(); NewIsland.builder().addon(addon).name(NAME).player(user).noPaste().reason(Reason.CREATE).build();
// Verifications // Verifications
verify(im).save(eq(island)); PowerMockito.verifyStatic(IslandsManager.class);
IslandsManager.updateIsland(eq(island));
verify(island).setFlagsDefaults(); verify(island).setFlagsDefaults();
verify(scheduler).runTask(any(BentoBox.class), any(Runnable.class)); verify(scheduler).runTask(any(BentoBox.class), any(Runnable.class));
verify(builder, times(2)).build(); verify(builder, times(2)).build();
@ -262,7 +266,8 @@ public class NewIslandTest {
when(location.distance(any())).thenReturn(30D); when(location.distance(any())).thenReturn(30D);
NewIsland.builder().addon(addon).name(NAME).player(user).reason(Reason.CREATE).build(); NewIsland.builder().addon(addon).name(NAME).player(user).reason(Reason.CREATE).build();
// Verifications // Verifications
verify(im).save(eq(island)); PowerMockito.verifyStatic(IslandsManager.class);
IslandsManager.updateIsland(eq(island));
verify(island).setFlagsDefaults(); verify(island).setFlagsDefaults();
verify(bpm).paste(eq(addon), eq(island), eq(NAME), any(Runnable.class), eq(false)); verify(bpm).paste(eq(addon), eq(island), eq(NAME), any(Runnable.class), eq(false));
verify(builder, times(2)).build(); verify(builder, times(2)).build();
@ -281,7 +286,8 @@ 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(island); PowerMockito.verifyStatic(IslandsManager.class);
IslandsManager.updateIsland(eq(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();
@ -299,7 +305,8 @@ public class NewIslandTest {
when(im.hasIsland(any(), any(User.class))).thenReturn(true); when(im.hasIsland(any(), any(User.class))).thenReturn(true);
NewIsland.builder().addon(addon).name(NAME).player(user).noPaste().reason(Reason.CREATE).oldIsland(oldIsland).build(); NewIsland.builder().addon(addon).name(NAME).player(user).noPaste().reason(Reason.CREATE).oldIsland(oldIsland).build();
// Verifications // Verifications
verify(im).save(eq(island)); PowerMockito.verifyStatic(IslandsManager.class);
IslandsManager.updateIsland(eq(island));
verify(island).setFlagsDefaults(); verify(island).setFlagsDefaults();
verify(scheduler).runTask(any(BentoBox.class), any(Runnable.class)); verify(scheduler).runTask(any(BentoBox.class), any(Runnable.class));
verify(builder, times(2)).build(); verify(builder, times(2)).build();
@ -320,7 +327,8 @@ public class NewIslandTest {
when(im.hasIsland(any(), any(User.class))).thenReturn(true); when(im.hasIsland(any(), any(User.class))).thenReturn(true);
NewIsland.builder().addon(addon).name(NAME).player(user).noPaste().reason(Reason.CREATE).oldIsland(oldIsland).build(); NewIsland.builder().addon(addon).name(NAME).player(user).noPaste().reason(Reason.CREATE).oldIsland(oldIsland).build();
// Verifications // Verifications
verify(im).save(eq(island)); PowerMockito.verifyStatic(IslandsManager.class);
IslandsManager.updateIsland(eq(island));
verify(island).setFlagsDefaults(); verify(island).setFlagsDefaults();
verify(scheduler).runTask(any(BentoBox.class), any(Runnable.class)); verify(scheduler).runTask(any(BentoBox.class), any(Runnable.class));
verify(builder, times(2)).build(); verify(builder, times(2)).build();
@ -342,7 +350,8 @@ public class NewIslandTest {
when(im.hasIsland(any(), any(User.class))).thenReturn(true); when(im.hasIsland(any(), any(User.class))).thenReturn(true);
NewIsland.builder().addon(addon).name(NAME).player(user).noPaste().reason(Reason.CREATE).oldIsland(oldIsland).build(); NewIsland.builder().addon(addon).name(NAME).player(user).noPaste().reason(Reason.CREATE).oldIsland(oldIsland).build();
// Verifications // Verifications
verify(im).save(eq(island)); PowerMockito.verifyStatic(IslandsManager.class);
IslandsManager.updateIsland(eq(island));
verify(island).setFlagsDefaults(); verify(island).setFlagsDefaults();
verify(scheduler).runTask(any(BentoBox.class), any(Runnable.class)); verify(scheduler).runTask(any(BentoBox.class), any(Runnable.class));
verify(builder, times(2)).build(); verify(builder, times(2)).build();

View File

@ -58,7 +58,7 @@ import world.bentobox.bentobox.util.teleport.ClosestSafeSpotTeleport.PositionDat
* *
*/ */
@RunWith(PowerMockRunner.class) @RunWith(PowerMockRunner.class)
@PrepareForTest({Util.class, Bukkit.class}) @PrepareForTest({ Util.class, Bukkit.class, IslandsManager.class })
public class ClosestSafeSpotTeleportTest { public class ClosestSafeSpotTeleportTest {
// Class under test // Class under test
@ -102,6 +102,9 @@ public class ClosestSafeSpotTeleportTest {
*/ */
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
// IslandsManager static
PowerMockito.mockStatic(IslandsManager.class, Mockito.RETURNS_MOCKS);
// Setup instance // Setup instance
Whitebox.setInternalState(BentoBox.class, "instance", plugin); Whitebox.setInternalState(BentoBox.class, "instance", plugin);
// IWM // IWM

View File

@ -47,7 +47,7 @@ import world.bentobox.bentobox.util.Util;
* *
*/ */
@RunWith(PowerMockRunner.class) @RunWith(PowerMockRunner.class)
@PrepareForTest({Util.class, Bukkit.class}) @PrepareForTest({ Util.class, Bukkit.class, IslandsManager.class })
public class SafeSpotTeleportTest { public class SafeSpotTeleportTest {
// Class under test // Class under test
@ -92,6 +92,7 @@ public class SafeSpotTeleportTest {
*/ */
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
PowerMockito.mockStatic(IslandsManager.class, Mockito.RETURNS_MOCKS);
// Setup instance // Setup instance
Whitebox.setInternalState(BentoBox.class, "instance", plugin); Whitebox.setInternalState(BentoBox.class, "instance", plugin);
// IWM // IWM