From 2057ed8a42829cdab6d10b0ef80d47cfa7082539 Mon Sep 17 00:00:00 2001 From: Aikar Date: Sun, 17 Dec 2017 13:46:22 -0500 Subject: [PATCH] More work on Command Conditions #58 --- .../co/aikar/commands/ACFBukkitListener.java | 61 ++++++++++++ .../aikar/commands/BukkitCommandManager.java | 65 +++++-------- .../commands/BukkitConditionContext.java | 32 ++++++ .../BukkitParameterConditionContext.java | 32 ++++++ .../aikar/commands/BungeeCommandManager.java | 29 +++++- .../commands/BungeeConditionContext.java | 9 ++ .../BungeeParameterConditionContext.java | 9 ++ .../java/co/aikar/commands/BaseCommand.java | 2 +- .../co/aikar/commands/CommandConditions.java | 55 ++++++++++- .../commands/CommandExecutionContext.java | 2 +- .../co/aikar/commands/CommandManager.java | 53 ++++++---- .../co/aikar/commands/ConditionContext.java | 31 +++++- .../main/java/co/aikar/commands/Locales.java | 2 +- .../co/aikar/commands/MessageFormatter.java | 18 ++-- .../commands/ParameterConditionContext.java | 97 +++++++++++++++++++ .../co/aikar/commands/RegisteredCommand.java | 17 ++-- .../aikar/commands/SpongeCommandManager.java | 29 +++++- .../commands/SpongeConditionContext.java | 9 ++ .../SpongeParameterConditionContext.java | 9 ++ 19 files changed, 468 insertions(+), 93 deletions(-) create mode 100644 bukkit/src/main/java/co/aikar/commands/ACFBukkitListener.java create mode 100644 bukkit/src/main/java/co/aikar/commands/BukkitConditionContext.java create mode 100644 bukkit/src/main/java/co/aikar/commands/BukkitParameterConditionContext.java create mode 100644 bungee/src/main/java/co/aikar/commands/BungeeConditionContext.java create mode 100644 bungee/src/main/java/co/aikar/commands/BungeeParameterConditionContext.java create mode 100644 core/src/main/java/co/aikar/commands/ParameterConditionContext.java create mode 100644 sponge/src/main/java/co/aikar/commands/SpongeConditionContext.java create mode 100644 sponge/src/main/java/co/aikar/commands/SpongeParameterConditionContext.java diff --git a/bukkit/src/main/java/co/aikar/commands/ACFBukkitListener.java b/bukkit/src/main/java/co/aikar/commands/ACFBukkitListener.java new file mode 100644 index 00000000..61e24488 --- /dev/null +++ b/bukkit/src/main/java/co/aikar/commands/ACFBukkitListener.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; + +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.event.server.PluginDisableEvent; +import org.bukkit.plugin.Plugin; + +class ACFBukkitListener implements Listener { + private BukkitCommandManager manager; + private final Plugin plugin; + + public ACFBukkitListener(BukkitCommandManager manager, Plugin plugin) { + this.manager = manager; + this.plugin = plugin; + } + + @EventHandler + public void onPluginDisable(PluginDisableEvent event) { + if (!(plugin.getName().equalsIgnoreCase(event.getPlugin().getName()))) { + return; + } + manager.unregisterCommands(); + } + @EventHandler + public void onPlayerJoin(PlayerJoinEvent event) { + Player player = event.getPlayer(); + manager.readPlayerLocale(player); + this.plugin.getServer().getScheduler().runTaskLater(this.plugin, () -> manager.readPlayerLocale(player), 20); + } + + @EventHandler + public void onPlayerJoin(PlayerQuitEvent event) { + manager.issuersLocale.remove(event.getPlayer().getUniqueId()); + } +} diff --git a/bukkit/src/main/java/co/aikar/commands/BukkitCommandManager.java b/bukkit/src/main/java/co/aikar/commands/BukkitCommandManager.java index 7f847cae..f3055428 100644 --- a/bukkit/src/main/java/co/aikar/commands/BukkitCommandManager.java +++ b/bukkit/src/main/java/co/aikar/commands/BukkitCommandManager.java @@ -23,6 +23,7 @@ package co.aikar.commands; +import co.aikar.commands.annotation.Conditions; import co.aikar.commands.apachecommonslang.ApacheCommonsExceptionUtil; import co.aikar.timings.lib.MCTiming; import co.aikar.timings.lib.TimingManager; @@ -35,11 +36,6 @@ import org.bukkit.command.CommandMap; import org.bukkit.command.CommandSender; import org.bukkit.command.SimpleCommandMap; import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.player.PlayerJoinEvent; -import org.bukkit.event.player.PlayerQuitEvent; -import org.bukkit.event.server.PluginDisableEvent; import org.bukkit.plugin.Plugin; import org.bukkit.scheduler.BukkitTask; import org.jetbrains.annotations.NotNull; @@ -57,7 +53,16 @@ import java.util.logging.Level; import java.util.logging.Logger; @SuppressWarnings("WeakerAccess") -public class BukkitCommandManager extends CommandManager { +public class BukkitCommandManager extends CommandManager< + CommandSender, + BukkitCommandIssuer, + ChatColor, + BukkitMessageFormatter, + BukkitCommandExecutionContext, + BukkitCommandCompletionContext, + BukkitConditionContext, + BukkitParameterConditionContext + > { @SuppressWarnings("WeakerAccess") protected final Plugin plugin; @@ -85,7 +90,7 @@ public class BukkitCommandManager extends CommandManager { if (cantReadLocale) { @@ -246,7 +251,7 @@ public class BukkitCommandManager extends CommandManager readPlayerLocale(player), 20); - } - - @EventHandler - public void onPlayerJoin(PlayerQuitEvent event) { - issuersLocale.remove(event.getPlayer().getUniqueId()); - } - } - public TimingManager getTimings() { return timingManager; } @@ -320,13 +298,12 @@ public class BukkitCommandManager extends CommandManager R createCommandContext(RegisteredCommand command, Parameter parameter, CommandIssuer sender, List args, int i, Map passedArgs) { - //noinspection unchecked - return (R) new BukkitCommandExecutionContext(command, parameter, (BukkitCommandIssuer) sender, args, i, passedArgs); + public BukkitCommandExecutionContext createCommandContext(RegisteredCommand command, Parameter parameter, CommandIssuer sender, List args, int i, Map passedArgs) { + return new BukkitCommandExecutionContext(command, parameter, (BukkitCommandIssuer) sender, args, i, passedArgs); } @Override - public CommandCompletionContext createCompletionContext(RegisteredCommand command, CommandIssuer sender, String input, String config, String[] args) { + public BukkitCommandCompletionContext createCompletionContext(RegisteredCommand command, CommandIssuer sender, String input, String config, String[] args) { return new BukkitCommandCompletionContext(command, sender, input, config, args); } @@ -335,6 +312,16 @@ public class BukkitCommandManager extends CommandManager BukkitParameterConditionContext createConditionContext(CommandOperationContext context, BukkitCommandExecutionContext execContext, Conditions conditions) { + return new BukkitParameterConditionContext

