mirror of
				https://github.com/IntellectualSites/PlotSquared.git
				synced 2025-10-31 01:23:44 +01:00 
			
		
		
		
	improve the requirement system
This commit is contained in:
		| @@ -28,7 +28,6 @@ import com.google.inject.Key; | |||||||
| import com.google.inject.TypeLiteral; | import com.google.inject.TypeLiteral; | ||||||
| import com.plotsquared.bukkit.BukkitPlatform; | import com.plotsquared.bukkit.BukkitPlatform; | ||||||
| import com.plotsquared.bukkit.util.BukkitUtil; | import com.plotsquared.bukkit.util.BukkitUtil; | ||||||
| import com.plotsquared.core.commands.CommonCommandRequirement; |  | ||||||
| import com.plotsquared.core.commands.PlotSquaredCaptionProvider; | import com.plotsquared.core.commands.PlotSquaredCaptionProvider; | ||||||
| import com.plotsquared.core.commands.processing.CommandRequirementPostprocessor; | import com.plotsquared.core.commands.processing.CommandRequirementPostprocessor; | ||||||
| import com.plotsquared.core.configuration.caption.TranslatableCaption; | import com.plotsquared.core.configuration.caption.TranslatableCaption; | ||||||
| @@ -83,7 +82,6 @@ public class CloudModule extends AbstractModule { | |||||||
|             } |             } | ||||||
|  |  | ||||||
|             final CommandRequirementPostprocessor requirementPostprocessor = new CommandRequirementPostprocessor(); |             final CommandRequirementPostprocessor requirementPostprocessor = new CommandRequirementPostprocessor(); | ||||||
|             requirementPostprocessor.registerRequirements(CommonCommandRequirement.values()); |  | ||||||
|             commandManager.registerCommandPostProcessor(requirementPostprocessor); |             commandManager.registerCommandPostProcessor(requirementPostprocessor); | ||||||
|  |  | ||||||
|             // TODO(City): Override parsing errors using MM parsing. |             // TODO(City): Override parsing errors using MM parsing. | ||||||
|   | |||||||
| @@ -19,15 +19,17 @@ | |||||||
| package com.plotsquared.core.commands; | package com.plotsquared.core.commands; | ||||||
|  |  | ||||||
| import cloud.commandframework.context.CommandContext; | import cloud.commandframework.context.CommandContext; | ||||||
| import cloud.commandframework.keys.CloudKeyHolder; |  | ||||||
| import com.plotsquared.core.configuration.caption.TranslatableCaption; | import com.plotsquared.core.configuration.caption.TranslatableCaption; | ||||||
|  | import com.plotsquared.core.permissions.Permission; | ||||||
| import com.plotsquared.core.player.PlotPlayer; | import com.plotsquared.core.player.PlotPlayer; | ||||||
|  | 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.checkerframework.checker.nullness.qual.NonNull; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Something that is required for a command to be executed. |  * Something that is required for a command to be executed. | ||||||
|  */ |  */ | ||||||
| public interface CommandRequirement extends CloudKeyHolder<Boolean> { | public interface CommandRequirement { | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * Returns the caption sent when the requirement is not met. |      * Returns the caption sent when the requirement is not met. | ||||||
| @@ -43,4 +45,42 @@ public interface CommandRequirement extends CloudKeyHolder<Boolean> { | |||||||
|      * @return {@code true} if the requirement is met, else {@code false} |      * @return {@code true} if the requirement is met, else {@code false} | ||||||
|      */ |      */ | ||||||
|     boolean evaluate(final @NonNull CommandContext<PlotPlayer<?>> context); |     boolean evaluate(final @NonNull CommandContext<PlotPlayer<?>> context); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Returns the placeholder values. | ||||||
|  |      * | ||||||
|  |      * @return placeholder values | ||||||
|  |      */ | ||||||
|  |     default @NonNull TagResolver @NonNull[] tagResolvers() { | ||||||
|  |         return new TagResolver[0]; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Returns a requirement that evaluates to {@code true} if the sender has the given {@code permission} or if | ||||||
|  |      * this requirement evaluates to {@code true}. | ||||||
|  |      * | ||||||
|  |      * @param permission the override permission | ||||||
|  |      * @return the new requirement | ||||||
|  |      */ | ||||||
|  |     default @NonNull CommandRequirement withPermissionOverride(final @NonNull Permission permission) { | ||||||
|  |         final CommandRequirement thisRequirement = this; | ||||||
|  |         return new CommandRequirement() { | ||||||
|  |             @Override | ||||||
|  |             public @NonNull TranslatableCaption failureCaption() { | ||||||
|  |                 return TranslatableCaption.of("permission.no_permission"); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             @Override | ||||||
|  |             public @NonNull TagResolver @NonNull [] tagResolvers() { | ||||||
|  |                 return new TagResolver[] { | ||||||
|  |                         TagResolver.resolver("node", Tag.inserting(Permission.PERMISSION_SET_FLAG_OTHER)) | ||||||
|  |                 }; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             @Override | ||||||
|  |             public boolean evaluate(final @NonNull CommandContext<PlotPlayer<?>> context) { | ||||||
|  |                 return context.sender().hasPermission(permission) || thisRequirement.evaluate(context); | ||||||
|  |             } | ||||||
|  |         }; | ||||||
|  |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -0,0 +1,61 @@ | |||||||
|  | /* | ||||||
|  |  * PlotSquared, a land and world management plugin for Minecraft. | ||||||
|  |  * Copyright (C) IntellectualSites <https://intellectualsites.com> | ||||||
|  |  * 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 <https://www.gnu.org/licenses/>. | ||||||
|  |  */ | ||||||
|  | package com.plotsquared.core.commands; | ||||||
|  |  | ||||||
|  | import cloud.commandframework.keys.CloudKey; | ||||||
|  | import org.checkerframework.checker.nullness.qual.NonNull; | ||||||
|  |  | ||||||
|  | import java.util.Collection; | ||||||
|  | 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<CommandRequirements> 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 Collection<@NonNull CommandRequirement> requirements) { | ||||||
|  |         return new CommandRequirements(requirements); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private final List<CommandRequirement> requirements; | ||||||
|  |  | ||||||
|  |     private CommandRequirements(final @NonNull Collection<@NonNull CommandRequirement> requirements) { | ||||||
|  |         this.requirements = List.copyOf(requirements); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public @NonNull Iterator<@NonNull CommandRequirement> iterator() { | ||||||
|  |         return this.requirements.iterator(); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -19,7 +19,6 @@ | |||||||
| package com.plotsquared.core.commands; | package com.plotsquared.core.commands; | ||||||
|  |  | ||||||
| import cloud.commandframework.context.CommandContext; | import cloud.commandframework.context.CommandContext; | ||||||
| import cloud.commandframework.keys.CloudKey; |  | ||||||
| import com.plotsquared.core.configuration.caption.TranslatableCaption; | import com.plotsquared.core.configuration.caption.TranslatableCaption; | ||||||
| import com.plotsquared.core.player.PlotPlayer; | import com.plotsquared.core.player.PlotPlayer; | ||||||
| import org.checkerframework.checker.nullness.qual.NonNull; | import org.checkerframework.checker.nullness.qual.NonNull; | ||||||
| @@ -39,7 +38,14 @@ public enum CommonCommandRequirement implements CommandRequirement { | |||||||
|      */ |      */ | ||||||
|     REQUIRES_OWNER(TranslatableCaption.of("working.plot_not_claimed"), |     REQUIRES_OWNER(TranslatableCaption.of("working.plot_not_claimed"), | ||||||
|             ctx -> ctx.sender().getCurrentPlot() != null && ctx.sender().getCurrentPlot().hasOwner() |             ctx -> ctx.sender().getCurrentPlot() != null && ctx.sender().getCurrentPlot().hasOwner() | ||||||
|     ); |     ), | ||||||
|  |     /** | ||||||
|  |      * Requires that the command sender is the plot owner. | ||||||
|  |      */ | ||||||
|  |     IS_OWNER(TranslatableCaption.of("permission.no_plot_perms"), | ||||||
|  |             ctx -> ctx.sender().getCurrentPlot() != null && ctx.sender().getCurrentPlot().isOwner(ctx.sender().getUUID()) | ||||||
|  |     ) | ||||||
|  |     ; | ||||||
|  |  | ||||||
|     private final TranslatableCaption failureCaption; |     private final TranslatableCaption failureCaption; | ||||||
|     private final Predicate<CommandContext<PlotPlayer<?>>> predicate; |     private final Predicate<CommandContext<PlotPlayer<?>>> predicate; | ||||||
| @@ -60,9 +66,4 @@ public enum CommonCommandRequirement implements CommandRequirement { | |||||||
|     public boolean evaluate(final @NonNull CommandContext<PlotPlayer<?>> context) { |     public boolean evaluate(final @NonNull CommandContext<PlotPlayer<?>> context) { | ||||||
|         return this.predicate.test(context); |         return this.predicate.test(context); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |  | ||||||
|     public @NonNull CloudKey<Boolean> key() { |  | ||||||
|         return CloudKey.of(String.format("requirement_%s", this.name()), Boolean.class); |  | ||||||
|     } |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -63,12 +63,8 @@ public abstract class PlotSquaredCommandBean extends CommandBean<PlotPlayer<?>> | |||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     protected final Command.@NonNull Builder<PlotPlayer<?>> configure(final Command.@NonNull Builder<PlotPlayer<?>> builder) { |     protected final Command.@NonNull Builder<PlotPlayer<?>> configure(final Command.@NonNull Builder<PlotPlayer<?>> builder) { | ||||||
|         Command.@NonNull Builder<PlotPlayer<?>> intermediaryBuilder = |         return this.configurePlotCommand(this.prepare(builder.meta(PlotSquaredCommandMeta.META_CATEGORY, this.category()))) | ||||||
|                 this.configurePlotCommand(this.prepare(builder.meta(PlotSquaredCommandMeta.META_CATEGORY, this.category()))); |                 .meta(CommandRequirements.REQUIREMENTS_KEY, CommandRequirements.create(this.requirements())); | ||||||
|         for (final CommandRequirement requirement : this.requirements()) { |  | ||||||
|             intermediaryBuilder = intermediaryBuilder.meta(requirement.key(), true); |  | ||||||
|         } |  | ||||||
|         return intermediaryBuilder; |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     protected abstract Command.@NonNull Builder<PlotPlayer<?>> configurePlotCommand( |     protected abstract Command.@NonNull Builder<PlotPlayer<?>> configurePlotCommand( | ||||||
|   | |||||||
| @@ -130,8 +130,11 @@ public abstract class FlagCommandBean extends PlotSquaredCommandBean { | |||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public @NonNull Set<@NonNull CommandRequirement> requirements() { |     public @NonNull Set<@NonNull CommandRequirement> requirements() { | ||||||
|         // TODO: Figure out how to handle the override permission check :) |         return Set.of( | ||||||
|         return Set.of(CommonCommandRequirement.REQUIRES_PLOT, CommonCommandRequirement.REQUIRES_OWNER); |                 CommonCommandRequirement.REQUIRES_PLOT, | ||||||
|  |                 CommonCommandRequirement.REQUIRES_OWNER, | ||||||
|  |                 CommonCommandRequirement.IS_OWNER.withPermissionOverride(Permission.PERMISSION_SET_FLAG_OTHER) | ||||||
|  |         ); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|   | |||||||
| @@ -22,58 +22,29 @@ import cloud.commandframework.execution.postprocessor.CommandPostprocessingConte | |||||||
| import cloud.commandframework.execution.postprocessor.CommandPostprocessor; | import cloud.commandframework.execution.postprocessor.CommandPostprocessor; | ||||||
| import cloud.commandframework.services.types.ConsumerService; | import cloud.commandframework.services.types.ConsumerService; | ||||||
| import com.plotsquared.core.commands.CommandRequirement; | import com.plotsquared.core.commands.CommandRequirement; | ||||||
|  | import com.plotsquared.core.commands.CommandRequirements; | ||||||
| import com.plotsquared.core.player.PlotPlayer; | import com.plotsquared.core.player.PlotPlayer; | ||||||
| import org.checkerframework.checker.nullness.qual.NonNull; | import org.checkerframework.checker.nullness.qual.NonNull; | ||||||
|  |  | ||||||
| import java.util.ArrayList; |  | ||||||
| import java.util.Arrays; |  | ||||||
| import java.util.Collection; |  | ||||||
| import java.util.Objects; |  | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Processor that evaluates registered {@link CommandRequirement command requirements} before a command is executed. |  * Processor that evaluates registered {@link CommandRequirement command requirements} before a command is executed. | ||||||
|  */ |  */ | ||||||
| public final class CommandRequirementPostprocessor implements CommandPostprocessor<PlotPlayer<?>> { | public final class CommandRequirementPostprocessor implements CommandPostprocessor<PlotPlayer<?>> { | ||||||
|  |  | ||||||
|     private final Collection<@NonNull CommandRequirement> requirements = new ArrayList<>(); |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * Requires a single requirement. |  | ||||||
|      * |  | ||||||
|      * @param requirement the requirement |  | ||||||
|      */ |  | ||||||
|     public void registerRequirement(final @NonNull CommandRequirement requirement) { |  | ||||||
|         this.requirements.add(Objects.requireNonNull(requirement, "requirement")); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * Registers the given {@code requirements}. |  | ||||||
|      * |  | ||||||
|      * @param requirements the requirements |  | ||||||
|      */ |  | ||||||
|     public void registerRequirements(final @NonNull Collection<@NonNull CommandRequirement> requirements) { |  | ||||||
|         requirements.forEach(this::registerRequirement); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * Registers the given {@code requirements}. |  | ||||||
|      * |  | ||||||
|      * @param requirements the requirements |  | ||||||
|      */ |  | ||||||
|     public void registerRequirements(final @NonNull CommandRequirement @NonNull... requirements) { |  | ||||||
|         this.registerRequirements(Arrays.asList(requirements)); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public void accept(final @NonNull CommandPostprocessingContext<PlotPlayer<?>> processingContext) { |     public void accept(final @NonNull CommandPostprocessingContext<PlotPlayer<?>> processingContext) { | ||||||
|         for (final CommandRequirement requirement : this.requirements) { |         final CommandRequirements requirements = processingContext.command().commandMeta().getOrDefault( | ||||||
|             if (!processingContext.command().commandMeta().getOrDefault(requirement.key(), false)) { |                 CommandRequirements.REQUIREMENTS_KEY, | ||||||
|                 continue; |                 null | ||||||
|             } |         ); | ||||||
|  |         if (requirements == null) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |         for (final CommandRequirement requirement : requirements) { | ||||||
|             if (requirement.evaluate(processingContext.commandContext())) { |             if (requirement.evaluate(processingContext.commandContext())) { | ||||||
|                 continue; |                 continue; | ||||||
|             } |             } | ||||||
|             processingContext.commandContext().sender().sendMessage(requirement.failureCaption()); |             processingContext.commandContext().sender().sendMessage(requirement.failureCaption(), requirement.tagResolvers()); | ||||||
|             // Not allowed :( |             // Not allowed :( | ||||||
|             ConsumerService.interrupt(); |             ConsumerService.interrupt(); | ||||||
|         } |         } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Alexander Söderberg
					Alexander Söderberg