diff --git a/bukkit/src/main/java/co/aikar/commands/BukkitCommandExecutionContext.java b/bukkit/src/main/java/co/aikar/commands/BukkitCommandExecutionContext.java index e3cd18fd..66799e8c 100644 --- a/bukkit/src/main/java/co/aikar/commands/BukkitCommandExecutionContext.java +++ b/bukkit/src/main/java/co/aikar/commands/BukkitCommandExecutionContext.java @@ -31,7 +31,7 @@ import java.util.List; import java.util.Map; public class BukkitCommandExecutionContext extends CommandExecutionContext { - BukkitCommandExecutionContext(RegisteredCommand cmd, Parameter param, BukkitCommandIssuer sender, List args, + BukkitCommandExecutionContext(RegisteredCommand cmd, CommandParameter param, BukkitCommandIssuer sender, List args, int index, Map passedArgs) { super(cmd, param, sender, args, index, passedArgs); } diff --git a/bukkit/src/main/java/co/aikar/commands/BukkitCommandManager.java b/bukkit/src/main/java/co/aikar/commands/BukkitCommandManager.java index d8390d42..e1fb03f3 100644 --- a/bukkit/src/main/java/co/aikar/commands/BukkitCommandManager.java +++ b/bukkit/src/main/java/co/aikar/commands/BukkitCommandManager.java @@ -46,7 +46,6 @@ import org.jetbrains.annotations.NotNull; import java.lang.reflect.Field; import java.lang.reflect.Method; -import java.lang.reflect.Parameter; import java.util.HashMap; import java.util.List; import java.util.Locale; @@ -317,7 +316,7 @@ public class BukkitCommandManager extends CommandManager< } @Override - public BukkitCommandExecutionContext createCommandContext(RegisteredCommand command, Parameter parameter, CommandIssuer sender, List args, int i, Map passedArgs) { + public BukkitCommandExecutionContext createCommandContext(RegisteredCommand command, CommandParameter parameter, CommandIssuer sender, List args, int i, Map passedArgs) { return new BukkitCommandExecutionContext(command, parameter, (BukkitCommandIssuer) sender, args, i, passedArgs); } diff --git a/bungee/src/main/java/co/aikar/commands/BungeeCommandExecutionContext.java b/bungee/src/main/java/co/aikar/commands/BungeeCommandExecutionContext.java index 2eec2765..746e1f8c 100644 --- a/bungee/src/main/java/co/aikar/commands/BungeeCommandExecutionContext.java +++ b/bungee/src/main/java/co/aikar/commands/BungeeCommandExecutionContext.java @@ -32,7 +32,7 @@ import java.util.Map; public class BungeeCommandExecutionContext extends CommandExecutionContext { - BungeeCommandExecutionContext(RegisteredCommand cmd, Parameter param, BungeeCommandIssuer sender, List args, int index, Map passedArgs) { + BungeeCommandExecutionContext(RegisteredCommand cmd, CommandParameter param, BungeeCommandIssuer sender, List args, int index, Map passedArgs) { super(cmd, param, sender, args, index, passedArgs); } diff --git a/bungee/src/main/java/co/aikar/commands/BungeeCommandManager.java b/bungee/src/main/java/co/aikar/commands/BungeeCommandManager.java index 8ebd6e21..d8cd689c 100644 --- a/bungee/src/main/java/co/aikar/commands/BungeeCommandManager.java +++ b/bungee/src/main/java/co/aikar/commands/BungeeCommandManager.java @@ -31,7 +31,6 @@ import net.md_5.bungee.api.connection.ProxiedPlayer; 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.Locale; @@ -178,7 +177,7 @@ public class BungeeCommandManager extends CommandManager< } @Override - public BungeeCommandExecutionContext createCommandContext(RegisteredCommand command, Parameter parameter, CommandIssuer sender, List args, int i, Map passedArgs) { + public BungeeCommandExecutionContext createCommandContext(RegisteredCommand command, CommandParameter parameter, CommandIssuer sender, List args, int i, Map passedArgs) { return new BungeeCommandExecutionContext(command, parameter, (BungeeCommandIssuer) sender, args, i, passedArgs); } diff --git a/core/src/main/java/co/aikar/commands/CommandCompletionContext.java b/core/src/main/java/co/aikar/commands/CommandCompletionContext.java index 2ec3a49c..72cf4cad 100644 --- a/core/src/main/java/co/aikar/commands/CommandCompletionContext.java +++ b/core/src/main/java/co/aikar/commands/CommandCompletionContext.java @@ -82,19 +82,19 @@ public class CommandCompletionContext { if (paramIdx >= command.parameters.length) { throw new IllegalArgumentException("Param index is higher than number of parameters"); } - Parameter param = command.parameters[paramIdx]; + CommandParameter param = command.parameters[paramIdx]; Class paramType = param.getType(); if (!clazz.isAssignableFrom(paramType)) { throw new IllegalArgumentException(param.getName() +":" + paramType.getName() + " can not satisfy " + clazz.getName()); } name = param.getName(); } else { - Parameter[] parameters = command.parameters; + CommandParameter[] parameters = command.parameters; for (int i = 0; i < parameters.length; i++) { - Parameter param = parameters[i]; - if (clazz.isAssignableFrom(param.getType())) { + final CommandParameter parameter = parameters[i]; + if (clazz.isAssignableFrom(parameter.getType())) { paramIdx = i; - name = param.getName(); + name = parameter.getName(); break; } } diff --git a/core/src/main/java/co/aikar/commands/CommandExecutionContext.java b/core/src/main/java/co/aikar/commands/CommandExecutionContext.java index b51497f3..cbb81079 100644 --- a/core/src/main/java/co/aikar/commands/CommandExecutionContext.java +++ b/core/src/main/java/co/aikar/commands/CommandExecutionContext.java @@ -23,13 +23,7 @@ package co.aikar.commands; -import co.aikar.commands.annotation.Default; -import co.aikar.commands.annotation.Flags; -import co.aikar.commands.annotation.Optional; import co.aikar.commands.contexts.ContextResolver; -import co.aikar.commands.contexts.IssuerAwareContextResolver; -import co.aikar.commands.contexts.IssuerOnlyContextResolver; -import com.google.common.collect.Maps; import java.lang.annotation.Annotation; import java.lang.reflect.Parameter; @@ -39,7 +33,7 @@ import java.util.Map; @SuppressWarnings({"WeakerAccess", "unused"}) public class CommandExecutionContext { private final RegisteredCommand cmd; - private final Parameter param; + private final CommandParameter param; protected final I issuer; private final List args; private final int index; @@ -47,8 +41,8 @@ public class CommandExecutionContext flags; private final CommandManager manager; - CommandExecutionContext(RegisteredCommand cmd, Parameter param, I sender, List args, - int index, Map passedArgs) { + CommandExecutionContext(RegisteredCommand cmd, CommandParameter param, I sender, List args, + int index, Map passedArgs) { this.cmd = cmd; this.manager = cmd.scope.manager; this.param = param; @@ -56,35 +50,8 @@ public class CommandExecutionContext pCls = param.getType(); - do { - parseFlags(scope.contextFlags.get(pCls)); - } while ((pCls = pCls.getSuperclass()) != null); - } - if (scope.parentCommand != null) { - inheritContextFlags(scope.parentCommand); - } - } - - private void parseFlags(String flags) { - if (flags != null) { - for (String s : ACFPatterns.COMMA.split(manager.getCommandReplacements().replace(flags))) { - String[] v = ACFPatterns.EQUALS.split(s, 2); - if (!this.flags.containsKey(v[0])) { - this.flags.put(v[0], v.length > 1 ? v[1] : null); - } - } - } } public String popFirstArg() { @@ -112,19 +79,7 @@ public class CommandExecutionContext resolver = cmd.resolvers[i]; - if (parameter.getAnnotation(Optional.class) != null || parameter.getAnnotation(Default.class) != null) { - numRequired--; - } else if (resolver instanceof IssuerAwareContextResolver || resolver instanceof IssuerOnlyContextResolver) { - numRequired--; - } - } - - return numRequired >= args.size(); + return cmd.requiredResolvers >= args.size(); } public Object getResolvedArg(String arg) { @@ -156,7 +111,7 @@ public class CommandExecutionContext T getAnnotation(Class cls) { - return param.getAnnotation(cls); + return param.getParameter().getAnnotation(cls); } public boolean hasAnnotation(Class cls) { - return param.getAnnotation(cls) != null; + return param.getParameter().isAnnotationPresent(cls); } public RegisteredCommand getCmd() { @@ -183,7 +138,7 @@ public class CommandExecutionContext args, int i, Map passedArgs); + public abstract CommandExecutionContext createCommandContext(RegisteredCommand command, CommandParameter parameter, CommandIssuer sender, List args, int i, Map passedArgs); public abstract CommandCompletionContext createCompletionContext(RegisteredCommand command, CommandIssuer sender, String input, String config, String[] args); diff --git a/core/src/main/java/co/aikar/commands/CommandParameter.java b/core/src/main/java/co/aikar/commands/CommandParameter.java new file mode 100644 index 00000000..3f565eb4 --- /dev/null +++ b/core/src/main/java/co/aikar/commands/CommandParameter.java @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2016-2018 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.Default; +import co.aikar.commands.annotation.Description; +import co.aikar.commands.annotation.Flags; +import co.aikar.commands.annotation.Optional; +import co.aikar.commands.annotation.Values; +import co.aikar.commands.contexts.ContextResolver; +import co.aikar.commands.contexts.IssuerAwareContextResolver; +import co.aikar.commands.contexts.IssuerOnlyContextResolver; +import co.aikar.commands.contexts.OptionalContextResolver; +import com.google.common.collect.Maps; + +import java.lang.reflect.Parameter; +import java.util.Map; + +public class CommandParameter > { + private final Parameter parameter; + private final Class type; + private final String name; + private final CommandManager manager; + private final int paramIndex; + private ContextResolver resolver; + private boolean optional; + private String description; + private String defaultValue; + private boolean requiresInput; + private boolean commandIssuer; + private String[] values; + private Map flags; + private boolean canConsumeInput; + private boolean optionalResolver; + + public CommandParameter(RegisteredCommand command, Parameter param, int paramIndex) { + this.parameter = param; + this.type = param.getType(); + this.name = param.getName(); // do we care for an annotation to supply name? + //noinspection unchecked + this.manager = command.manager; + this.paramIndex = paramIndex; + CommandReplacements replacements = manager.getCommandReplacements(); + + Default defaultAnno = param.getAnnotation(Default.class); + Description descAnno = param.getAnnotation(Description.class); + + //noinspection unchecked + this.resolver = manager.getCommandContexts().getResolver(type); + if (this.resolver == null) { + ACFUtil.sneaky(new InvalidCommandContextException( + "Parameter " + type.getSimpleName() + " of " + command + " has no applicable context resolver" + )); + } + + this.description = descAnno != null ? descAnno.value() : null; + String defaultValue = defaultAnno != null ? replacements.replace(defaultAnno.value()) : null; + this.defaultValue = defaultValue != null && (type == String.class || !defaultValue.isEmpty()) ? defaultValue : null; + + + this.optional = param.isAnnotationPresent(Optional.class) || this.defaultValue != null; + this.optionalResolver = isOptionalResolver(resolver); + this.requiresInput = !this.optional && !this.optionalResolver; + //noinspection unchecked + this.commandIssuer = manager.isCommandIssuer(type); + this.canConsumeInput = !(resolver instanceof IssuerOnlyContextResolver); + + final Values values = param.getAnnotation(Values.class); + if (values != null) { + this.values = ACFPatterns.PIPE.split(manager.getCommandReplacements().replace(values.value())); + } else { + this.values = null; + } + this.flags = Maps.newHashMap(); + Flags flags = param.getAnnotation(Flags.class); + if (flags != null) { + parseFlags(flags.value()); + } + inheritContextFlags(command.scope); + } + + private void inheritContextFlags(BaseCommand scope) { + if (!scope.contextFlags.isEmpty()) { + Class pCls = this.type; + do { + parseFlags(scope.contextFlags.get(pCls)); + } while ((pCls = pCls.getSuperclass()) != null); + } + if (scope.parentCommand != null) { + inheritContextFlags(scope.parentCommand); + } + } + + private void parseFlags(String flags) { + if (flags != null) { + for (String s : ACFPatterns.COMMA.split(manager.getCommandReplacements().replace(flags))) { + String[] v = ACFPatterns.EQUALS.split(s, 2); + if (!this.flags.containsKey(v[0])) { + this.flags.put(v[0], v.length > 1 ? v[1] : null); + } + } + } + } + + private boolean isOptionalResolver(ContextResolver resolver) { + return resolver instanceof IssuerAwareContextResolver + || resolver instanceof IssuerOnlyContextResolver + || resolver instanceof OptionalContextResolver; + } + + + public Parameter getParameter() { + return parameter; + } + + public Class getType() { + return type; + } + + public String getName() { + return name; + } + + public CommandManager getManager() { + return manager; + } + + public int getParamIndex() { + return paramIndex; + } + + public ContextResolver getResolver() { + return resolver; + } + + public void setResolver(ContextResolver resolver) { + this.resolver = resolver; + } + + public boolean isOptional() { + return optional; + } + + public void setOptional(boolean optional) { + this.optional = optional; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getDefaultValue() { + return defaultValue; + } + + public void setDefaultValue(String defaultValue) { + this.defaultValue = defaultValue; + } + + public boolean isCommandIssuer() { + return commandIssuer; + } + + public void setCommandIssuer(boolean commandIssuer) { + this.commandIssuer = commandIssuer; + } + + public String[] getValues() { + return values; + } + + public void setValues(String[] values) { + this.values = values; + } + + public Map getFlags() { + return flags; + } + + public void setFlags(Map flags) { + this.flags = flags; + } + + public boolean canConsumeInput() { + return canConsumeInput; + } + + public void setCanConsumeInput(boolean canConsumeInput) { + this.canConsumeInput = canConsumeInput; + } + + public void setOptionalResolver(boolean optionalResolver) { + this.optionalResolver = optionalResolver; + } + + public boolean isOptionalResolver() { + return optionalResolver; + } + + public boolean requiresInput() { + return requiresInput; + } + + public void setRequiresInput(boolean requiresInput) { + this.requiresInput = requiresInput; + } + +} diff --git a/core/src/main/java/co/aikar/commands/RegisteredCommand.java b/core/src/main/java/co/aikar/commands/RegisteredCommand.java index 3fcf2151..28e82176 100644 --- a/core/src/main/java/co/aikar/commands/RegisteredCommand.java +++ b/core/src/main/java/co/aikar/commands/RegisteredCommand.java @@ -26,15 +26,9 @@ package co.aikar.commands; import co.aikar.commands.annotation.CommandAlias; import co.aikar.commands.annotation.CommandCompletion; import co.aikar.commands.annotation.CommandPermission; -import co.aikar.commands.annotation.Default; import co.aikar.commands.annotation.Description; -import co.aikar.commands.annotation.Optional; import co.aikar.commands.annotation.Syntax; -import co.aikar.commands.annotation.Values; import co.aikar.commands.contexts.ContextResolver; -import co.aikar.commands.contexts.IssuerAwareContextResolver; -import co.aikar.commands.contexts.IssuerOnlyContextResolver; -import co.aikar.commands.contexts.OptionalContextResolver; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Lists; import com.google.common.collect.Maps; @@ -57,8 +51,7 @@ public class RegisteredCommand [] resolvers; + final CommandParameter[] parameters; final String syntaxText; final String helpText; @@ -67,7 +60,7 @@ public class RegisteredCommand registeredSubcommands = new ArrayList<>(); - private final CommandManager manager; + final CommandManager manager; RegisteredCommand(BaseCommand scope, String command, Method method, String prefSubCommand) { this.scope = scope; @@ -82,46 +75,35 @@ public class RegisteredCommand type = parameter.getType(); + CommandParameter parameter = this.parameters[i] = new CommandParameter<>(this, parameters[i], i); - //noinspection unchecked - final ContextResolver resolver = commandContexts.getResolver(type); - if (resolver != null) { - resolvers[i] = resolver; - - if (!scope.manager.isCommandIssuer(type)) { - String name = parameter.getName(); - if (isOptionalResolver(resolver, parameter)) { - optionalResolvers++; - if (!(resolver instanceof IssuerOnlyContextResolver)) { - syntaxB.append('[').append(name).append("] "); - } - } else { - requiredResolvers++; - syntaxB.append('<').append(name).append("> "); + if (!parameter.isCommandIssuer()) { + String name = parameter.getName(); + if (!parameter.requiresInput()) { + optionalResolvers++; + if (parameter.canConsumeInput()) { + syntaxB.append('[').append(name).append("] "); } + } else { + requiredResolvers++; + syntaxB.append('<').append(name).append("> "); } - } else { - ACFUtil.sneaky(new InvalidCommandContextException( - "Parameter " + type.getSimpleName() + " of " + this.command + " has no applicable context resolver" - )); } + } String syntaxText = syntaxB.toString(); this.syntaxText = this.manager.getCommandReplacements().replace(syntaxStr != null ? @@ -130,16 +112,6 @@ public class RegisteredCommand resolver, Parameter parameter) { - return isOptionalResolver(resolver) - || parameter.getAnnotation(Optional.class) != null - || parameter.getAnnotation(Default.class) != null; - } - - private boolean isOptionalResolver(ContextResolver resolver) { - return resolver instanceof IssuerAwareContextResolver || resolver instanceof IssuerOnlyContextResolver - || resolver instanceof OptionalContextResolver; - } void invoke(CommandIssuer sender, List args, CommandOperationContext context) { if (!scope.canExecute(sender, this)) { @@ -208,24 +180,22 @@ public class RegisteredCommand parameter = parameters[i]; final String parameterName = parameter.getName(); final Class type = parameter.getType(); //noinspection unchecked - final ContextResolver resolver = resolvers[i]; + final ContextResolver resolver = parameter.getResolver(); //noinspection unchecked CEC context = (CEC) this.manager.createCommandContext(this, parameter, sender, args, i, passedArgs); - boolean isOptionalResolver = isOptionalResolver(resolver, parameter); - if (!isOptionalResolver) { + boolean requiresInput = parameter.requiresInput(); + if (requiresInput && remainingRequired > 0) { remainingRequired--; } if (args.isEmpty() && !(isLast && type == String[].class)) { - Default def = parameter.getAnnotation(Default.class); - Optional opt = parameter.getAnnotation(Optional.class); - if (allowOptional && def != null) { - args.add(scope.manager.getCommandReplacements().replace(def.value())); - } else if (allowOptional && opt != null) { - Object value = isOptionalResolver(resolver) ? resolver.getContext(context) : null; + if (allowOptional && parameter.getDefaultValue() != null) { + args.add(parameter.getDefaultValue()); + } else if (allowOptional && parameter.isOptional()) { + Object value = parameter.isOptionalResolver() ? resolver.getContext(context) : null; if (value == null && parameter.getClass().isPrimitive()) { throw new IllegalStateException("Parameter " + parameter.getName() + " is primitive and does not support Optional."); } @@ -234,20 +204,19 @@ public class RegisteredCommand possible = Sets.newHashSet(); - for (String s : split) { + CommandCompletions commandCompletions = this.manager.getCommandCompletions(); + for (String s : parameter.getValues()) { //noinspection unchecked - List check = this.manager.getCommandCompletions().getCompletionValues(this, sender, s, origArgs, opContext.isAsync()); + List check = commandCompletions.getCompletionValues(this, sender, s, origArgs, opContext.isAsync()); if (!check.isEmpty()) { possible.addAll(check.stream().map(String::toLowerCase).collect(Collectors.toList())); } else { diff --git a/jda/src/main/java/co/aikar/commands/JDACommandExecutionContext.java b/jda/src/main/java/co/aikar/commands/JDACommandExecutionContext.java index be6d2877..35e8f496 100644 --- a/jda/src/main/java/co/aikar/commands/JDACommandExecutionContext.java +++ b/jda/src/main/java/co/aikar/commands/JDACommandExecutionContext.java @@ -5,7 +5,7 @@ import java.util.List; import java.util.Map; public class JDACommandExecutionContext extends CommandExecutionContext { - JDACommandExecutionContext(RegisteredCommand cmd, Parameter param, JDACommandEvent sender, List args, int index, Map passedArgs) { + JDACommandExecutionContext(RegisteredCommand cmd, CommandParameter param, JDACommandEvent sender, List args, int index, Map passedArgs) { super(cmd, param, sender, args, index, passedArgs); } } diff --git a/jda/src/main/java/co/aikar/commands/JDACommandManager.java b/jda/src/main/java/co/aikar/commands/JDACommandManager.java index 472f052b..df336b59 100644 --- a/jda/src/main/java/co/aikar/commands/JDACommandManager.java +++ b/jda/src/main/java/co/aikar/commands/JDACommandManager.java @@ -9,7 +9,6 @@ import net.dv8tion.jda.core.entities.Message; import net.dv8tion.jda.core.events.message.MessageReceivedEvent; import org.jetbrains.annotations.NotNull; -import java.lang.reflect.Parameter; import java.util.Arrays; import java.util.List; import java.util.Map; @@ -195,7 +194,7 @@ public class JDACommandManager extends CommandManager< } @Override - public CommandExecutionContext createCommandContext(RegisteredCommand command, Parameter parameter, CommandIssuer sender, List args, int i, Map passedArgs) { + public CommandExecutionContext createCommandContext(RegisteredCommand command, CommandParameter parameter, CommandIssuer sender, List args, int i, Map passedArgs) { return new JDACommandExecutionContext(command, parameter, (JDACommandEvent) sender, args, i, passedArgs); } diff --git a/sponge/src/main/java/co/aikar/commands/SpongeCommandExecutionContext.java b/sponge/src/main/java/co/aikar/commands/SpongeCommandExecutionContext.java index 9226df83..d06f70fe 100644 --- a/sponge/src/main/java/co/aikar/commands/SpongeCommandExecutionContext.java +++ b/sponge/src/main/java/co/aikar/commands/SpongeCommandExecutionContext.java @@ -32,7 +32,7 @@ import java.util.Map; public class SpongeCommandExecutionContext extends CommandExecutionContext { - SpongeCommandExecutionContext(RegisteredCommand cmd, Parameter param, SpongeCommandIssuer sender, List args, + SpongeCommandExecutionContext(RegisteredCommand cmd, CommandParameter param, SpongeCommandIssuer sender, List args, int index, Map passedArgs) { super(cmd, param, sender, args, index, passedArgs); } diff --git a/sponge/src/main/java/co/aikar/commands/SpongeCommandManager.java b/sponge/src/main/java/co/aikar/commands/SpongeCommandManager.java index 19798dc4..811c25d6 100644 --- a/sponge/src/main/java/co/aikar/commands/SpongeCommandManager.java +++ b/sponge/src/main/java/co/aikar/commands/SpongeCommandManager.java @@ -34,7 +34,6 @@ import org.spongepowered.api.text.format.TextColor; import org.spongepowered.api.text.format.TextColors; import java.lang.reflect.Method; -import java.lang.reflect.Parameter; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -146,7 +145,7 @@ public class SpongeCommandManager extends CommandManager< } @Override - public SpongeCommandExecutionContext createCommandContext(RegisteredCommand command, Parameter parameter, CommandIssuer sender, List args, int i, Map passedArgs) { + public SpongeCommandExecutionContext createCommandContext(RegisteredCommand command, CommandParameter parameter, CommandIssuer sender, List args, int i, Map passedArgs) { return new SpongeCommandExecutionContext(command, parameter, (SpongeCommandIssuer) sender, args, i, passedArgs); }