Skip to content

Commit 982f38a

Browse files
committed
improve the requirement system
1 parent b30b695 commit 982f38a

File tree

7 files changed

+128
-58
lines changed

7 files changed

+128
-58
lines changed

Bukkit/src/main/java/com/plotsquared/bukkit/inject/CloudModule.java

-2
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
import com.google.inject.TypeLiteral;
2929
import com.plotsquared.bukkit.BukkitPlatform;
3030
import com.plotsquared.bukkit.util.BukkitUtil;
31-
import com.plotsquared.core.commands.CommonCommandRequirement;
3231
import com.plotsquared.core.commands.PlotSquaredCaptionProvider;
3332
import com.plotsquared.core.commands.processing.CommandRequirementPostprocessor;
3433
import com.plotsquared.core.configuration.caption.TranslatableCaption;
@@ -83,7 +82,6 @@ protected void configure() {
8382
}
8483

8584
final CommandRequirementPostprocessor requirementPostprocessor = new CommandRequirementPostprocessor();
86-
requirementPostprocessor.registerRequirements(CommonCommandRequirement.values());
8785
commandManager.registerCommandPostProcessor(requirementPostprocessor);
8886

8987
// TODO(City): Override parsing errors using MM parsing.

Core/src/main/java/com/plotsquared/core/commands/CommandRequirement.java

+42-2
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,17 @@
1919
package com.plotsquared.core.commands;
2020

2121
import cloud.commandframework.context.CommandContext;
22-
import cloud.commandframework.keys.CloudKeyHolder;
2322
import com.plotsquared.core.configuration.caption.TranslatableCaption;
23+
import com.plotsquared.core.permissions.Permission;
2424
import com.plotsquared.core.player.PlotPlayer;
25+
import net.kyori.adventure.text.minimessage.tag.Tag;
26+
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
2527
import org.checkerframework.checker.nullness.qual.NonNull;
2628

