More work on multi island. Fixed tests so clean compile.

This commit is contained in:
tastybento 2023-08-19 18:20:41 -07:00
parent 3fdbb014c7
commit 6cae448efb
12 changed files with 139 additions and 87 deletions

View File

@ -88,7 +88,7 @@
<!-- Do not change unless you want different name for local builds. -->
<build.number>-LOCAL</build.number>
<!-- This allows to change between versions. -->
<build.version>1.24.2</build.version>
<build.version>2.0.0</build.version>
<sonar.organization>bentobox-world</sonar.organization>
<sonar.host.url>https://sonarcloud.io</sonar.host.url>
<server.jars>${project.basedir}/lib</server.jars>

View File

@ -31,6 +31,7 @@ import world.bentobox.bentobox.listeners.BlockEndDragon;
import world.bentobox.bentobox.listeners.DeathListener;
import world.bentobox.bentobox.listeners.JoinLeaveListener;
import world.bentobox.bentobox.listeners.PanelListenerManager;
import world.bentobox.bentobox.listeners.PrimaryIslandListener;
import world.bentobox.bentobox.listeners.StandardSpawnProtectionListener;
import world.bentobox.bentobox.listeners.teleports.EntityTeleportListener;
import world.bentobox.bentobox.listeners.teleports.PlayerTeleportListener;
@ -306,6 +307,8 @@ public class BentoBox extends JavaPlugin implements Listener {
// Island Delete Manager
islandDeletionManager = new IslandDeletionManager(this);
manager.registerEvents(islandDeletionManager, this);
// Primary Island Listener
manager.registerEvents(new PrimaryIslandListener(this), this);
}
@Override

View File

