Skip to content

Commit a66293e

Browse files
committed
add requirement inheritance
1 parent 22c253a commit a66293e

File tree

7 files changed

+123
-43
lines changed

7 files changed

+123
-43
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
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.bukkit.commands;
20+
21+
import cloud.commandframework.SenderMapper;
22+
import com.plotsquared.bukkit.util.BukkitUtil;
23+
import com.plotsquared.core.player.ConsolePlayer;
24+
import com.plotsquared.core.player.PlotPlayer;
25+
import org.bukkit.Bukkit;
26+
import org.bukkit.command.CommandSender;
27+
import org.bukkit.entity.Player;
28+
import org.checkerframework.checker.nullness.qual.NonNull;
29+
30+
/**
31+
* Mapper between {@link CommandSender} and {@link PlotPlayer}.
32+
*/
33+
public final class BukkitSenderMapper implements SenderMapper<CommandSender, PlotPlayer<?>> {
34+
35+
@Override
36+
public @NonNull PlotPlayer<?> map(final @NonNull CommandSender base) {
37+
if (base instanceof Player player) {
38+
return BukkitUtil.adapt(player);
39+
}
40+
return ConsolePlayer.getConsole();
41+
}
42+
43+
@Override
44+
public @NonNull CommandSender reverse(final @NonNull PlotPlayer<?> mapped) {
45+
if (mapped instanceof ConsolePlayer) {
46+
return Bukkit.getConsoleSender();
47+
}
48+
return (Player) mapped.getPlatformPlayer();
49+
}
50+
}

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

+23-27
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import com.google.inject.Key;
2828
import com.google.inject.TypeLiteral;
2929
import com.plotsquared.bukkit.BukkitPlatform;
30+
import com.plotsquared.bukkit.commands.BukkitSenderMapper;
3031
import com.plotsquared.bukkit.util.BukkitUtil;
3132
import com.plotsquared.core.commands.PlotSquaredCaptionProvider;
3233
import com.plotsquared.core.commands.processing.CommandRequirementPostprocessor;
@@ -66,35 +67,30 @@ public CloudModule(final @NonNull BukkitPlatform bukkitPlatform) {
6667

6768
@Override
6869
protected void configure() {
69-
try {
70-
final PaperCommandManager<PlotPlayer<?>> commandManager = new PaperCommandManager<PlotPlayer<?>>(
71-
this.bukkitPlatform,
72-
ExecutionCoordinator.asyncCoordinator(),
73-
CloudModule::convert,
74-
CloudModule::convert
75-
);
76-
commandManager.captionRegistry().registerProvider(new PlotSquaredCaptionProvider());
77-
if (commandManager.hasCapability(CloudBukkitCapabilities.ASYNCHRONOUS_COMPLETION)) {
78-
commandManager.registerAsynchronousCompletions();
79-
}
80-
if (commandManager.hasCapability(CloudBukkitCapabilities.NATIVE_BRIGADIER)) {
81-
commandManager.registerBrigadier();
82-
}
70+
final PaperCommandManager<PlotPlayer<?>> commandManager = new PaperCommandManager<PlotPlayer<?>>(
71+
this.bukkitPlatform,
72+
ExecutionCoordinator.asyncCoordinator(),
73+
new BukkitSenderMapper()
74+
);
75+
commandManager.captionRegistry().registerProvider(new PlotSquaredCaptionProvider());
76+
if (commandManager.hasCapability(CloudBukkitCapabilities.ASYNCHRONOUS_COMPLETION)) {
77+
commandManager.registerAsynchronousCompletions();
78+
}
79+
if (commandManager.hasCapability(CloudBukkitCapabilities.NATIVE_BRIGADIER)) {
80+
commandManager.registerBrigadier();
81+
}
8382

84-
final CommandRequirementPostprocessor requirementPostprocessor = new CommandRequirementPostprocessor();
85-
commandManager.registerCommandPostProcessor(requirementPostprocessor);
83+
final CommandRequirementPostprocessor requirementPostprocessor = new CommandRequirementPostprocessor();
84+
commandManager.registerCommandPostProcessor(requirementPostprocessor);
8685

87-
// TODO(City): Override parsing errors using MM parsing.
88-
MinecraftExceptionHandler.<PlotPlayer<?>>create(PlotPlayer::getAudience)
89-
.defaultHandlers()
90-
.decorator((ctx, component) -> TranslatableCaption.of("core.prefix").
91-
toComponent(ctx.context().sender())
92-
.append(component))
93-
.registerTo(commandManager);
86+
// TODO(City): Override parsing errors using MM parsing.
87+
MinecraftExceptionHandler.<PlotPlayer<?>>create(PlotPlayer::getAudience)
88+
.defaultHandlers()
89+
.decorator((ctx, component) -> TranslatableCaption.of("core.prefix").
90+
toComponent(ctx.context().sender())
91+
.append(component))
92+
.registerTo(commandManager);
9493

95-
bind(Key.get(new TypeLiteral<CommandManager<PlotPlayer<?>>>() {})).toInstance(commandManager);
96-
} catch (final Exception e) {
97-
LOGGER.error("Failed to configure command manager", e);
98-
}
94+
bind(Key.get(new TypeLiteral<CommandManager<PlotPlayer<?>>>() {})).toInstance(commandManager);
9995
}
10096
}

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

