diff --git a/cloud-core/src/main/java/cloud/commandframework/permission/CommandPermission.java b/cloud-core/src/main/java/cloud/commandframework/permission/CommandPermission.java index 93931012..7f22a673 100644 --- a/cloud-core/src/main/java/cloud/commandframework/permission/CommandPermission.java +++ b/cloud-core/src/main/java/cloud/commandframework/permission/CommandPermission.java @@ -59,7 +59,7 @@ public interface CommandPermission { * @return a new {@code or} permission * @since 1.4.0 */ - default CommandPermission or(final CommandPermission other) { + default @NonNull CommandPermission or(final @NonNull CommandPermission other) { requireNonNull(other, "other"); final Set permission = new HashSet<>(2); permission.add(this); @@ -74,7 +74,7 @@ public interface CommandPermission { * @return a new {@code or} permission * @since 1.4.0 */ - default CommandPermission or(final CommandPermission... other) { + default @NonNull CommandPermission or(final @NonNull CommandPermission @NonNull ... other) { requireNonNull(other, "other"); final Set permission = new HashSet<>(other.length + 1); permission.add(this); @@ -89,7 +89,7 @@ public interface CommandPermission { * @return a new {@code and} permission * @since 1.4.0 */ - default CommandPermission and(final CommandPermission other) { + default @NonNull CommandPermission and(final @NonNull CommandPermission other) { requireNonNull(other, "other"); final Set permission = new HashSet<>(2); permission.add(this); @@ -104,7 +104,7 @@ public interface CommandPermission { * @return a new {@code and} permission * @since 1.4.0 */ - default CommandPermission and(final CommandPermission... other) { + default @NonNull CommandPermission and(final @NonNull CommandPermission @NonNull ... other) { requireNonNull(other, "other"); final Set permission = new HashSet<>(other.length + 1); permission.add(this); diff --git a/cloud-minecraft/cloud-fabric/src/main/java/cloud/commandframework/fabric/FabricClientCommandManager.java b/cloud-minecraft/cloud-fabric/src/main/java/cloud/commandframework/fabric/FabricClientCommandManager.java index 370dad7b..ebd7a4e1 100644 --- a/cloud-minecraft/cloud-fabric/src/main/java/cloud/commandframework/fabric/FabricClientCommandManager.java +++ b/cloud-minecraft/cloud-fabric/src/main/java/cloud/commandframework/fabric/FabricClientCommandManager.java @@ -27,6 +27,7 @@ package cloud.commandframework.fabric; import cloud.commandframework.CommandTree; import cloud.commandframework.execution.AsynchronousCommandExecutionCoordinator; import cloud.commandframework.execution.CommandExecutionCoordinator; +import cloud.commandframework.permission.PredicatePermission; import net.fabricmc.fabric.api.client.command.v1.FabricClientCommandSource; import net.fabricmc.fabric.api.command.v1.CommandRegistrationCallback; import net.minecraft.client.MinecraftClient; @@ -115,4 +116,86 @@ public final class FabricClientCommandManager extends FabricCommandManager sender type + * @return a predicate permission + */ + public static @NonNull PredicatePermission integratedServerRunning() { + return sender -> MinecraftClient.getInstance().isIntegratedServerRunning(); + } + + /** + * Get a permission predicate which passes when the integrated server is not running. + * + * @param sender type + * @return a predicate permission + */ + public static @NonNull PredicatePermission integratedServerNotRunning() { + return sender -> !MinecraftClient.getInstance().isIntegratedServerRunning(); + } + + /** + * Get a permission predicate which passes when cheats are enabled on the currently running integrated server. + * + *

This predicate will always pass if there is no integrated server running, i.e. when connected to a multiplayer server.

+ * + * @param sender type + * @return a predicate permission + */ + public static @NonNull PredicatePermission cheatsAllowed() { + return cheatsAllowed(true); + } + + /** + * Get a permission predicate which passes when cheats are enabled on the currently running integrated server. + * + *

When there is no integrated server running, i.e. when connected to a multiplayer server, the predicate will + * fall back to the provided boolean argument.

+ * + * @param allowOnMultiplayer whether the predicate should pass on multiplayer servers + * @param sender type + * @return a predicate permission + */ + public static @NonNull PredicatePermission cheatsAllowed(final boolean allowOnMultiplayer) { + return sender -> { + if (!MinecraftClient.getInstance().isIntegratedServerRunning()) { + return allowOnMultiplayer; + } + return MinecraftClient.getInstance().getServer().getPlayerManager().areCheatsAllowed(); + }; + } + + /** + * Get a permission predicate which passes when cheats are disabled on the currently running integrated server. + * + *

This predicate will always pass if there is no integrated server running, i.e. when connected to a multiplayer server.

+ * + * @param sender type + * @return a predicate permission + */ + public static @NonNull PredicatePermission cheatsDisallowed() { + return cheatsDisallowed(true); + } + + /** + * Get a permission predicate which passes when cheats are disabled on the currently running integrated server. + * + *

When there is no integrated server running, i.e. when connected to a multiplayer server, the predicate will + * fall back to the provided boolean argument.

+ * + * @param allowOnMultiplayer whether the predicate should pass on multiplayer servers + * @param sender type + * @return a predicate permission + */ + public static @NonNull PredicatePermission cheatsDisallowed(final boolean allowOnMultiplayer) { + return sender -> { + if (!MinecraftClient.getInstance().isIntegratedServerRunning()) { + return allowOnMultiplayer; + } + return !MinecraftClient.getInstance().getServer().getPlayerManager().areCheatsAllowed(); + }; + } + } diff --git a/cloud-minecraft/cloud-fabric/src/main/java/cloud/commandframework/fabric/FabricCommandManager.java b/cloud-minecraft/cloud-fabric/src/main/java/cloud/commandframework/fabric/FabricCommandManager.java index 9f31ddc2..ad853e66 100644 --- a/cloud-minecraft/cloud-fabric/src/main/java/cloud/commandframework/fabric/FabricCommandManager.java +++ b/cloud-minecraft/cloud-fabric/src/main/java/cloud/commandframework/fabric/FabricCommandManager.java @@ -39,6 +39,7 @@ import cloud.commandframework.fabric.argument.TeamArgument; import cloud.commandframework.fabric.data.MinecraftTime; import cloud.commandframework.meta.CommandMeta; import cloud.commandframework.meta.SimpleCommandMeta; +import cloud.commandframework.permission.PredicatePermission; import com.mojang.brigadier.arguments.ArgumentType; import com.mojang.brigadier.suggestion.SuggestionProvider; import com.mojang.serialization.Codec; @@ -373,4 +374,16 @@ public abstract class FabricCommandManager extends C this.transitionOrThrow(RegistrationState.REGISTERING, RegistrationState.AFTER_REGISTRATION); } + /** + * Get a permission predicate which passes when the sender has the specified permission level. + * + * @param permissionLevel permission level to require + * @return a permission predicate + */ + public @NonNull PredicatePermission permissionLevel(final int permissionLevel) { + return sender -> this.getBackwardsCommandSourceMapper() + .apply(sender) + .hasPermissionLevel(permissionLevel); + } + } diff --git a/cloud-minecraft/cloud-fabric/src/main/java/cloud/commandframework/fabric/FabricParserParameters.java b/cloud-minecraft/cloud-fabric/src/main/java/cloud/commandframework/fabric/FabricParserParameters.java new file mode 100644 index 00000000..574257cc --- /dev/null +++ b/cloud-minecraft/cloud-fabric/src/main/java/cloud/commandframework/fabric/FabricParserParameters.java @@ -0,0 +1,51 @@ +// +// MIT License +// +// Copyright (c) 2021 Alexander Söderberg & Contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +package cloud.commandframework.fabric; + +import cloud.commandframework.arguments.parser.ParserParameter; +import io.leangen.geantyref.TypeToken; +import org.checkerframework.checker.nullness.qual.NonNull; + +/** + * {@link ParserParameter} keys for cloud-fabric. + * + * @since 1.5.0 + */ +public final class FabricParserParameters { + + /** + * Indicates that positions should be centered on the middle of blocks, i.e. x.5. + * + * @since 1.5.0 + */ + public static final ParserParameter CENTER_INTEGERS = create("center_integers", TypeToken.get(Boolean.class)); + + private static @NonNull ParserParameter create( + final @NonNull String key, + final @NonNull TypeToken expectedType + ) { + return new ParserParameter<>(key, expectedType); + } + +} diff --git a/cloud-minecraft/cloud-fabric/src/main/java/cloud/commandframework/fabric/FabricServerCommandManager.java b/cloud-minecraft/cloud-fabric/src/main/java/cloud/commandframework/fabric/FabricServerCommandManager.java index f58d6394..380c6f78 100644 --- a/cloud-minecraft/cloud-fabric/src/main/java/cloud/commandframework/fabric/FabricServerCommandManager.java +++ b/cloud-minecraft/cloud-fabric/src/main/java/cloud/commandframework/fabric/FabricServerCommandManager.java @@ -30,7 +30,6 @@ import cloud.commandframework.execution.AsynchronousCommandExecutionCoordinator; import cloud.commandframework.execution.CommandExecutionCoordinator; import cloud.commandframework.fabric.annotations.specifier.Center; import cloud.commandframework.fabric.argument.FabricArgumentParsers; -import cloud.commandframework.fabric.argument.FabricArgumentParsers.FabricParserParameters; import cloud.commandframework.fabric.data.Coordinates; import cloud.commandframework.fabric.data.Message; import cloud.commandframework.fabric.data.MultipleEntitySelector; diff --git a/cloud-minecraft/cloud-fabric/src/main/java/cloud/commandframework/fabric/argument/FabricArgumentParsers.java b/cloud-minecraft/cloud-fabric/src/main/java/cloud/commandframework/fabric/argument/FabricArgumentParsers.java index baaf1f99..076591aa 100644 --- a/cloud-minecraft/cloud-fabric/src/main/java/cloud/commandframework/fabric/argument/FabricArgumentParsers.java +++ b/cloud-minecraft/cloud-fabric/src/main/java/cloud/commandframework/fabric/argument/FabricArgumentParsers.java @@ -26,7 +26,6 @@ package cloud.commandframework.fabric.argument; import cloud.commandframework.arguments.parser.ArgumentParseResult; import cloud.commandframework.arguments.parser.ArgumentParser; -import cloud.commandframework.arguments.parser.ParserParameter; import cloud.commandframework.brigadier.argument.WrappedBrigadierParser; import cloud.commandframework.context.CommandContext; import cloud.commandframework.fabric.FabricCommandContextKeys; @@ -41,7 +40,6 @@ import cloud.commandframework.fabric.internal.EntitySelectorAccess; import cloud.commandframework.fabric.mixin.MessageArgumentTypeMessageFormatAccess; import cloud.commandframework.fabric.mixin.MessageArgumentTypeMessageSelectorAccess; import com.mojang.brigadier.exceptions.CommandSyntaxException; -import io.leangen.geantyref.TypeToken; import net.minecraft.command.CommandSource; import net.minecraft.command.EntitySelector; import net.minecraft.command.argument.BlockPosArgumentType; @@ -285,29 +283,6 @@ public final class FabricArgumentParsers { return resultFunction.apply((ServerCommandSource) nativeSource); } - /** - * {@link ParserParameter} keys for cloud-fabric. - * - * @since 1.5.0 - */ - public static final class FabricParserParameters { - - /** - * Indicates that positions should be centered on the middle of blocks, i.e. x.5. - * - * @since 1.5.0 - */ - public static final ParserParameter CENTER_INTEGERS = create("center_integers", TypeToken.get(Boolean.class)); - - private static @NonNull ParserParameter create( - final @NonNull String key, - final @NonNull TypeToken expectedType - ) { - return new ParserParameter<>(key, expectedType); - } - - } - static final class MessageImpl implements Message { private final Collection mentionedEntities; diff --git a/cloud-minecraft/cloud-fabric/src/testmod/java/cloud/commandframework/fabric/testmod/FabricClientExample.java b/cloud-minecraft/cloud-fabric/src/testmod/java/cloud/commandframework/fabric/testmod/FabricClientExample.java index 09d95bfb..131e4c19 100644 --- a/cloud-minecraft/cloud-fabric/src/testmod/java/cloud/commandframework/fabric/testmod/FabricClientExample.java +++ b/cloud-minecraft/cloud-fabric/src/testmod/java/cloud/commandframework/fabric/testmod/FabricClientExample.java @@ -106,6 +106,10 @@ public final class FabricClientExample implements ClientModInitializer { commandManager.command(base.literal("disconnect") .handler(ctx -> disconnectClient(MinecraftClient.getInstance()))); + + commandManager.command(base.literal("requires_cheats") + .permission(FabricClientCommandManager.cheatsAllowed(false)) + .handler(ctx -> ctx.getSender().sendFeedback(new LiteralText("Cheats are enabled!")))); } private static void disconnectClient(final @NonNull MinecraftClient client) {