diff --git a/gameserver/src/main/java/brainwine/gameserver/command/Command.java b/gameserver/src/main/java/brainwine/gameserver/command/Command.java index d6a0087..119c96a 100644 --- a/gameserver/src/main/java/brainwine/gameserver/command/Command.java +++ b/gameserver/src/main/java/brainwine/gameserver/command/Command.java @@ -4,6 +4,20 @@ public abstract class Command { public abstract void execute(CommandExecutor executor, String[] args); + public abstract String getName(); + + public String[] getAliases() { + return null; + } + + public String getDescription() { + return "No description for this command"; + } + + public String getUsage() { + return "/" + getName(); + } + public boolean requiresAdmin() { return false; } diff --git a/gameserver/src/main/java/brainwine/gameserver/command/CommandManager.java b/gameserver/src/main/java/brainwine/gameserver/command/CommandManager.java index 679b730..6cb7b9c 100644 --- a/gameserver/src/main/java/brainwine/gameserver/command/CommandManager.java +++ b/gameserver/src/main/java/brainwine/gameserver/command/CommandManager.java @@ -1,6 +1,8 @@ package brainwine.gameserver.command; +import java.util.Collection; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; import java.util.Set; @@ -8,6 +10,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import brainwine.gameserver.command.commands.BroadcastCommand; +import brainwine.gameserver.command.commands.HelpCommand; import brainwine.gameserver.command.commands.KickCommand; import brainwine.gameserver.command.commands.PlayerIdCommand; import brainwine.gameserver.command.commands.RegisterCommand; @@ -20,8 +23,10 @@ import brainwine.gameserver.entity.player.Player; public class CommandManager { + public static final String CUSTOM_COMMAND_PREFIX = "!"; // TODO configurable private static final Logger logger = LogManager.getLogger(); private static final Map commands = new HashMap<>(); + private static final Map aliases = new HashMap<>(); private static boolean initialized = false; public static void init() { @@ -36,15 +41,16 @@ public class CommandManager { private static void registerCommands() { logger.info("Registering commands ..."); - registerCommand("stop", new StopCommand()); - registerCommand("register", new RegisterCommand()); - registerCommand("tp", new TeleportCommand()); - registerCommand("kick", new KickCommand()); - registerCommand("say", new SayCommand()); - registerCommand("think", new ThinkCommand()); - registerCommand("bc", new BroadcastCommand()); - registerCommand("pid", new PlayerIdCommand()); - registerCommand("zid", new ZoneIdCommand()); + registerCommand(new StopCommand()); + registerCommand(new RegisterCommand()); + registerCommand(new TeleportCommand()); + registerCommand(new KickCommand()); + registerCommand(new SayCommand()); + registerCommand(new ThinkCommand()); + registerCommand(new BroadcastCommand()); + registerCommand(new PlayerIdCommand()); + registerCommand(new ZoneIdCommand()); + registerCommand(new HelpCommand()); } public static void executeCommand(CommandExecutor executor, String commandLine) { @@ -65,10 +71,14 @@ public class CommandManager { } public static void executeCommand(CommandExecutor executor, String commandName, String[] args) { - Command command = commands.get(commandName); + if(!(executor instanceof Player) && commandName.startsWith(CUSTOM_COMMAND_PREFIX) || commandName.startsWith("/")) { + commandName = commandName.substring(1); + } + + Command command = commands.getOrDefault(commandName, aliases.get(commandName)); if(command == null) { - executor.sendMessage("Sorry, that command does not exist."); + executor.sendMessage("Unknown command. Type '/help' for a list of commands."); return; } @@ -82,16 +92,37 @@ public class CommandManager { command.execute(executor, args); } - public static void registerCommand(String name, Command command) { + public static void registerCommand(Command command) { + String name = command.getName(); + if(commands.containsKey(name)) { logger.warn("Attempted to register duplicate command {} with name {}", command.getClass(), name); return; } commands.put(name, command); + String[] aliases = command.getAliases(); + + if(aliases != null) { + for(String alias : aliases) { + if(commands.containsKey(alias) || CommandManager.aliases.containsKey(alias)) { + logger.warn("Duplicate alias {} for command {}", alias, command.getClass()); + continue; + } + + CommandManager.aliases.put(alias, command); + } + } } public static Set getCommandNames() { - return commands.keySet(); + Set names = new HashSet<>(); + names.addAll(commands.keySet()); + names.addAll(aliases.keySet()); + return names; + } + + public static Collection getCommands() { + return commands.values(); } } diff --git a/gameserver/src/main/java/brainwine/gameserver/command/commands/BroadcastCommand.java b/gameserver/src/main/java/brainwine/gameserver/command/commands/BroadcastCommand.java index ed124a3..4848d00 100644 --- a/gameserver/src/main/java/brainwine/gameserver/command/commands/BroadcastCommand.java +++ b/gameserver/src/main/java/brainwine/gameserver/command/commands/BroadcastCommand.java @@ -10,7 +10,7 @@ public class BroadcastCommand extends Command { @Override public void execute(CommandExecutor executor, String[] args) { if(args.length == 0) { - executor.sendMessage("Usage: /broadcast "); + executor.sendMessage(String.format("Usage: %s", getUsage())); return; } @@ -22,10 +22,30 @@ public class BroadcastCommand extends Command { } for(Player player : GameServer.getInstance().getPlayerManager().getPlayers()) { - player.notify(text, 9); + player.notify(text, 11); } } + @Override + public String getName() { + return "broadcast"; + } + + @Override + public String[] getAliases() { + return new String[] { "bc" }; + } + + @Override + public String getDescription() { + return "Broadcasts a message to the entire server."; + } + + @Override + public String getUsage() { + return "/broadcast "; + } + @Override public boolean requiresAdmin() { return true; diff --git a/gameserver/src/main/java/brainwine/gameserver/command/commands/HelpCommand.java b/gameserver/src/main/java/brainwine/gameserver/command/commands/HelpCommand.java new file mode 100644 index 0000000..a87feee --- /dev/null +++ b/gameserver/src/main/java/brainwine/gameserver/command/commands/HelpCommand.java @@ -0,0 +1,44 @@ +package brainwine.gameserver.command.commands; + +import java.util.Collection; + +import brainwine.gameserver.command.Command; +import brainwine.gameserver.command.CommandExecutor; +import brainwine.gameserver.command.CommandManager; +import brainwine.gameserver.entity.player.Player; + +public class HelpCommand extends Command { + + @Override + public void execute(CommandExecutor executor, String[] args) { + boolean admin = true; + + if(executor instanceof Player) { + admin = ((Player)executor).isAdmin(); + } + + Collection commands = CommandManager.getCommands(); + executor.sendMessage("Command List"); + + for(Command command : commands) { + if(!command.requiresAdmin() || admin) { + executor.sendMessage(String.format("%s - %s", command.getUsage(), command.getDescription())); + } + } + } + + @Override + public String getName() { + return "help"; + } + + @Override + public String[] getAliases() { + return new String[] { "commands" }; + } + + @Override + public String getDescription() { + return "Displays a list of commands."; + } +} diff --git a/gameserver/src/main/java/brainwine/gameserver/command/commands/KickCommand.java b/gameserver/src/main/java/brainwine/gameserver/command/commands/KickCommand.java index 6b9c239..9aebccd 100644 --- a/gameserver/src/main/java/brainwine/gameserver/command/commands/KickCommand.java +++ b/gameserver/src/main/java/brainwine/gameserver/command/commands/KickCommand.java @@ -12,7 +12,7 @@ public class KickCommand extends Command { @Override public void execute(CommandExecutor executor, String[] args) { if(args.length < 1) { - executor.sendMessage("Usage: /kick [reason]"); + executor.sendMessage(String.format("Usage: %s", getUsage())); return; } @@ -36,6 +36,21 @@ public class KickCommand extends Command { executor.sendMessage("Kicked player " + player.getName() + " for '" + reason + "'"); } + @Override + public String getName() { + return "kick"; + } + + @Override + public String getDescription() { + return "Kicks a player from the server."; + } + + @Override + public String getUsage() { + return "/kick [reason]"; + } + @Override public boolean requiresAdmin() { return true; diff --git a/gameserver/src/main/java/brainwine/gameserver/command/commands/PlayerIdCommand.java b/gameserver/src/main/java/brainwine/gameserver/command/commands/PlayerIdCommand.java index c045d72..7b36dce 100644 --- a/gameserver/src/main/java/brainwine/gameserver/command/commands/PlayerIdCommand.java +++ b/gameserver/src/main/java/brainwine/gameserver/command/commands/PlayerIdCommand.java @@ -32,6 +32,21 @@ public class PlayerIdCommand extends Command { executor.sendMessage(target.getDocumentId()); } + @Override + public String getName() { + return "pid"; + } + + @Override + public String getDescription() { + return "Displays the document id of a player."; + } + + @Override + public String getUsage() { + return "/pid [player]"; + } + @Override public boolean requiresAdmin() { return true; diff --git a/gameserver/src/main/java/brainwine/gameserver/command/commands/RegisterCommand.java b/gameserver/src/main/java/brainwine/gameserver/command/commands/RegisterCommand.java index 5c4e714..7a49535 100644 --- a/gameserver/src/main/java/brainwine/gameserver/command/commands/RegisterCommand.java +++ b/gameserver/src/main/java/brainwine/gameserver/command/commands/RegisterCommand.java @@ -23,4 +23,14 @@ public class RegisterCommand extends Command{ player.showDialog(new RegistrationDialog()); } + + @Override + public String getName() { + return "register"; + } + + @Override + public String getDescription() { + return "Shows a prompt with which you can register your account."; + } } diff --git a/gameserver/src/main/java/brainwine/gameserver/command/commands/SayCommand.java b/gameserver/src/main/java/brainwine/gameserver/command/commands/SayCommand.java index fd0b81d..ef243e0 100644 --- a/gameserver/src/main/java/brainwine/gameserver/command/commands/SayCommand.java +++ b/gameserver/src/main/java/brainwine/gameserver/command/commands/SayCommand.java @@ -15,7 +15,7 @@ public class SayCommand extends Command { } if(args.length == 0) { - executor.sendMessage("Usage: /say "); + executor.sendMessage(String.format("Usage: %s", getUsage())); return; } @@ -23,4 +23,19 @@ public class SayCommand extends Command { Player player = ((Player)executor); player.getZone().chat(player, text, ChatType.SPEECH); } + + @Override + public String getName() { + return "say"; + } + + @Override + public String getDescription() { + return "Shows a speech bubble to nearby players."; + } + + @Override + public String getUsage() { + return "/say "; + } } diff --git a/gameserver/src/main/java/brainwine/gameserver/command/commands/StopCommand.java b/gameserver/src/main/java/brainwine/gameserver/command/commands/StopCommand.java index 4c137b6..92e894f 100644 --- a/gameserver/src/main/java/brainwine/gameserver/command/commands/StopCommand.java +++ b/gameserver/src/main/java/brainwine/gameserver/command/commands/StopCommand.java @@ -11,6 +11,21 @@ public class StopCommand extends Command { GameServer.getInstance().shutdown(); // YEET!! } + @Override + public String getName() { + return "stop"; + } + + @Override + public String[] getAliases() { + return new String[] { "exit", "close", "shutdown" }; + } + + @Override + public String getDescription() { + return "Gracefully shuts down the server after the current tick."; + } + @Override public boolean requiresAdmin() { return true; diff --git a/gameserver/src/main/java/brainwine/gameserver/command/commands/TeleportCommand.java b/gameserver/src/main/java/brainwine/gameserver/command/commands/TeleportCommand.java index 9a7def7..00060b3 100644 --- a/gameserver/src/main/java/brainwine/gameserver/command/commands/TeleportCommand.java +++ b/gameserver/src/main/java/brainwine/gameserver/command/commands/TeleportCommand.java @@ -14,7 +14,7 @@ public class TeleportCommand extends Command { } if(args.length != 2) { - executor.sendMessage("Usage: /teleport "); + executor.sendMessage(String.format("Usage: %s", getUsage())); return; } @@ -37,4 +37,24 @@ public class TeleportCommand extends Command { player.teleport(x, y); } + + @Override + public String getName() { + return "teleport"; + } + + @Override + public String[] getAliases() { + return new String[] { "tp" }; + } + + @Override + public String getDescription() { + return "Teleports you to the specified position."; + } + + @Override + public String getUsage() { + return "/teleport "; + } } diff --git a/gameserver/src/main/java/brainwine/gameserver/command/commands/ThinkCommand.java b/gameserver/src/main/java/brainwine/gameserver/command/commands/ThinkCommand.java index d25cdbf..e719fa8 100644 --- a/gameserver/src/main/java/brainwine/gameserver/command/commands/ThinkCommand.java +++ b/gameserver/src/main/java/brainwine/gameserver/command/commands/ThinkCommand.java @@ -15,7 +15,7 @@ public class ThinkCommand extends Command { } if(args.length == 0) { - executor.sendMessage("Usage: /think "); + executor.sendMessage(String.format("Usage: %s", getUsage())); return; } @@ -23,4 +23,19 @@ public class ThinkCommand extends Command { Player player = ((Player)executor); player.getZone().chat(player, text, ChatType.THOUGHT); } + + @Override + public String getName() { + return "think"; + } + + @Override + public String getDescription() { + return "Shows a thought bubble to nearby players."; + } + + @Override + public String getUsage() { + return "/think "; + } } diff --git a/gameserver/src/main/java/brainwine/gameserver/command/commands/ZoneIdCommand.java b/gameserver/src/main/java/brainwine/gameserver/command/commands/ZoneIdCommand.java index e37078c..81ac09b 100644 --- a/gameserver/src/main/java/brainwine/gameserver/command/commands/ZoneIdCommand.java +++ b/gameserver/src/main/java/brainwine/gameserver/command/commands/ZoneIdCommand.java @@ -33,6 +33,21 @@ public class ZoneIdCommand extends Command { executor.sendMessage(target.getDocumentId()); } + @Override + public String getName() { + return "zid"; + } + + @Override + public String getDescription() { + return "Displays the document id of a zone."; + } + + @Override + public String getUsage() { + return "/zid [zone]"; + } + @Override public boolean requiresAdmin() { return true; diff --git a/gameserver/src/main/java/brainwine/gameserver/server/requests/ChatRequest.java b/gameserver/src/main/java/brainwine/gameserver/server/requests/ChatRequest.java index b5381cb..bcb2f13 100644 --- a/gameserver/src/main/java/brainwine/gameserver/server/requests/ChatRequest.java +++ b/gameserver/src/main/java/brainwine/gameserver/server/requests/ChatRequest.java @@ -11,8 +11,7 @@ public class ChatRequest extends PlayerRequest { @Override public void process(Player player) { - // TODO configurable prefix - if(text.startsWith("!")) { + if(text.startsWith(CommandManager.CUSTOM_COMMAND_PREFIX)) { CommandManager.executeCommand(player, text.substring(1)); return; }