2729
/**
2830
* Something that is required for a command to be executed.
2931
*/
30-
public interface CommandRequirement extends CloudKeyHolder<Boolean> {
32+
public interface CommandRequirement {
3133

3234
/**
3335
* Returns the caption sent when the requirement is not met.
@@ -43,4 +45,42 @@ public interface CommandRequirement extends CloudKeyHolder<Boolean> {
4345
* @return {@code true} if the requirement is met, else {@code false}
4446
*/
4547
boolean evaluate(final @NonNull CommandContext<PlotPlayer<?>> context);
48+
49+
/**
50+
* Returns the placeholder values.
51+
*
52+
* @return placeholder values
53+
*/
54+
default @NonNull TagResolver @NonNull[] tagResolvers() {
55+
return new TagResolver[0];
56+
}
57+
58+
/**
59+
* Returns a requirement that evaluates to {@code true} if the sender has the given {@code permission} or if
60+
* this requirement evaluates to {@code true}.
61+
*
62+
* @param permission the override permission
63+
* @return the new requirement
64+
*/
65+
default @NonNull CommandRequirement withPermissionOverride(final @NonNull Permission permission) {
66+
final CommandRequirement thisRequirement = this;
67+
return new CommandRequirement() {
68+
@Override
69+
public @NonNull TranslatableCaption failureCaption() {
70+
return TranslatableCaption.of("permission.no_permission");
71+
}
72+
73+
@Override
74+
public @NonNull TagResolver @NonNull [] tagResolvers() {
75+
return new TagResolver[] {
76+
TagResolver.resolver("node", Tag.inserting(Permission.PERMISSION_SET_FLAG_OTHER))
77+
};
78+
}
79+
80+
@Override
81+
public boolean evaluate(final @NonNull CommandContext<PlotPlayer<?>> context) {
82+
return context.sender().hasPermission(permission) || thisRequirement.evaluate(context);
83+
}
84+
};
85+
}
4686
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
* PlotSquared, a land and world management plugin for Minecraft.
3+
* Copyright (C) IntellectualSites <https://intellectualsites.com>
4+
* Copyright (C) IntellectualSites team and contributors
5+
*
6+
* This program is free software: you can redistribute it and/or modify
7+
* it under the terms of the GNU General Public License as published by
8+
* the Free Software Foundation, either version 3 of the License, or
9+
* (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* GNU General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU General Public License
17+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
18+
*/
19+
package com.plotsquared.core.commands;
20+
21+
import cloud.commandframework.keys.CloudKey;
22+
import org.checkerframework.checker.nullness.qual.NonNull;
23+
24+
import java.util.Collection;
25+
import java.util.Iterator;
26+
import java.util.List;
27+
28+
/**
29+
* Holder of {@link CommandRequirement} requirements.
30+
*/
31+
public final class CommandRequirements implements Iterable<@NonNull CommandRequirement> {
32+
33+
/**
34+
* The key used to store the requirements in the {@link cloud.commandframework.meta.CommandMeta}.
35+
*/
36+
public static final CloudKey<CommandRequirements> REQUIREMENTS_KEY = CloudKey.of(
37+
"requirements",
38+
CommandRequirements.class
39+
);
40+
41+
/**
42+
* Creates a new instance.
43+
*
44+
* @param requirements the requirements
45+
* @return the instance
46+
*/
47+
public static @NonNull CommandRequirements create(final @NonNull Collection<@NonNull CommandRequirement> requirements) {
48+
return new CommandRequirements(requirements);
49+
}
50+
51+
private final List<CommandRequirement> requirements;
52+
53+
private CommandRequirements(final @NonNull Collection<@NonNull CommandRequirement> requirements) {
54+
this.requirements = List.copyOf(requirements);
55+
}
56+
57+
@Override
58+
public @NonNull Iterator<@NonNull CommandRequirement> iterator() {
59+
return this.requirements.iterator();
60+
}
61+
}

Core/src/main/java/com/plotsquared/core/commands/CommonCommandRequirement.java

+8-7
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
package com.plotsquared.core.commands;
2020

2121
import cloud.commandframework.context.CommandContext;
22-
import cloud.commandframework.keys.CloudKey;
2322
import com.plotsquared.core.configuration.caption.TranslatableCaption;
2423
import com.plotsquared.core.player.PlotPlayer;
2524
import org.checkerframework.checker.nullness.qual.NonNull;
@@ -39,7 +38,14 @@ public enum CommonCommandRequirement implements CommandRequirement {
3938
*/
4039
REQUIRES_OWNER(TranslatableCaption.of("working.plot_not_claimed"),
4140
ctx -> ctx.sender().getCurrentPlot() != null && ctx.sender().getCurrentPlot().hasOwner()
42-
);
41+
),
42+
/**
43+
* Requires that the command sender is the plot owner.
44+
*/
45+
IS_OWNER(TranslatableCaption.of("permission.no_plot_perms"),
46+
ctx -> ctx.sender().getCurrentPlot() != null && ctx.sender().getCurrentPlot().isOwner(ctx.sender().getUUID())
47+
)
48+
;
4349

4450
private final TranslatableCaption failureCaption;
4551
private final Predicate<CommandContext<PlotPlayer<?>>> predicate;
@@ -60,9 +66,4 @@ public enum CommonCommandRequirement implements CommandRequirement {
6066
public boolean evaluate(final @NonNull CommandContext<PlotPlayer<?>> context) {
6167
return this.predicate.test(context);
6268
}
63-
64-
@Override
65-
public @NonNull CloudKey<Boolean> key() {
66-
return CloudKey.of(String.format("requirement_%s", this.name()), Boolean.class);
67-
}
6869
}

Core/src/main/java/com/plotsquared/core/commands/PlotSquaredCommandBean.java

+2-6
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,8 @@ public abstract class PlotSquaredCommandBean extends CommandBean<PlotPlayer<?>>
6363

6464
@Override
6565
protected final Command.@NonNull Builder<PlotPlayer<?>> configure(final Command.@NonNull Builder<PlotPlayer<?>> builder) {
66-
Command.@NonNull Builder<PlotPlayer<?>> intermediaryBuilder =
67-
this.configurePlotCommand(this.prepare(builder.meta(PlotSquaredCommandMeta.META_CATEGORY, this.category())));
68-
for (final CommandRequirement requirement : this.requirements()) {
69-
intermediaryBuilder = intermediaryBuilder.meta(requirement.key(), true);
70-
}
71-
return intermediaryBuilder;
66+
return this.configurePlotCommand(this.prepare(builder.meta(PlotSquaredCommandMeta.META_CATEGORY, this.category())))
67+
.meta(CommandRequirements.REQUIREMENTS_KEY, CommandRequirements.create(this.requirements()));
7268
}
7369

7470
protected abstract Command.@NonNull Builder<PlotPlayer<?>> configurePlotCommand(

Core/src/main/java/com/plotsquared/core/commands/command/setting/flag/FlagCommandBean.java

+5-2
Original file line numberDiff line numberDiff line change
@@ -130,8 +130,11 @@ protected static boolean checkPermValue(
130130

131131
@Override
132132
public @NonNull Set<@NonNull CommandRequirement> requirements() {
133-
// TODO: Figure out how to handle the override permission check :)
134-
return Set.of(CommonCommandRequirement.REQUIRES_PLOT, CommonCommandRequirement.REQUIRES_OWNER);
133+
return Set.of(
134+
CommonCommandRequirement.REQUIRES_PLOT,
135+
CommonCommandRequirement.REQUIRES_OWNER,
136+
CommonCommandRequirement.IS_OWNER.withPermissionOverride(Permission.PERMISSION_SET_FLAG_OTHER)
137+
);
135138
}
136139

137140
@Override

Core/src/main/java/com/plotsquared/core/commands/processing/CommandRequirementPostprocessor.java

+10-39
Original file line numberDiff line numberDiff line change
@@ -22,58 +22,29 @@
2222
import cloud.commandframework.execution.postprocessor.CommandPostprocessor;
2323
import cloud.commandframework.services.types.ConsumerService;
2424
import com.plotsquared.core.commands.CommandRequirement;
25+
import com.plotsquared.core.commands.CommandRequirements;
2526
import com.plotsquared.core.player.PlotPlayer;
2627
import org.checkerframework.checker.nullness.qual.NonNull;
2728

28-
import java.util.ArrayList;
29-
import java.util.Arrays;
30-
import java.util.Collection;
31-
import java.util.Objects;
32-
3329
/**
3430
* Processor that evaluates registered {@link CommandRequirement command requirements} before a command is executed.
3531
*/
3632
public final class CommandRequirementPostprocessor implements CommandPostprocessor<PlotPlayer<?>> {
3733

38-
private final Collection<@NonNull CommandRequirement> requirements = new ArrayList<>();
39-
40-
/**
41-
* Requires a single requirement.
42-
*
43-
* @param requirement the requirement
44-
*/
45-
public void registerRequirement(final @NonNull CommandRequirement requirement) {
46-
this.requirements.add(Objects.requireNonNull(requirement, "requirement"));
47-
}
48-
49-
/**
50-
* Registers the given {@code requirements}.
51-
*
52-
* @param requirements the requirements
53-
*/
54-
public void registerRequirements(final @NonNull Collection<@NonNull CommandRequirement> requirements) {
55-
requirements.forEach(this::registerRequirement);
56-
}
57-
58-
/**
59-
* Registers the given {@code requirements}.
60-
*
61-
* @param requirements the requirements
62-
*/
63-
public void registerRequirements(final @NonNull CommandRequirement @NonNull... requirements) {
64-
this.registerRequirements(Arrays.asList(requirements));
65-
}
66-
6734
@Override
6835
public void accept(final @NonNull CommandPostprocessingContext<PlotPlayer<?>> processingContext) {
69-
for (final CommandRequirement requirement : this.requirements) {
70-
if (!processingContext.command().commandMeta().getOrDefault(requirement.key(), false)) {
71-
continue;
72-
}
36+
final CommandRequirements requirements = processingContext.command().commandMeta().getOrDefault(
37+
CommandRequirements.REQUIREMENTS_KEY,
38+
null
39+
);
40+
if (requirements == null) {
41+
return;
42+
}
43+
for (final CommandRequirement requirement : requirements) {
7344
if (requirement.evaluate(processingContext.commandContext())) {
7445
continue;
7546
}
76-
processingContext.commandContext().sender().sendMessage(requirement.failureCaption());
47+
processingContext.commandContext().sender().sendMessage(requirement.failureCaption(), requirement.tagResolvers());
7748
// Not allowed :(
7849
ConsumerService.interrupt();
7950
}

0 commit comments

Comments
 (0)