diff --git a/sakura-server/src/main/java/me/samsuik/sakura/command/BaseMenuCommand.java b/sakura-server/src/main/java/me/samsuik/sakura/command/BaseMenuCommand.java index 3574de6..e5fedff 100644 --- a/sakura-server/src/main/java/me/samsuik/sakura/command/BaseMenuCommand.java +++ b/sakura-server/src/main/java/me/samsuik/sakura/command/BaseMenuCommand.java @@ -66,23 +66,18 @@ public abstract class BaseMenuCommand extends BaseSubCommand { return Collections.emptyList(); } - final Command command = SakuraCommands.getCommand(args[0]); final List completions = new ArrayList<>(); - if (command != null && args.length > 1) { - final String[] newArgs = Arrays.copyOfRange(args, 1, args.length); - completions.addAll(command.tabComplete(sender, alias, newArgs)); - } else { - for (final Command subCommand : SakuraCommands.SUB_COMMANDS) { - final String commandName = subCommand.getName(); - if (commandName.startsWith(args[0])) { - completions.add(commandName); - } + for (final Command subCommand : this.subCommands()) { + final String commandName = subCommand.getName(); + if (commandName.startsWith(args[0])) { + completions.add(commandName); + } + if (commandName.equalsIgnoreCase(args[0])) { + final String[] newArgs = Arrays.copyOfRange(args, 1, args.length); + return subCommand.tabComplete(sender, alias, newArgs); } } - final String lastArg = args[args.length - 1]; - return completions.stream() - .filter(result -> result.startsWith(lastArg)) - .toList(); + return completions; } } diff --git a/sakura-server/src/main/java/me/samsuik/sakura/command/BaseSubCommand.java b/sakura-server/src/main/java/me/samsuik/sakura/command/BaseSubCommand.java index f5cfdb3..0fb9c8a 100644 --- a/sakura-server/src/main/java/me/samsuik/sakura/command/BaseSubCommand.java +++ b/sakura-server/src/main/java/me/samsuik/sakura/command/BaseSubCommand.java @@ -42,10 +42,6 @@ public abstract class BaseSubCommand extends Command { return completions; } - public void sendPlayerOnlyMessage(CommandSender sender) { - sender.sendRichMessage("This command can only be ran by players"); - } - protected final Optional parseInt(String[] args, int index) { return this.parse(args, index, Integer::parseInt); } diff --git a/sakura-server/src/main/java/me/samsuik/sakura/command/PlayerOnlySubCommand.java b/sakura-server/src/main/java/me/samsuik/sakura/command/PlayerOnlySubCommand.java new file mode 100644 index 0000000..b8acb58 --- /dev/null +++ b/sakura-server/src/main/java/me/samsuik/sakura/command/PlayerOnlySubCommand.java @@ -0,0 +1,22 @@ +package me.samsuik.sakura.command; + +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.jspecify.annotations.NullMarked; + +@NullMarked +public abstract class PlayerOnlySubCommand extends BaseSubCommand { + public PlayerOnlySubCommand(String name) { + super(name); + } + + public abstract void execute(Player player, String[] args); + + public final void execute(CommandSender sender, String[] args) { + if (sender instanceof Player player) { + this.execute(player, args); + } else { + sender.sendRichMessage("This command can only be used by players"); + } + } +} diff --git a/sakura-server/src/main/java/me/samsuik/sakura/command/SakuraCommands.java b/sakura-server/src/main/java/me/samsuik/sakura/command/SakuraCommands.java index 109600c..7ee3ed3 100644 --- a/sakura-server/src/main/java/me/samsuik/sakura/command/SakuraCommands.java +++ b/sakura-server/src/main/java/me/samsuik/sakura/command/SakuraCommands.java @@ -7,7 +7,6 @@ import me.samsuik.sakura.player.visibility.VisibilityTypes; import net.minecraft.server.MinecraftServer; import org.bukkit.command.Command; import org.jspecify.annotations.NullMarked; -import org.jspecify.annotations.Nullable; import java.util.HashMap; import java.util.HashSet; @@ -39,12 +38,4 @@ public final class SakuraCommands { server.server.getCommandMap().register(name, "sakura", command); }); } - - @Nullable - public static Command getCommand(String name) { - return SUB_COMMANDS.stream() - .filter(cmd -> cmd.getName().equalsIgnoreCase(name)) - .findFirst() - .orElse(null); - } } diff --git a/sakura-server/src/main/java/me/samsuik/sakura/command/subcommands/FPSCommand.java b/sakura-server/src/main/java/me/samsuik/sakura/command/subcommands/FPSCommand.java index b31c7e5..57a0b4f 100644 --- a/sakura-server/src/main/java/me/samsuik/sakura/command/subcommands/FPSCommand.java +++ b/sakura-server/src/main/java/me/samsuik/sakura/command/subcommands/FPSCommand.java @@ -1,13 +1,12 @@ package me.samsuik.sakura.command.subcommands; -import me.samsuik.sakura.command.BaseSubCommand; +import me.samsuik.sakura.command.PlayerOnlySubCommand; import me.samsuik.sakura.player.visibility.VisibilityGui; -import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.jspecify.annotations.NullMarked; @NullMarked -public final class FPSCommand extends BaseSubCommand { +public final class FPSCommand extends PlayerOnlySubCommand { private final VisibilityGui visibilityGui = new VisibilityGui(); public FPSCommand(String name) { @@ -15,9 +14,7 @@ public final class FPSCommand extends BaseSubCommand { } @Override - public void execute(CommandSender sender, String[] args) { - if (sender instanceof Player player) { - this.visibilityGui.showTo(player); - } + public void execute(Player player, String[] args) { + this.visibilityGui.showTo(player); } } diff --git a/sakura-server/src/main/java/me/samsuik/sakura/command/subcommands/VisualCommand.java b/sakura-server/src/main/java/me/samsuik/sakura/command/subcommands/VisualCommand.java index ee0d5c6..7d859d5 100644 --- a/sakura-server/src/main/java/me/samsuik/sakura/command/subcommands/VisualCommand.java +++ b/sakura-server/src/main/java/me/samsuik/sakura/command/subcommands/VisualCommand.java @@ -1,19 +1,18 @@ package me.samsuik.sakura.command.subcommands; -import me.samsuik.sakura.command.BaseSubCommand; +import me.samsuik.sakura.command.PlayerOnlySubCommand; import me.samsuik.sakura.configuration.GlobalConfiguration; import me.samsuik.sakura.player.visibility.VisibilitySettings; import me.samsuik.sakura.player.visibility.VisibilityState; import me.samsuik.sakura.player.visibility.VisibilityType; import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; -import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.jspecify.annotations.NullMarked; import java.util.Arrays; @NullMarked -public final class VisualCommand extends BaseSubCommand { +public final class VisualCommand extends PlayerOnlySubCommand { private final VisibilityType type; public VisualCommand(VisibilityType type, String... aliases) { @@ -23,11 +22,7 @@ public final class VisualCommand extends BaseSubCommand { } @Override - public void execute(CommandSender sender, String[] args) { - if (!(sender instanceof Player player)) { - return; - } - + public void execute(Player player, String[] args) { VisibilitySettings settings = player.getVisibility(); VisibilityState state = settings.toggle(type); diff --git a/sakura-server/src/main/java/me/samsuik/sakura/command/subcommands/debug/DebugLocalRegions.java b/sakura-server/src/main/java/me/samsuik/sakura/command/subcommands/debug/DebugLocalRegions.java index 2727680..87372f0 100644 --- a/sakura-server/src/main/java/me/samsuik/sakura/command/subcommands/debug/DebugLocalRegions.java +++ b/sakura-server/src/main/java/me/samsuik/sakura/command/subcommands/debug/DebugLocalRegions.java @@ -1,19 +1,19 @@ package me.samsuik.sakura.command.subcommands.debug; -import me.samsuik.sakura.command.BaseSubCommand; +import me.samsuik.sakura.command.PlayerOnlySubCommand; import me.samsuik.sakura.local.LocalRegion; import me.samsuik.sakura.local.storage.LocalStorageHandler; import me.samsuik.sakura.local.storage.LocalValueStorage; import org.bukkit.Location; import org.bukkit.World; -import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.jspecify.annotations.NullMarked; +import java.util.List; import java.util.Optional; @NullMarked -public final class DebugLocalRegions extends BaseSubCommand { +public final class DebugLocalRegions extends PlayerOnlySubCommand { private static final int DEFAULT_REGION_SIZE = 16; public DebugLocalRegions(String name) { @@ -21,9 +21,8 @@ public final class DebugLocalRegions extends BaseSubCommand { } @Override - public void execute(CommandSender sender, String[] args) { - if (!(sender instanceof Player player)) { - this.sendPlayerOnlyMessage(sender); + public void execute(Player player, String[] args) { + if (args.length == 0) { return; } @@ -34,14 +33,18 @@ public final class DebugLocalRegions extends BaseSubCommand { final int blockZ = location.getBlockZ(); final Optional currentRegion = storageHandler.locate(blockX, blockZ); - if ("create".equalsIgnoreCase(args[0])) { + if ("create".equalsIgnoreCase(args[0]) && args.length > 1) { final int size = parseInt(args, 1).orElse(DEFAULT_REGION_SIZE); final LocalRegion region = LocalRegion.at(blockX, blockZ, size); - storageHandler.put(region, new LocalValueStorage()); + if (currentRegion.isPresent()) { + player.sendRichMessage("regions cannot overlap"); + } else { + storageHandler.put(region, new LocalValueStorage()); + } } if ("get".equalsIgnoreCase(args[0])) { - sender.sendRichMessage("" + (currentRegion.isPresent() ? currentRegion.get() : "not inside of a region")); + player.sendRichMessage("" + (currentRegion.isPresent() ? currentRegion.get() : "not inside of a region")); } if (currentRegion.isPresent()) { @@ -51,4 +54,9 @@ public final class DebugLocalRegions extends BaseSubCommand { } } } + + @Override + public void tabComplete(List list, String[] args) throws IllegalArgumentException { + list.addAll(List.of("create", "get", "delete")); + } } diff --git a/sakura-server/src/main/java/me/samsuik/sakura/command/subcommands/debug/DebugRedstoneCache.java b/sakura-server/src/main/java/me/samsuik/sakura/command/subcommands/debug/DebugRedstoneCache.java index 7fec461..c5284ee 100644 --- a/sakura-server/src/main/java/me/samsuik/sakura/command/subcommands/debug/DebugRedstoneCache.java +++ b/sakura-server/src/main/java/me/samsuik/sakura/command/subcommands/debug/DebugRedstoneCache.java @@ -1,6 +1,6 @@ package me.samsuik.sakura.command.subcommands.debug; -import me.samsuik.sakura.command.BaseSubCommand; +import me.samsuik.sakura.command.PlayerOnlySubCommand; import me.samsuik.sakura.redstone.RedstoneNetwork; import net.minecraft.core.BlockPos; import net.minecraft.server.level.ServerPlayer; @@ -8,7 +8,6 @@ import net.minecraft.world.level.Level; import org.bukkit.DyeColor; import org.bukkit.Location; import org.bukkit.Material; -import org.bukkit.command.CommandSender; import org.bukkit.craftbukkit.entity.CraftPlayer; import org.bukkit.craftbukkit.util.CraftLocation; import org.bukkit.entity.Player; @@ -19,18 +18,13 @@ import java.util.Set; import java.util.concurrent.ThreadLocalRandom; @NullMarked -public final class DebugRedstoneCache extends BaseSubCommand { +public final class DebugRedstoneCache extends PlayerOnlySubCommand { public DebugRedstoneCache(String name) { super(name); } @Override - public void execute(CommandSender sender, String[] args) { - if (!(sender instanceof Player player)) { - this.sendPlayerOnlyMessage(sender); - return; - } - + public void execute(Player player, String[] args) { ServerPlayer nmsPlayer = ((CraftPlayer) player).getHandle(); Level level = nmsPlayer.level(); Set locations = new HashSet<>();