+16
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
2727
import org.checkerframework.checker.nullness.qual.NonNull;
2828

29+
import java.util.List;
30+
2931
/**
3032
* Something that is required for a command to be executed.
3133
*/
@@ -55,6 +57,15 @@ public interface CommandRequirement {
5557
return new TagResolver[0];
5658
}
5759

60+
/**
61+
* Returns the list of parent requirements that should be evaluated before this requirement.
62+
*
63+
* @return the requirements
64+
*/
65+
default @NonNull List<@NonNull CommandRequirement> parents() {
66+
return List.of();
67+
}
68+
5869
/**
5970
* Returns a requirement that evaluates to {@code true} if the sender has the given {@code permission} or if
6071
* this requirement evaluates to {@code true}.
@@ -77,6 +88,11 @@ public interface CommandRequirement {
7788
};
7889
}
7990

91+
@Override
92+
public @NonNull List<@NonNull CommandRequirement> parents() {
93+
return thisRequirement.parents();
94+
}
95+
8096
@Override
8197
public boolean evaluate(final @NonNull CommandContext<PlotPlayer<?>> context) {
8298
return context.sender().hasPermission(permission) || thisRequirement.evaluate(context);

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

+15-4
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
import cloud.commandframework.keys.CloudKey;
2222
import org.checkerframework.checker.nullness.qual.NonNull;
2323

24-
import java.util.Collection;
24+
import java.util.ArrayList;
2525
import java.util.Iterator;
2626
import java.util.List;
2727

@@ -44,14 +44,25 @@ public final class CommandRequirements implements Iterable<@NonNull CommandRequi
4444
* @param requirements the requirements
4545
* @return the instance
4646
*/
47-
public static @NonNull CommandRequirements create(final @NonNull Collection<@NonNull CommandRequirement> requirements) {
47+
public static @NonNull CommandRequirements create(final @NonNull List<@NonNull CommandRequirement> requirements) {
4848
return new CommandRequirements(requirements);
4949
}
5050

51+
private static @NonNull List<@NonNull CommandRequirement> extractRequirements(
52+
final @NonNull List<@NonNull CommandRequirement> requirements
53+
) {
54+
final List<CommandRequirement> extractedRequirements = new ArrayList<>();
55+
for (final CommandRequirement requirement : requirements) {
56+
extractedRequirements.addAll(extractRequirements(requirement.parents()));
57+
extractedRequirements.add(requirement);
58+
}
59+
return extractedRequirements;
60+
}
61+
5162
private final List<CommandRequirement> requirements;
5263

53-
private CommandRequirements(final @NonNull Collection<@NonNull CommandRequirement> requirements) {
54-
this.requirements = List.copyOf(requirements);
64+
private CommandRequirements(final @NonNull List<@NonNull CommandRequirement> requirements) {
65+
this.requirements = List.copyOf(extractRequirements(requirements));
5566
}
5667

5768
@Override

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

+15-3
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
import com.plotsquared.core.player.PlotPlayer;
2424
import org.checkerframework.checker.nullness.qual.NonNull;
2525

26+
import java.util.Arrays;
27+
import java.util.List;
2628
import java.util.function.Predicate;
2729

2830
/**
@@ -37,31 +39,41 @@ public enum CommonCommandRequirement implements CommandRequirement {
3739
* Requires that the command sender is in a claimed plot.
3840
*/
3941
REQUIRES_OWNER(TranslatableCaption.of("working.plot_not_claimed"),
40-
ctx -> ctx.sender().getCurrentPlot() != null && ctx.sender().getCurrentPlot().hasOwner()
42+
ctx -> ctx.sender().getCurrentPlot().hasOwner(),
43+
REQUIRES_PLOT
4144
),
4245
/**
4346
* Requires that the command sender is the plot owner.
4447
*/
4548
IS_OWNER(TranslatableCaption.of("permission.no_plot_perms"),
46-
ctx -> ctx.sender().getCurrentPlot() != null && ctx.sender().getCurrentPlot().isOwner(ctx.sender().getUUID())
49+
ctx -> ctx.sender().getCurrentPlot().isOwner(ctx.sender().getUUID()),
50+
REQUIRES_OWNER
4751
)
4852
;
4953

5054
private final TranslatableCaption failureCaption;
5155
private final Predicate<CommandContext<PlotPlayer<?>>> predicate;
56+
private final List<@NonNull CommandRequirement> parents;
5257

5358
CommonCommandRequirement(
5459
final @NonNull TranslatableCaption failureCaption,
55-
final @NonNull Predicate<CommandContext<PlotPlayer<?>>> predicate
60+
final @NonNull Predicate<CommandContext<PlotPlayer<?>>> predicate,
61+
final @NonNull CommandRequirement @NonNull... parents
5662
) {
5763
this.failureCaption = failureCaption;
5864
this.predicate = predicate;
65+
this.parents = Arrays.asList(parents);
5966
}
6067

6168
public @NonNull TranslatableCaption failureCaption() {
6269
return this.failureCaption;
6370
}
6471

72+
@Override
73+
public @NonNull List<@NonNull CommandRequirement> parents() {
74+
return this.parents;
75+
}
76+
6577
@Override
6678
public boolean evaluate(final @NonNull CommandContext<PlotPlayer<?>> context) {
6779
return this.predicate.test(context);

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
import com.plotsquared.core.player.PlotPlayer;
2626
import org.checkerframework.checker.nullness.qual.NonNull;
2727

28-
import java.util.Set;
28+
import java.util.List;
2929

3030
public abstract class PlotSquaredCommandBean extends CommandBean<PlotPlayer<?>> {
3131

@@ -41,7 +41,7 @@ public abstract class PlotSquaredCommandBean extends CommandBean<PlotPlayer<?>>
4141
*
4242
* @return the requirements
4343
*/
44-
public abstract @NonNull Set<@NonNull CommandRequirement> requirements();
44+
public abstract @NonNull List<@NonNull CommandRequirement> requirements();
4545

4646
/**
4747
* Prepares the given {@code builder}.

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

+2-7
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@
3939
import org.checkerframework.checker.nullness.qual.NonNull;
4040

4141
import java.util.List;
42-
import java.util.Set;
4342

4443
public abstract class FlagCommandBean extends PlotSquaredCommandBean {
4544

@@ -129,12 +128,8 @@ protected static boolean checkPermValue(
129128
}
130129

131130
@Override
132-
public @NonNull Set<@NonNull CommandRequirement> requirements() {
133-
return Set.of(
134-
CommonCommandRequirement.REQUIRES_PLOT,
135-
CommonCommandRequirement.REQUIRES_OWNER,
136-
CommonCommandRequirement.IS_OWNER.withPermissionOverride(Permission.PERMISSION_SET_FLAG_OTHER)
137-
);
131+
public @NonNull List<@NonNull CommandRequirement> requirements() {
132+
return List.of(CommonCommandRequirement.IS_OWNER.withPermissionOverride(Permission.PERMISSION_SET_FLAG_OTHER));
138133
}
139134

140135
@Override

0 commit comments

Comments
 (0)