Skip to content

Commit

Permalink
Enables permissions to set how many islands a play can create.
Browse files Browse the repository at this point in the history
Multiple Island Permissions #2199
  • Loading branch information
tastybento committed Oct 16, 2023
1 parent 489a1e3 commit 281d422
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import org.eclipse.jdt.annotation.Nullable;

import world.bentobox.bentobox.api.addons.GameModeAddon;
import world.bentobox.bentobox.api.commands.CompositeCommand;
import world.bentobox.bentobox.api.events.island.IslandEvent.Reason;
import world.bentobox.bentobox.api.user.User;
Expand Down Expand Up @@ -48,12 +49,11 @@ public boolean canExecute(User user, String label, List<String> args) {
if (island.isReserved()) {
return true;
}
// Get how many islands this player has
int num = this.getIslands().getNumberOfConcurrentIslands(user.getUniqueId(), getWorld());
int max = this.getIWM().getWorldSettings(getWorld()).getConcurrentIslands();
if (num < max) {
return true;
}
}
// Get how many islands this player has
int num = this.getIslands().getNumberOfConcurrentIslands(user.getUniqueId(), getWorld());
int max = user.getPermissionValue(this.getIWM().getAddon(getWorld()).map(GameModeAddon::getPermissionPrefix).orElse("") + "island.number", this.getIWM().getWorldSettings(getWorld()).getConcurrentIslands());
if (num >= max) {
// You cannot make an island
user.sendMessage("general.errors.you-cannot-make");
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import org.eclipse.jdt.annotation.Nullable;

import world.bentobox.bentobox.api.addons.GameModeAddon;
import world.bentobox.bentobox.api.commands.CompositeCommand;
import world.bentobox.bentobox.api.events.IslandBaseEvent;
import world.bentobox.bentobox.api.events.island.IslandEvent;
Expand Down Expand Up @@ -64,7 +65,9 @@ public boolean canExecute(User user, String label, List<String> args) {
return false;
}
// Check how many islands target has
if (getIslands().getNumberOfConcurrentIslands(targetUUID, getWorld()) >= this.getIWM().getWorldSettings(getWorld()).getConcurrentIslands()) {
int num = getIslands().getNumberOfConcurrentIslands(targetUUID, getWorld());
int max = user.getPermissionValue(this.getIWM().getAddon(getWorld()).map(GameModeAddon::getPermissionPrefix).orElse("") + "island.number", this.getIWM().getWorldSettings(getWorld()).getConcurrentIslands());
if (num >= max) {
// Too many
user.sendMessage("commands.island.team.setowner.errors.at-max");
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
Expand All @@ -13,6 +15,7 @@
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
Expand Down Expand Up @@ -106,15 +109,17 @@ public void setUp() throws Exception {
UUID uuid = UUID.randomUUID();
when(user.getUniqueId()).thenReturn(uuid);
when(user.getPlayer()).thenReturn(player);
when(user.hasPermission(Mockito.anyString())).thenReturn(true);
when(user.getTranslation(Mockito.any())).thenAnswer((Answer<String>) invocation -> invocation.getArgument(0, String.class));
when(user.hasPermission(anyString())).thenReturn(true);
when(user.getTranslation(any())).thenAnswer((Answer<String>) invocation -> invocation.getArgument(0, String.class));
// Return the default value for perm questions by default
when(user.getPermissionValue(anyString(), anyInt())).thenAnswer((Answer<Integer>) inv -> inv.getArgument(1, Integer.class));
User.setPlugin(plugin);
// Set up user already
User.getInstance(player);

// Addon
GameModeAddon addon = mock(GameModeAddon.class);

when(addon.getPermissionPrefix()).thenReturn("bskyblock.");

// Parent command has no aliases
when(ic.getSubCommandAliases()).thenReturn(new HashMap<>());
Expand Down Expand Up @@ -144,10 +149,11 @@ public void setUp() throws Exception {
PowerMockito.mockStatic(Bukkit.class);
when(Bukkit.getScheduler()).thenReturn(sch);

// IWM friendly name
// IWM
when(iwm.getFriendlyName(any())).thenReturn("BSkyBlock");
when(ws.getConcurrentIslands()).thenReturn(1); // One island allowed
when(iwm.getWorldSettings(world)).thenReturn(ws);
when(iwm.getAddon(world)).thenReturn(Optional.of(addon));
when(plugin.getIWM()).thenReturn(iwm);

// NewIsland
Expand Down Expand Up @@ -209,27 +215,53 @@ public void testCanExecuteUserStringListOfStringHasIsland() {
verify(user).sendMessage("general.errors.you-cannot-make");
}

/**
* Test method for {@link world.bentobox.bentobox.api.commands.island.IslandCreateCommand#canExecute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}.
*/
@Test
public void testCanExecuteUserStringListOfStringZeroAllowed() {
when(ws.getConcurrentIslands()).thenReturn(0); // No islands allowed
assertFalse(cc.canExecute(user, "", Collections.emptyList()));
verify(user).sendMessage("general.errors.you-cannot-make");

}

/**
* Test method for {@link world.bentobox.bentobox.api.commands.island.IslandCreateCommand#canExecute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}.
*/
@Test
public void testCanExecuteUserStringListOfStringHasPerm() {
// Currently user has two islands
when(im.getNumberOfConcurrentIslands(user.getUniqueId(), world)).thenReturn(19);
// Perm
when(user.getPermissionValue(anyString(), anyInt())).thenReturn(20); // 20 allowed!
assertTrue(cc.canExecute(user, "", Collections.emptyList()));
verify(user, never()).sendMessage(anyString());
}

/**
* Test method for {@link world.bentobox.bentobox.api.commands.island.IslandCreateCommand#canExecute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}.
*/
@Test
public void testCanExecuteUserStringListOfStringHasIslandReserved() {
@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);
when(island.isReserved()).thenReturn(true);
assertTrue(cc.canExecute(user, "", Collections.emptyList()));
verify(user, never()).sendMessage("general.errors.already-have-island");

}



/**
* Test method for {@link world.bentobox.bentobox.api.commands.island.IslandCreateCommand#canExecute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}.
*/
@Test
public void testCanExecuteUserStringListOfStringTooManyIslands() {
when(im.getPrimaryIsland(any(), Mockito.any(UUID.class))).thenReturn(null);
when(im.inTeam(any(), Mockito.any(UUID.class))).thenReturn(false);
when(im.getPrimaryIsland(any(), any(UUID.class))).thenReturn(null);
when(im.inTeam(any(), any(UUID.class))).thenReturn(false);
when(iwm.getMaxIslands(any())).thenReturn(100);
when(im.getIslandCount(any())).thenReturn(100L);
assertFalse(cc.canExecute(user, "", Collections.emptyList()));
Expand All @@ -247,7 +279,7 @@ public void testExecuteUserStringListOfStringSuccess() throws Exception {
// Has permission
when(bpm.checkPerm(any(), any(), any())).thenReturn(true);

assertTrue(cc.execute(user, "", Collections.singletonList("custom")));
assertTrue(cc.execute(user, "", List.of("custom")));
verify(builder).player(eq(user));
verify(builder).addon(any());
verify(builder).reason(eq(Reason.CREATE));
Expand All @@ -267,7 +299,7 @@ public void testExecuteUserStringListOfStringThrowException() throws Exception {
when(bpm.checkPerm(any(), any(), any())).thenReturn(true);

when(builder.build()).thenThrow(new IOException("commands.island.create.unable-create-island"));
assertFalse(cc.execute(user, "", Collections.singletonList("custom")));
assertFalse(cc.execute(user, "", List.of("custom")));
verify(user).sendMessage("commands.island.create.creating-island");
verify(user).sendMessage("commands.island.create.unable-create-island");
verify(plugin).logError("Could not create island for player. commands.island.create.unable-create-island");
Expand All @@ -291,7 +323,7 @@ public void testExecuteUserStringListOfStringBundleNoPermission() {
*/
@Test
public void testExecuteUserStringListOfStringUnknownBundle() {
assertFalse(cc.execute(user, "", Collections.singletonList("custom")));
assertFalse(cc.execute(user, "", List.of("custom")));
verify(user).sendMessage(eq("commands.island.create.unknown-blueprint"));
verify(user, never()).sendMessage("commands.island.create.creating-island");
}
Expand Down Expand Up @@ -347,10 +379,9 @@ public void testExecuteUserStringListOfStringNoCooldown() {
*/
@Test
public void testExecuteUserStringListOfStringShowPanel() {
Map<String, BlueprintBundle> map = new HashMap<>();
map.put("bundle1", new BlueprintBundle());
map.put("bundle2", new BlueprintBundle());
map.put("bundle3", new BlueprintBundle());
Map<String, BlueprintBundle> map = Map.of("bundle1", new BlueprintBundle(),
"bundle2", new BlueprintBundle(),
"bundle3", new BlueprintBundle());
when(bpm.getBlueprintBundles(any())).thenReturn(map);
assertTrue(cc.execute(user, "", Collections.emptyList()));
// Panel is shown, not the creation message
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
Expand All @@ -14,6 +15,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;

import org.bukkit.Bukkit;
Expand All @@ -29,6 +31,7 @@
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.stubbing.Answer;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
Expand Down Expand Up @@ -98,6 +101,8 @@ public void setUp() throws Exception {
when(user.getUniqueId()).thenReturn(uuid);
when(user.getPlayer()).thenReturn(player);
when(user.getName()).thenReturn("tastybento");
// Return the default value for perm questions by default
when(user.getPermissionValue(anyString(), anyInt())).thenAnswer((Answer<Integer>) inv -> inv.getArgument(1, Integer.class));

// Parent command has no aliases
ic = mock(CompositeCommand.class);
Expand Down Expand Up @@ -196,7 +201,7 @@ public void testCanExecuteUserStringListOfStringNotOwner() {
public void testCanExecuteUserStringListOfStringShowHelp() {
when(im.inTeam(any(), any())).thenReturn(true);
when(im.getOwner(any(), any())).thenReturn(uuid);
assertFalse(its.canExecute(user, "", Collections.emptyList()));
assertFalse(its.canExecute(user, "", List.of()));
verify(user).sendMessage("commands.help.header","[label]", null);
}

Expand All @@ -208,7 +213,7 @@ public void testCanExecuteUserStringListOfStringUnknownPlayer() {
when(im.inTeam(any(), any())).thenReturn(true);
when(im.getOwner(any(), any())).thenReturn(uuid);
when(pm.getUUID(anyString())).thenReturn(null);
assertFalse(its.canExecute(user, "", Collections.singletonList("tastybento")));
assertFalse(its.canExecute(user, "", List.of("tastybento")));
verify(user).sendMessage("general.errors.unknown-player", TextVariables.NAME, "tastybento");
}

Expand All @@ -220,7 +225,7 @@ public void testCanExecuteUserStringListOfStringSamePlayer() {
when(im.inTeam(any(), any())).thenReturn(true);
when(im.getOwner(any(), any())).thenReturn(uuid);
when(pm.getUUID(anyString())).thenReturn(uuid);
assertFalse(its.canExecute(user, "", Collections.singletonList("tastybento")));
assertFalse(its.canExecute(user, "", List.of("tastybento")));
verify(user).sendMessage("commands.island.team.setowner.errors.cant-transfer-to-yourself");
}

Expand All @@ -233,14 +238,14 @@ public void testCanExecuteUserStringListOfStringTargetAtMaxIslands() {
when(im.getOwner(any(), any())).thenReturn(uuid);
UUID target = UUID.randomUUID();
when(pm.getUUID(anyString())).thenReturn(target);
when(im.getMembers(any(), any())).thenReturn(Collections.singleton(target));
when(im.getMembers(any(), any())).thenReturn(Set.of(target));
@Nullable
Island island = mock(Island.class);
when(im.getIsland(any(), any(User.class))).thenReturn(island);

when(im.getNumberOfConcurrentIslands(target, world)).thenReturn(3);

assertFalse(its.canExecute(user, "", Collections.singletonList("tastybento")));
assertFalse(its.canExecute(user, "", List.of("tastybento")));
verify(user).sendMessage("commands.island.team.setowner.errors.at-max");
}

Expand All @@ -252,11 +257,50 @@ public void testCanExecuteUserStringListOfStringTargetNotInTeam() {
when(im.inTeam(any(), any())).thenReturn(true);
when(im.getOwner(any(), any())).thenReturn(uuid);
when(pm.getUUID(anyString())).thenReturn(UUID.randomUUID());
when(im.getMembers(any(), any())).thenReturn(Collections.singleton(uuid));
assertFalse(its.canExecute(user, "", Collections.singletonList("tastybento")));
when(im.getMembers(any(), any())).thenReturn(Set.of(uuid));
assertFalse(its.canExecute(user, "", List.of("tastybento")));
verify(user).sendMessage("commands.island.team.setowner.errors.target-is-not-member");
}

/**
* Test method for {@link world.bentobox.bentobox.api.commands.island.team.IslandTeamSetownerCommand#execute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}.
*/
@Test
public void testExecuteUserStringListOfStringTooManyConcurrent() {
when(im.getNumberOfConcurrentIslands(any(), eq(world))).thenReturn(20);
when(im.inTeam(any(), any())).thenReturn(true);
when(im.getOwner(any(), any())).thenReturn(uuid);
UUID target = UUID.randomUUID();
when(pm.getUUID(anyString())).thenReturn(target);
when(im.getMembers(any(), any())).thenReturn(Set.of(target));
@Nullable
Island island = mock(Island.class);
when(im.getIsland(any(), any(User.class))).thenReturn(island);
assertFalse(its.canExecute(user, "", List.of("tastybento")));
verify(user).sendMessage("commands.island.team.setowner.errors.at-max");
}

/**
* Test method for {@link world.bentobox.bentobox.api.commands.island.team.IslandTeamSetownerCommand#execute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}.
*/
@Test
public void testExecuteUserStringListOfStringHasManyConcurrentAndPerm() {
when(user.getPermissionValue(anyString(), anyInt())).thenReturn(40);
when(im.getNumberOfConcurrentIslands(any(), eq(world))).thenReturn(20);
when(im.inTeam(any(), any())).thenReturn(true);
when(im.getOwner(any(), any())).thenReturn(uuid);
UUID target = UUID.randomUUID();
when(pm.getUUID(anyString())).thenReturn(target);
when(im.getMembers(any(), any())).thenReturn(Set.of(target));
@Nullable
Island island = mock(Island.class);
when(im.getIsland(any(), any(User.class))).thenReturn(island);
assertTrue(its.canExecute(user, "", List.of("tastybento")));
assertTrue(its.execute(user, "", List.of("tastybento")));
verify(im).setOwner(any(), eq(user), eq(target));
verify(im).save(island);
}

/**
* Test method for {@link world.bentobox.bentobox.api.commands.island.team.IslandTeamSetownerCommand#execute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}.
*/
Expand All @@ -266,12 +310,12 @@ public void testExecuteUserStringListOfStringSuccess() {
when(im.getOwner(any(), any())).thenReturn(uuid);
UUID target = UUID.randomUUID();
when(pm.getUUID(anyString())).thenReturn(target);
when(im.getMembers(any(), any())).thenReturn(Collections.singleton(target));
when(im.getMembers(any(), any())).thenReturn(Set.of(target));
@Nullable
Island island = mock(Island.class);
when(im.getIsland(any(), any(User.class))).thenReturn(island);
assertTrue(its.canExecute(user, "", Collections.singletonList("tastybento")));
assertTrue(its.execute(user, "", Collections.singletonList("tastybento")));
assertTrue(its.canExecute(user, "", List.of("tastybento")));
assertTrue(its.execute(user, "", List.of("tastybento")));
verify(im).setOwner(any(), eq(user), eq(target));
verify(im).save(island);
}
Expand All @@ -281,15 +325,15 @@ public void testExecuteUserStringListOfStringSuccess() {
*/
@Test
public void testTabCompleteUserStringListOfString() {
assertTrue(its.tabComplete(user, "", Collections.emptyList()).get().isEmpty());
assertTrue(its.tabComplete(user, "", List.of()).get().isEmpty());
}

/**
* Test method for {@link world.bentobox.bentobox.api.commands.island.team.IslandTeamSetownerCommand#tabComplete(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}.
*/
@Test
public void testTabCompleteUserStringListOfStringUnknown() {
assertTrue(its.tabComplete(user, "ta", Collections.emptyList()).get().isEmpty());
assertTrue(its.tabComplete(user, "ta", List.of()).get().isEmpty());
}

/**
Expand All @@ -299,8 +343,8 @@ public void testTabCompleteUserStringListOfStringUnknown() {
public void testTabCompleteUserStringListOfStringMember() {
UUID target = UUID.randomUUID();
when(pm.getName(any())).thenReturn("tastybento");
when(im.getMembers(any(), any())).thenReturn(Collections.singleton(target));
assertEquals("tastybento", its.tabComplete(user, "", Collections.emptyList()).get().get(0));
when(im.getMembers(any(), any())).thenReturn(Set.of(target));
assertEquals("tastybento", its.tabComplete(user, "", List.of()).get().get(0));
}

}

0 comments on commit 281d422

Please sign in to comment.