diff --git a/common/src/main/java/com/dfsek/terra/api/command/CommandManager.java b/common/src/main/java/com/dfsek/terra/api/command/CommandManager.java index 8caa03072..e46517e7d 100644 --- a/common/src/main/java/com/dfsek/terra/api/command/CommandManager.java +++ b/common/src/main/java/com/dfsek/terra/api/command/CommandManager.java @@ -1,11 +1,12 @@ package com.dfsek.terra.api.command; import com.dfsek.terra.api.command.exception.CommandException; +import com.dfsek.terra.api.platform.CommandSender; import java.util.List; public interface CommandManager { - void execute(String command, List args) throws CommandException; + void execute(String command, CommandSender sender, List args) throws CommandException; void register(String name, Class clazz); } diff --git a/common/src/main/java/com/dfsek/terra/api/command/ExecutionState.java b/common/src/main/java/com/dfsek/terra/api/command/ExecutionState.java index b1665ff90..2a57b73a6 100644 --- a/common/src/main/java/com/dfsek/terra/api/command/ExecutionState.java +++ b/common/src/main/java/com/dfsek/terra/api/command/ExecutionState.java @@ -1,5 +1,7 @@ package com.dfsek.terra.api.command; +import com.dfsek.terra.api.platform.CommandSender; + import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -8,9 +10,10 @@ import java.util.Set; public final class ExecutionState { private final Set switches = new HashSet<>(); private final Map args = new HashMap<>(); + private final CommandSender sender; - protected ExecutionState() { - + protected ExecutionState(CommandSender sender) { + this.sender = sender; } protected void addSwitch(String flag) { @@ -42,4 +45,8 @@ public final class ExecutionState { public boolean hasSwitch(String flag) { return switches.contains(flag); } + + public CommandSender getSender() { + return sender; + } } diff --git a/common/src/main/java/com/dfsek/terra/api/command/TerraCommandManager.java b/common/src/main/java/com/dfsek/terra/api/command/TerraCommandManager.java index 57360bb0e..b7b57f818 100644 --- a/common/src/main/java/com/dfsek/terra/api/command/TerraCommandManager.java +++ b/common/src/main/java/com/dfsek/terra/api/command/TerraCommandManager.java @@ -1,13 +1,22 @@ package com.dfsek.terra.api.command; +import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.command.annotation.Argument; import com.dfsek.terra.api.command.annotation.Command; import com.dfsek.terra.api.command.annotation.Subcommand; import com.dfsek.terra.api.command.annotation.Switch; +import com.dfsek.terra.api.command.annotation.type.DebugCommand; +import com.dfsek.terra.api.command.annotation.type.PlayerCommand; +import com.dfsek.terra.api.command.annotation.type.WorldCommand; import com.dfsek.terra.api.command.exception.CommandException; import com.dfsek.terra.api.command.exception.InvalidArgumentsException; import com.dfsek.terra.api.command.exception.MalformedCommandException; import com.dfsek.terra.api.command.exception.SwitchFormatException; +import com.dfsek.terra.api.injection.Injector; +import com.dfsek.terra.api.injection.exception.InjectionException; +import com.dfsek.terra.api.platform.CommandSender; +import com.dfsek.terra.api.platform.entity.Player; +import com.dfsek.terra.world.TerraWorld; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; @@ -18,38 +27,63 @@ import java.util.Map; public class TerraCommandManager implements CommandManager { private final Map commands = new HashMap<>(); + private final Injector pluginInjector; + private final TerraPlugin main; - @Override - public void execute(String commandName, List argsIn) throws CommandException { - execute(commands.get(commandName), new ArrayList<>(argsIn)); + public TerraCommandManager(TerraPlugin main) { + this.main = main; + this.pluginInjector = new Injector<>(main); + pluginInjector.addExplicitTarget(TerraPlugin.class); } - private void execute(CommandHolder commandHolder, List args) throws CommandException { + @Override + public void execute(String commandName, CommandSender sender, List argsIn) throws CommandException { + execute(commands.get(commandName), sender, new ArrayList<>(argsIn)); + } + + private void execute(CommandHolder commandHolder, CommandSender sender, List args) throws CommandException { + Class commandClass = commandHolder.clazz; + + if(commandClass.isAnnotationPresent(DebugCommand.class) && !main.isDebug()) { + sender.sendMessage("Command must be executed with debug mode enabled."); + return; + } + + if(commandClass.isAnnotationPresent(PlayerCommand.class) && !(sender instanceof Player)) { + sender.sendMessage("Command must be executed by player."); + return; + } + + if(commandClass.isAnnotationPresent(WorldCommand.class) && (!(sender instanceof Player) || !TerraWorld.isTerraWorld(((Player) sender).getWorld()))) { + sender.sendMessage("Command must be executed in a Terra world."); + return; + } + List ogArgs = new ArrayList<>(args); - ExecutionState state = new ExecutionState(); - - Class commandClass = commandHolder.clazz; + ExecutionState state = new ExecutionState(sender); if(!commandClass.isAnnotationPresent(Command.class)) { invoke(commandClass, state); + return; } Command command = commandClass.getAnnotation(Command.class); if(command.arguments().length == 0 && command.subcommands().length == 0) { - if(args.isEmpty()) invoke(commandClass, state); - else throw new InvalidArgumentsException("Expected 0 arguments, found " + args.size()); + if(args.isEmpty()) { + invoke(commandClass, state); + return; + } else throw new InvalidArgumentsException("Expected 0 arguments, found " + args.size()); } if(commandHolder.subcommands.containsKey(args.get(0))) { String c = args.get(0); args.remove(0); - execute(commandHolder.subcommands.get(c), args); + execute(commandHolder.subcommands.get(c), sender, args); return; } - boolean req = true; for(Argument argument : command.arguments()) { if(!req && argument.required()) { @@ -83,15 +117,18 @@ public class TerraCommandManager implements CommandManager { state.addSwitch(commandHolder.switches.get(val)); } - invoke(commandClass, state); } private void invoke(Class clazz, ExecutionState state) throws MalformedCommandException { try { System.out.println("invocation"); - clazz.getConstructor().newInstance().execute(state); - } catch(InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { + CommandTemplate template = clazz.getConstructor().newInstance(); + + pluginInjector.inject(template); + + template.execute(state); + } catch(InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException | InjectionException e) { throw new MalformedCommandException("Unable to reflectively instantiate command: ", e); } } @@ -101,6 +138,9 @@ public class TerraCommandManager implements CommandManager { commands.put(name, new CommandHolder(clazz)); } + /** + * Pre-processes command metadata. + */ private static final class CommandHolder { private final Class clazz; private final Map subcommands = new HashMap<>(); diff --git a/common/src/main/java/com/dfsek/terra/api/command/annotation/type/DebugCommand.java b/common/src/main/java/com/dfsek/terra/api/command/annotation/type/DebugCommand.java new file mode 100644 index 000000000..174710401 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/command/annotation/type/DebugCommand.java @@ -0,0 +1,14 @@ +package com.dfsek.terra.api.command.annotation.type; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Command may only be executed with debug mode enabled. + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +public @interface DebugCommand { +} diff --git a/common/src/main/java/com/dfsek/terra/api/command/annotation/type/PlayerCommand.java b/common/src/main/java/com/dfsek/terra/api/command/annotation/type/PlayerCommand.java new file mode 100644 index 000000000..fd7b1e320 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/command/annotation/type/PlayerCommand.java @@ -0,0 +1,14 @@ +package com.dfsek.terra.api.command.annotation.type; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Marks command as player-only + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +public @interface PlayerCommand { +} diff --git a/common/src/main/java/com/dfsek/terra/api/command/annotation/type/WorldCommand.java b/common/src/main/java/com/dfsek/terra/api/command/annotation/type/WorldCommand.java new file mode 100644 index 000000000..c51ee570b --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/command/annotation/type/WorldCommand.java @@ -0,0 +1,14 @@ +package com.dfsek.terra.api.command.annotation.type; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Command may only be executed in a Terra world. + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +public @interface WorldCommand { +} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/entity/Entity.java b/common/src/main/java/com/dfsek/terra/api/platform/entity/Entity.java index e69ffbcbc..692ae6498 100644 --- a/common/src/main/java/com/dfsek/terra/api/platform/entity/Entity.java +++ b/common/src/main/java/com/dfsek/terra/api/platform/entity/Entity.java @@ -3,7 +3,10 @@ package com.dfsek.terra.api.platform.entity; import com.dfsek.terra.api.math.vector.Location; import com.dfsek.terra.api.platform.CommandSender; import com.dfsek.terra.api.platform.Handle; +import com.dfsek.terra.api.platform.world.World; public interface Entity extends Handle, CommandSender { Location getLocation(); + + World getWorld(); } diff --git a/common/src/main/java/com/dfsek/terra/commands/profiler/ProfileCommand.java b/common/src/main/java/com/dfsek/terra/commands/profiler/ProfileCommand.java new file mode 100644 index 000000000..b5bd9d270 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/commands/profiler/ProfileCommand.java @@ -0,0 +1,28 @@ +package com.dfsek.terra.commands.profiler; + +import com.dfsek.terra.api.command.CommandTemplate; +import com.dfsek.terra.api.command.ExecutionState; +import com.dfsek.terra.api.command.annotation.Command; +import com.dfsek.terra.api.command.annotation.Subcommand; +import com.dfsek.terra.api.command.annotation.type.DebugCommand; +import com.dfsek.terra.api.command.annotation.type.PlayerCommand; +import com.dfsek.terra.api.command.annotation.type.WorldCommand; + +@Command( + subcommands = { + @Subcommand(value = "query", aliases = {"q"}, clazz = ProfileQueryCommand.class), + @Subcommand(value = "start", aliases = {"s"}, clazz = ProfileStartCommand.class), + @Subcommand(value = "stop", aliases = {"st"}, clazz = ProfileStopCommand.class), + @Subcommand(value = "reset", aliases = {"r"}, clazz = ProfileResetCommand.class) + }, + usage = "Commands to enable/disable/query/reset the profiler." +) +@WorldCommand +@PlayerCommand +@DebugCommand +public class ProfileCommand implements CommandTemplate { + @Override + public void execute(ExecutionState state) { + + } +} diff --git a/common/src/main/java/com/dfsek/terra/commands/profiler/ProfileQueryCommand.java b/common/src/main/java/com/dfsek/terra/commands/profiler/ProfileQueryCommand.java new file mode 100644 index 000000000..b0004799f --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/commands/profiler/ProfileQueryCommand.java @@ -0,0 +1,28 @@ +package com.dfsek.terra.commands.profiler; + +import com.dfsek.terra.api.TerraPlugin; +import com.dfsek.terra.api.command.CommandTemplate; +import com.dfsek.terra.api.command.ExecutionState; +import com.dfsek.terra.api.command.annotation.Command; +import com.dfsek.terra.api.command.annotation.type.DebugCommand; +import com.dfsek.terra.api.command.annotation.type.PlayerCommand; +import com.dfsek.terra.api.command.annotation.type.WorldCommand; +import com.dfsek.terra.api.injection.annotations.Inject; +import com.dfsek.terra.api.platform.entity.Player; +import com.dfsek.terra.world.TerraWorld; + +@Command +@WorldCommand +@PlayerCommand +@DebugCommand +public class ProfileQueryCommand implements CommandTemplate { + @Inject + private TerraPlugin main; + + @Override + public void execute(ExecutionState state) { + Player player = (Player) state.getSender(); + TerraWorld world = main.getWorld(player.getWorld()); + state.getSender().sendMessage(world.getProfiler().getResultsFormatted()); + } +} diff --git a/common/src/main/java/com/dfsek/terra/commands/profiler/ProfileResetCommand.java b/common/src/main/java/com/dfsek/terra/commands/profiler/ProfileResetCommand.java new file mode 100644 index 000000000..4d2349291 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/commands/profiler/ProfileResetCommand.java @@ -0,0 +1,29 @@ +package com.dfsek.terra.commands.profiler; + +import com.dfsek.terra.api.TerraPlugin; +import com.dfsek.terra.api.command.CommandTemplate; +import com.dfsek.terra.api.command.ExecutionState; +import com.dfsek.terra.api.command.annotation.Command; +import com.dfsek.terra.api.command.annotation.type.DebugCommand; +import com.dfsek.terra.api.command.annotation.type.PlayerCommand; +import com.dfsek.terra.api.command.annotation.type.WorldCommand; +import com.dfsek.terra.api.injection.annotations.Inject; +import com.dfsek.terra.api.platform.entity.Player; +import com.dfsek.terra.world.TerraWorld; + +@Command +@WorldCommand +@PlayerCommand +@DebugCommand +public class ProfileResetCommand implements CommandTemplate { + @Inject + private TerraPlugin main; + + @Override + public void execute(ExecutionState state) { + Player player = (Player) state.getSender(); + TerraWorld world = main.getWorld(player.getWorld()); + world.getProfiler().reset(); + state.getSender().sendMessage("Profiler reset."); + } +} diff --git a/common/src/main/java/com/dfsek/terra/commands/profiler/ProfileStartCommand.java b/common/src/main/java/com/dfsek/terra/commands/profiler/ProfileStartCommand.java new file mode 100644 index 000000000..bb42588a1 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/commands/profiler/ProfileStartCommand.java @@ -0,0 +1,29 @@ +package com.dfsek.terra.commands.profiler; + +import com.dfsek.terra.api.TerraPlugin; +import com.dfsek.terra.api.command.CommandTemplate; +import com.dfsek.terra.api.command.ExecutionState; +import com.dfsek.terra.api.command.annotation.Command; +import com.dfsek.terra.api.command.annotation.type.DebugCommand; +import com.dfsek.terra.api.command.annotation.type.PlayerCommand; +import com.dfsek.terra.api.command.annotation.type.WorldCommand; +import com.dfsek.terra.api.injection.annotations.Inject; +import com.dfsek.terra.api.platform.entity.Player; +import com.dfsek.terra.world.TerraWorld; + +@Command +@WorldCommand +@PlayerCommand +@DebugCommand +public class ProfileStartCommand implements CommandTemplate { + @Inject + private TerraPlugin main; + + @Override + public void execute(ExecutionState state) { + Player player = (Player) state.getSender(); + TerraWorld world = main.getWorld(player.getWorld()); + world.getProfiler().setProfiling(true); + state.getSender().sendMessage("Profiling enabled."); + } +} diff --git a/common/src/main/java/com/dfsek/terra/commands/profiler/ProfileStopCommand.java b/common/src/main/java/com/dfsek/terra/commands/profiler/ProfileStopCommand.java new file mode 100644 index 000000000..67b0537d4 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/commands/profiler/ProfileStopCommand.java @@ -0,0 +1,29 @@ +package com.dfsek.terra.commands.profiler; + +import com.dfsek.terra.api.TerraPlugin; +import com.dfsek.terra.api.command.CommandTemplate; +import com.dfsek.terra.api.command.ExecutionState; +import com.dfsek.terra.api.command.annotation.Command; +import com.dfsek.terra.api.command.annotation.type.DebugCommand; +import com.dfsek.terra.api.command.annotation.type.PlayerCommand; +import com.dfsek.terra.api.command.annotation.type.WorldCommand; +import com.dfsek.terra.api.injection.annotations.Inject; +import com.dfsek.terra.api.platform.entity.Player; +import com.dfsek.terra.world.TerraWorld; + +@Command +@WorldCommand +@PlayerCommand +@DebugCommand +public class ProfileStopCommand implements CommandTemplate { + @Inject + private TerraPlugin main; + + @Override + public void execute(ExecutionState state) { + Player player = (Player) state.getSender(); + TerraWorld world = main.getWorld(player.getWorld()); + world.getProfiler().setProfiling(false); + state.getSender().sendMessage("Profiling enabled."); + } +} diff --git a/common/src/test/java/command/CommandTest.java b/common/src/test/java/command/CommandTest.java index 1a7df8ccf..42a419c49 100644 --- a/common/src/test/java/command/CommandTest.java +++ b/common/src/test/java/command/CommandTest.java @@ -20,34 +20,34 @@ import static org.junit.jupiter.api.Assertions.fail; public class CommandTest { @Test public void subcommand() throws CommandException { - CommandManager manager = new TerraCommandManager(); + CommandManager manager = new TerraCommandManager(null); manager.register("test", DemoParentCommand.class); - manager.execute("test", Arrays.asList("subcommand1", "first", "2")); - manager.execute("test", Arrays.asList("subcommand2", "first", "2")); - manager.execute("test", Arrays.asList("s1", "first", "2", "3.4")); - manager.execute("test", Arrays.asList("s2", "first", "2")); - manager.execute("test", Arrays.asList("sub1", "first", "2", "3.4")); - manager.execute("test", Arrays.asList("sub2", "first", "2")); - manager.execute("test", Arrays.asList("first", "2")); // Parent command args + manager.execute("test", null, Arrays.asList("subcommand1", "first", "2")); + manager.execute("test", null, Arrays.asList("subcommand2", "first", "2")); + manager.execute("test", null, Arrays.asList("s1", "first", "2", "3.4")); + manager.execute("test", null, Arrays.asList("s2", "first", "2")); + manager.execute("test", null, Arrays.asList("sub1", "first", "2", "3.4")); + manager.execute("test", null, Arrays.asList("sub2", "first", "2")); + manager.execute("test", null, Arrays.asList("first", "2")); // Parent command args } @Test public void args() throws CommandException { - CommandManager manager = new TerraCommandManager(); + CommandManager manager = new TerraCommandManager(null); manager.register("test", DemoCommand.class); - manager.execute("test", Arrays.asList("first", "2")); - manager.execute("test", Arrays.asList("first", "2", "3.4")); + manager.execute("test", null, Arrays.asList("first", "2")); + manager.execute("test", null, Arrays.asList("first", "2", "3.4")); } @Test public void argsBeforeFlags() throws CommandException { - CommandManager manager = new TerraCommandManager(); + CommandManager manager = new TerraCommandManager(null); manager.register("test", DemoCommand.class); try { - manager.execute("test", Arrays.asList("first", "-flag", "2")); + manager.execute("test", null, Arrays.asList("first", "-flag", "2")); fail(); } catch(InvalidArgumentsException ignore) { } @@ -55,11 +55,11 @@ public class CommandTest { @Test public void requiredArgsFirst() throws CommandException { - CommandManager manager = new TerraCommandManager(); + CommandManager manager = new TerraCommandManager(null); manager.register("test", DemoInvalidCommand.class); try { - manager.execute("test", Arrays.asList("first", "2")); + manager.execute("test", null, Arrays.asList("first", "2")); fail(); } catch(MalformedCommandException ignore) { } @@ -67,20 +67,20 @@ public class CommandTest { @Test public void switches() throws CommandException { - CommandManager manager = new TerraCommandManager(); + CommandManager manager = new TerraCommandManager(null); manager.register("test", DemoSwitchCommand.class); - manager.execute("test", Arrays.asList("first", "2")); - manager.execute("test", Arrays.asList("first", "2", "3.4")); + manager.execute("test", null, Arrays.asList("first", "2")); + manager.execute("test", null, Arrays.asList("first", "2", "3.4")); - manager.execute("test", Arrays.asList("first", "2", "-a")); - manager.execute("test", Arrays.asList("first", "2", "3.4", "-b")); + manager.execute("test", null, Arrays.asList("first", "2", "-a")); + manager.execute("test", null, Arrays.asList("first", "2", "3.4", "-b")); - manager.execute("test", Arrays.asList("first", "2", "-aSwitch")); - manager.execute("test", Arrays.asList("first", "2", "3.4", "-bSwitch")); + manager.execute("test", null, Arrays.asList("first", "2", "-aSwitch")); + manager.execute("test", null, Arrays.asList("first", "2", "3.4", "-bSwitch")); - manager.execute("test", Arrays.asList("first", "2", "-aSwitch", "-b")); - manager.execute("test", Arrays.asList("first", "2", "3.4", "-bSwitch", "-a")); + manager.execute("test", null, Arrays.asList("first", "2", "-aSwitch", "-b")); + manager.execute("test", null, Arrays.asList("first", "2", "3.4", "-bSwitch", "-a")); } @Command( @@ -88,7 +88,8 @@ public class CommandTest { @Argument(value = "arg0"), @Argument(value = "arg1", type = int.class), @Argument(value = "arg2", type = double.class, required = false) - }) + } + ) public static final class DemoCommand implements CommandTemplate { @Override @@ -136,7 +137,8 @@ public class CommandTest { @Argument(value = "arg0"), @Argument(value = "arg2", type = double.class, required = false), // optional arguments must be last. this command is invalid. @Argument(value = "arg1", type = int.class) - }) + } + ) public static final class DemoInvalidCommand implements CommandTemplate { @Override @@ -162,7 +164,8 @@ public class CommandTest { aliases = {"s2", "sub2"}, clazz = DemoChildCommand.class // Duplicate command intentional. ) - }) + } + ) public static final class DemoParentCommand implements CommandTemplate { @Override @@ -183,7 +186,8 @@ public class CommandTest { @Argument(value = "arg0"), @Argument(value = "arg1", type = int.class), @Argument(value = "arg2", type = double.class, required = false), - }) + } + ) public static final class DemoChildCommand implements CommandTemplate { @Override public void execute(ExecutionState state) { diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/BukkitEntity.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/BukkitEntity.java index 8d70cfa10..bb20cda6f 100644 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/BukkitEntity.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/BukkitEntity.java @@ -2,6 +2,7 @@ package com.dfsek.terra.bukkit; import com.dfsek.terra.api.math.vector.Location; import com.dfsek.terra.api.platform.entity.Entity; +import com.dfsek.terra.api.platform.world.World; import com.dfsek.terra.bukkit.world.BukkitAdapter; public class BukkitEntity implements Entity { @@ -21,6 +22,11 @@ public class BukkitEntity implements Entity { return BukkitAdapter.adapt(entity.getLocation()); } + @Override + public World getWorld() { + return BukkitAdapter.adapt(entity.getWorld()); + } + @Override public void sendMessage(String message) { entity.sendMessage(message); diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/BukkitPlayer.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/BukkitPlayer.java index 162e41131..fbf763e6b 100644 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/BukkitPlayer.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/BukkitPlayer.java @@ -2,6 +2,7 @@ package com.dfsek.terra.bukkit; import com.dfsek.terra.api.math.vector.Location; import com.dfsek.terra.api.platform.entity.Player; +import com.dfsek.terra.api.platform.world.World; import com.dfsek.terra.bukkit.world.BukkitAdapter; public class BukkitPlayer implements Player { @@ -22,6 +23,11 @@ public class BukkitPlayer implements Player { return new Location(BukkitAdapter.adapt(bukkit.getWorld()), bukkit.getX(), bukkit.getY(), bukkit.getZ()); } + @Override + public World getWorld() { + return BukkitAdapter.adapt(delegate.getWorld()); + } + @Override public void sendMessage(String message) { delegate.sendMessage(message); diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/TerraBukkitPlugin.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/TerraBukkitPlugin.java index eec52f7fb..87fd760d5 100644 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/TerraBukkitPlugin.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/TerraBukkitPlugin.java @@ -6,6 +6,8 @@ import com.dfsek.terra.api.addons.TerraAddon; import com.dfsek.terra.api.addons.annotations.Addon; import com.dfsek.terra.api.addons.annotations.Author; import com.dfsek.terra.api.addons.annotations.Version; +import com.dfsek.terra.api.command.CommandManager; +import com.dfsek.terra.api.command.TerraCommandManager; import com.dfsek.terra.api.event.EventManager; import com.dfsek.terra.api.event.TerraEventManager; import com.dfsek.terra.api.platform.block.BlockData; @@ -19,8 +21,7 @@ import com.dfsek.terra.api.util.logging.DebugLogger; import com.dfsek.terra.api.util.logging.JavaLogger; import com.dfsek.terra.api.util.logging.Logger; import com.dfsek.terra.api.world.generation.TerraChunkGenerator; -import com.dfsek.terra.bukkit.command.command.TerraCommand; -import com.dfsek.terra.bukkit.command.command.structure.LocateCommand; +import com.dfsek.terra.bukkit.command.BukkitCommandAdapter; import com.dfsek.terra.bukkit.generator.BukkitChunkGeneratorWrapper; import com.dfsek.terra.bukkit.handles.BukkitItemHandle; import com.dfsek.terra.bukkit.handles.BukkitWorldHandle; @@ -30,6 +31,7 @@ import com.dfsek.terra.bukkit.listeners.SpigotListener; import com.dfsek.terra.bukkit.listeners.TerraListener; import com.dfsek.terra.bukkit.util.PaperUtil; import com.dfsek.terra.bukkit.world.BukkitBiome; +import com.dfsek.terra.commands.profiler.ProfileCommand; import com.dfsek.terra.config.GenericLoaders; import com.dfsek.terra.config.PluginConfig; import com.dfsek.terra.config.lang.LangUtil; @@ -163,14 +165,16 @@ public class TerraBukkitPlugin extends JavaPlugin implements TerraPlugin { registry.loadAll(this); // Load all config packs. PluginCommand c = Objects.requireNonNull(getCommand("terra")); - TerraCommand command = new TerraCommand(this); // Set up main Terra command. - c.setExecutor(command); - c.setTabCompleter(command); + //TerraCommand command = new TerraCommand(this); // Set up main Terra command. - LocateCommand locate = new LocateCommand(command); - PluginCommand locatePl = Objects.requireNonNull(getCommand("locate")); - locatePl.setExecutor(locate); // Override locate command. Once Paper accepts StructureLocateEvent this will be unneeded on Paper implementations. - locatePl.setTabCompleter(locate); + CommandManager manager = new TerraCommandManager(this); + + manager.register("profile", ProfileCommand.class); + + BukkitCommandAdapter command = new BukkitCommandAdapter(manager); + + c.setExecutor(command); + //c.setTabCompleter(command); long save = config.getDataSaveInterval(); diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/BukkitCommandAdapter.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/BukkitCommandAdapter.java new file mode 100644 index 000000000..0d1bb052c --- /dev/null +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/BukkitCommandAdapter.java @@ -0,0 +1,36 @@ +package com.dfsek.terra.bukkit.command; + +import com.dfsek.terra.api.command.CommandManager; +import com.dfsek.terra.api.command.exception.CommandException; +import com.dfsek.terra.bukkit.world.BukkitAdapter; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class BukkitCommandAdapter implements CommandExecutor { + private final CommandManager manager; + + public BukkitCommandAdapter(CommandManager manager) { + this.manager = manager; + } + + @Override + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { + List argList = new ArrayList<>(Arrays.asList(args)); + if(argList.isEmpty()) { + sender.sendMessage("Command requires arguments."); + return true; + } + try { + manager.execute(argList.remove(0), BukkitAdapter.adapt(sender), argList); + } catch(CommandException e) { + sender.sendMessage(e.getMessage()); + } + return true; + } +} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/BukkitAdapter.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/BukkitAdapter.java index cd3e61b1d..c50cd2711 100644 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/BukkitAdapter.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/BukkitAdapter.java @@ -19,6 +19,7 @@ import com.dfsek.terra.api.platform.world.World; import com.dfsek.terra.api.transform.MapTransform; import com.dfsek.terra.api.transform.Transformer; import com.dfsek.terra.bukkit.BukkitCommandSender; +import com.dfsek.terra.bukkit.BukkitEntity; import com.dfsek.terra.bukkit.BukkitPlayer; import com.dfsek.terra.bukkit.world.block.BukkitBlockTypeAndItem; import com.dfsek.terra.bukkit.world.block.data.BukkitBlockData; @@ -27,6 +28,7 @@ import com.dfsek.terra.bukkit.world.inventory.meta.BukkitEnchantment; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.TreeType; +import org.bukkit.entity.Entity; import org.bukkit.entity.Player; import org.bukkit.util.Vector; @@ -351,6 +353,8 @@ public final class BukkitAdapter { } public static CommandSender adapt(org.bukkit.command.CommandSender sender) { + if(sender instanceof Player) return new BukkitPlayer((Player) sender); + if(sender instanceof Entity) return new BukkitEntity((Entity) sender); return new BukkitCommandSender(sender); } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/entity/FabricEntity.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/entity/FabricEntity.java index fd7da3d05..f19d6d820 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/entity/FabricEntity.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/entity/FabricEntity.java @@ -2,6 +2,7 @@ package com.dfsek.terra.fabric.world.entity; import com.dfsek.terra.api.math.vector.Location; import com.dfsek.terra.api.platform.entity.Entity; +import com.dfsek.terra.api.platform.world.World; import com.dfsek.terra.fabric.world.FabricAdapter; import com.dfsek.terra.fabric.world.handles.world.FabricWorldAccess; @@ -26,4 +27,9 @@ public class FabricEntity implements Entity { public Location getLocation() { return new Location(new FabricWorldAccess(delegate.world), FabricAdapter.adapt(delegate.getBlockPos())); } + + @Override + public World getWorld() { + return new FabricWorldAccess(delegate.world); + } }