summaryrefslogtreecommitdiff
path: root/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'src/main')
-rw-r--r--src/main/java/net/cflems/mc/sandbox/CommandUtils.java38
-rw-r--r--src/main/java/net/cflems/mc/sandbox/DelegableCommand.java24
-rw-r--r--src/main/java/net/cflems/mc/sandbox/PlayerTargetedCommand.java16
-rw-r--r--src/main/java/net/cflems/mc/sandbox/Sandbox.java12
-rw-r--r--src/main/java/net/cflems/mc/sandbox/commands/Fireball.java17
-rw-r--r--src/main/java/net/cflems/mc/sandbox/commands/PTSU.java59
-rw-r--r--src/main/java/net/cflems/mc/sandbox/commands/PowerTool.java20
-rw-r--r--src/main/java/net/cflems/mc/sandbox/listeners/PowerToolListener.java7
-rw-r--r--src/main/java/net/cflems/mc/sandbox/storage/DeserializationException.java7
-rw-r--r--src/main/java/net/cflems/mc/sandbox/storage/PowerToolBinding.java32
-rw-r--r--src/main/java/net/cflems/mc/sandbox/storage/PowerToolStore.java37
-rw-r--r--src/main/resources/plugin.yml10
12 files changed, 241 insertions, 38 deletions
diff --git a/src/main/java/net/cflems/mc/sandbox/CommandUtils.java b/src/main/java/net/cflems/mc/sandbox/CommandUtils.java
index a954c5b..781c332 100644
--- a/src/main/java/net/cflems/mc/sandbox/CommandUtils.java
+++ b/src/main/java/net/cflems/mc/sandbox/CommandUtils.java
@@ -1,9 +1,16 @@
package net.cflems.mc.sandbox;
+import java.util.Arrays;
+import java.util.UUID;
+import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
+import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
+import org.bukkit.command.PluginCommand;
+import org.bukkit.entity.Player;
public final class CommandUtils {
+ public static final UUID UUID_ZERO = new UUID(0, 0);
private static final String RESPONSE_PREFIX = ChatColor.GOLD + "[Sandbox] " + ChatColor.RESET;
private CommandUtils() {}
@@ -11,4 +18,35 @@ public final class CommandUtils {
public static void respond(CommandSender sender, String message) {
sender.sendMessage(RESPONSE_PREFIX + message);
}
+
+ public static UUID getUniqueId(CommandSender sender) {
+ return sender instanceof Player player ? player.getUniqueId() : UUID_ZERO;
+ }
+
+ public static void delegateCommand(Player player, UUID effectivePlayerId, String command) {
+ CommandSender effectiveSender =
+ effectivePlayerId.equals(UUID_ZERO)
+ ? Bukkit.getConsoleSender()
+ : Bukkit.getPlayer(effectivePlayerId);
+ if (effectiveSender == null) {
+ player.performCommand(command);
+ return;
+ }
+
+ String[] args = command.split(" ");
+ PluginCommand pluginCommand = Bukkit.getPluginCommand(args[0]);
+ if (pluginCommand == null) {
+ player.performCommand(command);
+ return;
+ }
+
+ CommandExecutor commandExecutor = pluginCommand.getExecutor();
+ if (!(commandExecutor instanceof DelegableCommand delegableCommand)) {
+ player.performCommand(command);
+ return;
+ }
+
+ delegableCommand.executeAs(
+ player, effectiveSender, pluginCommand, args[0], Arrays.copyOfRange(args, 1, args.length));
+ }
}
diff --git a/src/main/java/net/cflems/mc/sandbox/DelegableCommand.java b/src/main/java/net/cflems/mc/sandbox/DelegableCommand.java
new file mode 100644
index 0000000..073a427
--- /dev/null
+++ b/src/main/java/net/cflems/mc/sandbox/DelegableCommand.java
@@ -0,0 +1,24 @@
+package net.cflems.mc.sandbox;
+
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandExecutor;
+import org.bukkit.command.CommandSender;
+import org.jetbrains.annotations.NotNull;
+
+public abstract class DelegableCommand implements CommandExecutor {
+ public abstract boolean executeAs(
+ CommandSender sender,
+ CommandSender effectiveSender,
+ Command command,
+ String label,
+ String[] args);
+
+ @Override
+ public boolean onCommand(
+ @NotNull CommandSender sender,
+ @NotNull Command command,
+ @NotNull String label,
+ @NotNull String[] args) {
+ return executeAs(sender, sender, command, label, args);
+ }
+}
diff --git a/src/main/java/net/cflems/mc/sandbox/PlayerTargetedCommand.java b/src/main/java/net/cflems/mc/sandbox/PlayerTargetedCommand.java
index 8a553bc..85a335d 100644
--- a/src/main/java/net/cflems/mc/sandbox/PlayerTargetedCommand.java
+++ b/src/main/java/net/cflems/mc/sandbox/PlayerTargetedCommand.java
@@ -3,11 +3,10 @@ package net.cflems.mc.sandbox;
import com.google.errorprone.annotations.CompileTimeConstant;
import java.util.Arrays;
import java.util.function.Consumer;
-import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
-public abstract class PlayerTargetedCommand implements CommandExecutor {
+public abstract class PlayerTargetedCommand extends DelegableCommand {
private final int minArgs;
private final int maxArgs;
private final String permission;
@@ -45,11 +44,14 @@ public abstract class PlayerTargetedCommand implements CommandExecutor {
this.othersPermissionMessage = othersPermissionMessage;
}
- @SuppressWarnings("NullableProblems")
@Override
- public final boolean onCommand(
- CommandSender sender, org.bukkit.command.Command _command, String label, String[] args) {
- if (!sender.hasPermission(permission)) {
+ public final boolean executeAs(
+ CommandSender sender,
+ CommandSender effectiveSender,
+ org.bukkit.command.Command _command,
+ String label,
+ String[] args) {
+ if (!effectiveSender.hasPermission(permission)) {
CommandUtils.respond(sender, permissionMessage);
return true;
}
@@ -66,7 +68,7 @@ public abstract class PlayerTargetedCommand implements CommandExecutor {
sender, "Specified player not found, make sure to refer to them by name.");
return true;
}
- if (player != sender && !sender.hasPermission(othersPermission)) {
+ if (player != sender && !effectiveSender.hasPermission(othersPermission)) {
CommandUtils.respond(sender, othersPermissionMessage);
return true;
}
diff --git a/src/main/java/net/cflems/mc/sandbox/Sandbox.java b/src/main/java/net/cflems/mc/sandbox/Sandbox.java
index 34127f1..63439ce 100644
--- a/src/main/java/net/cflems/mc/sandbox/Sandbox.java
+++ b/src/main/java/net/cflems/mc/sandbox/Sandbox.java
@@ -1,10 +1,6 @@
package net.cflems.mc.sandbox;
-import net.cflems.mc.sandbox.commands.Enchant;
-import net.cflems.mc.sandbox.commands.Fireball;
-import net.cflems.mc.sandbox.commands.Fly;
-import net.cflems.mc.sandbox.commands.PowerTool;
-import net.cflems.mc.sandbox.commands.Repair;
+import net.cflems.mc.sandbox.commands.*;
import net.cflems.mc.sandbox.listeners.PowerToolListener;
import net.cflems.mc.sandbox.storage.PowerToolStore;
import org.bukkit.plugin.java.JavaPlugin;
@@ -12,14 +8,20 @@ import org.bukkit.plugin.java.JavaPlugin;
public class Sandbox extends JavaPlugin {
public static final String PERMISSION_NAMESPACE = "sandbox";
+ @SuppressWarnings("DataFlowIssue")
@Override
public void onEnable() {
+ PowerToolStore.registerSerializables();
PowerToolStore powerToolStore = new PowerToolStore(getDataFolder());
getServer().getPluginManager().registerEvents(new PowerToolListener(powerToolStore), this);
+
this.getCommand("enchant").setExecutor(new Enchant());
this.getCommand("fly").setExecutor(new Fly());
this.getCommand("repair").setExecutor(new Repair());
this.getCommand("fireball").setExecutor(new Fireball());
+
+ PowerTool powerTool = new PowerTool(powerToolStore);
this.getCommand("powertool").setExecutor(new PowerTool(powerToolStore));
+ this.getCommand("ptsu").setExecutor(new PTSU(powerTool));
}
}
diff --git a/src/main/java/net/cflems/mc/sandbox/commands/Fireball.java b/src/main/java/net/cflems/mc/sandbox/commands/Fireball.java
index 049c554..447d9dd 100644
--- a/src/main/java/net/cflems/mc/sandbox/commands/Fireball.java
+++ b/src/main/java/net/cflems/mc/sandbox/commands/Fireball.java
@@ -1,33 +1,36 @@
package net.cflems.mc.sandbox.commands;
import net.cflems.mc.sandbox.CommandUtils;
+import net.cflems.mc.sandbox.DelegableCommand;
import net.cflems.mc.sandbox.Sandbox;
-import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
-public final class Fireball implements CommandExecutor {
+public final class Fireball extends DelegableCommand {
private static final String PERMISSION = Sandbox.PERMISSION_NAMESPACE + ".fireball";
private static final String CUSTOM_PERMISSION = PERMISSION + ".custom";
private static final float DEFAULT_POWER = 5.0f;
- @SuppressWarnings("NullableProblems")
@Override
- public boolean onCommand(
- CommandSender sender, org.bukkit.command.Command _command, String _label, String[] args) {
+ public boolean executeAs(
+ CommandSender sender,
+ CommandSender effectiveSender,
+ org.bukkit.command.Command _command,
+ String _label,
+ String[] args) {
if (args.length > 1) return false;
if (!(sender instanceof Player player)) {
CommandUtils.respond(sender, "Only players can use fireballs.");
return true;
}
- if (!sender.hasPermission(PERMISSION)) {
+ if (!effectiveSender.hasPermission(PERMISSION)) {
CommandUtils.respond(sender, "You do not have permission to use fireballs.");
return true;
}
float yield = DEFAULT_POWER;
if (args.length > 0) {
- if (!sender.hasPermission(CUSTOM_PERMISSION)) {
+ if (!effectiveSender.hasPermission(CUSTOM_PERMISSION)) {
CommandUtils.respond(
sender, "You do not have permission to use fireballs of custom power.");
return true;
diff --git a/src/main/java/net/cflems/mc/sandbox/commands/PTSU.java b/src/main/java/net/cflems/mc/sandbox/commands/PTSU.java
new file mode 100644
index 0000000..6d28ba3
--- /dev/null
+++ b/src/main/java/net/cflems/mc/sandbox/commands/PTSU.java
@@ -0,0 +1,59 @@
+package net.cflems.mc.sandbox.commands;
+
+import java.util.Arrays;
+import java.util.UUID;
+import net.cflems.mc.sandbox.CommandUtils;
+import net.cflems.mc.sandbox.Sandbox;
+import org.bukkit.Bukkit;
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandExecutor;
+import org.bukkit.command.CommandSender;
+import org.jetbrains.annotations.NotNull;
+
+public class PTSU implements CommandExecutor {
+ private static final String PERMISSION = Sandbox.PERMISSION_NAMESPACE + ".ptsu";
+
+ private final PowerTool powerToolExecutor;
+
+ public PTSU(PowerTool powerToolExecutor) {
+ this.powerToolExecutor = powerToolExecutor;
+ }
+
+ @Override
+ public boolean onCommand(
+ @NotNull CommandSender sender,
+ @NotNull Command command,
+ @NotNull String label,
+ @NotNull String[] args) {
+ if (args.length < 1) return false;
+
+ if (!sender.hasPermission(PERMISSION)) {
+ CommandUtils.respond(
+ sender, "You do not have permission to use power tools as other players.");
+ return true;
+ }
+
+ CommandSender effectiveSender;
+ try {
+ UUID playerId = UUID.fromString(args[0]);
+ if (playerId.equals(CommandUtils.UUID_ZERO)) {
+ effectiveSender = Bukkit.getConsoleSender();
+ } else {
+ effectiveSender = Bukkit.getPlayer(playerId);
+ }
+ } catch (IllegalArgumentException _e) {
+ if (args[0].equalsIgnoreCase("console")) {
+ effectiveSender = Bukkit.getConsoleSender();
+ } else {
+ effectiveSender = Bukkit.getPlayer(args[0]);
+ }
+ }
+
+ if (effectiveSender == null) {
+ CommandUtils.respond(sender, "That player does not exist or is not online.");
+ }
+
+ return powerToolExecutor.executeAs(
+ sender, effectiveSender, command, label, Arrays.copyOfRange(args, 1, args.length));
+ }
+}
diff --git a/src/main/java/net/cflems/mc/sandbox/commands/PowerTool.java b/src/main/java/net/cflems/mc/sandbox/commands/PowerTool.java
index e4683f6..063f5b3 100644
--- a/src/main/java/net/cflems/mc/sandbox/commands/PowerTool.java
+++ b/src/main/java/net/cflems/mc/sandbox/commands/PowerTool.java
@@ -1,16 +1,16 @@
package net.cflems.mc.sandbox.commands;
import net.cflems.mc.sandbox.CommandUtils;
+import net.cflems.mc.sandbox.DelegableCommand;
import net.cflems.mc.sandbox.Sandbox;
import net.cflems.mc.sandbox.storage.NoMetaException;
import net.cflems.mc.sandbox.storage.PowerToolStore;
import org.bukkit.command.Command;
-import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
-public final class PowerTool implements CommandExecutor {
+public final class PowerTool extends DelegableCommand {
private static final String PERMISSION = Sandbox.PERMISSION_NAMESPACE + ".powertool";
private static final String RELOAD_PERMISSION = PERMISSION + ".reload";
@@ -20,11 +20,15 @@ public final class PowerTool implements CommandExecutor {
this.store = store;
}
- @SuppressWarnings("NullableProblems")
@Override
- public boolean onCommand(CommandSender sender, Command _command, String _label, String[] args) {
+ public boolean executeAs(
+ CommandSender sender,
+ CommandSender effectiveSender,
+ Command _command,
+ String _label,
+ String[] args) {
if (args.length == 1 && args[0].equalsIgnoreCase("reload")) {
- if (!sender.hasPermission(RELOAD_PERMISSION))
+ if (!effectiveSender.hasPermission(RELOAD_PERMISSION))
CommandUtils.respond(sender, "You do not have permission to reload power tool bindings.");
else if (store.reload())
CommandUtils.respond(sender, "Power tool bindings reloaded successfully.");
@@ -39,7 +43,7 @@ public final class PowerTool implements CommandExecutor {
CommandUtils.respond(sender, "Only players can make power tools.");
return true;
}
- if (!sender.hasPermission(PERMISSION)) {
+ if (!effectiveSender.hasPermission(PERMISSION)) {
CommandUtils.respond(sender, "You do not have permission to make power tools.");
return true;
}
@@ -49,13 +53,13 @@ public final class PowerTool implements CommandExecutor {
if (args.length > 0) {
String command = String.join(" ", args);
try {
- store.add(mhItem, command);
+ store.add(mhItem, command, CommandUtils.getUniqueId(effectiveSender));
CommandUtils.respond(sender, "Power tool created successfully.");
} catch (NoMetaException e) {
CommandUtils.respond(sender, "Power tools must be item types that can hold metadata.");
}
} else {
- store.clear(mhItem);
+ store.clear(mhItem, CommandUtils.getUniqueId(effectiveSender));
CommandUtils.respond(sender, "Power tool bindings cleared for this item.");
}
return true;
diff --git a/src/main/java/net/cflems/mc/sandbox/listeners/PowerToolListener.java b/src/main/java/net/cflems/mc/sandbox/listeners/PowerToolListener.java
index 25949d2..8f4211a 100644
--- a/src/main/java/net/cflems/mc/sandbox/listeners/PowerToolListener.java
+++ b/src/main/java/net/cflems/mc/sandbox/listeners/PowerToolListener.java
@@ -2,6 +2,7 @@ package net.cflems.mc.sandbox.listeners;
import java.util.List;
import net.cflems.mc.sandbox.CommandUtils;
+import net.cflems.mc.sandbox.storage.PowerToolBinding;
import net.cflems.mc.sandbox.storage.PowerToolStore;
import org.bukkit.entity.Player;
import org.bukkit.event.Event;
@@ -27,7 +28,7 @@ public final class PowerToolListener implements Listener {
|| (event.getAction() != Action.RIGHT_CLICK_AIR
&& event.getAction() != Action.RIGHT_CLICK_BLOCK)) return;
- List<String> commands = store.get(event.getItem());
+ List<PowerToolBinding> commands = store.get(event.getItem());
if (commands.isEmpty()) return;
Player player = event.getPlayer();
@@ -36,7 +37,9 @@ public final class PowerToolListener implements Listener {
return;
}
- commands.forEach(player::performCommand);
+ commands.forEach(
+ binding ->
+ CommandUtils.delegateCommand(player, binding.effectivePlayerId(), binding.command()));
event.setCancelled(true);
}
}
diff --git a/src/main/java/net/cflems/mc/sandbox/storage/DeserializationException.java b/src/main/java/net/cflems/mc/sandbox/storage/DeserializationException.java
new file mode 100644
index 0000000..f2bb0db
--- /dev/null
+++ b/src/main/java/net/cflems/mc/sandbox/storage/DeserializationException.java
@@ -0,0 +1,7 @@
+package net.cflems.mc.sandbox.storage;
+
+public class DeserializationException extends RuntimeException {
+ public DeserializationException(String message) {
+ super(message);
+ }
+}
diff --git a/src/main/java/net/cflems/mc/sandbox/storage/PowerToolBinding.java b/src/main/java/net/cflems/mc/sandbox/storage/PowerToolBinding.java
new file mode 100644
index 0000000..ea35a0a
--- /dev/null
+++ b/src/main/java/net/cflems/mc/sandbox/storage/PowerToolBinding.java
@@ -0,0 +1,32 @@
+package net.cflems.mc.sandbox.storage;
+
+import java.util.Map;
+import java.util.UUID;
+import org.bukkit.configuration.serialization.ConfigurationSerializable;
+import org.jetbrains.annotations.NotNull;
+
+public record PowerToolBinding(String command, UUID effectivePlayerId)
+ implements ConfigurationSerializable {
+ private static final String COMMAND_KEY = "command";
+ private static final String EFFECTIVE_PLAYER_ID_KEY = "effectivePlayerId";
+
+ @NotNull
+ @Override
+ public Map<String, Object> serialize() {
+ return Map.of(COMMAND_KEY, command, EFFECTIVE_PLAYER_ID_KEY, effectivePlayerId.toString());
+ }
+
+ public static PowerToolBinding deserialize(Map<String, Object> serialized) {
+ Object rawCommand = serialized.get(COMMAND_KEY);
+ if (!(rawCommand instanceof String command))
+ throw new DeserializationException(COMMAND_KEY + " must be a string.");
+
+ Object rawEffectivePlayerId = serialized.get(EFFECTIVE_PLAYER_ID_KEY);
+ if (!(rawEffectivePlayerId instanceof String effectivePlayerIdString))
+ throw new DeserializationException(EFFECTIVE_PLAYER_ID_KEY + " must be a UUID.");
+
+ UUID effectivePlayerId = UUID.fromString(effectivePlayerIdString);
+
+ return new PowerToolBinding(command, effectivePlayerId);
+ }
+}
diff --git a/src/main/java/net/cflems/mc/sandbox/storage/PowerToolStore.java b/src/main/java/net/cflems/mc/sandbox/storage/PowerToolStore.java
index bbbd2a5..5214761 100644
--- a/src/main/java/net/cflems/mc/sandbox/storage/PowerToolStore.java
+++ b/src/main/java/net/cflems/mc/sandbox/storage/PowerToolStore.java
@@ -3,6 +3,7 @@ package net.cflems.mc.sandbox.storage;
import com.google.common.base.Preconditions;
import java.io.File;
import java.io.IOException;
+import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
@@ -12,6 +13,7 @@ import org.bukkit.Bukkit;
import org.bukkit.NamespacedKey;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
+import org.bukkit.configuration.serialization.ConfigurationSerialization;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.persistence.PersistentDataType;
@@ -31,23 +33,34 @@ public final class PowerToolStore {
this.config = YamlConfiguration.loadConfiguration(configFile);
}
- public synchronized List<String> get(@Nullable ItemStack item) {
+ public static void registerSerializables() {
+ ConfigurationSerialization.registerClass(PowerToolBinding.class, "PowerToolBinding");
+ }
+
+ public synchronized List<PowerToolBinding> get(@Nullable ItemStack item) {
if (item == null) return List.of();
- return getId(item).map(id -> config.getStringList(id.toString())).orElseGet(List::of);
+ return getId(item).map(id -> getFromConfig(id.toString())).orElseGet(List::of);
}
- public synchronized void add(ItemStack item, String command) {
+ public synchronized void add(ItemStack item, String command, UUID effectivePlayerId) {
String path = getId(item).orElseGet(() -> createId(item)).toString();
- List<String> bindings = config.getStringList(path);
- bindings.add(command);
+ List<PowerToolBinding> bindings = getFromConfig(path);
+ bindings.add(new PowerToolBinding(command, effectivePlayerId));
config.set(path, bindings);
saveConfig();
}
- public synchronized void clear(ItemStack item) {
+ public synchronized void clear(ItemStack item, UUID effectivePlayerId) {
Optional<UUID> id = getId(item);
if (id.isEmpty()) return;
- config.set(id.get().toString(), null);
+ String path = id.get().toString();
+
+ List<PowerToolBinding> bindings = getFromConfig(path);
+ List<PowerToolBinding> purgedBindings =
+ bindings.stream()
+ .filter(binding -> !binding.effectivePlayerId().equals(effectivePlayerId))
+ .toList();
+ config.set(id.get().toString(), purgedBindings.isEmpty() ? null : purgedBindings);
saveConfig();
}
@@ -80,6 +93,16 @@ public final class PowerToolStore {
return id;
}
+ private List<PowerToolBinding> getFromConfig(String path) {
+ List<?> rawList = config.getList(path, List.of());
+ List<PowerToolBinding> convertedList = new ArrayList<>();
+ rawList.stream()
+ .filter(item -> item instanceof PowerToolBinding)
+ .map(item -> (PowerToolBinding) item)
+ .forEach(convertedList::add);
+ return convertedList;
+ }
+
private void saveConfig() {
try {
config.save(configFile);
diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml
index 3011fe1..b4db8ad 100644
--- a/src/main/resources/plugin.yml
+++ b/src/main/resources/plugin.yml
@@ -1,11 +1,11 @@
name: Sandbox
website: https://mc.cflems.net
author: cflems
-version: 0.1.0
+version: 0.2.0
description: Make your Minecraft server into your personal sandbox.
main: net.cflems.mc.sandbox.Sandbox
load: POSTWORLD
-api-version: '1.21.6'
+api-version: '1.21.7'
depend: [ ]
commands:
enchant:
@@ -24,6 +24,9 @@ commands:
aliases: [ "pt" ]
usage: /powertool [command...]
description: Binds a command to the item in your main hand, or clears bound commands if none specified.
+ ptsu:
+ usage: /ptsu <player|console> [command...]
+ description: Executes the powertool command as the specified player.
permissions:
sandbox.*:
default: op
@@ -40,6 +43,7 @@ permissions:
sandbox.powertool: true
sandbox.powertool.use: true
sandbox.powertool.reload: true
+ sandbox.powertool.su: true
sandbox.enchant:
description: Permission to enchant your items.
sandbox.enchant.others:
@@ -63,3 +67,5 @@ permissions:
description: Permission to use power tools.
sandbox.powertool.reload:
description: Permission to reload power tool bindings from disk.
+ sandbox.powertool.su:
+ description: Permission to use power tools as others.