diff --git a/proxy/src/main/java/net/md_5/bungee/ChatColor.java b/api/src/main/java/net/md_5/bungee/api/ChatColor.java similarity index 99% rename from proxy/src/main/java/net/md_5/bungee/ChatColor.java rename to api/src/main/java/net/md_5/bungee/api/ChatColor.java index ca157672..a72c01d1 100644 --- a/proxy/src/main/java/net/md_5/bungee/ChatColor.java +++ b/api/src/main/java/net/md_5/bungee/api/ChatColor.java @@ -1,4 +1,4 @@ -package net.md_5.bungee; +package net.md_5.bungee.api; import java.util.regex.Pattern; diff --git a/api/src/main/java/net/md_5/bungee/api/plugin/Command.java b/api/src/main/java/net/md_5/bungee/api/plugin/Command.java new file mode 100644 index 00000000..d89a910d --- /dev/null +++ b/api/src/main/java/net/md_5/bungee/api/plugin/Command.java @@ -0,0 +1,42 @@ +package net.md_5.bungee.api.plugin; + +import lombok.AccessLevel; +import lombok.Data; +import lombok.RequiredArgsConstructor; +import net.md_5.bungee.api.CommandSender; + +/** + * A command that can be executed by a {@link CommandSender}. + */ +@Data +@RequiredArgsConstructor(access = AccessLevel.NONE) +public abstract class Command +{ + + private final String name; + private final String permission; + private final String[] aliases; + + /** + * Construct a new command. + * + * @param name primary name of this command + * @param permission the permission node required to execute this command, + * null or empty string allows it to be executed by everyone + * @param aliases aliases which map back to this command + */ + public Command(String name, String permission, String... aliases) + { + this.name = name; + this.permission = permission; + this.aliases = aliases; + } + + /** + * Execute this command with the specified sender and arguments. + * + * @param sender the executor of this command + * @param args arguments used to invoke this command + */ + public abstract void execute(CommandSender sender, String[] args); +} diff --git a/api/src/main/java/net/md_5/bungee/api/plugin/PluginManager.java b/api/src/main/java/net/md_5/bungee/api/plugin/PluginManager.java index 8974c0a2..89ec5aa0 100644 --- a/api/src/main/java/net/md_5/bungee/api/plugin/PluginManager.java +++ b/api/src/main/java/net/md_5/bungee/api/plugin/PluginManager.java @@ -7,12 +7,16 @@ import java.io.File; import java.io.InputStream; import java.net.URL; import java.net.URLClassLoader; +import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.logging.Level; +import java.util.regex.Pattern; +import net.md_5.bungee.api.ChatColor; +import net.md_5.bungee.api.CommandSender; import net.md_5.bungee.api.ProxyServer; import org.yaml.snakeyaml.Yaml; @@ -23,9 +27,72 @@ import org.yaml.snakeyaml.Yaml; public class PluginManager { + private static final Pattern argsSplit = Pattern.compile(" "); + /*========================================================================*/ private final Yaml yaml = new Yaml(); private final EventBus eventBus = new EventBus(); private final Map plugins = new HashMap<>(); + private final Map commandMap = new HashMap<>(); + + /** + * Register a command so that it may be executed. + * + * @param command the command to register + */ + public void registerCommand(Command command) + { + commandMap.put(command.getName(), command); + for (String alias : command.getAliases()) + { + commandMap.put(alias, command); + } + } + + /** + * Unregister a command so it will no longer be executed. + * + * @param command the command to unregister + */ + public void unregisterCommand(Command command) + { + commandMap.values().remove(command); + } + + /** + * Execute a command if it is registered, else return false. + * + * @param sender the sender executing the command + * @param commandLine the complete command line including command name and + * arguments + * @return whether the command was handled + */ + public boolean dispatchCommand(CommandSender sender, String commandLine) + { + String[] split = argsSplit.split(commandLine); + Command command = commandMap.get(split[0]); + if (command == null) + { + return false; + } + + String permission = command.getPermission(); + if (permission != null && !permission.isEmpty() && !sender.hasPermission(permission)) + { + sender.sendMessage(ChatColor.RED + "You do not have permission to execute this command!"); + return true; + } + + String[] args = Arrays.copyOfRange(split, 1, split.length); + try + { + command.execute(sender, args); + } catch (Exception ex) + { + sender.sendMessage(ChatColor.RED + "An internal error occurred whilst executing this command, please check the console log for details."); + ProxyServer.getInstance().getLogger().log(Level.WARNING, "Error in dispatching command", ex); + } + return true; + } /** * Returns the {@link Plugin} objects corresponding to all loaded plugins. diff --git a/proxy/src/main/java/net/md_5/bungee/BungeeCord.java b/proxy/src/main/java/net/md_5/bungee/BungeeCord.java index b25ef180..c8d9fdf2 100644 --- a/proxy/src/main/java/net/md_5/bungee/BungeeCord.java +++ b/proxy/src/main/java/net/md_5/bungee/BungeeCord.java @@ -16,6 +16,7 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.logging.Level; import static net.md_5.bungee.Logger.$; +import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.command.*; import net.md_5.bungee.packet.DefinedPacket; import net.md_5.bungee.packet.PacketFAPluginMessage; diff --git a/proxy/src/main/java/net/md_5/bungee/Configuration.java b/proxy/src/main/java/net/md_5/bungee/Configuration.java index 23ec2af3..01b507b0 100644 --- a/proxy/src/main/java/net/md_5/bungee/Configuration.java +++ b/proxy/src/main/java/net/md_5/bungee/Configuration.java @@ -15,6 +15,7 @@ import java.util.List; import java.util.Map; import java.util.UUID; import static net.md_5.bungee.Logger.$; +import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.command.CommandSender; import net.md_5.bungee.command.ConsoleCommandSender; import org.yaml.snakeyaml.DumperOptions; diff --git a/proxy/src/main/java/net/md_5/bungee/InitialHandler.java b/proxy/src/main/java/net/md_5/bungee/InitialHandler.java index 28872d34..b2fe6660 100644 --- a/proxy/src/main/java/net/md_5/bungee/InitialHandler.java +++ b/proxy/src/main/java/net/md_5/bungee/InitialHandler.java @@ -1,12 +1,12 @@ package net.md_5.bungee; -import java.io.BufferedOutputStream; import java.io.IOException; import java.io.OutputStream; import java.net.Socket; import java.util.ArrayList; import java.util.List; import javax.crypto.SecretKey; +import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.packet.Packet2Handshake; import net.md_5.bungee.packet.PacketFCEncryptionResponse; import net.md_5.bungee.packet.PacketFDEncryptionRequest; diff --git a/proxy/src/main/java/net/md_5/bungee/command/CommandAlert.java b/proxy/src/main/java/net/md_5/bungee/command/CommandAlert.java index 270e89c1..f8d1c761 100644 --- a/proxy/src/main/java/net/md_5/bungee/command/CommandAlert.java +++ b/proxy/src/main/java/net/md_5/bungee/command/CommandAlert.java @@ -1,9 +1,9 @@ package net.md_5.bungee.command; import net.md_5.bungee.BungeeCord; -import net.md_5.bungee.ChatColor; import net.md_5.bungee.Permission; import net.md_5.bungee.UserConnection; +import net.md_5.bungee.api.ChatColor; public class CommandAlert extends Command { diff --git a/proxy/src/main/java/net/md_5/bungee/command/CommandBungee.java b/proxy/src/main/java/net/md_5/bungee/command/CommandBungee.java index 8ea902df..7e34debb 100644 --- a/proxy/src/main/java/net/md_5/bungee/command/CommandBungee.java +++ b/proxy/src/main/java/net/md_5/bungee/command/CommandBungee.java @@ -1,7 +1,7 @@ package net.md_5.bungee.command; import net.md_5.bungee.BungeeCord; -import net.md_5.bungee.ChatColor; +import net.md_5.bungee.api.ChatColor; public class CommandBungee extends Command { diff --git a/proxy/src/main/java/net/md_5/bungee/command/CommandEnd.java b/proxy/src/main/java/net/md_5/bungee/command/CommandEnd.java index 3750dfd1..570d308c 100644 --- a/proxy/src/main/java/net/md_5/bungee/command/CommandEnd.java +++ b/proxy/src/main/java/net/md_5/bungee/command/CommandEnd.java @@ -1,8 +1,8 @@ package net.md_5.bungee.command; import net.md_5.bungee.BungeeCord; -import net.md_5.bungee.ChatColor; import net.md_5.bungee.Permission; +import net.md_5.bungee.api.ChatColor; /** * Command to terminate the proxy instance. May only be used by the console. diff --git a/proxy/src/main/java/net/md_5/bungee/command/CommandIP.java b/proxy/src/main/java/net/md_5/bungee/command/CommandIP.java index d1b75f4b..755f7b6c 100644 --- a/proxy/src/main/java/net/md_5/bungee/command/CommandIP.java +++ b/proxy/src/main/java/net/md_5/bungee/command/CommandIP.java @@ -1,9 +1,9 @@ package net.md_5.bungee.command; import net.md_5.bungee.BungeeCord; -import net.md_5.bungee.ChatColor; import net.md_5.bungee.Permission; import net.md_5.bungee.UserConnection; +import net.md_5.bungee.api.ChatColor; public class CommandIP extends Command { diff --git a/proxy/src/main/java/net/md_5/bungee/command/CommandList.java b/proxy/src/main/java/net/md_5/bungee/command/CommandList.java index 42584a4d..988106dd 100644 --- a/proxy/src/main/java/net/md_5/bungee/command/CommandList.java +++ b/proxy/src/main/java/net/md_5/bungee/command/CommandList.java @@ -2,8 +2,8 @@ package net.md_5.bungee.command; import java.util.Collection; import net.md_5.bungee.BungeeCord; -import net.md_5.bungee.ChatColor; import net.md_5.bungee.UserConnection; +import net.md_5.bungee.api.ChatColor; /** * Command to list all players connected to the proxy. diff --git a/proxy/src/main/java/net/md_5/bungee/command/CommandMotd.java b/proxy/src/main/java/net/md_5/bungee/command/CommandMotd.java index 3d26c066..3acab4c1 100644 --- a/proxy/src/main/java/net/md_5/bungee/command/CommandMotd.java +++ b/proxy/src/main/java/net/md_5/bungee/command/CommandMotd.java @@ -1,8 +1,8 @@ package net.md_5.bungee.command; import net.md_5.bungee.BungeeCord; -import net.md_5.bungee.ChatColor; import net.md_5.bungee.Permission; +import net.md_5.bungee.api.ChatColor; /** * Command to set a temp copy of the motd in real-time without stopping the diff --git a/proxy/src/main/java/net/md_5/bungee/command/CommandReload.java b/proxy/src/main/java/net/md_5/bungee/command/CommandReload.java index 18c922d0..337fdf1e 100644 --- a/proxy/src/main/java/net/md_5/bungee/command/CommandReload.java +++ b/proxy/src/main/java/net/md_5/bungee/command/CommandReload.java @@ -1,8 +1,8 @@ package net.md_5.bungee.command; import net.md_5.bungee.BungeeCord; -import net.md_5.bungee.ChatColor; import net.md_5.bungee.Permission; +import net.md_5.bungee.api.ChatColor; public class CommandReload extends Command { diff --git a/proxy/src/main/java/net/md_5/bungee/command/CommandServer.java b/proxy/src/main/java/net/md_5/bungee/command/CommandServer.java index a2956b56..f7bdce4d 100644 --- a/proxy/src/main/java/net/md_5/bungee/command/CommandServer.java +++ b/proxy/src/main/java/net/md_5/bungee/command/CommandServer.java @@ -2,8 +2,8 @@ package net.md_5.bungee.command; import java.util.Collection; import net.md_5.bungee.BungeeCord; -import net.md_5.bungee.ChatColor; import net.md_5.bungee.UserConnection; +import net.md_5.bungee.api.ChatColor; /** * Command to list and switch a player between available servers. diff --git a/proxy/src/main/java/net/md_5/bungee/command/ConsoleCommandSender.java b/proxy/src/main/java/net/md_5/bungee/command/ConsoleCommandSender.java index 79401a03..52d2216c 100644 --- a/proxy/src/main/java/net/md_5/bungee/command/ConsoleCommandSender.java +++ b/proxy/src/main/java/net/md_5/bungee/command/ConsoleCommandSender.java @@ -1,6 +1,6 @@ package net.md_5.bungee.command; -import net.md_5.bungee.ChatColor; +import net.md_5.bungee.api.ChatColor; /** * Command sender representing the proxy console.