Merge branch 'develop' into bbox_perms_command

This commit is contained in:
tastybento 2023-06-24 10:15:34 -07:00 committed by GitHub
commit a7ffb79f1d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 270 additions and 16 deletions

View File

@ -248,7 +248,6 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
CompositeCommand cmd = getCommandFromArgs(args);
String cmdLabel = (cmd.subCommandLevel > 0) ? args[cmd.subCommandLevel-1] : label;
List<String> cmdArgs = Arrays.asList(args).subList(cmd.subCommandLevel, args.length);
// Call
return cmd.call(user, cmdLabel, cmdArgs);
}
@ -268,6 +267,7 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
user.sendMessage("general.errors.use-in-game");
return false;
}
if (isOnlyConsole() && user.isPlayer()) {
user.sendMessage("general.errors.use-in-console");
return false;
@ -278,7 +278,6 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
// Error message is displayed by permission check.
return false;
}
// Set the user's addon context
user.setAddon(addon);
// Execute and trim args

View File

@ -35,7 +35,7 @@ public class AdminInfoCommand extends CompositeCommand {
}
// If there are no args, then the player wants info on the island at this location
if (args.isEmpty()) {
getIslands().getIslandAt(user.getLocation()).ifPresentOrElse(i -> new IslandInfo(i).showAdminInfo(user), () ->
getIslands().getIslandAt(user.getLocation()).ifPresentOrElse(i -> new IslandInfo(i).showAdminInfo(user, getAddon()), () ->
user.sendMessage("commands.admin.info.no-island"));
return true;
}
@ -48,7 +48,7 @@ public class AdminInfoCommand extends CompositeCommand {
// Show info for this player
Island island = getIslands().getIsland(getWorld(), targetUUID);
if (island != null) {
new IslandInfo(island).showAdminInfo(user);
new IslandInfo(island).showAdminInfo(user, getAddon());
if (!getIslands().getQuarantinedIslandByUser(getWorld(), targetUUID).isEmpty()) {
user.sendMessage("commands.admin.info.islands-in-trash");
}

View File

@ -9,6 +9,7 @@ import org.bukkit.event.HandlerList;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import world.bentobox.bentobox.api.addons.Addon;
import world.bentobox.bentobox.api.events.IslandBaseEvent;
import world.bentobox.bentobox.blueprints.dataobjects.BlueprintBundle;
import world.bentobox.bentobox.database.objects.Island;
@ -175,7 +176,12 @@ public class IslandEvent extends IslandBaseEvent {
* Event that will fire when an island is named or renamed
* @since 1.24.0
*/
NAME
NAME,
/**
* Event that will fire when the info command is executed. Allows addons to add to it
* @since 1.24.0
*/
INFO
}
public static IslandEventBuilder builder() {
@ -223,6 +229,10 @@ public class IslandEvent extends IslandBaseEvent {
* @since 1.24.0 Previous name of island
*/
private String previousName;
/**
* @since 1.24.0 GameMode addon causing this event
*/
private Addon addon;
public IslandEventBuilder island(Island island) {
this.island = island;
@ -324,6 +334,16 @@ public class IslandEvent extends IslandBaseEvent {
this.previousName = previousName;
return this;
}
/**
* Addon that triggered this event, e.g. BSkyBlock
* @param addon Addon.
* @since 1.24.0
*/
public IslandEventBuilder addon(Addon addon) {
this.addon = addon;
return this;
}
private IslandBaseEvent getEvent() {
return switch (reason) {
@ -350,6 +370,7 @@ public class IslandEvent extends IslandBaseEvent {
case RANK_CHANGE -> new IslandRankChangeEvent(island, player, admin, location, oldRank, newRank);
case NEW_ISLAND -> new IslandNewIslandEvent(island, player, admin, location);
case NAME -> new IslandNameEvent(island, player, admin, location, previousName);
case INFO -> new IslandInfoEvent(island, player, admin, location, addon);
default -> new IslandGeneralEvent(island, player, admin, location);
};
}

View File

@ -0,0 +1,55 @@
package world.bentobox.bentobox.api.events.island;
import java.util.UUID;
import org.bukkit.Location;
import org.bukkit.event.HandlerList;
import org.eclipse.jdt.annotation.NonNull;
import world.bentobox.bentobox.api.addons.Addon;
import world.bentobox.bentobox.api.events.IslandBaseEvent;
import world.bentobox.bentobox.database.objects.Island;
/**
* Fired when an a player reuqets info about an island
* Cancellation has no effect.
* @since 1.24.0
*/
public class IslandInfoEvent extends IslandBaseEvent {
private final Addon addon;
private static final HandlerList handlers = new HandlerList();
@Override
public @NonNull HandlerList getHandlers() {
return getHandlerList();
}
public static HandlerList getHandlerList() {
return handlers;
}
/**
* @param island island
* @param player player asking for the info
* @param admin true if this is an admin request
* @param location location of the player asking for the info
* @param addon the addon parent that is calling this info command, e.g., BSkyBlock
*/
public IslandInfoEvent(Island island, UUID player, boolean admin, Location location, Addon addon) {
// Final variables have to be declared in the constructor
super(island, player, admin, location);
this.addon = addon;
}
/**
* @return the gameMode that is for this island
*/
public Addon getAddon() {
return addon;
}
}

View File

@ -472,7 +472,10 @@ public class User implements MetaDataAble {
// Then replace variables
if (variables.length > 1) {
for (int i = 0; i < variables.length; i += 2) {
translation = translation.replace(variables[i], variables[i + 1]);
// Prevent a NPE if the substituting variable is null
if (variables[i + 1] != null) {
translation = translation.replace(variables[i], variables[i + 1]);
}
}
}

View File

@ -57,20 +57,19 @@ public class BannedCommands implements Listener {
}
private boolean checkCmd(String cmd, String[] args) {
// Commands are guilty until proven innocent :-)
boolean banned = true;
// Get the elements of the banned command by splitting it
String[] bannedSplit = cmd.toLowerCase(java.util.Locale.ENGLISH).split(" ");
// If the banned command has the same number of elements or less than the entered command then it may be banned
if (bannedSplit.length <= args.length) {
if (bannedSplit.length <= args.length) {
for (int i = 0; i < bannedSplit.length; i++) {
if (!bannedSplit[i].equals(args[i])) {
banned = false;
break;
if (!bannedSplit[i].equalsIgnoreCase(args[i])) {
return false;
}
}
} else {
return false;
}
return banned;
return true;
}
/**

View File

@ -143,6 +143,16 @@ public class IslandWorldManager {
.anyMatch(gm -> gm.getWorldSettings().getFriendlyName().equalsIgnoreCase(name));
}
/**
* Associate a world with a game mode. This enables game modes to register more worlds than just the standard
* overworld, nether, and end worlds.
* @param world world
* @param gameMode game mode
* @since 1.24.0
*/
public void addWorld(World world, GameModeAddon gameMode) {
gameModes.put(world, gameMode);
}
/**
* Adds a GameMode to island world manager

View File

@ -10,6 +10,8 @@ import org.bukkit.util.Vector;
import org.eclipse.jdt.annotation.Nullable;
import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.api.addons.Addon;
import world.bentobox.bentobox.api.events.island.IslandEvent;
import world.bentobox.bentobox.api.localization.TextVariables;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.database.objects.Island;
@ -43,8 +45,9 @@ public class IslandInfo {
/**
* Shows admin info of this island
* @param user user asking
* @param addon Addon executing this command
*/
public void showAdminInfo(User user) {
public void showAdminInfo(User user, Addon addon) {
user.sendMessage("commands.admin.info.title");
user.sendMessage("commands.admin.info.island-uuid", TextVariables.UUID, island.getUniqueId());
if (owner == null) {
@ -98,6 +101,15 @@ public class IslandInfo {
if (island.getPurgeProtected()) {
user.sendMessage("commands.admin.info.purge-protected");
}
// Fire info event to allow other addons to add to info
IslandEvent.builder()
.island(island)
.location(island.getCenter())
.reason(IslandEvent.Reason.INFO)
.involvedPlayer(user.getUniqueId())
.addon(addon)
.admin(true)
.build();
}
@ -130,6 +142,13 @@ public class IslandInfo {
user.sendMessage("commands.admin.info.banned-players");
island.getBanned().forEach(u -> user.sendMessage("commands.admin.info.banned-format", TextVariables.NAME, plugin.getPlayers().getName(u)));
}
// Fire info event
IslandEvent.builder()
.island(island)
.location(island.getCenter())
.reason(IslandEvent.Reason.INFO)
.involvedPlayer(user.getUniqueId())
.build();
return true;
}

View File

@ -13,6 +13,7 @@ import static org.mockito.Mockito.when;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
@ -44,6 +45,7 @@ import world.bentobox.bentobox.managers.CommandsManager;
import world.bentobox.bentobox.managers.IslandWorldManager;
import world.bentobox.bentobox.managers.IslandsManager;
import world.bentobox.bentobox.managers.LocalesManager;
import world.bentobox.bentobox.managers.PlaceholdersManager;
import world.bentobox.bentobox.managers.PlayersManager;
import world.bentobox.bentobox.util.Util;
@ -74,6 +76,8 @@ public class AdminTeleportCommandTest {
private World netherWorld;
@Mock
private World endWorld;
@Mock
private PlaceholdersManager phm;
/**
@ -96,16 +100,25 @@ public class AdminTeleportCommandTest {
while(notUUID.equals(uuid)) {
notUUID = UUID.randomUUID();
}
when(p.getUniqueId()).thenReturn(uuid);
when(p.hasPermission("admin.tp")).thenReturn(true);
when(p.hasPermission("admin")).thenReturn(false);
when(user.getUniqueId()).thenReturn(uuid);
when(user.getPlayer()).thenReturn(p);
when(user.getName()).thenReturn("tastybento");
when(user.isPlayer()).thenReturn(true);
when(user.hasPermission("admin.tp")).thenReturn(true);
when(user.hasPermission("admin")).thenReturn(false);
User.setPlugin(plugin);
// Parent command has no aliases
when(ac.getSubCommandAliases()).thenReturn(new HashMap<>());
when(ac.getTopLabel()).thenReturn("bskyblock");
when(ac.getLabel()).thenReturn("bskyblock");
when(ac.getWorld()).thenReturn(world);
when(ac.getPermission()).thenReturn("admin");
// World
when(world.getEnvironment()).thenReturn(Environment.NORMAL);
@ -132,12 +145,12 @@ public class AdminTeleportCommandTest {
// Server & Scheduler
BukkitScheduler sch = mock(BukkitScheduler.class);
PowerMockito.mockStatic(Bukkit.class);
PowerMockito.mockStatic(Bukkit.class, Mockito.RETURNS_MOCKS);
when(Bukkit.getScheduler()).thenReturn(sch);
// Locales
LocalesManager lm = mock(LocalesManager.class);
when(lm.get(any(), any())).thenReturn("mock translation");
when(lm.get(any(), any())).thenAnswer((Answer<String>) invocation -> invocation.getArgument(1, String.class));
when(plugin.getLocalesManager()).thenReturn(lm);
when(user.getTranslation(Mockito.anyString(),Mockito.anyString(), Mockito.anyString())).thenAnswer((Answer<String>) invocation -> invocation.getArgument(0, String.class));
@ -165,6 +178,9 @@ public class AdminTeleportCommandTest {
// Util
PowerMockito.mockStatic(Util.class, Mockito.RETURNS_MOCKS);
when(Util.getUUID(anyString())).thenCallRealMethod();
// Placeholder manager
when(plugin.getPlaceholdersManager()).thenReturn(phm);
}
@After
@ -276,5 +292,36 @@ public class AdminTeleportCommandTest {
verify(user).getTranslation(eq("commands.admin.tp.manual"), eq("[location]"), eq("0 0 0"));
}
@Test
public void testPermissionsNoRootPermission() {
when(p.hasPermission("admin.tp")).thenReturn(true);
when(p.hasPermission("admin")).thenReturn(false);
when(pm.getUUID(eq("tastybento"))).thenReturn(notUUID);
when(im.hasIsland(any(), any(UUID.class))).thenReturn(true);
AdminTeleportCommand atc = new AdminTeleportCommand(ac,"tpend");
assertTrue(atc.canExecute(user, "tpend", List.of("tastybento")));
String[] list = new String[2];
list[0] = "tpend";
list[1] = "tastybento";
// Should fail
assertFalse(atc.execute(p, "tpend", list));
}
@Test
public void testPermissionsHasRootPermission() {
when(p.hasPermission("admin.tp")).thenReturn(true);
when(p.hasPermission("admin")).thenReturn(true);
when(pm.getUUID(eq("tastybento"))).thenReturn(notUUID);
when(im.hasIsland(any(), any(UUID.class))).thenReturn(true);
AdminTeleportCommand atc = new AdminTeleportCommand(ac,"tpend");
assertTrue(atc.canExecute(user, "tpend", List.of("tastybento")));
String[] list = new String[2];
list[0] = "tpend";
list[1] = "tastybento";
// Should pass
assertTrue(atc.execute(p, "tpend", list));
verify(p).hasPermission("admin.tp");
verify(p).hasPermission("admin");
}
}

View File

@ -262,6 +262,106 @@ public class BannedCommandsTest {
}
/**
* Test for {@link BannedCommands#onCommand(PlayerCommandPreprocessEvent)}
*/
@Test
public void testBannedCommandsWithBannedCommand2() {
PlayerCommandPreprocessEvent e = new PlayerCommandPreprocessEvent(player, "/spawn");
BannedCommands bvc = new BannedCommands(plugin);
List<String> banned = new ArrayList<>();
banned.add("cmi sethome");
when(iwm.getVisitorBannedCommands(any())).thenReturn(banned);
bvc.onVisitorCommand(e);
verify(iwm).getVisitorBannedCommands(any());
assertFalse(e.isCancelled());
}
/**
* Test for {@link BannedCommands#onCommand(PlayerCommandPreprocessEvent)}
*/
@Test
public void testBannedCommandsWithBannedCommand3() {
PlayerCommandPreprocessEvent e = new PlayerCommandPreprocessEvent(player, "/cmi sethome");
BannedCommands bvc = new BannedCommands(plugin);
List<String> banned = new ArrayList<>();
banned.add("cmi sethome");
when(iwm.getVisitorBannedCommands(any())).thenReturn(banned);
bvc.onVisitorCommand(e);
verify(iwm).getVisitorBannedCommands(any());
assertTrue(e.isCancelled());
}
/**
* Test for {@link BannedCommands#onCommand(PlayerCommandPreprocessEvent)}
*/
@Test
public void testBannedCommandsWithBannedComman4() {
PlayerCommandPreprocessEvent e = new PlayerCommandPreprocessEvent(player, "/cmi");
BannedCommands bvc = new BannedCommands(plugin);
List<String> banned = new ArrayList<>();
banned.add("cmi sethome");
when(iwm.getVisitorBannedCommands(any())).thenReturn(banned);
bvc.onVisitorCommand(e);
verify(iwm).getVisitorBannedCommands(any());
assertFalse(e.isCancelled());
}
/**
* Test for {@link BannedCommands#onCommand(PlayerCommandPreprocessEvent)}
*/
@Test
public void testBannedCommandsWithBannedCommand5() {
PlayerCommandPreprocessEvent e = new PlayerCommandPreprocessEvent(player, "/cmi homey");
BannedCommands bvc = new BannedCommands(plugin);
List<String> banned = new ArrayList<>();
banned.add("cmi sethome");
when(iwm.getVisitorBannedCommands(any())).thenReturn(banned);
bvc.onVisitorCommand(e);
verify(iwm).getVisitorBannedCommands(any());
assertFalse(e.isCancelled());
}
/**
* Test for {@link BannedCommands#onCommand(PlayerCommandPreprocessEvent)}
*/
@Test
public void testBannedCommandsWithBannedCommand6() {
PlayerCommandPreprocessEvent e = new PlayerCommandPreprocessEvent(player, "/spawn");
BannedCommands bvc = new BannedCommands(plugin);
List<String> banned = new ArrayList<>();
banned.add("cmi sethome");
banned.add("spawn sethome now");
when(iwm.getVisitorBannedCommands(any())).thenReturn(banned);
bvc.onVisitorCommand(e);
verify(iwm).getVisitorBannedCommands(any());
assertFalse(e.isCancelled());
}
/**
* Test for {@link BannedCommands#onCommand(PlayerCommandPreprocessEvent)}
*/
@Test
public void testBannedCommandsWithBannedCommand7() {
PlayerCommandPreprocessEvent e = new PlayerCommandPreprocessEvent(player, "/spawn");
BannedCommands bvc = new BannedCommands(plugin);
List<String> banned = new ArrayList<>();
banned.add("cmi sethome");
banned.add("spawn sethome now");
banned.add("cmi multi now");
when(iwm.getVisitorBannedCommands(any())).thenReturn(banned);
bvc.onVisitorCommand(e);
verify(iwm).getVisitorBannedCommands(any());
assertFalse(e.isCancelled());
}
/**
* Test for {@link BannedCommands#onCommand(PlayerCommandPreprocessEvent)}
*/

View File

@ -123,6 +123,7 @@ public abstract class AbstractCommonSetup {
when(player.getInventory()).thenReturn(inv);
User.setPlugin(plugin);
User.clearUsers();
User.getInstance(player);
// IWM