From 7bc59ee3a47083e32ba883b59dd6433c851a46af Mon Sep 17 00:00:00 2001 From: T14D3 <73843330+T14D3@users.noreply.github.com> Date: Wed, 15 Jan 2025 15:34:13 +0100 Subject: [PATCH 01/12] [ci skip] init --- build.gradle | 3 + .../java/de/t14d3/zones/PaperBootstrap.java | 139 ++++++++++++++++++ src/main/java/de/t14d3/zones/Region.java | 23 +++ src/main/java/de/t14d3/zones/Zones.java | 21 +-- .../t14d3/zones/brigadier/FlagArgument.java | 21 +++ .../t14d3/zones/brigadier/NameArgument.java | 17 +++ .../zones/brigadier/RegionKeyArgument.java | 78 ++++++++++ .../zones/brigadier/SubCommandArgument.java | 35 +++++ .../de/t14d3/zones/brigadier/SubCommands.java | 32 ++++ .../zones/listeners/CommandListener.java | 2 +- .../java/de/t14d3/zones/utils/Actions.java | 26 +++- src/main/resources/paper-plugin.yml | 5 + 12 files changed, 384 insertions(+), 18 deletions(-) create mode 100644 src/main/java/de/t14d3/zones/PaperBootstrap.java create mode 100644 src/main/java/de/t14d3/zones/brigadier/FlagArgument.java create mode 100644 src/main/java/de/t14d3/zones/brigadier/NameArgument.java create mode 100644 src/main/java/de/t14d3/zones/brigadier/RegionKeyArgument.java create mode 100644 src/main/java/de/t14d3/zones/brigadier/SubCommandArgument.java create mode 100644 src/main/java/de/t14d3/zones/brigadier/SubCommands.java create mode 100644 src/main/resources/paper-plugin.yml diff --git a/build.gradle b/build.gradle index c2f7493..91479bb 100644 --- a/build.gradle +++ b/build.gradle @@ -70,6 +70,9 @@ processResources { filesMatching('plugin.yml') { expand props } + filesMatching('paper-plugin.yml') { + expand props + } } tasks { diff --git a/src/main/java/de/t14d3/zones/PaperBootstrap.java b/src/main/java/de/t14d3/zones/PaperBootstrap.java new file mode 100644 index 0000000..92bbece --- /dev/null +++ b/src/main/java/de/t14d3/zones/PaperBootstrap.java @@ -0,0 +1,139 @@ +package de.t14d3.zones; + +import com.mojang.brigadier.Command; +import com.mojang.brigadier.context.CommandContext; +import de.t14d3.zones.brigadier.*; +import de.t14d3.zones.utils.Actions; +import io.papermc.paper.command.brigadier.CommandSourceStack; +import io.papermc.paper.command.brigadier.Commands; +import io.papermc.paper.command.brigadier.MessageComponentSerializer; +import io.papermc.paper.command.brigadier.argument.ArgumentTypes; +import io.papermc.paper.plugin.bootstrap.BootstrapContext; +import io.papermc.paper.plugin.bootstrap.PluginBootstrap; +import io.papermc.paper.plugin.bootstrap.PluginProviderContext; +import io.papermc.paper.plugin.lifecycle.event.LifecycleEventManager; +import io.papermc.paper.plugin.lifecycle.event.types.LifecycleEvents; +import io.papermc.paper.registry.RegistryKey; +import net.kyori.adventure.text.Component; +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; +import org.bukkit.plugin.java.JavaPlugin; + +import java.util.List; +import java.util.Map; + +@SuppressWarnings("UnstableApiUsage") +public class PaperBootstrap implements PluginBootstrap { + + private Zones zones; + + @Override + public void bootstrap(BootstrapContext context) { + LifecycleEventManager eventManager = context.getLifecycleManager(); + eventManager.registerEventHandler(LifecycleEvents.COMMANDS, event -> { + final Commands commands = event.registrar(); + commands.register( + Commands.literal("zone") + .then(Commands.argument("subcommand", new SubCommandArgument()) + .executes(ctx -> { + Zones.getInstance().getCommandListener().execute(ctx.getSource(), new String[]{ctx.getArgument("subcommand", SubCommands.class).name()}); + ctx.getSource().getSender().sendMessage(ctx.getInput()); + return 1; + }) + .then(Commands.argument("key", new RegionKeyArgument()) + .suggests((ctx, builder) -> { + for (Map.Entry region : Zones.getInstance().getRegionManager().regions().entrySet()) { + if (ctx.getSource().getSender().hasPermission("zones.info.other") + || (ctx.getSource().getSender() instanceof Player player && region.getValue().isAdmin(player.getUniqueId()))) { + builder.suggest( + region.getKey(), + MessageComponentSerializer.message().serialize( + RegionKeyArgument.regionInfo(Map.entry(region.getKey(), region.getValue())) + ) + ); + } + } + return builder.buildFuture(); + }) + .executes(ctx -> { + Zones.getInstance().getCommandListener().execute(ctx.getSource(), ctx.getInput().substring(5).split(" ")); + ctx.getSource().getSender().sendMessage("arg: " + ctx.getInput()); + ctx.getSource().getSender().sendMessage("root: " + ctx.getRootNode().getName()); + return Command.SINGLE_SUCCESS; + }) + .then(Commands.argument("player", new NameArgument()) + .suggests((ctx, builder) -> { + for (OfflinePlayer offlinePlayer : Bukkit.getOfflinePlayers()) { + builder.suggest(offlinePlayer.getName()); + } + return builder.buildFuture(); + }) + .executes(ctx -> { + Zones.getInstance().getCommandListener().execute(ctx.getSource(), ctx.getInput().substring(5).split(" ")); + ctx.getSource().getSender().sendMessage("arg: " + ctx.getInput()); + ctx.getSource().getSender().sendMessage("root: " + ctx.getRootNode().getName()); + return Command.SINGLE_SUCCESS; + }) + .then(Commands.argument("flag", new FlagArgument()) + .suggests((ctx, builder) -> { + for (Actions action : Actions.values()) { + builder.suggest(action.name(), MessageComponentSerializer.message().serialize(Component.text(action.getKey()))); + } + return builder.buildFuture(); + }) + .executes(ctx -> { + Zones.getInstance().getCommandListener().execute(ctx.getSource(), ctx.getInput().substring(5).split(" ")); + ctx.getSource().getSender().sendMessage("arg: " + ctx.getInput()); + ctx.getSource().getSender().sendMessage("root: " + ctx.getRootNode().getName()); + return Command.SINGLE_SUCCESS; + }) + .then(Commands.argument("value", ArgumentTypes.resource(RegistryKey.BLOCK)) + .suggests((ctx, builder) -> { + Zones plugin = Zones.getInstance(); + List types; + switch (arg(ctx, 4).toUpperCase()) { + case "PLACE", "BREAK" -> + types = plugin.getTypes().blockTypes; + case "CONTAINER" -> + types = plugin.getTypes().containerTypes; + case "REDSTONE" -> + types = plugin.getTypes().redstoneTypes; + case "ENTITY", "DAMAGE" -> + types = plugin.getTypes().entityTypes; + case "IGNITE" -> + types = List.of("TRUE", "FALSE"); + default -> + types = plugin.getTypes().allTypes; + } + for (String value : types) { + builder.suggest(value, MessageComponentSerializer.message().serialize(Component.text(value))); + } + return builder.buildFuture(); + }) + ) + ) + ) + ) + ).build() + ); + }); + } + + @Override + public JavaPlugin createPlugin(PluginProviderContext context) { + zones = new Zones(); + return zones; + } + + /** + * Helper function to get the argument of a command at the given index + * + * @param ctx Command context + * @param index Index of the argument + * @return Argument at the given index + */ + public static String arg(CommandContext ctx, int index) { + return ctx.getInput().split(" ")[index]; + } +} \ No newline at end of file diff --git a/src/main/java/de/t14d3/zones/Region.java b/src/main/java/de/t14d3/zones/Region.java index 522126b..f635ab5 100644 --- a/src/main/java/de/t14d3/zones/Region.java +++ b/src/main/java/de/t14d3/zones/Region.java @@ -122,6 +122,12 @@ public Map> getMembers() { return members; } + /** + * Get the names of all groups in this region + * + * @return List of group names + * @since 0.1.5 + */ public List getGroupNames() { List groupNames = new ArrayList<>(); for (Map.Entry> entry : members.entrySet()) { @@ -132,6 +138,23 @@ public List getGroupNames() { return groupNames; } + /** + * Get the members of a group in this region + * + * @param group Group name + * @return List of members + * @since 0.1.6 + */ + public List getGroupMembers(String group) { + List groupMembers = new ArrayList<>(); + for (Map.Entry> entry : members.entrySet()) { + if (entry.getValue().containsKey("group") && entry.getValue().get("group").contains(group.substring(7))) { + groupMembers.add(entry.getKey()); + } + } + return groupMembers; + } + void setMembers(Map> members, RegionManager regionManager, String key) { this.members = members; regionManager.saveRegion(key, this); // Ensure changes are saved diff --git a/src/main/java/de/t14d3/zones/Zones.java b/src/main/java/de/t14d3/zones/Zones.java index ba861f1..35d5348 100644 --- a/src/main/java/de/t14d3/zones/Zones.java +++ b/src/main/java/de/t14d3/zones/Zones.java @@ -9,12 +9,8 @@ import de.t14d3.zones.listeners.PlayerInteractListener; import de.t14d3.zones.listeners.PlayerQuitListener; import de.t14d3.zones.utils.*; -import io.papermc.paper.command.brigadier.Commands; -import io.papermc.paper.plugin.lifecycle.event.LifecycleEventManager; -import io.papermc.paper.plugin.lifecycle.event.types.LifecycleEvents; import it.unimi.dsi.fastutil.Pair; import org.bukkit.Location; -import org.bukkit.plugin.Plugin; import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.util.BoundingBox; @@ -37,6 +33,7 @@ public final class Zones extends JavaPlugin { private Types types; private Messages messages; private static Zones instance; + private CommandListener commandListener; @Override @SuppressWarnings("UnstableApiUsage") @@ -86,12 +83,14 @@ public void onEnable() { types.populateTypes(); // Register command executor and tab completer - LifecycleEventManager manager = this.getLifecycleManager(); - manager.registerEventHandler(LifecycleEvents.COMMANDS, event -> { - final Commands commands = event.registrar(); - commands.register("zone", new CommandListener(this, regionManager)); - }); +// LifecycleEventManager manager = this.getLifecycleManager(); +// manager.registerEventHandler(LifecycleEvents.COMMANDS, event -> { +// final Commands commands = event.registrar(); +// commands.register("zone", commandListener); +// }); + + this.commandListener = new CommandListener(this, regionManager); // Register saving task if (getSavingMode() == Utils.SavingModes.PERIODIC) { getServer().getScheduler().runTaskTimerAsynchronously(this, () -> { @@ -154,4 +153,8 @@ public Utils.SavingModes getSavingMode() { public static Zones getInstance() { return instance; } + + public CommandListener getCommandListener() { + return commandListener; + } } diff --git a/src/main/java/de/t14d3/zones/brigadier/FlagArgument.java b/src/main/java/de/t14d3/zones/brigadier/FlagArgument.java new file mode 100644 index 0000000..900ffcd --- /dev/null +++ b/src/main/java/de/t14d3/zones/brigadier/FlagArgument.java @@ -0,0 +1,21 @@ +package de.t14d3.zones.brigadier; + +import com.mojang.brigadier.arguments.ArgumentType; +import com.mojang.brigadier.arguments.StringArgumentType; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import de.t14d3.zones.utils.Actions; +import io.papermc.paper.command.brigadier.argument.CustomArgumentType; + +@SuppressWarnings("UnstableApiUsage") +public class FlagArgument implements CustomArgumentType.Converted { + + @Override + public Actions convert(String nativeType) throws CommandSyntaxException { + return Actions.valueOf(nativeType.toUpperCase()); + } + + @Override + public ArgumentType getNativeType() { + return StringArgumentType.word(); + } +} diff --git a/src/main/java/de/t14d3/zones/brigadier/NameArgument.java b/src/main/java/de/t14d3/zones/brigadier/NameArgument.java new file mode 100644 index 0000000..14611e0 --- /dev/null +++ b/src/main/java/de/t14d3/zones/brigadier/NameArgument.java @@ -0,0 +1,17 @@ +package de.t14d3.zones.brigadier; + +import com.mojang.brigadier.arguments.ArgumentType; +import com.mojang.brigadier.arguments.StringArgumentType; +import io.papermc.paper.command.brigadier.argument.CustomArgumentType; + +public class NameArgument implements CustomArgumentType.Converted { + @Override + public String convert(String arg) { + return arg; + } + + @Override + public ArgumentType getNativeType() { + return StringArgumentType.word(); + } +} diff --git a/src/main/java/de/t14d3/zones/brigadier/RegionKeyArgument.java b/src/main/java/de/t14d3/zones/brigadier/RegionKeyArgument.java new file mode 100644 index 0000000..2e34f97 --- /dev/null +++ b/src/main/java/de/t14d3/zones/brigadier/RegionKeyArgument.java @@ -0,0 +1,78 @@ +package de.t14d3.zones.brigadier; + +import com.mojang.brigadier.arguments.ArgumentType; +import com.mojang.brigadier.arguments.StringArgumentType; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import de.t14d3.zones.Region; +import de.t14d3.zones.Zones; +import de.t14d3.zones.utils.Messages; +import io.papermc.paper.command.brigadier.argument.CustomArgumentType; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import net.kyori.adventure.text.minimessage.MiniMessage; +import org.bukkit.Bukkit; +import org.jetbrains.annotations.NotNull; + +import java.util.Map; +import java.util.UUID; + +import static net.kyori.adventure.text.minimessage.tag.resolver.Placeholder.parsed; + +@SuppressWarnings("UnstableApiUsage") +public class RegionKeyArgument implements CustomArgumentType.Converted { + public RegionKeyArgument() { + + } + + /** + * Get a region object from a string + * + * @param nativeType native argument provided value + * @return Region object + * @throws CommandSyntaxException if region is not found + */ + @Override + public @NotNull Region convert(@NotNull String nativeType) throws CommandSyntaxException { + Region region = Zones.getInstance().getRegionManager().regions().get(nativeType); + if (region == null) { + throw new CommandSyntaxException(null, () -> "Region not found!"); + } + return region; + } + + @Override + public @NotNull ArgumentType getNativeType() { + return StringArgumentType.word(); + } + + + public static Component regionInfo(Map.Entry entry) { + Messages messages = Zones.getInstance().getMessages(); + var mm = MiniMessage.miniMessage(); + Component comp = Component.empty(); + comp = comp.append(mm.deserialize("Name: " + messages.get("region.info.name") + " ", parsed("name", entry.getValue().getName()))); + if (entry.getValue().getParent() != null) { + comp = comp.append(mm.deserialize(messages.get("region.info.parent") + " ", parsed("parent", entry.getValue().getParent()))); + } + comp = comp.append(mm.deserialize("(" + messages.get("region.info.min") + " - ", parsed("min", entry.getValue().getMinString()))); + comp = comp.append(mm.deserialize(messages.get("region.info.max") + ")", parsed("max", entry.getValue().getMaxString()))); + comp = comp.append(Component.text(" Members: ").color(NamedTextColor.LIGHT_PURPLE)); + + // Iterate over members to format permissions + for (Map.Entry> member : entry.getValue().getMembers().entrySet()) { + String playerName = null; + try { + playerName = Bukkit.getOfflinePlayer(UUID.fromString(member.getKey())).getName(); + } catch (IllegalArgumentException ignored) { + } + if (playerName == null) { + playerName = member.getKey(); + } + Component playerComponent = mm.deserialize(messages.get("region.info.members.name") + " ", parsed("name", playerName)); + comp = comp.append(playerComponent); + } + + comp = comp.append(mm.deserialize(" " + messages.get("region.info.key"), parsed("key", entry.getKey()))); + return comp; + } +} \ No newline at end of file diff --git a/src/main/java/de/t14d3/zones/brigadier/SubCommandArgument.java b/src/main/java/de/t14d3/zones/brigadier/SubCommandArgument.java new file mode 100644 index 0000000..df39391 --- /dev/null +++ b/src/main/java/de/t14d3/zones/brigadier/SubCommandArgument.java @@ -0,0 +1,35 @@ +package de.t14d3.zones.brigadier; + +import com.mojang.brigadier.arguments.ArgumentType; +import com.mojang.brigadier.arguments.StringArgumentType; +import com.mojang.brigadier.context.CommandContext; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.mojang.brigadier.suggestion.Suggestions; +import com.mojang.brigadier.suggestion.SuggestionsBuilder; +import io.papermc.paper.command.brigadier.MessageComponentSerializer; +import io.papermc.paper.command.brigadier.argument.CustomArgumentType; +import org.jetbrains.annotations.NotNull; + +import java.util.concurrent.CompletableFuture; + + +@SuppressWarnings("UnstableApiUsage") +public class SubCommandArgument implements CustomArgumentType.Converted { + @Override + public @NotNull SubCommands convert(@NotNull String nativeType) throws CommandSyntaxException { + return SubCommands.get(nativeType.toUpperCase()); + } + + @Override + public @NotNull ArgumentType getNativeType() { + return StringArgumentType.string(); + } + + @Override + public @NotNull CompletableFuture listSuggestions(@NotNull CommandContext context, @NotNull SuggestionsBuilder builder) { + for (SubCommands subCommand : SubCommands.values()) { + builder.suggest(subCommand.name(), MessageComponentSerializer.message().serialize(subCommand.getInfo())); + } + return builder.buildFuture(); + } +} diff --git a/src/main/java/de/t14d3/zones/brigadier/SubCommands.java b/src/main/java/de/t14d3/zones/brigadier/SubCommands.java new file mode 100644 index 0000000..ba605d9 --- /dev/null +++ b/src/main/java/de/t14d3/zones/brigadier/SubCommands.java @@ -0,0 +1,32 @@ +package de.t14d3.zones.brigadier; + +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; + +public enum SubCommands { + INFO(Component.text("Shows information about a region\nTEXT").color(NamedTextColor.GOLD)), + LIST(Component.text("Lists all regions").color(NamedTextColor.GOLD)), + DELETE(Component.text("Deletes a region").color(NamedTextColor.DARK_RED)), + CREATE(Component.text("Creates a new region").color(NamedTextColor.GREEN)), + EXPAND(Component.text("Expands a region").color(NamedTextColor.AQUA)), + SELECT(Component.text("Visually selects a region").color(NamedTextColor.LIGHT_PURPLE)), + SET(Component.text("Sets permissions for a region").color(NamedTextColor.BLUE)), + CANCEL(Component.text("Cancels the current operation").color(NamedTextColor.RED)), + SAVE(Component.text("Saves all regions to file")), + LOAD(Component.text("Loads all regions from file")); + + + private final Component info; + + SubCommands(Component info) { + this.info = info; + } + + public Component getInfo() { + return info; + } + + public static SubCommands get(String input) { + return SubCommands.valueOf(input.split(" ")[0]); + } +} \ No newline at end of file diff --git a/src/main/java/de/t14d3/zones/listeners/CommandListener.java b/src/main/java/de/t14d3/zones/listeners/CommandListener.java index a9a7942..dbdea79 100644 --- a/src/main/java/de/t14d3/zones/listeners/CommandListener.java +++ b/src/main/java/de/t14d3/zones/listeners/CommandListener.java @@ -435,7 +435,7 @@ private void handleInfoCommand(CommandSender sender, String[] args) { private void handleSetCommand(CommandSender sender, String[] args) { - if (args.length < 4) { + if (args.length < 5) { sender.sendMessage(miniMessage.deserialize(messages.get("commands.set.invalid-usage"))); return; } diff --git a/src/main/java/de/t14d3/zones/utils/Actions.java b/src/main/java/de/t14d3/zones/utils/Actions.java index 161f0d6..a405f75 100644 --- a/src/main/java/de/t14d3/zones/utils/Actions.java +++ b/src/main/java/de/t14d3/zones/utils/Actions.java @@ -1,12 +1,22 @@ package de.t14d3.zones.utils; public enum Actions { - BREAK, - PLACE, - INTERACT, - CONTAINER, - REDSTONE, - ENTITY, - IGNITE, - DAMAGE + BREAK("Allows breaking blocks"), + PLACE("Allows placing blocks"), + INTERACT("Allows interacting"), + CONTAINER("Allows opening containers"), + REDSTONE("Allows interacting with redstone"), + ENTITY("Allows interacting with entities"), + IGNITE("Allows igniting tnt"), + DAMAGE("Allows damaging entities"); + + private final String key; + + Actions(String key) { + this.key = key; + } + + public String getKey() { + return key; + } } diff --git a/src/main/resources/paper-plugin.yml b/src/main/resources/paper-plugin.yml new file mode 100644 index 0000000..399fbda --- /dev/null +++ b/src/main/resources/paper-plugin.yml @@ -0,0 +1,5 @@ +name: Zones +version: '${version}' +main: de.t14d3.zones.Zones +api-version: '1.21' +bootstrapper: de.t14d3.zones.PaperBootstrap \ No newline at end of file From 42b8b1975d270244135d3f213a7a4bd86594084b Mon Sep 17 00:00:00 2001 From: T14D3 <73843330+T14D3@users.noreply.github.com> Date: Wed, 15 Jan 2025 17:17:10 +0100 Subject: [PATCH 02/12] Only show relevant suggestions --- .../java/de/t14d3/zones/brigadier/SubCommandArgument.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/de/t14d3/zones/brigadier/SubCommandArgument.java b/src/main/java/de/t14d3/zones/brigadier/SubCommandArgument.java index df39391..fd33a96 100644 --- a/src/main/java/de/t14d3/zones/brigadier/SubCommandArgument.java +++ b/src/main/java/de/t14d3/zones/brigadier/SubCommandArgument.java @@ -28,7 +28,10 @@ public class SubCommandArgument implements CustomArgumentType.Converted @NotNull CompletableFuture listSuggestions(@NotNull CommandContext context, @NotNull SuggestionsBuilder builder) { for (SubCommands subCommand : SubCommands.values()) { - builder.suggest(subCommand.name(), MessageComponentSerializer.message().serialize(subCommand.getInfo())); + String[] args = context.getInput().split(" "); + if (args.length == 1 || subCommand.name().toLowerCase().startsWith(args[1].toLowerCase())) { + builder.suggest(subCommand.name().toLowerCase(), MessageComponentSerializer.message().serialize(subCommand.getInfo())); + } } return builder.buildFuture(); } From 4dd434e44418bae473b03ca5300f51456c1c9e4e Mon Sep 17 00:00:00 2001 From: T14D3 <73843330+T14D3@users.noreply.github.com> Date: Wed, 15 Jan 2025 18:03:37 +0100 Subject: [PATCH 03/12] More work on brigadier command stuff, change group prefix to "+" --- .../java/de/t14d3/zones/PaperBootstrap.java | 29 +++++++++++++++++-- .../de/t14d3/zones/PermissionManager.java | 4 +-- src/main/java/de/t14d3/zones/Region.java | 2 +- .../t14d3/zones/brigadier/NameArgument.java | 17 ----------- 4 files changed, 29 insertions(+), 23 deletions(-) delete mode 100644 src/main/java/de/t14d3/zones/brigadier/NameArgument.java diff --git a/src/main/java/de/t14d3/zones/PaperBootstrap.java b/src/main/java/de/t14d3/zones/PaperBootstrap.java index 92bbece..fb6ccdd 100644 --- a/src/main/java/de/t14d3/zones/PaperBootstrap.java +++ b/src/main/java/de/t14d3/zones/PaperBootstrap.java @@ -1,8 +1,12 @@ package de.t14d3.zones; import com.mojang.brigadier.Command; +import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.context.CommandContext; -import de.t14d3.zones.brigadier.*; +import de.t14d3.zones.brigadier.FlagArgument; +import de.t14d3.zones.brigadier.RegionKeyArgument; +import de.t14d3.zones.brigadier.SubCommandArgument; +import de.t14d3.zones.brigadier.SubCommands; import de.t14d3.zones.utils.Actions; import io.papermc.paper.command.brigadier.CommandSourceStack; import io.papermc.paper.command.brigadier.Commands; @@ -20,8 +24,10 @@ import org.bukkit.entity.Player; import org.bukkit.plugin.java.JavaPlugin; +import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.UUID; @SuppressWarnings("UnstableApiUsage") public class PaperBootstrap implements PluginBootstrap { @@ -62,10 +68,27 @@ public void bootstrap(BootstrapContext context) { ctx.getSource().getSender().sendMessage("root: " + ctx.getRootNode().getName()); return Command.SINGLE_SUCCESS; }) - .then(Commands.argument("player", new NameArgument()) + .then(Commands.argument("player", StringArgumentType.word()) .suggests((ctx, builder) -> { for (OfflinePlayer offlinePlayer : Bukkit.getOfflinePlayers()) { - builder.suggest(offlinePlayer.getName()); + if (ctx.getInput().split(" ").length <= 3 || (offlinePlayer.getName() != null ? offlinePlayer.getName() : offlinePlayer.getUniqueId().toString()).startsWith(arg(ctx, 3))) { + builder.suggest(offlinePlayer.getName()); + } + } + for (Map.Entry region : Zones.getInstance().getRegionManager().regions().entrySet()) { + if (!ctx.getInput().split(" ")[2].equalsIgnoreCase(region.getKey())) { + continue; + } + if (ctx.getSource().getSender().hasPermission("zones.info.other") + || (ctx.getSource().getSender() instanceof Player player && region.getValue().isAdmin(player.getUniqueId()))) { + region.getValue().getGroupNames().forEach(group -> { + List groupMembers = new ArrayList<>(); + region.getValue().getGroupMembers(group).forEach(val -> { + groupMembers.add(Bukkit.getOfflinePlayer(UUID.fromString(val)).getName()); + }); + builder.suggest(group, MessageComponentSerializer.message().serialize(Component.text(groupMembers.toString()))); + }); + } } return builder.buildFuture(); }) diff --git a/src/main/java/de/t14d3/zones/PermissionManager.java b/src/main/java/de/t14d3/zones/PermissionManager.java index a3c6213..63e0275 100644 --- a/src/main/java/de/t14d3/zones/PermissionManager.java +++ b/src/main/java/de/t14d3/zones/PermissionManager.java @@ -184,14 +184,14 @@ private boolean calculatePermission(String who, String permission, String type, return hasPermission(who, permission, type, region.getParentRegion(this.regionManager)); } if (permissions.containsKey("group")) { - if (who.startsWith(":group-") && !Zones.getInstance().getConfig().getBoolean("allow-group-recursion", false)) { + if (who.startsWith("+group-") && !Zones.getInstance().getConfig().getBoolean("allow-group-recursion", false)) { Zones.getInstance().getLogger().severe("Recursive group permissions detected!! Groups are not allowed to contain other groups!"); Zones.getInstance().getLogger().severe("Group '" + who.substring(7) + "' contains 'group' permission entry in region '" + region.getKey() + "'"); Zones.getInstance().getLogger().severe("If you are 100% sure this is fine, add 'allow-group-recursion: true' to your config.yml"); return false; } for (String group : permissions.get("group").split(",")) { - return hasPermission(":group-" + group, permission, type, region); + return hasPermission("+group-" + group, permission, type, region); } } // Nothing found, deny access diff --git a/src/main/java/de/t14d3/zones/Region.java b/src/main/java/de/t14d3/zones/Region.java index f635ab5..2995b41 100644 --- a/src/main/java/de/t14d3/zones/Region.java +++ b/src/main/java/de/t14d3/zones/Region.java @@ -131,7 +131,7 @@ public Map> getMembers() { public List getGroupNames() { List groupNames = new ArrayList<>(); for (Map.Entry> entry : members.entrySet()) { - if (entry.getKey().startsWith(":group-")) { + if (entry.getKey().startsWith("+group-")) { groupNames.add(entry.getKey()); } } diff --git a/src/main/java/de/t14d3/zones/brigadier/NameArgument.java b/src/main/java/de/t14d3/zones/brigadier/NameArgument.java deleted file mode 100644 index 14611e0..0000000 --- a/src/main/java/de/t14d3/zones/brigadier/NameArgument.java +++ /dev/null @@ -1,17 +0,0 @@ -package de.t14d3.zones.brigadier; - -import com.mojang.brigadier.arguments.ArgumentType; -import com.mojang.brigadier.arguments.StringArgumentType; -import io.papermc.paper.command.brigadier.argument.CustomArgumentType; - -public class NameArgument implements CustomArgumentType.Converted { - @Override - public String convert(String arg) { - return arg; - } - - @Override - public ArgumentType getNativeType() { - return StringArgumentType.word(); - } -} From fe78e3cbb6550102d8ef1007a873f3c912a2bbac Mon Sep 17 00:00:00 2001 From: T14D3 <73843330+T14D3@users.noreply.github.com> Date: Wed, 15 Jan 2025 20:48:54 +0100 Subject: [PATCH 04/12] Even more work, technically functional now --- .../java/de/t14d3/zones/PaperBootstrap.java | 60 ++++--- .../de/t14d3/zones/PermissionManager.java | 18 +- .../zones/brigadier/RegionKeyArgument.java | 6 +- .../zones/listeners/CommandListener.java | 154 ++++-------------- 4 files changed, 70 insertions(+), 168 deletions(-) diff --git a/src/main/java/de/t14d3/zones/PaperBootstrap.java b/src/main/java/de/t14d3/zones/PaperBootstrap.java index fb6ccdd..0f956d3 100644 --- a/src/main/java/de/t14d3/zones/PaperBootstrap.java +++ b/src/main/java/de/t14d3/zones/PaperBootstrap.java @@ -6,19 +6,17 @@ import de.t14d3.zones.brigadier.FlagArgument; import de.t14d3.zones.brigadier.RegionKeyArgument; import de.t14d3.zones.brigadier.SubCommandArgument; -import de.t14d3.zones.brigadier.SubCommands; import de.t14d3.zones.utils.Actions; import io.papermc.paper.command.brigadier.CommandSourceStack; import io.papermc.paper.command.brigadier.Commands; import io.papermc.paper.command.brigadier.MessageComponentSerializer; -import io.papermc.paper.command.brigadier.argument.ArgumentTypes; import io.papermc.paper.plugin.bootstrap.BootstrapContext; import io.papermc.paper.plugin.bootstrap.PluginBootstrap; import io.papermc.paper.plugin.bootstrap.PluginProviderContext; import io.papermc.paper.plugin.lifecycle.event.LifecycleEventManager; import io.papermc.paper.plugin.lifecycle.event.types.LifecycleEvents; -import io.papermc.paper.registry.RegistryKey; import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; import org.bukkit.entity.Player; @@ -43,15 +41,21 @@ public void bootstrap(BootstrapContext context) { Commands.literal("zone") .then(Commands.argument("subcommand", new SubCommandArgument()) .executes(ctx -> { - Zones.getInstance().getCommandListener().execute(ctx.getSource(), new String[]{ctx.getArgument("subcommand", SubCommands.class).name()}); - ctx.getSource().getSender().sendMessage(ctx.getInput()); + Zones.getInstance().getCommandListener().execute(ctx.getSource(), ctx.getInput()); return 1; }) .then(Commands.argument("key", new RegionKeyArgument()) .suggests((ctx, builder) -> { + switch (arg(ctx, 1).toUpperCase()) { + case "LIST", "CANCEL", "CREATE", "SAVE", "LOAD" -> { + return builder.buildFuture(); + } + default -> { + } + } + boolean hasPerm = ctx.getSource().getSender().hasPermission("zones." + arg(ctx, 1).toLowerCase() + ".other"); for (Map.Entry region : Zones.getInstance().getRegionManager().regions().entrySet()) { - if (ctx.getSource().getSender().hasPermission("zones.info.other") - || (ctx.getSource().getSender() instanceof Player player && region.getValue().isAdmin(player.getUniqueId()))) { + if (hasPerm || ctx.getSource().getSender() instanceof Player player && region.getValue().isAdmin(player.getUniqueId())) { builder.suggest( region.getKey(), MessageComponentSerializer.message().serialize( @@ -63,15 +67,17 @@ public void bootstrap(BootstrapContext context) { return builder.buildFuture(); }) .executes(ctx -> { - Zones.getInstance().getCommandListener().execute(ctx.getSource(), ctx.getInput().substring(5).split(" ")); - ctx.getSource().getSender().sendMessage("arg: " + ctx.getInput()); - ctx.getSource().getSender().sendMessage("root: " + ctx.getRootNode().getName()); + Zones.getInstance().getCommandListener().execute(ctx.getSource(), ctx.getInput()); + ctx.getSource().getSender().sendMessage(String.join(", ", ctx.getInput().split(" "))); return Command.SINGLE_SUCCESS; }) .then(Commands.argument("player", StringArgumentType.word()) .suggests((ctx, builder) -> { + if (arg(ctx, 1).equalsIgnoreCase("INFO") || arg(ctx, 1).equalsIgnoreCase("DELETE") || arg(ctx, 1).equalsIgnoreCase("SELECT")) { + return builder.buildFuture(); + } for (OfflinePlayer offlinePlayer : Bukkit.getOfflinePlayers()) { - if (ctx.getInput().split(" ").length <= 3 || (offlinePlayer.getName() != null ? offlinePlayer.getName() : offlinePlayer.getUniqueId().toString()).startsWith(arg(ctx, 3))) { + if (ctx.getInput().split(" ").length <= 3 || (offlinePlayer.getName() != null ? offlinePlayer.getName() : offlinePlayer.getUniqueId().toString()).toLowerCase().startsWith(arg(ctx, 3).toLowerCase())) { builder.suggest(offlinePlayer.getName()); } } @@ -86,32 +92,24 @@ public void bootstrap(BootstrapContext context) { region.getValue().getGroupMembers(group).forEach(val -> { groupMembers.add(Bukkit.getOfflinePlayer(UUID.fromString(val)).getName()); }); - builder.suggest(group, MessageComponentSerializer.message().serialize(Component.text(groupMembers.toString()))); + if (ctx.getInput().split(" ").length <= 3 + || group.toLowerCase().startsWith(arg(ctx, 3).toLowerCase()) + || group.toLowerCase().replace("+", "").startsWith(arg(ctx, 3).toLowerCase())) { + builder.suggest(group, MessageComponentSerializer.message().serialize(Component.text(groupMembers.toString()))); + } }); } } return builder.buildFuture(); }) - .executes(ctx -> { - Zones.getInstance().getCommandListener().execute(ctx.getSource(), ctx.getInput().substring(5).split(" ")); - ctx.getSource().getSender().sendMessage("arg: " + ctx.getInput()); - ctx.getSource().getSender().sendMessage("root: " + ctx.getRootNode().getName()); - return Command.SINGLE_SUCCESS; - }) .then(Commands.argument("flag", new FlagArgument()) .suggests((ctx, builder) -> { for (Actions action : Actions.values()) { - builder.suggest(action.name(), MessageComponentSerializer.message().serialize(Component.text(action.getKey()))); + builder.suggest(action.name().toLowerCase(), MessageComponentSerializer.message().serialize(Component.text(action.getKey()))); } return builder.buildFuture(); }) - .executes(ctx -> { - Zones.getInstance().getCommandListener().execute(ctx.getSource(), ctx.getInput().substring(5).split(" ")); - ctx.getSource().getSender().sendMessage("arg: " + ctx.getInput()); - ctx.getSource().getSender().sendMessage("root: " + ctx.getRootNode().getName()); - return Command.SINGLE_SUCCESS; - }) - .then(Commands.argument("value", ArgumentTypes.resource(RegistryKey.BLOCK)) + .then(Commands.argument("value", StringArgumentType.greedyString()) .suggests((ctx, builder) -> { Zones plugin = Zones.getInstance(); List types; @@ -129,11 +127,19 @@ public void bootstrap(BootstrapContext context) { default -> types = plugin.getTypes().allTypes; } + String[] args = ctx.getInput().split(" "); for (String value : types) { - builder.suggest(value, MessageComponentSerializer.message().serialize(Component.text(value))); + if (args.length == 5 || value.toLowerCase().startsWith(args[args.length - 1])) { + builder.suggest(value.toLowerCase(), MessageComponentSerializer.message().serialize( + Component.text(value).color(value.startsWith("!") ? NamedTextColor.RED : NamedTextColor.GREEN))); + } } return builder.buildFuture(); }) + .executes(ctx -> { + Zones.getInstance().getCommandListener().execute(ctx.getSource(), ctx.getInput()); + return Command.SINGLE_SUCCESS; + }) ) ) ) diff --git a/src/main/java/de/t14d3/zones/PermissionManager.java b/src/main/java/de/t14d3/zones/PermissionManager.java index 63e0275..c86f5c1 100644 --- a/src/main/java/de/t14d3/zones/PermissionManager.java +++ b/src/main/java/de/t14d3/zones/PermissionManager.java @@ -203,6 +203,7 @@ private boolean calculatePermission(String who, String permission, String type, // Analyze permission values boolean explicitAllow = false; boolean explicitDeny = false; + boolean result = false; if (value != null) { for (String permittedValue : value.split(",")) { @@ -210,31 +211,24 @@ private boolean calculatePermission(String who, String permission, String type, // Check for wildcard allow if ("*".equals(permittedValue) || "true".equalsIgnoreCase(permittedValue)) { - explicitAllow = true; + result = true; } // Check for wildcard deny else if ("! *".equals(permittedValue) || "false".equalsIgnoreCase(permittedValue)) { - explicitDeny = true; + result = false; } // Check for specific type allow else if (permittedValue.equalsIgnoreCase(type)) { - explicitAllow = true; + result = true; } // Check for specific type deny else if (permittedValue.equalsIgnoreCase("!" + type)) { - explicitDeny = true; + result = false; } } } - // Determine final access based on explicit allow/deny flags - if (explicitDeny) { - return false; - } else if (explicitAllow) { - return true; - } - // Deny by default - return false; + return result; } public boolean isAdmin(String who, Region region) { diff --git a/src/main/java/de/t14d3/zones/brigadier/RegionKeyArgument.java b/src/main/java/de/t14d3/zones/brigadier/RegionKeyArgument.java index 2e34f97..4fa3d53 100644 --- a/src/main/java/de/t14d3/zones/brigadier/RegionKeyArgument.java +++ b/src/main/java/de/t14d3/zones/brigadier/RegionKeyArgument.java @@ -33,11 +33,7 @@ public RegionKeyArgument() { */ @Override public @NotNull Region convert(@NotNull String nativeType) throws CommandSyntaxException { - Region region = Zones.getInstance().getRegionManager().regions().get(nativeType); - if (region == null) { - throw new CommandSyntaxException(null, () -> "Region not found!"); - } - return region; + return Zones.getInstance().getRegionManager().regions().get(nativeType); } @Override diff --git a/src/main/java/de/t14d3/zones/listeners/CommandListener.java b/src/main/java/de/t14d3/zones/listeners/CommandListener.java index dbdea79..b7aec2e 100644 --- a/src/main/java/de/t14d3/zones/listeners/CommandListener.java +++ b/src/main/java/de/t14d3/zones/listeners/CommandListener.java @@ -4,10 +4,8 @@ import de.t14d3.zones.Region; import de.t14d3.zones.RegionManager; import de.t14d3.zones.Zones; -import de.t14d3.zones.utils.Actions; import de.t14d3.zones.utils.Direction; import de.t14d3.zones.utils.Messages; -import io.papermc.paper.command.brigadier.BasicCommand; import io.papermc.paper.command.brigadier.CommandSourceStack; import it.unimi.dsi.fastutil.Pair; import net.kyori.adventure.text.Component; @@ -21,7 +19,6 @@ import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.bukkit.util.BoundingBox; -import org.jetbrains.annotations.NotNull; import java.util.*; import java.util.concurrent.CompletableFuture; @@ -29,8 +26,7 @@ import static de.t14d3.zones.utils.BeaconUtils.resetBeacon; import static net.kyori.adventure.text.minimessage.tag.resolver.Placeholder.parsed; -@SuppressWarnings("UnstableApiUsage") -public class CommandListener implements BasicCommand { +public class CommandListener { private final Zones plugin; private final RegionManager regionManager; @@ -45,12 +41,9 @@ public CommandListener(Zones plugin, RegionManager regionManager) { this.pm = plugin.getPermissionManager(); } - @Override - public void execute(CommandSourceStack stack, String[] args) { - if (args.length < 1) { - stack.getSender().sendMessage(miniMessage.deserialize(messages.get("commands.invalid"))); - return; - } + public void execute(CommandSourceStack stack, String arg) { + String[] args = arg.replaceFirst("zone ", "").split(" "); + stack.getSender().sendMessage(String.join(", ", args)); CommandSender sender = stack.getSender(); String command = args[0].toLowerCase(); @@ -106,14 +99,14 @@ public void execute(CommandSourceStack stack, String[] args) { break; case "save": if (sender.hasPermission("zones.save")) { - handleSaveCommand(sender, args); + handleSaveCommand(sender); } else { sender.sendMessage(miniMessage.deserialize(messages.get("commands.no-permission"))); } break; case "load": if (sender.hasPermission("zones.load")) { - handleLoadCommand(sender, args); + handleLoadCommand(sender); } else { sender.sendMessage(miniMessage.deserialize(messages.get("commands.no-permission"))); } @@ -145,106 +138,11 @@ public void execute(CommandSourceStack stack, String[] args) { } } - @Override - public @NotNull Collection suggest(@NotNull CommandSourceStack stack, String[] args) { - if (args.length <= 1) { - List suggestions = new ArrayList<>(); - for (String command : List.of("info", "delete", "create", "subcreate", "cancel", "list", "set", "load", "save", "expand", "select")) { - if (stack.getSender().hasPermission("zones." + command) - && (args.length == 0 || command.startsWith(args[0].toLowerCase()))) { - suggestions.add(command); - } - } - return suggestions; - } - if (stack.getSender() instanceof Player player) { - if (args.length == 2 && (args[0].equalsIgnoreCase("info") - || args[0].equalsIgnoreCase("delete") - || args[0].equalsIgnoreCase("subcreate") - || args[0].equalsIgnoreCase("expand") - || args[0].equalsIgnoreCase("select") - || args[0].equalsIgnoreCase("set") - || args[0].equalsIgnoreCase("rename"))) { - List suggestions = new ArrayList<>(); - regionManager.regions().forEach((regionKey, region) -> { - if (region.isAdmin(player.getUniqueId()) && regionKey.startsWith(args[1])) { - suggestions.add(regionKey); - } - }); - return suggestions; - } - if (args[0].equalsIgnoreCase("set")) { - Region region = plugin.getRegionManager().regions().get(args[1]); - if (args.length == 3) { - List suggestions = new ArrayList<>(); - for (OfflinePlayer offlinePlayer : Bukkit.getOfflinePlayers()) { - if (offlinePlayer.getName() != null && offlinePlayer.getName().toLowerCase().startsWith(args[2].toLowerCase())) { - suggestions.add(offlinePlayer.getName()); - } - } - if (region != null && region.isAdmin(player.getUniqueId())) { - suggestions.addAll(region.getGroupNames()); - } - return suggestions; - } - if (args.length == 4) { - List suggestions = new ArrayList<>(); - for (Actions action : Actions.values()) { - if (action.name().toLowerCase().startsWith(args[3].toLowerCase())) { - String who; - if (args[2].startsWith(":")) { - who = args[2]; - } else { - who = Bukkit.getOfflinePlayer(args[2]).getUniqueId().toString(); - } - String temp = action.name(); - if (region.getMemberPermissions(who).get(action.name()) != null) { - temp += " " + region.getMemberPermissions(who).get(action.name()).replace(",", "").toLowerCase(); - } - suggestions.add(temp); - } - } - return suggestions; - } - if (args.length >= 5) { - List suggestions = new ArrayList<>(); - List types; - switch (args[3].toUpperCase()) { - case "PLACE", "BREAK" -> types = plugin.getTypes().blockTypes; - case "CONTAINER" -> types = plugin.getTypes().containerTypes; - case "REDSTONE" -> types = plugin.getTypes().redstoneTypes; - case "ENTITY", "DAMAGE" -> types = plugin.getTypes().entityTypes; - case "IGNITE" -> { - types = List.of("TRUE", "FALSE"); - } - default -> types = plugin.getTypes().allTypes; - - } - for (String value : types) { - if (value.toLowerCase().startsWith(args[4].toLowerCase())) { - suggestions.add(value); - } - } - return suggestions; - } - } - if (args[0].equalsIgnoreCase("expand")) { - if (args.length == 3) { - List suggestions = new ArrayList<>(); - for (int i = 1; i < 10; i++) { - suggestions.add(String.valueOf(i)); - } - return suggestions; - } - if (args.length == 4 && stack.getSender().hasPermission("zones.expand.overlap")) { - return List.of("overlap"); - } - } - } - return List.of(); + public void def(CommandSender sender, String[] args) { + sender.sendMessage(miniMessage.deserialize(messages.get("commands.invalid"))); } - private void handleDeleteCommand(CommandSender sender, String[] args) { + public void handleDeleteCommand(CommandSender sender, String[] args) { if (args.length < 2) { sender.sendMessage(miniMessage.deserialize(messages.get("commands.invalid-region"))); return; @@ -267,7 +165,7 @@ private void handleDeleteCommand(CommandSender sender, String[] args) { regionManager.triggerSave(); } - private void handleCreateCommand(CommandSender sender) { + public void handleCreateCommand(CommandSender sender) { if (sender instanceof Player player) { if (!plugin.selection.containsKey(player.getUniqueId())) { plugin.selection.put(player.getUniqueId(), Pair.of(null, null)); @@ -298,7 +196,7 @@ private void handleCreateCommand(CommandSender sender) { } } - private void handleSubCreateCommand(CommandSender sender, String[] args) { + public void handleSubCreateCommand(CommandSender sender, String[] args) { if (sender instanceof Player player) { if (!plugin.selection.containsKey(player.getUniqueId())) { plugin.selection.put(player.getUniqueId(), Pair.of(null, null)); @@ -354,7 +252,7 @@ private void handleSubCreateCommand(CommandSender sender, String[] args) { } } - private void handleCancelCommand(CommandSender sender) { + public void handleCancelCommand(CommandSender sender) { if (sender instanceof Player player) { if (plugin.selection.containsKey(player.getUniqueId())) { Pair selection = plugin.selection.get(player.getUniqueId()); @@ -371,7 +269,7 @@ private void handleCancelCommand(CommandSender sender) { } } - private void handleListCommand(CommandSender sender) { + public void handleListCommand(CommandSender sender) { Map regions = regionManager.regions(); if (regions.isEmpty()) { sender.sendMessage(miniMessage.deserialize(messages.get("region.none-found"))); @@ -402,7 +300,7 @@ private void handleListCommand(CommandSender sender) { } } - private void handleInfoCommand(CommandSender sender, String[] args) { + public void handleInfoCommand(CommandSender sender, String[] args) { String regionKey; if (args.length < 2) { if (sender instanceof Player player) { @@ -433,7 +331,7 @@ private void handleInfoCommand(CommandSender sender, String[] args) { } - private void handleSetCommand(CommandSender sender, String[] args) { + public void handleSetCommand(CommandSender sender, String[] args) { if (args.length < 5) { sender.sendMessage(miniMessage.deserialize(messages.get("commands.set.invalid-usage"))); @@ -445,13 +343,16 @@ private void handleSetCommand(CommandSender sender, String[] args) { if (sender instanceof Player) { player = (Player) sender; } - if (region == null || (player != null && !pm.hasPermission(player.getUniqueId(), "role", "owner", region))) { + if (region == null || (player != null && !pm.hasPermission(player.getUniqueId(), "role", "owner", region) && !player.hasPermission("zones.set.other"))) { sender.sendMessage(miniMessage.deserialize(messages.get("commands.invalid-region"))); return; } OfflinePlayer target = Bukkit.getOfflinePlayer(args[2]); String permission = args[3]; - String value = args[4]; + // Yes, I know this is terrible. + // No, I will not change it. + List arg = Arrays.stream(args).toList().subList(4, args.length); + String value = String.join(", ", arg); regionManager.addMemberPermission(target.getUniqueId(), permission, value, regionKey); regionManager.triggerSave(); sender.sendMessage(miniMessage.deserialize(messages.get("commands.set.success"), @@ -461,7 +362,7 @@ private void handleSetCommand(CommandSender sender, String[] args) { parsed("value", value))); } - private void handleExpandCommand(CommandSender sender, String[] args) { + public void handleExpandCommand(CommandSender sender, String[] args) { if (args.length < 2) { sender.sendMessage(miniMessage.deserialize(messages.get("commands.invalid-region"))); return; @@ -495,7 +396,7 @@ private void handleExpandCommand(CommandSender sender, String[] args) { } } - private void handleRenameCommand(CommandSender sender, String[] args) { + public void handleRenameCommand(CommandSender sender, String[] args) { if (args.length < 2) { sender.sendMessage(miniMessage.deserialize(messages.get("commands.invalid-region"))); return; @@ -521,19 +422,19 @@ private void handleRenameCommand(CommandSender sender, String[] args) { } - private void handleSaveCommand(CommandSender sender, String[] args) { + public void handleSaveCommand(CommandSender sender) { regionManager.saveRegions(); int count = regionManager.regions().size(); sender.sendMessage(miniMessage.deserialize(messages.get("commands.save"), parsed("count", String.valueOf(count)))); } - private void handleLoadCommand(CommandSender sender, String[] args) { + public void handleLoadCommand(CommandSender sender) { regionManager.loadRegions(); int count = regionManager.loadedRegions.size(); sender.sendMessage(miniMessage.deserialize(messages.get("commands.load"), parsed("count", String.valueOf(count)))); } - private void handleSelectCommand(CommandSender sender, String[] args) { + public void handleSelectCommand(CommandSender sender, String[] args) { if (sender instanceof Player player) { Region region; if (args.length == 1) { @@ -545,8 +446,13 @@ private void handleSelectCommand(CommandSender sender, String[] args) { return; } } else { + region = regionManager.regions().get(args[1]); } + if (region == null) { + player.sendMessage(miniMessage.deserialize(messages.get("commands.invalid-region"))); + return; + } if (!plugin.particles.containsKey(player.getUniqueId()) || args.length >= 2) { plugin.particles.put(player.getUniqueId(), BoundingBox.of(region.getMin(), region.getMax())); player.sendMessage(miniMessage.deserialize(messages.get("commands.select.selected"), parsed("region", region.getName()))); From d009903227997109d9eff4da5266cdf1c7753831 Mon Sep 17 00:00:00 2001 From: T14D3 <73843330+T14D3@users.noreply.github.com> Date: Wed, 15 Jan 2025 21:16:41 +0100 Subject: [PATCH 05/12] Improve readability (hopefully), re-add permissions --- .../java/de/t14d3/zones/PaperBootstrap.java | 146 +--------------- .../de/t14d3/zones/PermissionManager.java | 2 +- .../de/t14d3/zones/brigadier/Command.java | 156 ++++++++++++++++++ .../zones/brigadier/SubCommandArgument.java | 17 -- src/main/resources/paper-plugin.yml | 92 ++++++++++- 5 files changed, 254 insertions(+), 159 deletions(-) create mode 100644 src/main/java/de/t14d3/zones/brigadier/Command.java diff --git a/src/main/java/de/t14d3/zones/PaperBootstrap.java b/src/main/java/de/t14d3/zones/PaperBootstrap.java index 0f956d3..3e4d28c 100644 --- a/src/main/java/de/t14d3/zones/PaperBootstrap.java +++ b/src/main/java/de/t14d3/zones/PaperBootstrap.java @@ -1,31 +1,14 @@ package de.t14d3.zones; -import com.mojang.brigadier.Command; -import com.mojang.brigadier.arguments.StringArgumentType; -import com.mojang.brigadier.context.CommandContext; -import de.t14d3.zones.brigadier.FlagArgument; -import de.t14d3.zones.brigadier.RegionKeyArgument; -import de.t14d3.zones.brigadier.SubCommandArgument; -import de.t14d3.zones.utils.Actions; -import io.papermc.paper.command.brigadier.CommandSourceStack; +import de.t14d3.zones.brigadier.Command; import io.papermc.paper.command.brigadier.Commands; -import io.papermc.paper.command.brigadier.MessageComponentSerializer; import io.papermc.paper.plugin.bootstrap.BootstrapContext; import io.papermc.paper.plugin.bootstrap.PluginBootstrap; import io.papermc.paper.plugin.bootstrap.PluginProviderContext; import io.papermc.paper.plugin.lifecycle.event.LifecycleEventManager; import io.papermc.paper.plugin.lifecycle.event.types.LifecycleEvents; -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.format.NamedTextColor; -import org.bukkit.Bukkit; -import org.bukkit.OfflinePlayer; -import org.bukkit.entity.Player; import org.bukkit.plugin.java.JavaPlugin; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.UUID; +import org.jetbrains.annotations.NotNull; @SuppressWarnings("UnstableApiUsage") public class PaperBootstrap implements PluginBootstrap { @@ -34,135 +17,18 @@ public class PaperBootstrap implements PluginBootstrap { @Override public void bootstrap(BootstrapContext context) { - LifecycleEventManager eventManager = context.getLifecycleManager(); + LifecycleEventManager<@NotNull BootstrapContext> eventManager = context.getLifecycleManager(); eventManager.registerEventHandler(LifecycleEvents.COMMANDS, event -> { final Commands commands = event.registrar(); - commands.register( - Commands.literal("zone") - .then(Commands.argument("subcommand", new SubCommandArgument()) - .executes(ctx -> { - Zones.getInstance().getCommandListener().execute(ctx.getSource(), ctx.getInput()); - return 1; - }) - .then(Commands.argument("key", new RegionKeyArgument()) - .suggests((ctx, builder) -> { - switch (arg(ctx, 1).toUpperCase()) { - case "LIST", "CANCEL", "CREATE", "SAVE", "LOAD" -> { - return builder.buildFuture(); - } - default -> { - } - } - boolean hasPerm = ctx.getSource().getSender().hasPermission("zones." + arg(ctx, 1).toLowerCase() + ".other"); - for (Map.Entry region : Zones.getInstance().getRegionManager().regions().entrySet()) { - if (hasPerm || ctx.getSource().getSender() instanceof Player player && region.getValue().isAdmin(player.getUniqueId())) { - builder.suggest( - region.getKey(), - MessageComponentSerializer.message().serialize( - RegionKeyArgument.regionInfo(Map.entry(region.getKey(), region.getValue())) - ) - ); - } - } - return builder.buildFuture(); - }) - .executes(ctx -> { - Zones.getInstance().getCommandListener().execute(ctx.getSource(), ctx.getInput()); - ctx.getSource().getSender().sendMessage(String.join(", ", ctx.getInput().split(" "))); - return Command.SINGLE_SUCCESS; - }) - .then(Commands.argument("player", StringArgumentType.word()) - .suggests((ctx, builder) -> { - if (arg(ctx, 1).equalsIgnoreCase("INFO") || arg(ctx, 1).equalsIgnoreCase("DELETE") || arg(ctx, 1).equalsIgnoreCase("SELECT")) { - return builder.buildFuture(); - } - for (OfflinePlayer offlinePlayer : Bukkit.getOfflinePlayers()) { - if (ctx.getInput().split(" ").length <= 3 || (offlinePlayer.getName() != null ? offlinePlayer.getName() : offlinePlayer.getUniqueId().toString()).toLowerCase().startsWith(arg(ctx, 3).toLowerCase())) { - builder.suggest(offlinePlayer.getName()); - } - } - for (Map.Entry region : Zones.getInstance().getRegionManager().regions().entrySet()) { - if (!ctx.getInput().split(" ")[2].equalsIgnoreCase(region.getKey())) { - continue; - } - if (ctx.getSource().getSender().hasPermission("zones.info.other") - || (ctx.getSource().getSender() instanceof Player player && region.getValue().isAdmin(player.getUniqueId()))) { - region.getValue().getGroupNames().forEach(group -> { - List groupMembers = new ArrayList<>(); - region.getValue().getGroupMembers(group).forEach(val -> { - groupMembers.add(Bukkit.getOfflinePlayer(UUID.fromString(val)).getName()); - }); - if (ctx.getInput().split(" ").length <= 3 - || group.toLowerCase().startsWith(arg(ctx, 3).toLowerCase()) - || group.toLowerCase().replace("+", "").startsWith(arg(ctx, 3).toLowerCase())) { - builder.suggest(group, MessageComponentSerializer.message().serialize(Component.text(groupMembers.toString()))); - } - }); - } - } - return builder.buildFuture(); - }) - .then(Commands.argument("flag", new FlagArgument()) - .suggests((ctx, builder) -> { - for (Actions action : Actions.values()) { - builder.suggest(action.name().toLowerCase(), MessageComponentSerializer.message().serialize(Component.text(action.getKey()))); - } - return builder.buildFuture(); - }) - .then(Commands.argument("value", StringArgumentType.greedyString()) - .suggests((ctx, builder) -> { - Zones plugin = Zones.getInstance(); - List types; - switch (arg(ctx, 4).toUpperCase()) { - case "PLACE", "BREAK" -> - types = plugin.getTypes().blockTypes; - case "CONTAINER" -> - types = plugin.getTypes().containerTypes; - case "REDSTONE" -> - types = plugin.getTypes().redstoneTypes; - case "ENTITY", "DAMAGE" -> - types = plugin.getTypes().entityTypes; - case "IGNITE" -> - types = List.of("TRUE", "FALSE"); - default -> - types = plugin.getTypes().allTypes; - } - String[] args = ctx.getInput().split(" "); - for (String value : types) { - if (args.length == 5 || value.toLowerCase().startsWith(args[args.length - 1])) { - builder.suggest(value.toLowerCase(), MessageComponentSerializer.message().serialize( - Component.text(value).color(value.startsWith("!") ? NamedTextColor.RED : NamedTextColor.GREEN))); - } - } - return builder.buildFuture(); - }) - .executes(ctx -> { - Zones.getInstance().getCommandListener().execute(ctx.getSource(), ctx.getInput()); - return Command.SINGLE_SUCCESS; - }) - ) - ) - ) - ) - ).build() - ); + commands.register(Command.node()); }); } @Override - public JavaPlugin createPlugin(PluginProviderContext context) { + public @NotNull JavaPlugin createPlugin(@NotNull PluginProviderContext context) { zones = new Zones(); return zones; } - /** - * Helper function to get the argument of a command at the given index - * - * @param ctx Command context - * @param index Index of the argument - * @return Argument at the given index - */ - public static String arg(CommandContext ctx, int index) { - return ctx.getInput().split(" ")[index]; - } + } \ No newline at end of file diff --git a/src/main/java/de/t14d3/zones/PermissionManager.java b/src/main/java/de/t14d3/zones/PermissionManager.java index c86f5c1..b3cf1d8 100644 --- a/src/main/java/de/t14d3/zones/PermissionManager.java +++ b/src/main/java/de/t14d3/zones/PermissionManager.java @@ -214,7 +214,7 @@ private boolean calculatePermission(String who, String permission, String type, result = true; } // Check for wildcard deny - else if ("! *".equals(permittedValue) || "false".equalsIgnoreCase(permittedValue)) { + else if ("!*".equals(permittedValue) || "false".equalsIgnoreCase(permittedValue)) { result = false; } // Check for specific type allow diff --git a/src/main/java/de/t14d3/zones/brigadier/Command.java b/src/main/java/de/t14d3/zones/brigadier/Command.java new file mode 100644 index 0000000..9fb2191 --- /dev/null +++ b/src/main/java/de/t14d3/zones/brigadier/Command.java @@ -0,0 +1,156 @@ +package de.t14d3.zones.brigadier; + +import com.mojang.brigadier.arguments.StringArgumentType; +import com.mojang.brigadier.context.CommandContext; +import com.mojang.brigadier.tree.LiteralCommandNode; +import de.t14d3.zones.Region; +import de.t14d3.zones.Zones; +import de.t14d3.zones.utils.Actions; +import io.papermc.paper.command.brigadier.CommandSourceStack; +import io.papermc.paper.command.brigadier.Commands; +import io.papermc.paper.command.brigadier.MessageComponentSerializer; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +public class Command { + + @SuppressWarnings("UnstableApiUsage") + public static LiteralCommandNode node() { + return Commands.literal("zone") + .then(Commands.argument("subcommand", new SubCommandArgument()) + .suggests((ctx, builder) -> { + for (SubCommands subCommand : SubCommands.values()) { + if (!ctx.getSource().getSender().hasPermission("zones." + subCommand.name().toLowerCase())) { + continue; + } + String[] args = ctx.getInput().split(" "); + if (args.length == 1 || subCommand.name().toLowerCase().startsWith(args[1].toLowerCase())) { + builder.suggest(subCommand.name().toLowerCase(), MessageComponentSerializer.message().serialize(subCommand.getInfo())); + } + } + return builder.buildFuture(); + }) + .executes(ctx -> { + Zones.getInstance().getCommandListener().execute(ctx.getSource(), ctx.getInput()); + return 1; + }) + .then(Commands.argument("key", new RegionKeyArgument()) + .suggests((ctx, builder) -> { + switch (arg(ctx, 1).toUpperCase()) { + case "LIST", "CANCEL", "CREATE", "SAVE", "LOAD" -> { + return builder.buildFuture(); + } + default -> { + } + } + boolean hasPerm = ctx.getSource().getSender().hasPermission("zones." + arg(ctx, 1).toLowerCase() + ".other"); + for (Map.Entry region : Zones.getInstance().getRegionManager().regions().entrySet()) { + if (hasPerm || ctx.getSource().getSender() instanceof Player player && region.getValue().isAdmin(player.getUniqueId())) { + builder.suggest( + region.getKey(), + MessageComponentSerializer.message().serialize( + RegionKeyArgument.regionInfo(Map.entry(region.getKey(), region.getValue())) + ) + ); + } + } + return builder.buildFuture(); + }) + .executes(ctx -> { + Zones.getInstance().getCommandListener().execute(ctx.getSource(), ctx.getInput()); + ctx.getSource().getSender().sendMessage(String.join(", ", ctx.getInput().split(" "))); + return com.mojang.brigadier.Command.SINGLE_SUCCESS; + }) + .then(Commands.argument("player", StringArgumentType.word()) + .suggests((ctx, builder) -> { + if (arg(ctx, 1).equalsIgnoreCase("INFO") || arg(ctx, 1).equalsIgnoreCase("DELETE") || arg(ctx, 1).equalsIgnoreCase("SELECT")) { + return builder.buildFuture(); + } + for (OfflinePlayer offlinePlayer : Bukkit.getOfflinePlayers()) { + if (ctx.getInput().split(" ").length <= 3 || (offlinePlayer.getName() != null ? offlinePlayer.getName() : offlinePlayer.getUniqueId().toString()).toLowerCase().startsWith(arg(ctx, 3).toLowerCase())) { + builder.suggest(offlinePlayer.getName()); + } + } + for (Map.Entry region : Zones.getInstance().getRegionManager().regions().entrySet()) { + if (!ctx.getInput().split(" ")[2].equalsIgnoreCase(region.getKey())) { + continue; + } + if (ctx.getSource().getSender().hasPermission("zones.info.other") + || (ctx.getSource().getSender() instanceof Player player && region.getValue().isAdmin(player.getUniqueId()))) { + region.getValue().getGroupNames().forEach(group -> { + List groupMembers = new ArrayList<>(); + region.getValue().getGroupMembers(group).forEach(val -> { + groupMembers.add(Bukkit.getOfflinePlayer(UUID.fromString(val)).getName()); + }); + if (ctx.getInput().split(" ").length <= 3 + || group.toLowerCase().startsWith(arg(ctx, 3).toLowerCase()) + || group.toLowerCase().replace("+", "").startsWith(arg(ctx, 3).toLowerCase())) { + builder.suggest(group, MessageComponentSerializer.message().serialize(Component.text(groupMembers.toString()))); + } + }); + } + } + return builder.buildFuture(); + }) + .then(Commands.argument("flag", new FlagArgument()) + .suggests((ctx, builder) -> { + for (Actions action : Actions.values()) { + builder.suggest(action.name().toLowerCase(), MessageComponentSerializer.message().serialize(Component.text(action.getKey()))); + } + return builder.buildFuture(); + }) + .then(Commands.argument("value", StringArgumentType.greedyString()) + .suggests((ctx, builder) -> { + Zones plugin = Zones.getInstance(); + List types; + switch (arg(ctx, 4).toUpperCase()) { + case "PLACE", "BREAK" -> + types = plugin.getTypes().blockTypes; + case "CONTAINER" -> + types = plugin.getTypes().containerTypes; + case "REDSTONE" -> + types = plugin.getTypes().redstoneTypes; + case "ENTITY", "DAMAGE" -> + types = plugin.getTypes().entityTypes; + case "IGNITE" -> types = List.of("TRUE", "FALSE"); + default -> types = plugin.getTypes().allTypes; + } + String[] args = ctx.getInput().split(" "); + for (String value : types) { + if (args.length == 5 || value.toLowerCase().startsWith(args[args.length - 1])) { + builder.suggest(value.toLowerCase(), MessageComponentSerializer.message().serialize( + Component.text(value).color(value.startsWith("!") ? NamedTextColor.RED : NamedTextColor.GREEN))); + } + } + return builder.buildFuture(); + }) + .executes(ctx -> { + Zones.getInstance().getCommandListener().execute(ctx.getSource(), ctx.getInput()); + return com.mojang.brigadier.Command.SINGLE_SUCCESS; + }) + ) + ) + ) + ) + ).build(); + } + + /** + * Helper function to get the argument of a command at the given index + * + * @param ctx Command context + * @param index Index of the argument + * @return Argument at the given index + */ + public static String arg(CommandContext ctx, int index) { + return ctx.getInput().split(" ")[index]; + } +} diff --git a/src/main/java/de/t14d3/zones/brigadier/SubCommandArgument.java b/src/main/java/de/t14d3/zones/brigadier/SubCommandArgument.java index fd33a96..c8e8eb9 100644 --- a/src/main/java/de/t14d3/zones/brigadier/SubCommandArgument.java +++ b/src/main/java/de/t14d3/zones/brigadier/SubCommandArgument.java @@ -2,16 +2,10 @@ import com.mojang.brigadier.arguments.ArgumentType; import com.mojang.brigadier.arguments.StringArgumentType; -import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.exceptions.CommandSyntaxException; -import com.mojang.brigadier.suggestion.Suggestions; -import com.mojang.brigadier.suggestion.SuggestionsBuilder; -import io.papermc.paper.command.brigadier.MessageComponentSerializer; import io.papermc.paper.command.brigadier.argument.CustomArgumentType; import org.jetbrains.annotations.NotNull; -import java.util.concurrent.CompletableFuture; - @SuppressWarnings("UnstableApiUsage") public class SubCommandArgument implements CustomArgumentType.Converted { @@ -24,15 +18,4 @@ public class SubCommandArgument implements CustomArgumentType.Converted getNativeType() { return StringArgumentType.string(); } - - @Override - public @NotNull CompletableFuture listSuggestions(@NotNull CommandContext context, @NotNull SuggestionsBuilder builder) { - for (SubCommands subCommand : SubCommands.values()) { - String[] args = context.getInput().split(" "); - if (args.length == 1 || subCommand.name().toLowerCase().startsWith(args[1].toLowerCase())) { - builder.suggest(subCommand.name().toLowerCase(), MessageComponentSerializer.message().serialize(subCommand.getInfo())); - } - } - return builder.buildFuture(); - } } diff --git a/src/main/resources/paper-plugin.yml b/src/main/resources/paper-plugin.yml index 399fbda..df3f79a 100644 --- a/src/main/resources/paper-plugin.yml +++ b/src/main/resources/paper-plugin.yml @@ -2,4 +2,94 @@ name: Zones version: '${version}' main: de.t14d3.zones.Zones api-version: '1.21' -bootstrapper: de.t14d3.zones.PaperBootstrap \ No newline at end of file +bootstrapper: de.t14d3.zones.PaperBootstrap +permissions: + zones.info: + description: Allow players to view region information + default: true + children: + zones.info.other: true + zones.delete: + description: Allow players to delete regions + default: true + children: + zones.delete.other: true + zones.create: + description: Allow players to create regions + default: true + children: + zones.create.overlap: true + zones.subcreate: + description: Allow players to create sub-regions + default: true + children: + zones.subcreate.other: true + zones.cancel: + description: Allow players to cancel the current operation + default: true + zones.list: + description: Allow players to list all regions + default: true + zones.set: + description: Allow players to set permissions for regions + default: true + children: + zones.set.other: true + zones.expand: + description: Allow players to expand regions + default: true + children: + zones.expand.other: true + zones.expand.overlap: true + zones.select: + description: Allow players to select regions + default: true + children: + zones.select.other: true + zones.rename: + description: Allow players to rename regions + default: true + children: + zones.rename.other: true + + zones.save: + description: Allow players to save all regions to file + default: op + zones.load: + description: Allow players to load all regions from file + default: op + + zones.info.other: + description: Allow players to view other player's regions + default: op + zones.select.other: + description: Allow players to select other player's regions + default: op + zones.delete.other: + description: Allow players to delete other player's regions + default: op + zones.subcreate.other: + description: Allow players to create sub-regions for other player's regions + default: op + zones.expand.other: + description: Allow players to expand regions over other regions + default: op + zones.expand.overlap: + description: Allow players to expand regions over other regions + default: op + zones.set.other: + description: Allow players to set permissions for other player's regions + default: op + zones.create.overlap: + description: Allow players to create regions that overlap existing regions + default: op + zones.rename.other: + description: Allow players to rename other player's regions + default: op + + zones.bypass.unclaimed: + description: Allow players to interact with unclaimed regions + default: op + zones.bypass.claimed: + description: Allow players to interact with other players' regions + default: op \ No newline at end of file From 8ef64c0c9673bffb685824c34540f624ce119a78 Mon Sep 17 00:00:00 2001 From: T14D3 <73843330+T14D3@users.noreply.github.com> Date: Wed, 15 Jan 2025 21:21:23 +0100 Subject: [PATCH 06/12] Fix: Added missing subcommands --- src/main/java/de/t14d3/zones/brigadier/SubCommands.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main/java/de/t14d3/zones/brigadier/SubCommands.java b/src/main/java/de/t14d3/zones/brigadier/SubCommands.java index ba605d9..a50db39 100644 --- a/src/main/java/de/t14d3/zones/brigadier/SubCommands.java +++ b/src/main/java/de/t14d3/zones/brigadier/SubCommands.java @@ -4,7 +4,7 @@ import net.kyori.adventure.text.format.NamedTextColor; public enum SubCommands { - INFO(Component.text("Shows information about a region\nTEXT").color(NamedTextColor.GOLD)), + INFO(Component.text("Shows information about a region").color(NamedTextColor.GOLD)), LIST(Component.text("Lists all regions").color(NamedTextColor.GOLD)), DELETE(Component.text("Deletes a region").color(NamedTextColor.DARK_RED)), CREATE(Component.text("Creates a new region").color(NamedTextColor.GREEN)), @@ -12,8 +12,10 @@ public enum SubCommands { SELECT(Component.text("Visually selects a region").color(NamedTextColor.LIGHT_PURPLE)), SET(Component.text("Sets permissions for a region").color(NamedTextColor.BLUE)), CANCEL(Component.text("Cancels the current operation").color(NamedTextColor.RED)), - SAVE(Component.text("Saves all regions to file")), - LOAD(Component.text("Loads all regions from file")); + RENAME(Component.text("Renames a region").color(NamedTextColor.YELLOW)), + SUBCREATE(Component.text("Creates a sub-region").color(NamedTextColor.DARK_PURPLE)), + SAVE(Component.text("Saves all regions to file").color(NamedTextColor.DARK_GREEN)), + LOAD(Component.text("Loads all regions from file").color(NamedTextColor.DARK_AQUA)); private final Component info; From 570286174668467acb281b33043094ea562f205d Mon Sep 17 00:00:00 2001 From: T14D3 <73843330+T14D3@users.noreply.github.com> Date: Wed, 15 Jan 2025 21:59:23 +0100 Subject: [PATCH 07/12] Improve rename --- .../de/t14d3/zones/brigadier/Command.java | 51 +++++++++++-------- .../zones/listeners/CommandListener.java | 5 +- 2 files changed, 32 insertions(+), 24 deletions(-) diff --git a/src/main/java/de/t14d3/zones/brigadier/Command.java b/src/main/java/de/t14d3/zones/brigadier/Command.java index 9fb2191..7745423 100644 --- a/src/main/java/de/t14d3/zones/brigadier/Command.java +++ b/src/main/java/de/t14d3/zones/brigadier/Command.java @@ -69,37 +69,44 @@ public static LiteralCommandNode node() { ctx.getSource().getSender().sendMessage(String.join(", ", ctx.getInput().split(" "))); return com.mojang.brigadier.Command.SINGLE_SUCCESS; }) - .then(Commands.argument("player", StringArgumentType.word()) + .then(Commands.argument("name", StringArgumentType.string()) .suggests((ctx, builder) -> { - if (arg(ctx, 1).equalsIgnoreCase("INFO") || arg(ctx, 1).equalsIgnoreCase("DELETE") || arg(ctx, 1).equalsIgnoreCase("SELECT")) { + if (arg(ctx, 1).equalsIgnoreCase("RENAME")) { + builder.suggest("", MessageComponentSerializer.message().serialize(Component.text("Type the new name for the region"))); return builder.buildFuture(); } - for (OfflinePlayer offlinePlayer : Bukkit.getOfflinePlayers()) { - if (ctx.getInput().split(" ").length <= 3 || (offlinePlayer.getName() != null ? offlinePlayer.getName() : offlinePlayer.getUniqueId().toString()).toLowerCase().startsWith(arg(ctx, 3).toLowerCase())) { - builder.suggest(offlinePlayer.getName()); - } - } - for (Map.Entry region : Zones.getInstance().getRegionManager().regions().entrySet()) { - if (!ctx.getInput().split(" ")[2].equalsIgnoreCase(region.getKey())) { - continue; + if (arg(ctx, 1).equalsIgnoreCase("SET")) { + for (OfflinePlayer offlinePlayer : Bukkit.getOfflinePlayers()) { + if (ctx.getInput().split(" ").length <= 3 || (offlinePlayer.getName() != null ? offlinePlayer.getName() : offlinePlayer.getUniqueId().toString()).toLowerCase().startsWith(arg(ctx, 3).toLowerCase())) { + builder.suggest(offlinePlayer.getName()); + } } - if (ctx.getSource().getSender().hasPermission("zones.info.other") - || (ctx.getSource().getSender() instanceof Player player && region.getValue().isAdmin(player.getUniqueId()))) { - region.getValue().getGroupNames().forEach(group -> { - List groupMembers = new ArrayList<>(); - region.getValue().getGroupMembers(group).forEach(val -> { - groupMembers.add(Bukkit.getOfflinePlayer(UUID.fromString(val)).getName()); + for (Map.Entry region : Zones.getInstance().getRegionManager().regions().entrySet()) { + if (!ctx.getInput().split(" ")[2].equalsIgnoreCase(region.getKey())) { + continue; + } + if (ctx.getSource().getSender().hasPermission("zones.info.other") + || (ctx.getSource().getSender() instanceof Player player && region.getValue().isAdmin(player.getUniqueId()))) { + region.getValue().getGroupNames().forEach(group -> { + List groupMembers = new ArrayList<>(); + region.getValue().getGroupMembers(group).forEach(val -> { + groupMembers.add(Bukkit.getOfflinePlayer(UUID.fromString(val)).getName()); + }); + if (ctx.getInput().split(" ").length <= 3 + || group.toLowerCase().startsWith(arg(ctx, 3).toLowerCase()) + || group.toLowerCase().replace("+", "").startsWith(arg(ctx, 3).toLowerCase())) { + builder.suggest(group, MessageComponentSerializer.message().serialize(Component.text(groupMembers.toString()))); + } }); - if (ctx.getInput().split(" ").length <= 3 - || group.toLowerCase().startsWith(arg(ctx, 3).toLowerCase()) - || group.toLowerCase().replace("+", "").startsWith(arg(ctx, 3).toLowerCase())) { - builder.suggest(group, MessageComponentSerializer.message().serialize(Component.text(groupMembers.toString()))); - } - }); + } } } return builder.buildFuture(); }) + .executes(ctx -> { + Zones.getInstance().getCommandListener().execute(ctx.getSource(), ctx.getInput()); + return com.mojang.brigadier.Command.SINGLE_SUCCESS; + }) .then(Commands.argument("flag", new FlagArgument()) .suggests((ctx, builder) -> { for (Actions action : Actions.values()) { diff --git a/src/main/java/de/t14d3/zones/listeners/CommandListener.java b/src/main/java/de/t14d3/zones/listeners/CommandListener.java index b7aec2e..cb04f78 100644 --- a/src/main/java/de/t14d3/zones/listeners/CommandListener.java +++ b/src/main/java/de/t14d3/zones/listeners/CommandListener.java @@ -415,10 +415,11 @@ public void handleRenameCommand(CommandSender sender, String[] args) { sender.sendMessage(miniMessage.deserialize(messages.get("commands.rename.provide-name"))); return; } - region.setName(args[2], regionManager); + String name = String.join(" ", args).substring(16).replace("\"", "").replace("'", ""); + region.setName(name, regionManager); sender.sendMessage(miniMessage.deserialize(messages.get("commands.rename.success"), parsed("region", regionKey), - parsed("name", args[2]))); + parsed("name", name))); } From 8778949083c8e6e244d95a37653f6fa2595eee5c Mon Sep 17 00:00:00 2001 From: T14D3 <73843330+T14D3@users.noreply.github.com> Date: Thu, 16 Jan 2025 09:33:41 +0100 Subject: [PATCH 08/12] [ci skip] Cleanup/Annotation fixing --- src/main/java/de/t14d3/zones/Zones.java | 8 ------- .../de/t14d3/zones/brigadier/Command.java | 2 +- .../t14d3/zones/brigadier/FlagArgument.java | 5 ++-- .../zones/integrations/PlaceholderAPI.java | 24 ++++++++++++------- .../zones/listeners/CommandListener.java | 7 ++---- 5 files changed, 21 insertions(+), 25 deletions(-) diff --git a/src/main/java/de/t14d3/zones/Zones.java b/src/main/java/de/t14d3/zones/Zones.java index 35d5348..657398e 100644 --- a/src/main/java/de/t14d3/zones/Zones.java +++ b/src/main/java/de/t14d3/zones/Zones.java @@ -36,7 +36,6 @@ public final class Zones extends JavaPlugin { private CommandListener commandListener; @Override - @SuppressWarnings("UnstableApiUsage") public void onEnable() { instance = this; // Initialize PermissionManager first without RegionManager @@ -82,13 +81,6 @@ public void onEnable() { types = new Types(); types.populateTypes(); - // Register command executor and tab completer -// LifecycleEventManager manager = this.getLifecycleManager(); -// manager.registerEventHandler(LifecycleEvents.COMMANDS, event -> { -// final Commands commands = event.registrar(); -// commands.register("zone", commandListener); -// }); - this.commandListener = new CommandListener(this, regionManager); // Register saving task diff --git a/src/main/java/de/t14d3/zones/brigadier/Command.java b/src/main/java/de/t14d3/zones/brigadier/Command.java index 7745423..5360d35 100644 --- a/src/main/java/de/t14d3/zones/brigadier/Command.java +++ b/src/main/java/de/t14d3/zones/brigadier/Command.java @@ -20,9 +20,9 @@ import java.util.Map; import java.util.UUID; +@SuppressWarnings("UnstableApiUsage") public class Command { - @SuppressWarnings("UnstableApiUsage") public static LiteralCommandNode node() { return Commands.literal("zone") .then(Commands.argument("subcommand", new SubCommandArgument()) diff --git a/src/main/java/de/t14d3/zones/brigadier/FlagArgument.java b/src/main/java/de/t14d3/zones/brigadier/FlagArgument.java index 900ffcd..56ce3d9 100644 --- a/src/main/java/de/t14d3/zones/brigadier/FlagArgument.java +++ b/src/main/java/de/t14d3/zones/brigadier/FlagArgument.java @@ -5,17 +5,18 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException; import de.t14d3.zones.utils.Actions; import io.papermc.paper.command.brigadier.argument.CustomArgumentType; +import org.jetbrains.annotations.NotNull; @SuppressWarnings("UnstableApiUsage") public class FlagArgument implements CustomArgumentType.Converted { @Override - public Actions convert(String nativeType) throws CommandSyntaxException { + public @NotNull Actions convert(String nativeType) throws CommandSyntaxException { return Actions.valueOf(nativeType.toUpperCase()); } @Override - public ArgumentType getNativeType() { + public @NotNull ArgumentType getNativeType() { return StringArgumentType.word(); } } diff --git a/src/main/java/de/t14d3/zones/integrations/PlaceholderAPI.java b/src/main/java/de/t14d3/zones/integrations/PlaceholderAPI.java index 56fd31e..8ee77a9 100644 --- a/src/main/java/de/t14d3/zones/integrations/PlaceholderAPI.java +++ b/src/main/java/de/t14d3/zones/integrations/PlaceholderAPI.java @@ -9,6 +9,7 @@ import org.jetbrains.annotations.NotNull; import java.util.List; +import java.util.UUID; public class PlaceholderAPI extends PlaceholderExpansion { private final Zones plugin; @@ -79,16 +80,21 @@ public String onPlaceholderRequest(Player player, @NotNull String params) { } if (params.equalsIgnoreCase("get_members")) { final String[] members = {""}; - regions.get(0).getMembers().keySet().forEach(uuid -> { - String member = Bukkit.getOfflinePlayer(uuid).getName() != null ? Bukkit.getOfflinePlayer(uuid).getName() : uuid.toString(); + regions.get(0).getMembers().keySet().forEach(val -> { + String member; + try { + UUID uuid = UUID.fromString(val); + member = Bukkit.getOfflinePlayer(uuid).getName() != null ? Bukkit.getOfflinePlayer(uuid).getName() : String.valueOf(uuid); + } catch (IllegalArgumentException ignored) { + member = val; + } - if (members[0].isEmpty()) { - members[0] = member; - } else { - members[0] = members[0] + ", " + member; - } - } - ); + if (members[0].isEmpty()) { + members[0] = member; + } else { + members[0] = members[0] + ", " + member; + } + }); return members[0]; } if (params.equalsIgnoreCase("get_owner")) { diff --git a/src/main/java/de/t14d3/zones/listeners/CommandListener.java b/src/main/java/de/t14d3/zones/listeners/CommandListener.java index cb04f78..3157cde 100644 --- a/src/main/java/de/t14d3/zones/listeners/CommandListener.java +++ b/src/main/java/de/t14d3/zones/listeners/CommandListener.java @@ -41,6 +41,7 @@ public CommandListener(Zones plugin, RegionManager regionManager) { this.pm = plugin.getPermissionManager(); } + @SuppressWarnings("UnstableApiUsage") public void execute(CommandSourceStack stack, String arg) { String[] args = arg.replaceFirst("zone ", "").split(" "); stack.getSender().sendMessage(String.join(", ", args)); @@ -133,15 +134,11 @@ public void execute(CommandSourceStack stack, String arg) { } break; default: - stack.getSender().sendMessage(miniMessage.deserialize(messages.get("commands.invalid"))); + sender.sendMessage(miniMessage.deserialize(messages.get("commands.invalid"))); break; } } - public void def(CommandSender sender, String[] args) { - sender.sendMessage(miniMessage.deserialize(messages.get("commands.invalid"))); - } - public void handleDeleteCommand(CommandSender sender, String[] args) { if (args.length < 2) { sender.sendMessage(miniMessage.deserialize(messages.get("commands.invalid-region"))); From a0257daabd873cb0aacf67c23eb0a9fc863b91f8 Mon Sep 17 00:00:00 2001 From: T14D3 <73843330+T14D3@users.noreply.github.com> Date: Thu, 16 Jan 2025 10:38:39 +0100 Subject: [PATCH 09/12] Initial work on custom flags --- .../java/de/t14d3/zones/PaperBootstrap.java | 18 ++++++- src/main/java/de/t14d3/zones/Zones.java | 5 ++ .../de/t14d3/zones/brigadier/Command.java | 23 ++++++-- .../t14d3/zones/brigadier/FlagArgument.java | 13 +++-- src/main/java/de/t14d3/zones/utils/Flags.java | 53 +++++++++++++++++++ .../java/de/t14d3/zones/utils/Messages.java | 4 ++ src/main/java/de/t14d3/zones/utils/Utils.java | 17 ++++++ src/main/resources/messages.properties | 9 ++++ 8 files changed, 131 insertions(+), 11 deletions(-) create mode 100644 src/main/java/de/t14d3/zones/utils/Flags.java diff --git a/src/main/java/de/t14d3/zones/PaperBootstrap.java b/src/main/java/de/t14d3/zones/PaperBootstrap.java index 3e4d28c..2468e28 100644 --- a/src/main/java/de/t14d3/zones/PaperBootstrap.java +++ b/src/main/java/de/t14d3/zones/PaperBootstrap.java @@ -1,6 +1,8 @@ package de.t14d3.zones; import de.t14d3.zones.brigadier.Command; +import de.t14d3.zones.utils.Flags; +import de.t14d3.zones.utils.Utils; import io.papermc.paper.command.brigadier.Commands; import io.papermc.paper.plugin.bootstrap.BootstrapContext; import io.papermc.paper.plugin.bootstrap.PluginBootstrap; @@ -10,25 +12,37 @@ import org.bukkit.plugin.java.JavaPlugin; import org.jetbrains.annotations.NotNull; +import java.util.Map; + @SuppressWarnings("UnstableApiUsage") public class PaperBootstrap implements PluginBootstrap { private Zones zones; + private Flags flags; @Override public void bootstrap(BootstrapContext context) { + flags = new Flags(); + for (Map.Entry entry : Utils.defaultFlags().entrySet()) { + flags.registerFlag(entry.getKey(), entry.getValue()); + } + Command cmd = new Command(this); LifecycleEventManager<@NotNull BootstrapContext> eventManager = context.getLifecycleManager(); eventManager.registerEventHandler(LifecycleEvents.COMMANDS, event -> { final Commands commands = event.registrar(); - commands.register(Command.node()); + commands.register(cmd.node()); }); } @Override public @NotNull JavaPlugin createPlugin(@NotNull PluginProviderContext context) { - zones = new Zones(); + zones = new Zones(this); return zones; } + public Flags getFlags() { + return flags; + } + } \ No newline at end of file diff --git a/src/main/java/de/t14d3/zones/Zones.java b/src/main/java/de/t14d3/zones/Zones.java index 657398e..3c38a97 100644 --- a/src/main/java/de/t14d3/zones/Zones.java +++ b/src/main/java/de/t14d3/zones/Zones.java @@ -34,6 +34,11 @@ public final class Zones extends JavaPlugin { private Messages messages; private static Zones instance; private CommandListener commandListener; + private PaperBootstrap bootstrap; + + public Zones(PaperBootstrap bootstrap) { + this.bootstrap = bootstrap; + } @Override public void onEnable() { diff --git a/src/main/java/de/t14d3/zones/brigadier/Command.java b/src/main/java/de/t14d3/zones/brigadier/Command.java index 5360d35..01914ec 100644 --- a/src/main/java/de/t14d3/zones/brigadier/Command.java +++ b/src/main/java/de/t14d3/zones/brigadier/Command.java @@ -3,14 +3,16 @@ import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.tree.LiteralCommandNode; +import de.t14d3.zones.PaperBootstrap; import de.t14d3.zones.Region; import de.t14d3.zones.Zones; -import de.t14d3.zones.utils.Actions; +import de.t14d3.zones.utils.Flags; import io.papermc.paper.command.brigadier.CommandSourceStack; import io.papermc.paper.command.brigadier.Commands; import io.papermc.paper.command.brigadier.MessageComponentSerializer; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; +import net.kyori.adventure.text.minimessage.MiniMessage; import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; import org.bukkit.entity.Player; @@ -22,8 +24,13 @@ @SuppressWarnings("UnstableApiUsage") public class Command { + private final PaperBootstrap context; - public static LiteralCommandNode node() { + public Command(PaperBootstrap context) { + this.context = context; + } + + public LiteralCommandNode node() { return Commands.literal("zone") .then(Commands.argument("subcommand", new SubCommandArgument()) .suggests((ctx, builder) -> { @@ -107,11 +114,17 @@ public static LiteralCommandNode node() { Zones.getInstance().getCommandListener().execute(ctx.getSource(), ctx.getInput()); return com.mojang.brigadier.Command.SINGLE_SUCCESS; }) - .then(Commands.argument("flag", new FlagArgument()) + .then(Commands.argument("flag", new FlagArgument(context)) .suggests((ctx, builder) -> { - for (Actions action : Actions.values()) { - builder.suggest(action.name().toLowerCase(), MessageComponentSerializer.message().serialize(Component.text(action.getKey()))); + Flags flags = context.getFlags(); + MiniMessage mm = MiniMessage.miniMessage(); + for (Map.Entry entry : flags.getFlags().entrySet()) { + builder.suggest(entry.getKey(), + MessageComponentSerializer.message().serialize( + mm.deserialize(Zones.getInstance().getMessages().getOrDefault("flags." + entry.getKey(), entry.getValue())) + )); } + return builder.buildFuture(); }) .then(Commands.argument("value", StringArgumentType.greedyString()) diff --git a/src/main/java/de/t14d3/zones/brigadier/FlagArgument.java b/src/main/java/de/t14d3/zones/brigadier/FlagArgument.java index 56ce3d9..a366ef9 100644 --- a/src/main/java/de/t14d3/zones/brigadier/FlagArgument.java +++ b/src/main/java/de/t14d3/zones/brigadier/FlagArgument.java @@ -3,16 +3,21 @@ import com.mojang.brigadier.arguments.ArgumentType; import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.exceptions.CommandSyntaxException; -import de.t14d3.zones.utils.Actions; +import de.t14d3.zones.PaperBootstrap; +import de.t14d3.zones.utils.Flags; import io.papermc.paper.command.brigadier.argument.CustomArgumentType; import org.jetbrains.annotations.NotNull; @SuppressWarnings("UnstableApiUsage") -public class FlagArgument implements CustomArgumentType.Converted { +public class FlagArgument implements CustomArgumentType.Converted { + private final Flags flags; + public FlagArgument(PaperBootstrap context) { + this.flags = context.getFlags(); + } @Override - public @NotNull Actions convert(String nativeType) throws CommandSyntaxException { - return Actions.valueOf(nativeType.toUpperCase()); + public @NotNull String convert(@NotNull String nativeType) throws CommandSyntaxException { + return flags.getFlags().get(nativeType); } @Override diff --git a/src/main/java/de/t14d3/zones/utils/Flags.java b/src/main/java/de/t14d3/zones/utils/Flags.java new file mode 100644 index 0000000..6ba44bd --- /dev/null +++ b/src/main/java/de/t14d3/zones/utils/Flags.java @@ -0,0 +1,53 @@ +package de.t14d3.zones.utils; + +import org.jetbrains.annotations.NotNull; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +public class Flags { + + private Map flags = new HashMap<>(); + + public Flags() { + } + + /** + * Register a flag with a fallback description + * + * @param flag Flag to register + * @param desc Fallback description + * @return {@code true} if it was registered, {@code false} if it already exists + * @see #registerFlag(String, String, boolean) + */ + public boolean registerFlag(@NotNull String flag, @NotNull String desc) { + return registerFlag(flag, desc, false); + } + + /** + * Register a flag with a fallback description + * + * @param flag Flag to register + * @param desc Fallback description + * @param overwrite Whether to overwrite an existing flag + * @return {@code true} if it was registered, {@code false} if it already exists and {@code overwrite} is {@code false} + * @see #registerFlag(String, String) + */ + public boolean registerFlag(@NotNull String flag, @NotNull String desc, boolean overwrite) { + if (flags.containsKey(flag) && !overwrite) { + return false; + } + flags.put(flag, desc); + return true; + } + + /** + * Immutable List of all flags recognized by the plugin + * + * @return Map of {@code } + */ + public Map getFlags() { + return Collections.unmodifiableMap(flags); + } +} diff --git a/src/main/java/de/t14d3/zones/utils/Messages.java b/src/main/java/de/t14d3/zones/utils/Messages.java index 930d28a..d42f6aa 100644 --- a/src/main/java/de/t14d3/zones/utils/Messages.java +++ b/src/main/java/de/t14d3/zones/utils/Messages.java @@ -29,4 +29,8 @@ public Messages(Properties messagesConfig, Zones zones) { public @NotNull String get(String key) { return messages.getOrDefault(key, zones.getConfig().getString("messages.default", key).replaceAll("", key)); } + + public @NotNull String getOrDefault(String key, String defaultValue) { + return messages.getOrDefault(key, defaultValue); + } } diff --git a/src/main/java/de/t14d3/zones/utils/Utils.java b/src/main/java/de/t14d3/zones/utils/Utils.java index b86d176..b37c64a 100644 --- a/src/main/java/de/t14d3/zones/utils/Utils.java +++ b/src/main/java/de/t14d3/zones/utils/Utils.java @@ -10,6 +10,9 @@ import org.bukkit.persistence.PersistentDataContainer; import org.bukkit.persistence.PersistentDataType; +import java.util.HashMap; +import java.util.Map; + /** * Utility methods for the plugin. *

@@ -58,4 +61,18 @@ public static SavingModes fromString(String string) { return mode; } } + + public static Map defaultFlags() { + Map flags = new HashMap<>(); + flags.put("break", "Allows breaking blocks"); + flags.put("place", "Allows placing blocks"); + flags.put("interact", "Allows interacting"); + flags.put("container", "Allows opening containers"); + flags.put("redstone", "Allows interacting with redstone"); + flags.put("entity", "Allows interacting with entities"); + flags.put("ignite", "Allows igniting tnt"); + flags.put("damage", "Allows damaging entities"); + flags.put("group", "Add a group to the player"); + return flags; + } } diff --git a/src/main/resources/messages.properties b/src/main/resources/messages.properties index 3e55fff..7bdcf12 100644 --- a/src/main/resources/messages.properties +++ b/src/main/resources/messages.properties @@ -33,3 +33,12 @@ region.info.members.name= region.info.members.permission= : region.info.members.values.allowed= region.info.members.values.denied= +flags.break=Allows breaking blocks +flags.place=Allows placing blocks +flags.interact=Allows interacting +flags.container=Allows opening containers +flags.redstone=Allows interacting with redstone +flags.entity=Allows interacting with entities +flags.ignite=Allows igniting tnt +flags.damage=Allows damaging entities +flags.group=Add a group to the player From 0b8a3ea8aed61bc8b537113ed700b2888e0a5207 Mon Sep 17 00:00:00 2001 From: T14D3 <73843330+T14D3@users.noreply.github.com> Date: Thu, 16 Jan 2025 11:08:09 +0100 Subject: [PATCH 10/12] Remove debug messages, fix using namespaced root command --- .../de/t14d3/zones/brigadier/Command.java | 29 +++++++++++++++---- .../zones/listeners/CommandListener.java | 3 +- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/main/java/de/t14d3/zones/brigadier/Command.java b/src/main/java/de/t14d3/zones/brigadier/Command.java index 01914ec..ecd51d5 100644 --- a/src/main/java/de/t14d3/zones/brigadier/Command.java +++ b/src/main/java/de/t14d3/zones/brigadier/Command.java @@ -32,6 +32,12 @@ public Command(PaperBootstrap context) { public LiteralCommandNode node() { return Commands.literal("zone") + .executes(ctx -> { + MiniMessage mm = MiniMessage.miniMessage(); + Component comp = mm.deserialize(Zones.getInstance().getMessages().get("commands.invalid")); + ctx.getSource().getSender().sendMessage(comp); + return 1; + }) .then(Commands.argument("subcommand", new SubCommandArgument()) .suggests((ctx, builder) -> { for (SubCommands subCommand : SubCommands.values()) { @@ -73,8 +79,7 @@ public LiteralCommandNode node() { }) .executes(ctx -> { Zones.getInstance().getCommandListener().execute(ctx.getSource(), ctx.getInput()); - ctx.getSource().getSender().sendMessage(String.join(", ", ctx.getInput().split(" "))); - return com.mojang.brigadier.Command.SINGLE_SUCCESS; + return 1; }) .then(Commands.argument("name", StringArgumentType.string()) .suggests((ctx, builder) -> { @@ -112,7 +117,7 @@ public LiteralCommandNode node() { }) .executes(ctx -> { Zones.getInstance().getCommandListener().execute(ctx.getSource(), ctx.getInput()); - return com.mojang.brigadier.Command.SINGLE_SUCCESS; + return 1; }) .then(Commands.argument("flag", new FlagArgument(context)) .suggests((ctx, builder) -> { @@ -124,7 +129,6 @@ public LiteralCommandNode node() { mm.deserialize(Zones.getInstance().getMessages().getOrDefault("flags." + entry.getKey(), entry.getValue())) )); } - return builder.buildFuture(); }) .then(Commands.argument("value", StringArgumentType.greedyString()) @@ -141,6 +145,18 @@ public LiteralCommandNode node() { case "ENTITY", "DAMAGE" -> types = plugin.getTypes().entityTypes; case "IGNITE" -> types = List.of("TRUE", "FALSE"); + case "GROUP" -> { + types = new ArrayList<>(); + for (Map.Entry region : Zones.getInstance().getRegionManager().regions().entrySet()) { + if (!ctx.getInput().split(" ")[2].equalsIgnoreCase(region.getKey())) { + continue; + } + if (ctx.getSource().getSender().hasPermission("zones.info.other") + || (ctx.getSource().getSender() instanceof Player player && region.getValue().isAdmin(player.getUniqueId()))) { + types.addAll(region.getValue().getGroupNames()); + } + } + } default -> types = plugin.getTypes().allTypes; } String[] args = ctx.getInput().split(" "); @@ -154,7 +170,7 @@ public LiteralCommandNode node() { }) .executes(ctx -> { Zones.getInstance().getCommandListener().execute(ctx.getSource(), ctx.getInput()); - return com.mojang.brigadier.Command.SINGLE_SUCCESS; + return 1; }) ) ) @@ -171,6 +187,7 @@ public LiteralCommandNode node() { * @return Argument at the given index */ public static String arg(CommandContext ctx, int index) { - return ctx.getInput().split(" ")[index]; + String arg = ctx.getInput().replace("zones:", ""); + return arg.split(" ")[index]; } } diff --git a/src/main/java/de/t14d3/zones/listeners/CommandListener.java b/src/main/java/de/t14d3/zones/listeners/CommandListener.java index 3157cde..021a189 100644 --- a/src/main/java/de/t14d3/zones/listeners/CommandListener.java +++ b/src/main/java/de/t14d3/zones/listeners/CommandListener.java @@ -43,8 +43,7 @@ public CommandListener(Zones plugin, RegionManager regionManager) { @SuppressWarnings("UnstableApiUsage") public void execute(CommandSourceStack stack, String arg) { - String[] args = arg.replaceFirst("zone ", "").split(" "); - stack.getSender().sendMessage(String.join(", ", args)); + String[] args = arg.replaceFirst("zone ", "").replaceFirst("zones:", "").split(" "); CommandSender sender = stack.getSender(); String command = args[0].toLowerCase(); From cf7b41d4777e1bd3e84750b7aee79a527115d5d8 Mon Sep 17 00:00:00 2001 From: T14D3 <73843330+T14D3@users.noreply.github.com> Date: Thu, 16 Jan 2025 11:25:09 +0100 Subject: [PATCH 11/12] Fix some errors --- src/main/java/de/t14d3/zones/brigadier/Command.java | 3 ++- .../de/t14d3/zones/brigadier/SubCommandArgument.java | 12 +++++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/main/java/de/t14d3/zones/brigadier/Command.java b/src/main/java/de/t14d3/zones/brigadier/Command.java index ecd51d5..013154f 100644 --- a/src/main/java/de/t14d3/zones/brigadier/Command.java +++ b/src/main/java/de/t14d3/zones/brigadier/Command.java @@ -94,7 +94,8 @@ public LiteralCommandNode node() { } } for (Map.Entry region : Zones.getInstance().getRegionManager().regions().entrySet()) { - if (!ctx.getInput().split(" ")[2].equalsIgnoreCase(region.getKey())) { + String[] args = ctx.getInput().split(" "); + if (args.length <= 2 || !args[2].equalsIgnoreCase(region.getKey())) { continue; } if (ctx.getSource().getSender().hasPermission("zones.info.other") diff --git a/src/main/java/de/t14d3/zones/brigadier/SubCommandArgument.java b/src/main/java/de/t14d3/zones/brigadier/SubCommandArgument.java index c8e8eb9..8beb764 100644 --- a/src/main/java/de/t14d3/zones/brigadier/SubCommandArgument.java +++ b/src/main/java/de/t14d3/zones/brigadier/SubCommandArgument.java @@ -1,9 +1,14 @@ package de.t14d3.zones.brigadier; +import com.mojang.brigadier.Message; import com.mojang.brigadier.arguments.ArgumentType; import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; +import de.t14d3.zones.Zones; +import io.papermc.paper.command.brigadier.MessageComponentSerializer; import io.papermc.paper.command.brigadier.argument.CustomArgumentType; +import net.kyori.adventure.text.minimessage.MiniMessage; import org.jetbrains.annotations.NotNull; @@ -11,7 +16,12 @@ public class SubCommandArgument implements CustomArgumentType.Converted { @Override public @NotNull SubCommands convert(@NotNull String nativeType) throws CommandSyntaxException { - return SubCommands.get(nativeType.toUpperCase()); + try { + return SubCommands.valueOf(nativeType.toUpperCase().split(" ")[0]); + } catch (IllegalArgumentException ignored) { + Message message = MessageComponentSerializer.message().serialize(MiniMessage.miniMessage().deserialize(Zones.getInstance().getMessages().get("commands.invalid"))); + throw new CommandSyntaxException(new SimpleCommandExceptionType(message), message); + } } @Override From 626e4b39d74e6e4d83096a60deae7c778ba13619 Mon Sep 17 00:00:00 2001 From: T14D3 <73843330+T14D3@users.noreply.github.com> Date: Thu, 16 Jan 2025 11:29:06 +0100 Subject: [PATCH 12/12] Bump version --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 91479bb..64115d3 100644 --- a/build.gradle +++ b/build.gradle @@ -8,7 +8,7 @@ plugins { } group = 'de.t14d3' -version = '0.1.5' +version = '0.1.6' repositories { mavenCentral()