diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/inject/CloudModule.java b/Bukkit/src/main/java/com/plotsquared/bukkit/inject/CloudModule.java index af098aef9d..dade29c3d7 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/inject/CloudModule.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/inject/CloudModule.java @@ -29,8 +29,9 @@ import com.plotsquared.bukkit.BukkitPlatform; import com.plotsquared.bukkit.commands.BukkitSenderMapper; import com.plotsquared.bukkit.util.BukkitUtil; +import com.plotsquared.core.commands.CommandRequirement; import com.plotsquared.core.commands.PlotSquaredCaptionProvider; -import com.plotsquared.core.commands.processing.CommandRequirementPostprocessor; +import com.plotsquared.core.commands.PlotSquaredRequirementFailureHandler; import com.plotsquared.core.configuration.caption.TranslatableCaption; import com.plotsquared.core.player.ConsolePlayer; import com.plotsquared.core.player.PlotPlayer; @@ -40,6 +41,7 @@ import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.checkerframework.checker.nullness.qual.NonNull; +import org.incendo.cloud.requirement.RequirementPostprocessor; public class CloudModule extends AbstractModule { @@ -80,7 +82,8 @@ protected void configure() { commandManager.registerAsynchronousCompletions(); } - final CommandRequirementPostprocessor requirementPostprocessor = new CommandRequirementPostprocessor(); + final RequirementPostprocessor, CommandRequirement> requirementPostprocessor = + RequirementPostprocessor.of(CommandRequirement.REQUIREMENTS_KEY, new PlotSquaredRequirementFailureHandler()); commandManager.registerCommandPostProcessor(requirementPostprocessor); // TODO(City): Override parsing errors using MM parsing. diff --git a/Core/build.gradle.kts b/Core/build.gradle.kts index 3ea85bff09..7e1dd24eb9 100644 --- a/Core/build.gradle.kts +++ b/Core/build.gradle.kts @@ -18,6 +18,7 @@ dependencies { // Cloud api(libs.cloud) api(libs.cloudMinecraftExtras) + api(libs.cloudRequirements) // Guice api(libs.guice) { diff --git a/Core/src/main/java/com/plotsquared/core/commands/CommandRequirement.java b/Core/src/main/java/com/plotsquared/core/commands/CommandRequirement.java index 89dd70b365..d5a7bd8dcc 100644 --- a/Core/src/main/java/com/plotsquared/core/commands/CommandRequirement.java +++ b/Core/src/main/java/com/plotsquared/core/commands/CommandRequirement.java @@ -19,34 +19,39 @@ package com.plotsquared.core.commands; import cloud.commandframework.context.CommandContext; +import cloud.commandframework.keys.CloudKey; import com.plotsquared.core.configuration.caption.TranslatableCaption; import com.plotsquared.core.permissions.Permission; import com.plotsquared.core.player.PlotPlayer; +import io.leangen.geantyref.TypeToken; import net.kyori.adventure.text.minimessage.tag.Tag; import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; import org.checkerframework.checker.nullness.qual.NonNull; +import org.incendo.cloud.requirement.Requirement; +import org.incendo.cloud.requirement.Requirements; import java.util.List; /** * Something that is required for a command to be executed. */ -public interface CommandRequirement { +public interface CommandRequirement extends Requirement, CommandRequirement> { /** - * Returns the caption sent when the requirement is not met. - * - * @return the caption + * The key used to store the requirements in the {@link cloud.commandframework.meta.CommandMeta}. */ - @NonNull TranslatableCaption failureCaption(); + CloudKey, CommandRequirement>> REQUIREMENTS_KEY = CloudKey.of( + "requirements", + new TypeToken, CommandRequirement>>() { + } + ); /** - * Evaluates whether the requirement is met. + * Returns the caption sent when the requirement is not met. * - * @param context command context to evaluate - * @return {@code true} if the requirement is met, else {@code false} + * @return the caption */ - boolean evaluate(final @NonNull CommandContext> context); + @NonNull TranslatableCaption failureCaption(); /** * Returns the placeholder values. @@ -57,15 +62,6 @@ public interface CommandRequirement { return new TagResolver[0]; } - /** - * Returns the list of parent requirements that should be evaluated before this requirement. - * - * @return the requirements - */ - default @NonNull List<@NonNull CommandRequirement> parents() { - return List.of(); - } - /** * Returns a requirement that evaluates to {@code true} if the sender has the given {@code permission} or if * this requirement evaluates to {@code true}. @@ -94,8 +90,8 @@ public interface CommandRequirement { } @Override - public boolean evaluate(final @NonNull CommandContext> context) { - return context.sender().hasPermission(permission) || thisRequirement.evaluate(context); + public boolean evaluateRequirement(final @NonNull CommandContext> context) { + return context.sender().hasPermission(permission) || thisRequirement.evaluateRequirement(context); } }; } diff --git a/Core/src/main/java/com/plotsquared/core/commands/CommandRequirements.java b/Core/src/main/java/com/plotsquared/core/commands/CommandRequirements.java deleted file mode 100644 index 7f5aa69d01..0000000000 --- a/Core/src/main/java/com/plotsquared/core/commands/CommandRequirements.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * PlotSquared, a land and world management plugin for Minecraft. - * Copyright (C) IntellectualSites - * Copyright (C) IntellectualSites team and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.plotsquared.core.commands; - -import cloud.commandframework.keys.CloudKey; -import org.checkerframework.checker.nullness.qual.NonNull; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -/** - * Holder of {@link CommandRequirement} requirements. - */ -public final class CommandRequirements implements Iterable<@NonNull CommandRequirement> { - - /** - * The key used to store the requirements in the {@link cloud.commandframework.meta.CommandMeta}. - */ - public static final CloudKey REQUIREMENTS_KEY = CloudKey.of( - "requirements", - CommandRequirements.class - ); - - /** - * Creates a new instance. - * - * @param requirements the requirements - * @return the instance - */ - public static @NonNull CommandRequirements create(final @NonNull List<@NonNull CommandRequirement> requirements) { - return new CommandRequirements(requirements); - } - - private static @NonNull List<@NonNull CommandRequirement> extractRequirements( - final @NonNull List<@NonNull CommandRequirement> requirements - ) { - final List extractedRequirements = new ArrayList<>(); - for (final CommandRequirement requirement : requirements) { - extractedRequirements.addAll(extractRequirements(requirement.parents())); - extractedRequirements.add(requirement); - } - return extractedRequirements; - } - - private final List requirements; - - private CommandRequirements(final @NonNull List<@NonNull CommandRequirement> requirements) { - this.requirements = List.copyOf(extractRequirements(requirements)); - } - - @Override - public @NonNull Iterator<@NonNull CommandRequirement> iterator() { - return this.requirements.iterator(); - } -} diff --git a/Core/src/main/java/com/plotsquared/core/commands/CommonCommandRequirement.java b/Core/src/main/java/com/plotsquared/core/commands/CommonCommandRequirement.java index e58da8b6ea..30914c564d 100644 --- a/Core/src/main/java/com/plotsquared/core/commands/CommonCommandRequirement.java +++ b/Core/src/main/java/com/plotsquared/core/commands/CommonCommandRequirement.java @@ -75,7 +75,7 @@ public enum CommonCommandRequirement implements CommandRequirement { } @Override - public boolean evaluate(final @NonNull CommandContext> context) { + public boolean evaluateRequirement(final @NonNull CommandContext> context) { return this.predicate.test(context); } } diff --git a/Core/src/main/java/com/plotsquared/core/commands/PlotSquaredCommandBean.java b/Core/src/main/java/com/plotsquared/core/commands/PlotSquaredCommandBean.java index 484b160d95..7859eb314a 100644 --- a/Core/src/main/java/com/plotsquared/core/commands/PlotSquaredCommandBean.java +++ b/Core/src/main/java/com/plotsquared/core/commands/PlotSquaredCommandBean.java @@ -24,11 +24,16 @@ import com.plotsquared.core.command.CommandCategory; import com.plotsquared.core.player.PlotPlayer; import org.checkerframework.checker.nullness.qual.NonNull; +import org.incendo.cloud.requirement.RequirementApplicable; +import org.incendo.cloud.requirement.Requirements; import java.util.List; public abstract class PlotSquaredCommandBean extends CommandBean> { + private final RequirementApplicable.RequirementApplicableFactory, CommandRequirement> + requirementApplicableFactory = RequirementApplicable.factory(CommandRequirement.REQUIREMENTS_KEY); + /** * Returns the category of the command. * @@ -64,7 +69,7 @@ public abstract class PlotSquaredCommandBean extends CommandBean> @Override protected final Command.@NonNull Builder> configure(final Command.@NonNull Builder> builder) { return this.configurePlotCommand(this.prepare(builder.meta(PlotSquaredCommandMeta.META_CATEGORY, this.category()))) - .meta(CommandRequirements.REQUIREMENTS_KEY, CommandRequirements.create(this.requirements())); + .apply(this.requirementApplicableFactory.create(Requirements.of(this.requirements()))); } protected abstract Command.@NonNull Builder> configurePlotCommand( diff --git a/Core/src/main/java/com/plotsquared/core/commands/PlotSquaredRequirementFailureHandler.java b/Core/src/main/java/com/plotsquared/core/commands/PlotSquaredRequirementFailureHandler.java new file mode 100644 index 0000000000..50d26b1fd2 --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/commands/PlotSquaredRequirementFailureHandler.java @@ -0,0 +1,35 @@ +/* + * PlotSquared, a land and world management plugin for Minecraft. + * Copyright (C) IntellectualSites + * Copyright (C) IntellectualSites team and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.plotsquared.core.commands; + +import cloud.commandframework.context.CommandContext; +import com.plotsquared.core.player.PlotPlayer; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.incendo.cloud.requirement.RequirementFailureHandler; + +public final class PlotSquaredRequirementFailureHandler implements RequirementFailureHandler, CommandRequirement> { + + @Override + public void handleFailure( + final @NonNull CommandContext> context, + final @NonNull CommandRequirement requirement + ) { + context.sender().sendMessage(requirement.failureCaption(), requirement.tagResolvers()); + } +} diff --git a/Core/src/main/java/com/plotsquared/core/commands/processing/CommandRequirementPostprocessor.java b/Core/src/main/java/com/plotsquared/core/commands/processing/CommandRequirementPostprocessor.java deleted file mode 100644 index 36fad14d1f..0000000000 --- a/Core/src/main/java/com/plotsquared/core/commands/processing/CommandRequirementPostprocessor.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * PlotSquared, a land and world management plugin for Minecraft. - * Copyright (C) IntellectualSites - * Copyright (C) IntellectualSites team and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.plotsquared.core.commands.processing; - -import cloud.commandframework.execution.postprocessor.CommandPostprocessingContext; -import cloud.commandframework.execution.postprocessor.CommandPostprocessor; -import cloud.commandframework.services.types.ConsumerService; -import com.plotsquared.core.commands.CommandRequirement; -import com.plotsquared.core.commands.CommandRequirements; -import com.plotsquared.core.player.PlotPlayer; -import org.checkerframework.checker.nullness.qual.NonNull; - -/** - * Processor that evaluates registered {@link CommandRequirement command requirements} before a command is executed. - */ -public final class CommandRequirementPostprocessor implements CommandPostprocessor> { - - @Override - public void accept(final @NonNull CommandPostprocessingContext> processingContext) { - final CommandRequirements requirements = processingContext.command().commandMeta().getOrDefault( - CommandRequirements.REQUIREMENTS_KEY, - null - ); - if (requirements == null) { - return; - } - for (final CommandRequirement requirement : requirements) { - if (requirement.evaluate(processingContext.commandContext())) { - continue; - } - processingContext.commandContext().sender().sendMessage(requirement.failureCaption(), requirement.tagResolvers()); - // Not allowed :( - ConsumerService.interrupt(); - } - } -} diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index a5a7ccab00..37449159ff 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -32,6 +32,7 @@ informative-annotations = "1.4" vault = "1.7.1" serverlib = "2.3.4" cloud = "2.0.0-SNAPSHOT" +cloudRequirements = "1.0.0-SNAPSHOT" # Gradle plugins shadow = "8.1.1" @@ -81,6 +82,7 @@ serverlib = { group = "dev.notmyfault.serverlib", name = "ServerLib", version.re cloud = { group = "cloud.commandframework", name = "cloud-core", version.ref = "cloud" } cloudPaper = { group = "cloud.commandframework", name = "cloud-paper", version.ref = "cloud" } cloudMinecraftExtras = { group = "cloud.commandframework", name = "cloud-minecraft-extras", version.ref = "cloud" } +cloudRequirements = { group = "org.incendo", name = "cloud-requirements", version.ref = "cloudRequirements" } [plugins] shadow = { id = "com.github.johnrengelman.shadow", version.ref = "shadow" }