diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/commands/BukkitSenderMapper.java b/Bukkit/src/main/java/com/plotsquared/bukkit/commands/BukkitSenderMapper.java new file mode 100644 index 000000000..692a04066 --- /dev/null +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/commands/BukkitSenderMapper.java @@ -0,0 +1,50 @@ +/* + * 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.bukkit.commands; + +import cloud.commandframework.SenderMapper; +import com.plotsquared.bukkit.util.BukkitUtil; +import com.plotsquared.core.player.ConsolePlayer; +import com.plotsquared.core.player.PlotPlayer; +import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.checkerframework.checker.nullness.qual.NonNull; + +/** + * Mapper between {@link CommandSender} and {@link PlotPlayer}. + */ +public final class BukkitSenderMapper implements SenderMapper> { + + @Override + public @NonNull PlotPlayer map(final @NonNull CommandSender base) { + if (base instanceof Player player) { + return BukkitUtil.adapt(player); + } + return ConsolePlayer.getConsole(); + } + + @Override + public @NonNull CommandSender reverse(final @NonNull PlotPlayer mapped) { + if (mapped instanceof ConsolePlayer) { + return Bukkit.getConsoleSender(); + } + return (Player) mapped.getPlatformPlayer(); + } +} 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 9528ff3ae..082836064 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/inject/CloudModule.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/inject/CloudModule.java @@ -27,6 +27,7 @@ import com.google.inject.AbstractModule; import com.google.inject.Key; import com.google.inject.TypeLiteral; import com.plotsquared.bukkit.BukkitPlatform; +import com.plotsquared.bukkit.commands.BukkitSenderMapper; import com.plotsquared.bukkit.util.BukkitUtil; import com.plotsquared.core.commands.PlotSquaredCaptionProvider; import com.plotsquared.core.commands.processing.CommandRequirementPostprocessor; @@ -66,35 +67,30 @@ public class CloudModule extends AbstractModule { @Override protected void configure() { - try { - final PaperCommandManager> commandManager = new PaperCommandManager>( - this.bukkitPlatform, - ExecutionCoordinator.asyncCoordinator(), - CloudModule::convert, - CloudModule::convert - ); - commandManager.captionRegistry().registerProvider(new PlotSquaredCaptionProvider()); - if (commandManager.hasCapability(CloudBukkitCapabilities.ASYNCHRONOUS_COMPLETION)) { - commandManager.registerAsynchronousCompletions(); - } - if (commandManager.hasCapability(CloudBukkitCapabilities.NATIVE_BRIGADIER)) { - commandManager.registerBrigadier(); - } - - final CommandRequirementPostprocessor requirementPostprocessor = new CommandRequirementPostprocessor(); - commandManager.registerCommandPostProcessor(requirementPostprocessor); - - // TODO(City): Override parsing errors using MM parsing. - MinecraftExceptionHandler.>create(PlotPlayer::getAudience) - .defaultHandlers() - .decorator((ctx, component) -> TranslatableCaption.of("core.prefix"). - toComponent(ctx.context().sender()) - .append(component)) - .registerTo(commandManager); - - bind(Key.get(new TypeLiteral>>() {})).toInstance(commandManager); - } catch (final Exception e) { - LOGGER.error("Failed to configure command manager", e); + final PaperCommandManager> commandManager = new PaperCommandManager>( + this.bukkitPlatform, + ExecutionCoordinator.asyncCoordinator(), + new BukkitSenderMapper() + ); + commandManager.captionRegistry().registerProvider(new PlotSquaredCaptionProvider()); + if (commandManager.hasCapability(CloudBukkitCapabilities.ASYNCHRONOUS_COMPLETION)) { + commandManager.registerAsynchronousCompletions(); } + if (commandManager.hasCapability(CloudBukkitCapabilities.NATIVE_BRIGADIER)) { + commandManager.registerBrigadier(); + } + + final CommandRequirementPostprocessor requirementPostprocessor = new CommandRequirementPostprocessor(); + commandManager.registerCommandPostProcessor(requirementPostprocessor); + + // TODO(City): Override parsing errors using MM parsing. + MinecraftExceptionHandler.>create(PlotPlayer::getAudience) + .defaultHandlers() + .decorator((ctx, component) -> TranslatableCaption.of("core.prefix"). + toComponent(ctx.context().sender()) + .append(component)) + .registerTo(commandManager); + + bind(Key.get(new TypeLiteral>>() {})).toInstance(commandManager); } } 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 11bc1321b..89dd70b36 100644 --- a/Core/src/main/java/com/plotsquared/core/commands/CommandRequirement.java +++ b/Core/src/main/java/com/plotsquared/core/commands/CommandRequirement.java @@ -26,6 +26,8 @@ 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 java.util.List; + /** * Something that is required for a command to be executed. */ @@ -55,6 +57,15 @@ 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}. @@ -77,6 +88,11 @@ public interface CommandRequirement { }; } + @Override + public @NonNull List<@NonNull CommandRequirement> parents() { + return thisRequirement.parents(); + } + @Override public boolean evaluate(final @NonNull CommandContext> context) { return context.sender().hasPermission(permission) || thisRequirement.evaluate(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 index 046c09b26..7f5aa69d0 100644 --- a/Core/src/main/java/com/plotsquared/core/commands/CommandRequirements.java +++ b/Core/src/main/java/com/plotsquared/core/commands/CommandRequirements.java @@ -21,7 +21,7 @@ package com.plotsquared.core.commands; import cloud.commandframework.keys.CloudKey; import org.checkerframework.checker.nullness.qual.NonNull; -import java.util.Collection; +import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -44,14 +44,25 @@ public final class CommandRequirements implements Iterable<@NonNull CommandRequi * @param requirements the requirements * @return the instance */ - public static @NonNull CommandRequirements create(final @NonNull Collection<@NonNull CommandRequirement> requirements) { + 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 Collection<@NonNull CommandRequirement> requirements) { - this.requirements = List.copyOf(requirements); + private CommandRequirements(final @NonNull List<@NonNull CommandRequirement> requirements) { + this.requirements = List.copyOf(extractRequirements(requirements)); } @Override 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 93f55c5f5..e58da8b6e 100644 --- a/Core/src/main/java/com/plotsquared/core/commands/CommonCommandRequirement.java +++ b/Core/src/main/java/com/plotsquared/core/commands/CommonCommandRequirement.java @@ -23,6 +23,8 @@ import com.plotsquared.core.configuration.caption.TranslatableCaption; import com.plotsquared.core.player.PlotPlayer; import org.checkerframework.checker.nullness.qual.NonNull; +import java.util.Arrays; +import java.util.List; import java.util.function.Predicate; /** @@ -37,31 +39,41 @@ public enum CommonCommandRequirement implements CommandRequirement { * Requires that the command sender is in a claimed plot. */ REQUIRES_OWNER(TranslatableCaption.of("working.plot_not_claimed"), - ctx -> ctx.sender().getCurrentPlot() != null && ctx.sender().getCurrentPlot().hasOwner() + ctx -> ctx.sender().getCurrentPlot().hasOwner(), + REQUIRES_PLOT ), /** * 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()) + ctx -> ctx.sender().getCurrentPlot().isOwner(ctx.sender().getUUID()), + REQUIRES_OWNER ) ; private final TranslatableCaption failureCaption; private final Predicate>> predicate; + private final List<@NonNull CommandRequirement> parents; CommonCommandRequirement( final @NonNull TranslatableCaption failureCaption, - final @NonNull Predicate>> predicate + final @NonNull Predicate>> predicate, + final @NonNull CommandRequirement @NonNull... parents ) { this.failureCaption = failureCaption; this.predicate = predicate; + this.parents = Arrays.asList(parents); } public @NonNull TranslatableCaption failureCaption() { return this.failureCaption; } + @Override + public @NonNull List<@NonNull CommandRequirement> parents() { + return this.parents; + } + @Override public boolean evaluate(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 60dddd855..484b160d9 100644 --- a/Core/src/main/java/com/plotsquared/core/commands/PlotSquaredCommandBean.java +++ b/Core/src/main/java/com/plotsquared/core/commands/PlotSquaredCommandBean.java @@ -25,7 +25,7 @@ import com.plotsquared.core.command.CommandCategory; import com.plotsquared.core.player.PlotPlayer; import org.checkerframework.checker.nullness.qual.NonNull; -import java.util.Set; +import java.util.List; public abstract class PlotSquaredCommandBean extends CommandBean> { @@ -41,7 +41,7 @@ public abstract class PlotSquaredCommandBean extends CommandBean> * * @return the requirements */ - public abstract @NonNull Set<@NonNull CommandRequirement> requirements(); + public abstract @NonNull List<@NonNull CommandRequirement> requirements(); /** * Prepares the given {@code builder}. diff --git a/Core/src/main/java/com/plotsquared/core/commands/command/setting/flag/FlagCommandBean.java b/Core/src/main/java/com/plotsquared/core/commands/command/setting/flag/FlagCommandBean.java index ae6445e43..d29bdcb83 100644 --- a/Core/src/main/java/com/plotsquared/core/commands/command/setting/flag/FlagCommandBean.java +++ b/Core/src/main/java/com/plotsquared/core/commands/command/setting/flag/FlagCommandBean.java @@ -39,7 +39,6 @@ import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; import org.checkerframework.checker.nullness.qual.NonNull; import java.util.List; -import java.util.Set; public abstract class FlagCommandBean extends PlotSquaredCommandBean { @@ -129,12 +128,8 @@ public abstract class FlagCommandBean extends PlotSquaredCommandBean { } @Override - public @NonNull Set<@NonNull CommandRequirement> requirements() { - return Set.of( - CommonCommandRequirement.REQUIRES_PLOT, - CommonCommandRequirement.REQUIRES_OWNER, - CommonCommandRequirement.IS_OWNER.withPermissionOverride(Permission.PERMISSION_SET_FLAG_OTHER) - ); + public @NonNull List<@NonNull CommandRequirement> requirements() { + return List.of(CommonCommandRequirement.IS_OWNER.withPermissionOverride(Permission.PERMISSION_SET_FLAG_OTHER)); } @Override