diff --git a/core/src/main/java/co/aikar/commands/CommandConditions.java b/core/src/main/java/co/aikar/commands/CommandConditions.java new file mode 100644 index 00000000..4fb56566 --- /dev/null +++ b/core/src/main/java/co/aikar/commands/CommandConditions.java @@ -0,0 +1,86 @@ +/* + * 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 com.google.common.collect.Maps; + +import java.util.Map; + +@SuppressWarnings("BooleanMethodIsAlwaysInverted") // No IDEA, you are wrong +public class CommandConditions { + M manager; + Map> conditions = Maps.newHashMap(); + CommandConditions(M manager) { + this.manager = manager; + } + + Condition addCondition(String id, Condition handler) { + return this.conditions.put(id.toLowerCase(), handler); + } + + boolean validateConditions(CommandOperationContext context) { + RegisteredCommand cmd = context.getRegisteredCommand(); + Conditions conditions = cmd.method.getAnnotation(Conditions.class); + if (conditions != null) { + if (!validateConditions(conditions, context)) { + return false; + } + } + return validateConditions(cmd.scope, context); + } + + + private boolean validateConditions(BaseCommand scope, CommandOperationContext operationContext) { + Conditions conditions = scope.getClass().getAnnotation(Conditions.class); + //noinspection SimplifiableIfStatement + if (!validateConditions(conditions, operationContext)) { + return false; + } + return scope.parentCommand == null || validateConditions(scope.parentCommand, operationContext); + } + + private boolean validateConditions(Conditions condAnno, CommandOperationContext context) { + if (condAnno == null) { + return true; + } + //noinspection unchecked + CC conditionContext = (CC) this.manager.createConditionContext(context); + String conditions = this.manager.getCommandReplacements().replace(condAnno.value()); + for (String cond : ACFPatterns.PIPE.split(conditions)) { + String[] split = ACFPatterns.EQUALS.split(cond, 2); + Condition condition = this.conditions.get(split[0].toLowerCase()); + + if (!condition.validateCondition(conditionContext)) { + return false; + } + } + + return true; + } + + interface Condition { + boolean validateCondition(CC context); + } +} diff --git a/core/src/main/java/co/aikar/commands/CommandManager.java b/core/src/main/java/co/aikar/commands/CommandManager.java index 7d8fae07..319b5143 100644 --- a/core/src/main/java/co/aikar/commands/CommandManager.java +++ b/core/src/main/java/co/aikar/commands/CommandManager.java @@ -195,6 +195,10 @@ public abstract class CommandManager R createConditionContext(CommandOperationContext context) { + //noinspection unchecked + return (R) new ConditionContext<>(context.getRegisteredCommand(), context.getCommandIssuer()); + } public abstract R createCommandContext(RegisteredCommand command, Parameter parameter, CommandIssuer sender, List args, int i, Map passedArgs); @@ -327,10 +331,11 @@ public abstract class CommandManager createCommandOperationContext(BaseCommand command, CommandIssuer issuer, String commandLabel, String[] args, boolean isAsync) { + //noinspection unchecked + return new CommandOperationContext<>( this, - issuer, + (AI) issuer, command, commandLabel, args, diff --git a/core/src/main/java/co/aikar/commands/CommandOperationContext.java b/core/src/main/java/co/aikar/commands/CommandOperationContext.java index 4cd87932..8e9c0e40 100644 --- a/core/src/main/java/co/aikar/commands/CommandOperationContext.java +++ b/core/src/main/java/co/aikar/commands/CommandOperationContext.java @@ -28,17 +28,17 @@ import java.lang.annotation.Annotation; /** * Holds information about the currently executing command on this thread */ -public class CommandOperationContext { +public class CommandOperationContext { private final CommandManager manager; - private final CommandIssuer issuer; + private final I issuer; private final BaseCommand command; private final String commandLabel; private final String[] args; private final boolean isAsync; private RegisteredCommand registeredCommand; - CommandOperationContext(CommandManager manager, CommandIssuer issuer, BaseCommand command, String commandLabel, String[] args, boolean isAsync) { + CommandOperationContext(CommandManager manager, I issuer, BaseCommand command, String commandLabel, String[] args, boolean isAsync) { this.manager = manager; this.issuer = issuer; this.command = command; @@ -51,7 +51,7 @@ public class CommandOperationContext { return manager; } - public CommandIssuer getCommandIssuer() { + public I getCommandIssuer() { return issuer; } diff --git a/core/src/main/java/co/aikar/commands/ConditionContext.java b/core/src/main/java/co/aikar/commands/ConditionContext.java new file mode 100644 index 00000000..853814ca --- /dev/null +++ b/core/src/main/java/co/aikar/commands/ConditionContext.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; + +public class ConditionContext { + + private final RegisteredCommand cmd; + private final I issuer; + + ConditionContext(RegisteredCommand cmd, I issuer) { + this.cmd = cmd; + this.issuer = issuer; + } + + public RegisteredCommand getCmd() { + return cmd; + } + + public I getIssuer() { + return issuer; + } +} diff --git a/core/src/main/java/co/aikar/commands/annotation/Conditions.java b/core/src/main/java/co/aikar/commands/annotation/Conditions.java new file mode 100644 index 00000000..f53fbe86 --- /dev/null +++ b/core/src/main/java/co/aikar/commands/annotation/Conditions.java @@ -0,0 +1,35 @@ +/* + * 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.annotation; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * @deprecated This isn't ready yet + */ +@Retention(RetentionPolicy.RUNTIME) +public @interface Conditions { + String value(); +} diff --git a/example/src/main/java/co/aikar/acfexample/SomeCommand.java b/example/src/main/java/co/aikar/acfexample/SomeCommand.java index de43ab8d..a2f83e16 100644 --- a/example/src/main/java/co/aikar/acfexample/SomeCommand.java +++ b/example/src/main/java/co/aikar/acfexample/SomeCommand.java @@ -27,6 +27,7 @@ import co.aikar.commands.BaseCommand; import co.aikar.commands.annotation.CommandAlias; import co.aikar.commands.annotation.CommandCompletion; import co.aikar.commands.annotation.CommandPermission; +import co.aikar.commands.annotation.Conditions; import co.aikar.commands.annotation.Default; import co.aikar.commands.annotation.Optional; import co.aikar.commands.annotation.Subcommand; @@ -48,6 +49,12 @@ public class SomeCommand extends BaseCommand { sender.sendMessage("You got an object of type: " + someObject.getClass().getName() + " with a value of: " + someObject.getValue()); } + @Subcommand("condition") + @Conditions("condition=1") + public void onCondition(CommandSender sender) { + + } + // /acf admin - requires permission some.perm // May also be accessed with /acfa or /acfadmin @Subcommand("admin")