@ -215,33 +215,30 @@ public class JoinLeaveListener implements Listener {
}
private void updateIslandRange(User user) {
plugin.getIWM().getOverWorlds().stream()
.filter(world -> plugin.getIslands().isOwner(world, user.getUniqueId()))
.forEach(world -> {
Island island = plugin.getIslands().getIsland(world, user);
if (island != null) {
// Check if new owner has a different range permission than the island size
int range = user.getPermissionValue(plugin.getIWM().getAddon(island.getWorld()).map(GameModeAddon::getPermissionPrefix).orElse("") + "island.range", island.getRawProtectionRange());
// Range cannot be greater than the island distance
range = Math.min(range, plugin.getIWM().getIslandDistance(island.getWorld()));
// Range can go up or down
if (range != island.getRawProtectionRange()) {
user.sendMessage("commands.admin.setrange.range-updated", TextVariables.NUMBER, String.valueOf(range));
int oldRange = island.getProtectionRange();
island.setProtectionRange(range);
plugin.getIslands().getIslands().stream()
.filter(island -> island.getOwner() != null && island.getOwner().equals(user.getUniqueId()))
.forEach(island -> {
// Check if new owner has a different range permission than the island size
int range = user.getPermissionValue(plugin.getIWM().getAddon(island.getWorld()).map(GameModeAddon::getPermissionPrefix).orElse("") + "island.range", island.getRawProtectionRange());
// Range cannot be greater than the island distance
range = Math.min(range, plugin.getIWM().getIslandDistance(island.getWorld()));
// Range can go up or down
if (range != island.getRawProtectionRange()) {
user.sendMessage("commands.admin.setrange.range-updated", TextVariables.NUMBER, String.valueOf(range));
int oldRange = island.getProtectionRange();
island.setProtectionRange(range);
plugin.log("Island protection range changed from " + oldRange + " to "
+ island.getProtectionRange() + " for " + user.getName() + " due to permission.");
// Call Protection Range Change event. Does not support canceling.
IslandEvent.builder()
.island(island)
.location(island.getProtectionCenter())
.reason(IslandEvent.Reason.RANGE_CHANGE)
.involvedPlayer(user.getUniqueId())
.admin(true)
.protectionRange(island.getProtectionRange(), oldRange)
.build();
}
plugin.log("Island protection range changed from " + oldRange + " to "
+ island.getProtectionRange() + " for " + user.getName() + " due to permission.");
// Call Protection Range Change event. Does not support canceling.
IslandEvent.builder()
.island(island)
.location(island.getProtectionCenter())
.reason(IslandEvent.Reason.RANGE_CHANGE)
.involvedPlayer(user.getUniqueId())
.admin(true)
.protectionRange(island.getProtectionRange(), oldRange)
.build();
}
});
}

View File

@ -0,0 +1,57 @@
package world.bentobox.bentobox.listeners;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.event.player.PlayerTeleportEvent;
import org.eclipse.jdt.annotation.NonNull;
import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.managers.IslandsManager;
/**
* Sets the player's primary island based on where they teleported or moved to
* @author tastybento
*
*/
public class PrimaryIslandListener implements Listener {
private final IslandsManager im;
/**
* @param plugin - plugin object
*/
public PrimaryIslandListener(@NonNull BentoBox plugin) {
this.im = plugin.getIslands();
}
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void onPlayerJoin(final PlayerJoinEvent event) {
setIsland(event.getPlayer(), event.getPlayer().getLocation());
}
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void onPlayerMove(final PlayerMoveEvent event) {
if (event.getTo() != null && !event.getFrom().toVector().equals(event.getTo().toVector())) {
setIsland(event.getPlayer(), event.getTo());
}
}
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void onPlayerMove(final PlayerTeleportEvent event) {
if (event.getTo() != null) {
setIsland(event.getPlayer(), event.getTo());
}
}
private void setIsland(Player player, Location location) {
im.getIslandAt(location)
.filter(i -> i.getOwner() != null && i.getOwner().equals(player.getUniqueId()))
.ifPresent(i -> im.setPrimaryIsland(player.getUniqueId(), i));
}
}

View File

@ -1901,4 +1901,13 @@ public class IslandsManager {
return islandCache.getAllIslands(world, uuid).size();
}
/**
* Sets the user's primary island
* @param uuid user's uuid
* @param i island
*/
public void setPrimaryIsland(UUID uuid, Island i) {
this.getIslandCache().setPrimaryIsland(uuid, i);
}
}

View File

@ -274,9 +274,10 @@ public class IslandCache {
}*/
/**
* Get the UUID of the owner of the island of the player, which may be their UUID
* @param world the world to check
* @param uuid the player's UUID
* @return island owner's UUID, the player UUID if they are not in a team, or null if there is no island
* @return island owner's UUID or null if there is no island
*/
@Nullable
public UUID getOwner(@NonNull World world, @NonNull UUID uuid) {
@ -285,11 +286,11 @@ public class IslandCache {
return null;
}
List<Island> islands = islandsByUUID.computeIfAbsent(w, k -> new HashMap<>()).get(uuid);
return islands != null ? islands.get(0).getOwner() : null;
return islands == null ? null : islands.get(0).getOwner();
}
/**
* Checks is a player has an island and owns it
* @param world the world to check
* @param uuid the player
* @return true if player has island and owns it
@ -299,8 +300,9 @@ public class IslandCache {
if (w == null) {
return false;
}
Island island = islandsByUUID.computeIfAbsent(w, k -> new HashMap<>()).get(uuid).get(0);
return island != null && uuid.equals(island.getOwner());
List<Island> island = islandsByUUID.computeIfAbsent(w, k -> new HashMap<>()).get(uuid);
if (island == null) return false;
return !island.isEmpty() && uuid.equals(island.get(0).getOwner());
}
/**

View File

@ -297,9 +297,6 @@ public class NewIsland {
// Clear the reservation
island.setReserved(false);
return l;
} else {
// This should never happen unless we allow another way to paste over islands without reserving
plugin.logError("New island for user " + user.getName() + " was not reserved!");
}
}
return null;

View File

@ -11,18 +11,22 @@ import static org.mockito.Mockito.when;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitScheduler;
import org.bukkit.scheduler.BukkitTask;
import org.bukkit.util.Vector;
import org.eclipse.jdt.annotation.Nullable;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
@ -49,12 +53,20 @@ import world.bentobox.bentobox.util.Util;
@PrepareForTest({Bukkit.class, BentoBox.class, User.class })
public class AdminDeleteCommandTest {
@Mock
private CompositeCommand ac;
@Mock
private User user;
@Mock
private IslandsManager im;
@Mock
private PlayersManager pm;
private UUID notUUID;
private UUID uuid;
@Mock
private World world;
@Mock
private @Nullable Island island;
/**
*/
@ -79,7 +91,6 @@ public class AdminDeleteCommandTest {
// Player
Player p = mock(Player.class);
// Sometimes use Mockito.withSettings().verboseLogging()
user = mock(User.class);
when(user.isOp()).thenReturn(false);
uuid = UUID.randomUUID();
notUUID = UUID.randomUUID();
@ -92,9 +103,9 @@ public class AdminDeleteCommandTest {
User.setPlugin(plugin);
// Parent command has no aliases
ac = mock(CompositeCommand.class);
when(ac.getSubCommandAliases()).thenReturn(new HashMap<>());
when(ac.getTopLabel()).thenReturn("admin");
when(ac.getWorld()).thenReturn(world);
// Island World Manager
IslandWorldManager iwm = mock(IslandWorldManager.class);
@ -102,15 +113,17 @@ public class AdminDeleteCommandTest {
// Player has island to begin with
im = mock(IslandsManager.class);
when(im.hasIsland(any(), any(UUID.class))).thenReturn(true);
when(im.hasIsland(any(), any(User.class))).thenReturn(true);
when(im.isOwner(any(),any())).thenReturn(true);
when(im.getOwner(any(),any())).thenReturn(uuid);
when(im.getIsland(world, user)).thenReturn(island);
when(plugin.getIslands()).thenReturn(im);
// Island
when(island.getOwner()).thenReturn(uuid);
// Has team
pm = mock(PlayersManager.class);
when(im.inTeam(any(), eq(uuid))).thenReturn(true);
when(plugin.getPlayers()).thenReturn(pm);
@ -162,10 +175,9 @@ public class AdminDeleteCommandTest {
@Test
public void testExecutePlayerNoIsland() {
AdminDeleteCommand itl = new AdminDeleteCommand(ac);
String[] name = {"tastybento"};
when(pm.getUUID(any())).thenReturn(notUUID);
when(im.getOwner(any(), any())).thenReturn(null);
assertFalse(itl.canExecute(user, itl.getLabel(), Arrays.asList(name)));
when(im.getIsland(world, user)).thenReturn(null);
assertFalse(itl.canExecute(user, "", List.of("tastybento")));
verify(user).sendMessage(eq("general.errors.player-has-no-island"));
}
@ -174,6 +186,7 @@ public class AdminDeleteCommandTest {
*/
@Test
public void testExecuteOwner() {
when(im.inTeam(any(),any())).thenReturn(true);
when(im.getOwner(any(), any())).thenReturn(notUUID);
String[] name = {"tastybento"};

View File

@ -18,8 +18,10 @@ import java.util.Optional;
import java.util.UUID;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitScheduler;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.junit.After;
import org.junit.Before;
@ -37,6 +39,7 @@ import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.Settings;
import world.bentobox.bentobox.api.addons.GameModeAddon;
import world.bentobox.bentobox.api.commands.CompositeCommand;
import world.bentobox.bentobox.api.configuration.WorldSettings;
import world.bentobox.bentobox.api.events.island.IslandEvent.Reason;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.blueprints.dataobjects.BlueprintBundle;
@ -75,6 +78,10 @@ public class IslandCreateCommandTest {
private CompositeCommand ic;
@Mock
private BlueprintsManager bpm;
@Mock
private World world;
@Mock
private @NonNull WorldSettings ws;
/**
*/
@ -115,6 +122,7 @@ public class IslandCreateCommandTest {
when(ic.getUsage()).thenReturn("");
when(ic.getSubCommand(Mockito.anyString())).thenReturn(Optional.empty());
when(ic.getAddon()).thenReturn(addon);
when(ic.getWorld()).thenReturn(world);
// No island for player to begin with (set it later in the tests)
@ -136,6 +144,8 @@ public class IslandCreateCommandTest {
// IWM friendly name
when(iwm.getFriendlyName(any())).thenReturn("BSkyBlock");
when(ws.getConcurrentIslands()).thenReturn(1); // One island allowed
when(iwm.getWorldSettings(world)).thenReturn(ws);
when(plugin.getIWM()).thenReturn(iwm);
// NewIsland
@ -190,9 +200,12 @@ public class IslandCreateCommandTest {
*/
@Test
public void testCanExecuteUserStringListOfStringHasIsland() {
// Currently user has two islands
when(im.getNumberOfConcurrentIslands(user.getUniqueId(), world)).thenReturn(2);
// Player has an island
@Nullable
Island island = mock(Island.class);
when(im.getIsland(any(), Mockito.any(User.class))).thenReturn(island);
when(im.getIsland(any(), any(User.class))).thenReturn(island);
assertFalse(cc.canExecute(user, "", Collections.emptyList()));
verify(user).sendMessage(eq("general.errors.already-have-island"));
}

View File

@ -12,6 +12,7 @@ import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@ -46,6 +47,8 @@ import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.reflect.Whitebox;
import com.mysql.cj.x.protobuf.MysqlxCrud.CollectionOrBuilder;
import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.Settings;
import world.bentobox.bentobox.api.addons.GameModeAddon;
@ -162,6 +165,7 @@ public class JoinLeaveListenerTest {
when(im.getIsland(any(), any(User.class))).thenReturn(island);
when(im.getIsland(any(), any(UUID.class))).thenReturn(island);
when(im.getIslands()).thenReturn(Collections.singletonList(island));
Map<UUID, Integer> memberMap = new HashMap<>();
memberMap.put(uuid, RanksManager.OWNER_RANK);

View File

@ -16,7 +16,6 @@ import java.util.UUID;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.plugin.PluginAwareness.Flags;
import org.eclipse.jdt.annotation.NonNull;
import org.junit.After;
import org.junit.Before;
@ -253,7 +252,7 @@ public class IslandCacheTest {
@Test
public void testGetOwner() {
ic.addIsland(island);
// Should be no owner, so null
assertEquals(owner, ic.getOwner(world, owner));
assertNull(ic.getOwner(world, UUID.randomUUID()));
}

View File

@ -275,46 +275,4 @@ public class NewIslandTest {
verify(island).setReserved(eq(false));
}
/**
* Test method for {@link world.bentobox.bentobox.managers.island.NewIsland#builder()}.
*/
@Test
public void testBuilderHasIslandFail() throws Exception {
when(im.getIsland(any(), any(User.class))).thenReturn(null);
when(im.hasIsland(any(), any(User.class))).thenReturn(true);
NewIsland.builder().addon(addon).name(NAME).player(user).noPaste().reason(Reason.CREATE).oldIsland(oldIsland).build();
// Verifications
verify(im).save(eq(island));
verify(island).setFlagsDefaults();
verify(scheduler).runTask(any(BentoBox.class), any(Runnable.class));
verify(builder, times(2)).build();
verify(bpb).getUniqueId();
verify(ice).getBlueprintBundle();
verify(pm).setDeaths(eq(world), eq(uuid), eq(0));
verify(im).setHomeLocation(eq(user), any());
verify(island).setProtectionRange(eq(20));
verify(plugin).logError("New island for user tastybento was not reserved!");
}
/**
* Test method for {@link world.bentobox.bentobox.managers.island.NewIsland#builder()}.
*/
@Test
public void testBuilderHasIslandFailnoReserve() throws Exception {
when(island.isReserved()).thenReturn(false);
when(im.hasIsland(any(), any(User.class))).thenReturn(true);
NewIsland.builder().addon(addon).name(NAME).player(user).noPaste().reason(Reason.CREATE).oldIsland(oldIsland).build();
// Verifications
verify(im).save(eq(island));
verify(island).setFlagsDefaults();
verify(scheduler).runTask(any(BentoBox.class), any(Runnable.class));
verify(builder, times(2)).build();
verify(bpb).getUniqueId();
verify(ice).getBlueprintBundle();
verify(pm).setDeaths(eq(world), eq(uuid), eq(0));
verify(im).setHomeLocation(eq(user), any());
verify(island).setProtectionRange(eq(20));
verify(plugin).logError("New island for user tastybento was not reserved!");
}
}