(context.getRegisteredCommand(), (BukkitCommandIssuer) context.getCommandIssuer(), execContext, conditions); + } + @Override public void log(LogLevel level, String message, Throwable throwable) { Level logLevel = level == LogLevel.INFO ? Level.INFO : Level.SEVERE; diff --git a/bukkit/src/main/java/co/aikar/commands/BukkitConditionContext.java b/bukkit/src/main/java/co/aikar/commands/BukkitConditionContext.java new file mode 100644 index 00000000..e26095b6 --- /dev/null +++ b/bukkit/src/main/java/co/aikar/commands/BukkitConditionContext.java @@ -0,0 +1,32 @@ +/* + * 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.Conditions; + +public class BukkitConditionContext extends ConditionContext { + BukkitConditionContext(RegisteredCommand cmd, BukkitCommandIssuer issuer, Conditions condAnno) { + super(cmd, issuer, condAnno); + } +} diff --git a/bukkit/src/main/java/co/aikar/commands/BukkitParameterConditionContext.java b/bukkit/src/main/java/co/aikar/commands/BukkitParameterConditionContext.java new file mode 100644 index 00000000..070ae7bd --- /dev/null +++ b/bukkit/src/main/java/co/aikar/commands/BukkitParameterConditionContext.java @@ -0,0 +1,32 @@ +/* + * 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.Conditions; + +public class BukkitParameterConditionContext

extends ParameterConditionContext { + BukkitParameterConditionContext(RegisteredCommand cmd, BukkitCommandIssuer issuer, BukkitCommandExecutionContext execContext, Conditions conditions) { + super(cmd, issuer, execContext, conditions); + } +} diff --git a/bungee/src/main/java/co/aikar/commands/BungeeCommandManager.java b/bungee/src/main/java/co/aikar/commands/BungeeCommandManager.java index aa48f84b..45ea391b 100644 --- a/bungee/src/main/java/co/aikar/commands/BungeeCommandManager.java +++ b/bungee/src/main/java/co/aikar/commands/BungeeCommandManager.java @@ -23,6 +23,7 @@ package co.aikar.commands; +import co.aikar.commands.annotation.Conditions; import co.aikar.commands.apachecommonslang.ApacheCommonsExceptionUtil; import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.CommandSender; @@ -36,7 +37,16 @@ import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; -public class BungeeCommandManager extends CommandManager { +public class BungeeCommandManager extends CommandManager< + CommandSender, + BungeeCommandIssuer, + ChatColor, + BungeeMessageFormatter, + BungeeCommandExecutionContext, + BungeeCommandCompletionContext, + BungeeConditionContext, + BungeeParameterConditionContext + > { protected final Plugin plugin; protected Map registeredCommands = new HashMap<>(); @@ -144,9 +154,8 @@ public class BungeeCommandManager extends CommandManager R createCommandContext(RegisteredCommand command, Parameter parameter, CommandIssuer sender, List args, int i, Map passedArgs) { - //noinspection unchecked - return (R) new BungeeCommandExecutionContext(command, parameter, (BungeeCommandIssuer) sender, args, i, passedArgs); + public BungeeCommandExecutionContext createCommandContext(RegisteredCommand command, Parameter parameter, CommandIssuer sender, List args, int i, Map passedArgs) { + return new BungeeCommandExecutionContext(command, parameter, (BungeeCommandIssuer) sender, args, i, passedArgs); } @Override @@ -154,6 +163,18 @@ public class BungeeCommandManager extends CommandManager BungeeParameterConditionContext createConditionContext(CommandOperationContext context, BungeeCommandExecutionContext execContext, Conditions conditions) { + return new BungeeParameterConditionContext

(context.getRegisteredCommand(), (BungeeCommandIssuer) context.getCommandIssuer(), execContext, conditions); + } + + @Override public RegisteredCommand createRegisteredCommand(BaseCommand command, String cmdName, Method method, String prefSubCommand) { return new RegisteredCommand(command, cmdName, method, prefSubCommand); diff --git a/bungee/src/main/java/co/aikar/commands/BungeeConditionContext.java b/bungee/src/main/java/co/aikar/commands/BungeeConditionContext.java new file mode 100644 index 00000000..d9abeacc --- /dev/null +++ b/bungee/src/main/java/co/aikar/commands/BungeeConditionContext.java @@ -0,0 +1,9 @@ +package co.aikar.commands; + +import co.aikar.commands.annotation.Conditions; + +public class BungeeConditionContext extends ConditionContext { + BungeeConditionContext(RegisteredCommand cmd, BungeeCommandIssuer issuer, Conditions condAnno) { + super(cmd, issuer, condAnno); + } +} diff --git a/bungee/src/main/java/co/aikar/commands/BungeeParameterConditionContext.java b/bungee/src/main/java/co/aikar/commands/BungeeParameterConditionContext.java new file mode 100644 index 00000000..b605e5f2 --- /dev/null +++ b/bungee/src/main/java/co/aikar/commands/BungeeParameterConditionContext.java @@ -0,0 +1,9 @@ +package co.aikar.commands; + +import co.aikar.commands.annotation.Conditions; + +public class BungeeParameterConditionContext

extends ParameterConditionContext { + BungeeParameterConditionContext(RegisteredCommand cmd, BungeeCommandIssuer issuer, BungeeCommandExecutionContext execContext, Conditions conditions) { + super(cmd, issuer, execContext, conditions); + } +} diff --git a/core/src/main/java/co/aikar/commands/BaseCommand.java b/core/src/main/java/co/aikar/commands/BaseCommand.java index e93e32c8..ec323bd1 100644 --- a/core/src/main/java/co/aikar/commands/BaseCommand.java +++ b/core/src/main/java/co/aikar/commands/BaseCommand.java @@ -71,7 +71,7 @@ public abstract class BaseCommand { private String execSubcommand; @SuppressWarnings("WeakerAccess") private String[] origArgs; - CommandManager manager = null; + CommandManager manager = null; BaseCommand parentCommand; Map registeredCommands = new HashMap<>(); String description; diff --git a/core/src/main/java/co/aikar/commands/CommandConditions.java b/core/src/main/java/co/aikar/commands/CommandConditions.java index 4fb56566..1c5018a5 100644 --- a/core/src/main/java/co/aikar/commands/CommandConditions.java +++ b/core/src/main/java/co/aikar/commands/CommandConditions.java @@ -24,14 +24,23 @@ package co.aikar.commands; import co.aikar.commands.annotation.Conditions; +import com.google.common.collect.HashBasedTable; import com.google.common.collect.Maps; +import com.google.common.collect.Table; import java.util.Map; @SuppressWarnings("BooleanMethodIsAlwaysInverted") // No IDEA, you are wrong -public class CommandConditions { +public class CommandConditions < + I extends CommandIssuer, + M extends CommandManager, + CC extends ConditionContext, + CEC extends CommandExecutionContext, + PCC extends ParameterConditionContext + > { M manager; Map> conditions = Maps.newHashMap(); + Table, String, ParameterCondition> paramConditions = HashBasedTable.create(); CommandConditions(M manager) { this.manager = manager; } @@ -40,6 +49,15 @@ public class CommandConditions ParameterCondition addCondition(Class

clazz, String id, ParameterCondition handler) { + return this.paramConditions.put(clazz, id.toLowerCase(), handler); + } + + boolean validateConditions(CommandOperationContext context, CEC cec) { + Conditions conditions = cec.getParam().getAnnotation(Conditions.class); + return conditions == null || validateConditions(conditions, context, cec); + } + boolean validateConditions(CommandOperationContext context) { RegisteredCommand cmd = context.getRegisteredCommand(); Conditions conditions = cmd.method.getAnnotation(Conditions.class); @@ -66,7 +84,7 @@ public class CommandConditions cls = execContext.getParam().getClass(); + String id = split[0].toLowerCase(); + do { + condition = this.paramConditions.get(cls, id); + if (condition == null && cls.getSuperclass() != null && cls.getSuperclass() != Object.class) { + cls = cls.getSuperclass(); + } else { + break; + } + } while (cls != null); + + //noinspection unchecked + if (condition != null && !condition.validateCondition(conditionContext)) { + return false; + } + } + + return true; + } + interface Condition { boolean validateCondition(CC context); } + interface ParameterCondition { + boolean validateCondition(PCC context); + } } diff --git a/core/src/main/java/co/aikar/commands/CommandExecutionContext.java b/core/src/main/java/co/aikar/commands/CommandExecutionContext.java index 25f918f6..8dc4084b 100644 --- a/core/src/main/java/co/aikar/commands/CommandExecutionContext.java +++ b/core/src/main/java/co/aikar/commands/CommandExecutionContext.java @@ -38,7 +38,7 @@ import java.util.List; import java.util.Map; @SuppressWarnings({"WeakerAccess", "unused"}) -public class CommandExecutionContext { +public class CommandExecutionContext { private final RegisteredCommand cmd; private final Parameter param; protected final I issuer; diff --git a/core/src/main/java/co/aikar/commands/CommandManager.java b/core/src/main/java/co/aikar/commands/CommandManager.java index 319b5143..24c73c24 100644 --- a/core/src/main/java/co/aikar/commands/CommandManager.java +++ b/core/src/main/java/co/aikar/commands/CommandManager.java @@ -23,6 +23,7 @@ package co.aikar.commands; +import co.aikar.commands.annotation.Conditions; import co.aikar.locales.MessageKeyProvider; import com.google.common.collect.Lists; import com.google.common.collect.Sets; @@ -40,7 +41,16 @@ import java.util.Set; import java.util.Stack; @SuppressWarnings("WeakerAccess") -public abstract class CommandManager > { +public abstract class CommandManager < + IT, + I extends CommandIssuer, + FT, + MF extends MessageFormatter, + CEC extends CommandExecutionContext, + CCC extends CommandCompletionContext, + CC extends ConditionContext, + PCC extends ParameterConditionContext + > { /** * This is a stack incase a command calls a command @@ -58,10 +68,10 @@ public abstract class CommandManager > localeChangedCallbacks = Lists.newArrayList(); + protected List> localeChangedCallbacks = Lists.newArrayList(); protected Set supportedLanguages = Sets.newHashSet(Locales.ENGLISH, Locales.GERMAN, Locales.SPANISH, Locales.CZECH); - protected Map formatters = new IdentityHashMap<>(); - protected F defaultFormatter; + protected Map formatters = new IdentityHashMap<>(); + protected MF defaultFormatter; protected int defaultHelpPerPage = 10; private Set unstableAPIs = Sets.newHashSet(); @@ -80,31 +90,31 @@ public abstract class CommandManager type); // TODO: Change this to I if we make a breaking change - public abstract AI getCommandIssuer(Object issuer); + public abstract I getCommandIssuer(Object issuer); public abstract RootCommand createRootCommand(String cmd); @@ -195,12 +205,17 @@ public abstract class CommandManager R createConditionContext(CommandOperationContext context) { + public ConditionContext createConditionContext(CommandOperationContext context, Conditions conditions) { //noinspection unchecked - return (R) new ConditionContext<>(context.getRegisteredCommand(), context.getCommandIssuer()); + return new ConditionContext<>(context.getRegisteredCommand(), context.getCommandIssuer(), conditions); } - public abstract R createCommandContext(RegisteredCommand command, Parameter parameter, CommandIssuer sender, List args, int i, Map passedArgs); + public

ParameterConditionContext createConditionContext(CommandOperationContext context, CEC execContext, Conditions conditions) { + //noinspection unchecked + return new ParameterConditionContext(context.getRegisteredCommand(), (I) context.getCommandIssuer(), execContext, conditions); + } + + public abstract CommandExecutionContext createCommandContext(RegisteredCommand command, Parameter parameter, CommandIssuer sender, List args, int i, Map passedArgs); public abstract CommandCompletionContext createCompletionContext(RegisteredCommand command, CommandIssuer sender, String input, String config, String[] args); @@ -286,7 +301,7 @@ public abstract class CommandManager onChange) { + public void onLocaleChange(IssuerLocaleChangedCallback onChange) { localeChangedCallbacks.add(onChange); } - public void notifyLocaleChange(AI issuer, Locale oldLocale, Locale newLocale) { + public void notifyLocaleChange(I issuer, Locale oldLocale, Locale newLocale) { localeChangedCallbacks.forEach(cb -> { try { cb.onIssuerLocaleChange(issuer, oldLocale, newLocale); @@ -331,11 +346,11 @@ public abstract class CommandManager createCommandOperationContext(BaseCommand command, CommandIssuer issuer, String commandLabel, String[] args, boolean isAsync) { + CommandOperationContext createCommandOperationContext(BaseCommand command, CommandIssuer issuer, String commandLabel, String[] args, boolean isAsync) { //noinspection unchecked return new CommandOperationContext<>( this, - (AI) issuer, + (I) issuer, command, commandLabel, args, diff --git a/core/src/main/java/co/aikar/commands/ConditionContext.java b/core/src/main/java/co/aikar/commands/ConditionContext.java index 853814ca..bc6ab02c 100644 --- a/core/src/main/java/co/aikar/commands/ConditionContext.java +++ b/core/src/main/java/co/aikar/commands/ConditionContext.java @@ -23,21 +23,42 @@ package co.aikar.commands; +import co.aikar.commands.annotation.Conditions; +import com.google.common.collect.Maps; + +import java.util.Map; + public class ConditionContext { private final RegisteredCommand cmd; private final I issuer; + private final Conditions condAnno; + private final Map flags; - ConditionContext(RegisteredCommand cmd, I issuer) { + ConditionContext(RegisteredCommand cmd, I issuer, Conditions condAnno) { this.cmd = cmd; this.issuer = issuer; - } - - public RegisteredCommand getCmd() { - return cmd; + this.condAnno = condAnno; + this.flags = Maps.newHashMap(); + for (String s : ACFPatterns.COMMA.split(cmd.scope.manager.getCommandReplacements().replace(condAnno.value()))) { + String[] v = ACFPatterns.EQUALS.split(s, 2); + this.flags.put(v[0], v.length > 1 ? v[1] : null); + } } public I getIssuer() { return issuer; } + + public boolean hasFlag(String flag) { + return flags.containsKey(flag); + } + + public String getFlagValue(String flag, String def) { + return flags.getOrDefault(flag, def); + } + + public Integer getFlagValue(String flag, Integer def) { + return ACFUtil.parseInt(this.flags.get(flag), def); + } } diff --git a/core/src/main/java/co/aikar/commands/Locales.java b/core/src/main/java/co/aikar/commands/Locales.java index 38cc4d54..e7e64687 100644 --- a/core/src/main/java/co/aikar/commands/Locales.java +++ b/core/src/main/java/co/aikar/commands/Locales.java @@ -72,7 +72,7 @@ public class Locales { public static final Locale WELSH = new Locale("cy"); - private final CommandManager manager; + private final CommandManager manager; private final LocaleManager localeManager; private final SetMultimap loadedBundles = HashMultimap.create(); diff --git a/core/src/main/java/co/aikar/commands/MessageFormatter.java b/core/src/main/java/co/aikar/commands/MessageFormatter.java index b36464cc..878122e8 100644 --- a/core/src/main/java/co/aikar/commands/MessageFormatter.java +++ b/core/src/main/java/co/aikar/commands/MessageFormatter.java @@ -31,18 +31,18 @@ import java.util.regex.Matcher; /** * Handles formatting Messages and managing colors - * @param The platform specific color object + * @param The platform specific color object */ -public abstract class MessageFormatter { +public abstract class MessageFormatter { - private final List colors = new ArrayList<>(); + private final List colors = new ArrayList<>(); @SafeVarargs - public MessageFormatter(C... colors) { + public MessageFormatter(FT... colors) { this.colors.addAll(Arrays.asList(colors)); } - public C setColor(int index, C color) { + public FT setColor(int index, FT color) { if (index > 0) { index--; } else { @@ -60,24 +60,24 @@ public abstract class MessageFormatter { } } - public C getColor(int index) { + public FT getColor(int index) { if (index > 0) { index--; } else { index = 0; } - C color = colors.get(index); + FT color = colors.get(index); if (color == null) { color = getDefaultColor(); } return color; } - public C getDefaultColor() { + public FT getDefaultColor() { return getColor(1); } - abstract String format(C color, String message); + abstract String format(FT color, String message); public String format(int index, String message) { return format(getColor(index), message); diff --git a/core/src/main/java/co/aikar/commands/ParameterConditionContext.java b/core/src/main/java/co/aikar/commands/ParameterConditionContext.java new file mode 100644 index 00000000..7b754e29 --- /dev/null +++ b/core/src/main/java/co/aikar/commands/ParameterConditionContext.java @@ -0,0 +1,97 @@ +/* + * 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.Conditions; + +import java.lang.annotation.Annotation; +import java.util.List; +import java.util.Map; + +public class ParameterConditionContext extends ConditionContext { + + private final CEC execContext; + + ParameterConditionContext(RegisteredCommand cmd, I issuer, CEC execContext, Conditions conditions) { + super(cmd, issuer, conditions); + + this.execContext = execContext; + } + + public boolean isLastArg() { + return execContext.isLastArg(); + } + + public int getNumParams() { + return execContext.getNumParams(); + } + + public boolean canOverridePlayerContext() { + return execContext.canOverridePlayerContext(); + } + + public Object getResolvedArg(String arg) { + return execContext.getResolvedArg(arg); + } + + public Object getResolvedArg(Class[] classes) { + return execContext.getResolvedArg(classes); + } + + public Object getResolvedArg(String key, Class[] classes) { + return execContext.getResolvedArg(key, classes); + } + + public boolean isOptional() { + return execContext.isOptional(); + } + + public Annotation getAnnotation(Class cls) { + return execContext.getAnnotation(cls); + } + + public boolean hasAnnotation(Class cls) { + return execContext.hasAnnotation(cls); + } + + public List getArgs() { + return execContext.getArgs(); + } + + public int getIndex() { + return execContext.getIndex(); + } + + public Map getPassedArgs() { + return execContext.getPassedArgs(); + } + + public String joinArgs() { + return execContext.joinArgs(); + } + + public String joinArgs(String sep) { + return execContext.joinArgs(sep); + } +} diff --git a/core/src/main/java/co/aikar/commands/RegisteredCommand.java b/core/src/main/java/co/aikar/commands/RegisteredCommand.java index 879231f2..ec8b258a 100644 --- a/core/src/main/java/co/aikar/commands/RegisteredCommand.java +++ b/core/src/main/java/co/aikar/commands/RegisteredCommand.java @@ -52,13 +52,13 @@ import java.util.Set; import java.util.stream.Collectors; @SuppressWarnings("WeakerAccess") -public class RegisteredCommand > { +public class RegisteredCommand > { final BaseCommand scope; final String command; final Method method; final String prefSubCommand; final Parameter[] parameters; - final ContextResolver[] resolvers; + final ContextResolver[] resolvers; final String syntaxText; final String helpText; @@ -67,7 +67,7 @@ public class RegisteredCommand registeredSubcommands = new ArrayList<>(); - private final CommandManager manager; + private final CommandManager manager; RegisteredCommand(BaseCommand scope, String command, Method method, String prefSubCommand) { this.scope = scope; @@ -100,7 +100,7 @@ public class RegisteredCommand type = parameter.getType(); //noinspection unchecked - final ContextResolver resolver = commandContexts.getResolver(type); + final ContextResolver resolver = commandContexts.getResolver(type); if (resolver != null) { resolvers[i] = resolver; @@ -129,13 +129,13 @@ public class RegisteredCommand resolver, Parameter parameter) { + private boolean isOptionalResolver(ContextResolver resolver, Parameter parameter) { return isOptionalResolver(resolver) || parameter.getAnnotation(Optional.class) != null || parameter.getAnnotation(Default.class) != null; } - private boolean isOptionalResolver(ContextResolver resolver) { + private boolean isOptionalResolver(ContextResolver resolver) { return resolver instanceof IssuerAwareContextResolver || resolver instanceof IssuerOnlyContextResolver || resolver instanceof OptionalContextResolver; } @@ -203,8 +203,9 @@ public class RegisteredCommand type = parameter.getType(); //noinspection unchecked - final ContextResolver resolver = resolvers[i]; - R context = this.manager.createCommandContext(this, parameter, sender, args, i, passedArgs); + final ContextResolver resolver = resolvers[i]; + //noinspection unchecked + CEC context = (CEC) this.manager.createCommandContext(this, parameter, sender, args, i, passedArgs); boolean isOptionalResolver = isOptionalResolver(resolver, parameter); if (!isOptionalResolver) { remainingRequired--; diff --git a/sponge/src/main/java/co/aikar/commands/SpongeCommandManager.java b/sponge/src/main/java/co/aikar/commands/SpongeCommandManager.java index 4ed8f8db..4376e809 100644 --- a/sponge/src/main/java/co/aikar/commands/SpongeCommandManager.java +++ b/sponge/src/main/java/co/aikar/commands/SpongeCommandManager.java @@ -23,6 +23,7 @@ package co.aikar.commands; +import co.aikar.commands.annotation.Conditions; import co.aikar.commands.apachecommonslang.ApacheCommonsExceptionUtil; import co.aikar.timings.Timing; import co.aikar.timings.Timings; @@ -40,7 +41,16 @@ import java.util.List; import java.util.Map; @SuppressWarnings("WeakerAccess") -public class SpongeCommandManager extends CommandManager { +public class SpongeCommandManager extends CommandManager< + CommandSource, + SpongeCommandIssuer, + TextColor, + SpongeMessageFormatter, + SpongeCommandExecutionContext, + SpongeCommandCompletionContext, + SpongeConditionContext, + SpongeParameterConditionContext + > { protected final PluginContainer plugin; protected Map registeredCommands = new HashMap<>(); @@ -134,9 +144,8 @@ public class SpongeCommandManager extends CommandManager R createCommandContext(RegisteredCommand command, Parameter parameter, CommandIssuer sender, List args, int i, Map passedArgs) { - //noinspection unchecked - return (R) new SpongeCommandExecutionContext(command, parameter, (SpongeCommandIssuer) sender, args, i, passedArgs); + public SpongeCommandExecutionContext createCommandContext(RegisteredCommand command, Parameter parameter, CommandIssuer sender, List args, int i, Map passedArgs) { + return new SpongeCommandExecutionContext(command, parameter, (SpongeCommandIssuer) sender, args, i, passedArgs); } @Override @@ -182,4 +191,16 @@ public class SpongeCommandManager extends CommandManager SpongeParameterConditionContext createConditionContext(CommandOperationContext context, SpongeCommandExecutionContext execContext, Conditions conditions) { + return new SpongeParameterConditionContext

(context.getRegisteredCommand(), (SpongeCommandIssuer) context.getCommandIssuer(), execContext, conditions); + } + } diff --git a/sponge/src/main/java/co/aikar/commands/SpongeConditionContext.java b/sponge/src/main/java/co/aikar/commands/SpongeConditionContext.java new file mode 100644 index 00000000..c06658bf --- /dev/null +++ b/sponge/src/main/java/co/aikar/commands/SpongeConditionContext.java @@ -0,0 +1,9 @@ +package co.aikar.commands; + +import co.aikar.commands.annotation.Conditions; + +public class SpongeConditionContext extends ConditionContext { + SpongeConditionContext(RegisteredCommand cmd, SpongeCommandIssuer issuer, Conditions condAnno) { + super(cmd, issuer, condAnno); + } +} diff --git a/sponge/src/main/java/co/aikar/commands/SpongeParameterConditionContext.java b/sponge/src/main/java/co/aikar/commands/SpongeParameterConditionContext.java new file mode 100644 index 00000000..2dcac52e --- /dev/null +++ b/sponge/src/main/java/co/aikar/commands/SpongeParameterConditionContext.java @@ -0,0 +1,9 @@ +package co.aikar.commands; + +import co.aikar.commands.annotation.Conditions; + +public class SpongeParameterConditionContext

extends ParameterConditionContext { + SpongeParameterConditionContext(RegisteredCommand cmd, SpongeCommandIssuer issuer, SpongeCommandExecutionContext execContext, Conditions conditions) { + super(cmd, issuer, execContext, conditions); + } +}