diff --git a/bungee/acf-bungee.iml b/bungee/acf-bungee.iml new file mode 100644 index 00000000..892a370e --- /dev/null +++ b/bungee/acf-bungee.iml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/bungee/pom.xml b/bungee/pom.xml new file mode 100644 index 00000000..c6ef3c6f --- /dev/null +++ b/bungee/pom.xml @@ -0,0 +1,39 @@ + + + + acf-parent + co.aikar + 0.5.0-SNAPSHOT + + 4.0.0 + + acf-bungee + 0.5.0-SNAPSHOT + + ACF (Bungee) + + + + BungeeCord-repo + https://oss.sonatype.org/content/repositories/snapshots + + + + + + + co.aikar + acf-core + 0.5.0-SNAPSHOT + compile + + + net.md-5 + BungeeCord-api + 1.11-SNAPSHOT + + + + \ No newline at end of file diff --git a/bungee/src/main/java/co/aikar/commands/ACFBungeeUtil.java b/bungee/src/main/java/co/aikar/commands/ACFBungeeUtil.java new file mode 100644 index 00000000..55e8948b --- /dev/null +++ b/bungee/src/main/java/co/aikar/commands/ACFBungeeUtil.java @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package co.aikar.commands; + +import net.md_5.bungee.api.ChatColor; +import net.md_5.bungee.api.CommandSender; +import net.md_5.bungee.api.ProxyServer; +import net.md_5.bungee.api.connection.ProxiedPlayer; + +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Pattern; + +public class ACFBungeeUtil { + + public static String color(String message) { + return ChatColor.translateAlternateColorCodes('&', message); + } + + public static void sendMsg(CommandSender player, String message) { + message = color(message); + for (String msg : ACFPatterns.NEWLINE.split(message)) { + player.sendMessage(msg); + } + } + + public static String removeColors(String msg) { + return ChatColor.stripColor(color(msg)); + } + + public static String replaceChatString(String message, String replace, String with) { + return replaceChatString(message, Pattern.compile(Pattern.quote(replace), Pattern.CASE_INSENSITIVE), with); + } + + public static String replaceChatString(String message, Pattern replace, String with) { + final String[] split = replace.split(message + "1"); + + if (split.length < 2) { + return replace.matcher(message).replaceAll(with); + } + message = split[0]; + + for (int i = 1; i < split.length; i++) { + final String prev = getLastColors(message); + message += with + prev + split[i]; + } + return message.substring(0, message.length() - 1); + } + + //Imported from org.bukkit.ChatColor + + public static final char COLOR_CHAR = '\u00A7'; + + public static String getLastColors(String input) { + String result = ""; + int length = input.length(); + + // Search backwards from the end as it is faster + for (int index = length - 1; index > -1; index--) { + char section = input.charAt(index); + if (section == COLOR_CHAR && index < length - 1) { + char c = input.charAt(index + 1); + ChatColor color = ChatColor.getByChar(c); + + if (color != null) { + result = color.toString() + result; + + // Once we find a color or reset we can stop searching + if (isChatColorAColor(color) || color.equals(ChatColor.RESET)) { + break; + } + } + } + } + return result; + } + + public static boolean isChatColorAColor(ChatColor chatColor) { + return chatColor != ChatColor.MAGIC && chatColor != ChatColor.BOLD + && chatColor != ChatColor.STRIKETHROUGH && chatColor != ChatColor.UNDERLINE + && chatColor != ChatColor.ITALIC; + } + + + public static ProxiedPlayer findPlayerSmart(CommandSender requester, String origName) { + String name = ACFUtil.replace(origName, ":confirm", ""); + if (name.length() < 3) { + requester.sendMessage("§cUsername too short, must be at least three characters"); + return null; + } + if (!isValidName(name)) { + requester.sendMessage("§c'" + name + "' is not a valid username"); + return null; + } + + List matches = new ArrayList<>(ProxyServer.getInstance().matchPlayer(name)); + + if (matches.size() > 1) { + requester.sendMessage("§cMultiple players matched '" + name + "', please be more specific"); + return null; + } + + if (matches.isEmpty()) { + requester.sendMessage("§cNo player matching '" + name + "' is connected to this server"); + return null; + } + + return matches.get(0); + } + + public static boolean isValidName(String name) { + return name != null && !name.isEmpty() && ACFPatterns.VALID_NAME_PATTERN.matcher(name).matches(); + } + + public static T validate(T object, String message, Object... values) { + if (object == null) { + throw new NullPointerException(String.format(message, values)); + } + return object; + } + + +} diff --git a/bungee/src/main/java/co/aikar/commands/BungeeCommandCompletionContext.java b/bungee/src/main/java/co/aikar/commands/BungeeCommandCompletionContext.java new file mode 100644 index 00000000..02f8661c --- /dev/null +++ b/bungee/src/main/java/co/aikar/commands/BungeeCommandCompletionContext.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package co.aikar.commands; + +import net.md_5.bungee.api.CommandSender; + +public class BungeeCommandCompletionContext extends CommandCompletionContext { + + BungeeCommandCompletionContext(RegisteredCommand command, CommandIssuer issuer, String input, String config, String[] args) { + super(command, issuer, input, config, args); + } + + public CommandSender getSender() { + return this.getIssuer().getIssuer(); + } +} diff --git a/bungee/src/main/java/co/aikar/commands/BungeeCommandCompletions.java b/bungee/src/main/java/co/aikar/commands/BungeeCommandCompletions.java new file mode 100644 index 00000000..7a53196c --- /dev/null +++ b/bungee/src/main/java/co/aikar/commands/BungeeCommandCompletions.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package co.aikar.commands; + +import co.aikar.commands.apachecommonslang.ApacheCommonsLangUtil; +import net.md_5.bungee.api.ChatColor; +import net.md_5.bungee.api.CommandSender; +import net.md_5.bungee.api.ProxyServer; +import net.md_5.bungee.api.connection.ProxiedPlayer; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class BungeeCommandCompletions extends CommandCompletions { + + public BungeeCommandCompletions(CommandManager manager) { + super(manager); + registerCompletion("chatcolors", (sender, config, input, c) -> { + Stream colors = Stream.of(ChatColor.values()); + if (c.hasConfig("colorsonly")) { + colors = colors.filter(color -> color.ordinal() <= 0xF); + } + String filter = c.getConfig("filter"); + if (filter != null) { + Set filters = Arrays.stream(ACFPatterns.COLON.split(filter)) + .map(ACFUtil::simplifyString).collect(Collectors.toSet()); + + colors = colors.filter(color -> filters.contains(ACFUtil.simplifyString(color.name()))); + } + + return colors.map(color -> ACFUtil.simplifyString(color.name())).collect(Collectors.toList()); + }); + registerCompletion("players", (sender, config, input, c) -> { + ACFBungeeUtil.validate(sender, "Sender cannot be null"); + + ArrayList matchedPlayers = new ArrayList<>(); + for (ProxiedPlayer player : ProxyServer.getInstance().getPlayers()) { + String name = player.getName(); + if (ApacheCommonsLangUtil.startsWithIgnoreCase(name, input)) { + matchedPlayers.add(name); + } + } + + matchedPlayers.sort(String.CASE_INSENSITIVE_ORDER); + return matchedPlayers; + }); + } +} diff --git a/bungee/src/main/java/co/aikar/commands/BungeeCommandContexts.java b/bungee/src/main/java/co/aikar/commands/BungeeCommandContexts.java new file mode 100644 index 00000000..cb9a0924 --- /dev/null +++ b/bungee/src/main/java/co/aikar/commands/BungeeCommandContexts.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package co.aikar.commands; + + +import co.aikar.commands.annotation.Optional; +import co.aikar.commands.contexts.OnlineProxiedPlayer; +import net.md_5.bungee.api.ChatColor; +import net.md_5.bungee.api.CommandSender; +import net.md_5.bungee.api.connection.ProxiedPlayer; + +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class BungeeCommandContexts extends CommandContexts { + + BungeeCommandContexts(CommandManager manager) { + super(manager); + registerContext(OnlineProxiedPlayer.class, (c) -> { + final String playercheck = c.popFirstArg(); + ProxiedPlayer proxiedPlayer = ACFBungeeUtil.findPlayerSmart(c.getSender(), playercheck); + if (proxiedPlayer == null) { + if (c.hasAnnotation(Optional.class)) { + return null; + } + ACFBungeeUtil.sendMsg(c.getSender(), "§cCould not find a player by the name " + playercheck); + throw new InvalidCommandArgument(false); + } + return new OnlineProxiedPlayer(proxiedPlayer); + }); + registerSenderAwareContext(CommandSender.class, BungeeCommandExecutionContext::getSender); + registerSenderAwareContext(ProxiedPlayer.class, (c) -> { + ProxiedPlayer proxiedPlayer = c.getSender() instanceof ProxiedPlayer ? (ProxiedPlayer) c.getSender() : null; + if (proxiedPlayer == null && !c.hasAnnotation(Optional.class)) { + throw new InvalidCommandArgument("Requires a player to run this command", false); + } + return proxiedPlayer; + }); + registerContext(ChatColor.class, c -> { + String first = c.popFirstArg(); + Stream colors = Stream.of(ChatColor.values()); + if (c.hasFlag("colorsonly")) { + colors = colors.filter(color -> color.ordinal() <= 0xF); + } + String filter = c.getFlagValue("filter", (String) null); + if (filter != null) { + filter = ACFUtil.simplifyString(filter); + String finalFilter = filter; + colors = colors.filter(color -> finalFilter.equals(ACFUtil.simplifyString(color.name()))); + } + + ChatColor match = ACFUtil.simpleMatch(ChatColor.class, first); + if (match == null) { + String valid = colors + .map(color -> ChatColor.YELLOW + ACFUtil.simplifyString(color.name())) + .collect(Collectors.joining("&c, ")); + + throw new InvalidCommandArgument("Please specify one of: " + valid); + } + return match; + }); + } +} diff --git a/bungee/src/main/java/co/aikar/commands/BungeeCommandExecutionContext.java b/bungee/src/main/java/co/aikar/commands/BungeeCommandExecutionContext.java new file mode 100644 index 00000000..e8439177 --- /dev/null +++ b/bungee/src/main/java/co/aikar/commands/BungeeCommandExecutionContext.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package co.aikar.commands; + +import net.md_5.bungee.api.CommandSender; + +import java.lang.reflect.Parameter; +import java.util.List; +import java.util.Map; + +public class BungeeCommandExecutionContext extends CommandExecutionContext { + + BungeeCommandExecutionContext(RegisteredCommand cmd, Parameter param, CommandIssuer sender, List args, int index, Map passedArgs) { + super(cmd, param, sender, args, index, passedArgs); + } + + public CommandSender getSender() { + return this.issuer.getIssuer(); + } +} diff --git a/bungee/src/main/java/co/aikar/commands/BungeeCommandIssuer.java b/bungee/src/main/java/co/aikar/commands/BungeeCommandIssuer.java new file mode 100644 index 00000000..4d9dcb8d --- /dev/null +++ b/bungee/src/main/java/co/aikar/commands/BungeeCommandIssuer.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package co.aikar.commands; + +import net.md_5.bungee.api.CommandSender; +import net.md_5.bungee.api.chat.TextComponent; +import net.md_5.bungee.api.connection.ProxiedPlayer; + +public class BungeeCommandIssuer implements CommandIssuer{ + private final CommandSender sender; + + BungeeCommandIssuer(CommandSender sender) { + this.sender = sender; + } + + + @Override + public T getIssuer() { + return (T) sender; + } + + @Override + public boolean isPlayer() { + return sender instanceof ProxiedPlayer; + } + + @Override + public void sendMessage(String message) { + sender.sendMessage(new TextComponent(ACFBungeeUtil.color(message))); + } + + @Override + public boolean hasPermission(String name) { + return sender.hasPermission(name); + } +} diff --git a/bungee/src/main/java/co/aikar/commands/BungeeCommandManager.java b/bungee/src/main/java/co/aikar/commands/BungeeCommandManager.java new file mode 100644 index 00000000..4c28e683 --- /dev/null +++ b/bungee/src/main/java/co/aikar/commands/BungeeCommandManager.java @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package co.aikar.commands; + +import co.aikar.commands.apachecommonslang.ApacheCommonsExceptionUtil; +import net.md_5.bungee.api.CommandSender; +import net.md_5.bungee.api.plugin.Command; +import net.md_5.bungee.api.plugin.Plugin; + +import java.lang.reflect.Method; +import java.lang.reflect.Parameter; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.logging.Level; + +public class BungeeCommandManager extends CommandManager { + + protected final Plugin plugin; + protected Map knownCommands = new HashMap<>(); + protected Map registeredCommands = new HashMap<>(); + protected BungeeCommandContexts contexts; + protected BungeeCommandCompletions completions; + + public BungeeCommandManager(Plugin plugin) { + this.plugin = plugin; + } + + public Plugin getPlugin() { + return this.plugin; + } + + @Override + public synchronized CommandContexts getCommandContexts() { + if (this.contexts == null) { + this.contexts = new BungeeCommandContexts(this); + } + return contexts; + } + + @Override + public synchronized CommandCompletions getCommandCompletions() { + if (this.completions == null) { + this.completions = new BungeeCommandCompletions(this); + } + return completions; + } + + @Override + public void registerCommand(BaseCommand command) { + final String plugin = this.plugin.getDescription().getName().toLowerCase(); + command.onRegister(this); + for (Map.Entry entry : command.registeredCommands.entrySet()) { + String key = entry.getKey().toLowerCase(); + BungeeRootCommand value = (BungeeRootCommand) entry.getValue(); + if (!value.isRegistered) { + this.plugin.getProxy().getPluginManager().registerCommand(this.plugin, value); + } + value.isRegistered = true; + registeredCommands.put(key, value); + } + } + + @Override + public boolean hasRegisteredCommands() { + return !registeredCommands.isEmpty(); + } + + @Override + public boolean isCommandIssuer(Class aClass) { + return CommandSender.class.isAssignableFrom(aClass); + } + + @Override + public CommandIssuer getCommandIssuer(Object issuer) { + if (!(issuer instanceof CommandSender)) { + throw new IllegalArgumentException(issuer.getClass().getName() + " is not a Command Issuer."); + } + return new BungeeCommandIssuer((CommandSender) issuer); + } + + @Override + public RootCommand createRootCommand(String cmd) { + return new BungeeRootCommand(this, cmd); + } + + @Override + public R createCommandContext(RegisteredCommand command, Parameter parameter, CommandIssuer sender, List args, int i, Map passedArgs) { + return (R) new BungeeCommandExecutionContext(command, parameter, sender, args, i, passedArgs); + } + + @Override + public CommandCompletionContext createCompletionContext(RegisteredCommand command, CommandIssuer sender, String input, String config, String[] args) { + return new BungeeCommandCompletionContext(command, sender, input, config, args); + } + + @Override + public RegisteredCommand createRegisteredCommand(BaseCommand command, String cmdName, Method method, String prefSubCommand) { + return new RegisteredCommand(command, cmdName, method, prefSubCommand); + } + + @Override + public void log(LogLevel level, String message) { + switch(level) { + case INFO: + this.plugin.getLogger().info(LogLevel.LOG_PREFIX + message); + return; + case ERROR: + this.plugin.getLogger().severe(LogLevel.LOG_PREFIX + message); + } + } + + @Override + public void log(LogLevel level, String message, Throwable throwable) { + switch(level) { + case INFO: + this.plugin.getLogger().log(Level.INFO, LogLevel.LOG_PREFIX + message, throwable); + return; + case ERROR: + this.plugin.getLogger().log(Level.SEVERE, LogLevel.LOG_PREFIX + message); + for(String line : ACFPatterns.NEWLINE.split(ApacheCommonsExceptionUtil.getFullStackTrace(throwable))) { + this.plugin.getLogger().severe(LogLevel.LOG_PREFIX + line); + } + } + } +} diff --git a/bungee/src/main/java/co/aikar/commands/BungeeRegisteredCommand.java b/bungee/src/main/java/co/aikar/commands/BungeeRegisteredCommand.java new file mode 100644 index 00000000..4693ab17 --- /dev/null +++ b/bungee/src/main/java/co/aikar/commands/BungeeRegisteredCommand.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package co.aikar.commands; + +import java.lang.reflect.Method; + +public class BungeeRegisteredCommand extends RegisteredCommand { + + BungeeRegisteredCommand(BaseCommand scope, String command, Method method, String prefSubCommand) { + super(scope, command, method, prefSubCommand); + } + + @Override + public void preCommand() { + super.preCommand(); + } + + @Override + public void postCommand() { + super.postCommand(); + } +} diff --git a/bungee/src/main/java/co/aikar/commands/BungeeRootCommand.java b/bungee/src/main/java/co/aikar/commands/BungeeRootCommand.java new file mode 100644 index 00000000..c5760894 --- /dev/null +++ b/bungee/src/main/java/co/aikar/commands/BungeeRootCommand.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package co.aikar.commands; + +import co.aikar.commands.apachecommonslang.ApacheCommonsLangUtil; +import net.md_5.bungee.api.CommandSender; +import net.md_5.bungee.api.plugin.Command; +import net.md_5.bungee.api.plugin.TabExecutor; + +import java.util.*; + +public class BungeeRootCommand extends Command implements RootCommand, TabExecutor { + + private final BungeeCommandManager manager; + private final String name; + private BaseCommand defCommand; + private Map subCommands = new HashMap<>(); + private List children = new ArrayList<>(); + private String permission; + boolean isRegistered = false; + + BungeeRootCommand(BungeeCommandManager manager, String name) { + super(name); + this.manager = manager; + this.name = name; + } + + @Override + public void addChild(BaseCommand command) { + if (this.defCommand == null || !command.subCommands.get("__default").isEmpty()) { + this.defCommand = command; + this.permission = command.permission; + //this.setPermissionMessage(command.permissionMessage); + //this.setDescription(command.getDescription()); + //this.setUsage(command.getUsage()); + } + command.subCommands.keySet().forEach(key -> { + if (key.equals(BaseCommand.DEFAULT) || key.equals(BaseCommand.UNKNOWN)) { + return; + } + BaseCommand regged = this.subCommands.get(key); + if (regged != null) { + this.manager.log(LogLevel.ERROR, "ACF Error: " + command.getName() + " registered subcommand " + key + " for root command " + getName() + " - but it is already defined in " + regged.getName()); + this.manager.log(LogLevel.ERROR, "2 subcommands of the same prefix may not be spread over 2 different classes. Ignoring this."); + return; + } + this.subCommands.put(key, command); + }); + this.children.add(command); + } + + @Override + public CommandManager getManager() { + return manager; + } + + @Override + public void execute(CommandSender sender, String[] args) { + execute(new BungeeCommandIssuer(sender), getName(), args); + } + + private void execute(CommandIssuer sender, String commandLabel, String[] args) { + for (int i = args.length; i >= 0; i--) { + String checkSub = ApacheCommonsLangUtil.join(args, " ", 0, i).toLowerCase(); + BaseCommand subHandler = this.subCommands.get(checkSub); + if (subHandler != null) { + subHandler.execute(sender, commandLabel, args); + return; + } + } + + this.defCommand.execute(sender, commandLabel, args); + } + + @Override + public Iterable onTabComplete(CommandSender commandSender, String[] strings) { + return onTabComplete(new BungeeCommandIssuer(commandSender), getName(), strings); + } + + private List onTabComplete(CommandIssuer sender, String alias, String[] args) throws IllegalArgumentException { + Set completions = new HashSet<>(); + this.children.forEach(child -> completions.addAll(child.tabComplete(sender, alias, args))); + return new ArrayList<>(completions); + } +} diff --git a/bungee/src/main/java/co/aikar/commands/contexts/OnlineProxiedPlayer.java b/bungee/src/main/java/co/aikar/commands/contexts/OnlineProxiedPlayer.java new file mode 100644 index 00000000..258b8ea9 --- /dev/null +++ b/bungee/src/main/java/co/aikar/commands/contexts/OnlineProxiedPlayer.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2016-2017 Daniel Ennis (Aikar) - MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package co.aikar.commands.contexts; + +import net.md_5.bungee.api.connection.ProxiedPlayer; + +import java.util.Objects; + +public class OnlineProxiedPlayer { + + public final ProxiedPlayer player; + + public OnlineProxiedPlayer(ProxiedPlayer player) { + this.player = player; + } + + public ProxiedPlayer getPlayer(){ + return player; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + OnlineProxiedPlayer that = (OnlineProxiedPlayer) o; + return Objects.equals(player, that.player); + } + + @Override + public int hashCode() { + return Objects.hash(player); + } + + @Override + public String toString() { + return "OnlineProxiedPlayer{" + + "proxiedPlayer=" + player + + '}'; + } +} diff --git a/pom.xml b/pom.xml index e84ee9af..2127295d 100644 --- a/pom.xml +++ b/pom.xml @@ -99,7 +99,7 @@ core bukkit paper - + bungee sponge