diff --git a/core/src/main/java/org/geysermc/geyser/command/CommandRegistry.java b/core/src/main/java/org/geysermc/geyser/command/CommandRegistry.java index 838ab71b1..9a160e378 100644 --- a/core/src/main/java/org/geysermc/geyser/command/CommandRegistry.java +++ b/core/src/main/java/org/geysermc/geyser/command/CommandRegistry.java @@ -97,6 +97,9 @@ public class CommandRegistry implements EventRegistrar { private static final String GEYSER_ROOT_PERMISSION = "geyser.command"; + public final static boolean STANDALONE_COMMAND_MANAGER = GeyserImpl.getInstance().getPlatformType() == PlatformType.STANDALONE || + GeyserImpl.getInstance().getPlatformType() == PlatformType.VIAPROXY; + protected final GeyserImpl geyser; private final CommandManager cloud; private final boolean applyRootPermission; @@ -274,12 +277,15 @@ public class CommandRegistry implements EventRegistrar { cloud.command(builder.handler(context -> { GeyserCommandSource source = context.sender(); - if (!source.hasPermission(help.permission())) { - // delegate if possible - otherwise we have nothing else to offer the user. + if (source.hasPermission(help.permission())) { + // Delegate to help if possible + help.execute(source); + } else if (STANDALONE_COMMAND_MANAGER && source instanceof GeyserSession session) { + // If we are on an appropriate platform, forward the command to the backend + session.sendCommand(context.rawInput().input()); + } else { source.sendLocaleString(ExceptionHandlers.PERMISSION_FAIL_LANG_KEY); - return; } - help.execute(source); })); } diff --git a/core/src/main/java/org/geysermc/geyser/command/ExceptionHandlers.java b/core/src/main/java/org/geysermc/geyser/command/ExceptionHandlers.java index 45657a596..6348b8515 100644 --- a/core/src/main/java/org/geysermc/geyser/command/ExceptionHandlers.java +++ b/core/src/main/java/org/geysermc/geyser/command/ExceptionHandlers.java @@ -28,10 +28,12 @@ package org.geysermc.geyser.command; import io.leangen.geantyref.GenericTypeReflector; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.GeyserLogger; +import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.text.ChatColor; import org.geysermc.geyser.text.GeyserLocale; import org.geysermc.geyser.text.MinecraftLocale; import org.incendo.cloud.CommandManager; +import org.incendo.cloud.context.CommandContext; import org.incendo.cloud.exception.ArgumentParseException; import org.incendo.cloud.exception.CommandExecutionException; import org.incendo.cloud.exception.InvalidCommandSenderException; @@ -71,36 +73,51 @@ final class ExceptionHandlers { controller.clearHandlers(); registerExceptionHandler(InvalidSyntaxException.class, - (src, e) -> src.sendLocaleString("geyser.command.invalid_syntax", e.correctSyntax())); + (ctx, e) -> ctx.sender().sendLocaleString("geyser.command.invalid_syntax", e.correctSyntax())); - registerExceptionHandler(InvalidCommandSenderException.class, (src, e) -> { + registerExceptionHandler(InvalidCommandSenderException.class, (ctx, e) -> { // We currently don't use cloud sender type requirements anywhere. // This can be implemented better in the future if necessary. Type type = e.requiredSenderTypes().iterator().next(); // just grab the first String typeString = GenericTypeReflector.getTypeName(type); - src.sendLocaleString("geyser.command.invalid_sender", e.commandSender().getClass().getSimpleName(), typeString); + ctx.sender().sendLocaleString("geyser.command.invalid_sender", e.commandSender().getClass().getSimpleName(), typeString); }); registerExceptionHandler(NoPermissionException.class, ExceptionHandlers::handleNoPermission); registerExceptionHandler(NoSuchCommandException.class, - (src, e) -> src.sendLocaleString("geyser.command.not_found")); + (ctx, e) -> { + // Let backend server receive & handle the command + if (CommandRegistry.STANDALONE_COMMAND_MANAGER && ctx.sender() instanceof GeyserSession session) { + session.sendCommand(ctx.rawInput().input()); + } else { + ctx.sender().sendLocaleString("geyser.command.not_found"); + } + }); registerExceptionHandler(ArgumentParseException.class, - (src, e) -> src.sendLocaleString("geyser.command.invalid_argument", e.getCause().getMessage())); + (ctx, e) -> ctx.sender().sendLocaleString("geyser.command.invalid_argument", e.getCause().getMessage())); registerExceptionHandler(CommandExecutionException.class, - (src, e) -> handleUnexpectedThrowable(src, e.getCause())); + (ctx, e) -> handleUnexpectedThrowable(ctx.sender(), e.getCause())); registerExceptionHandler(Throwable.class, - (src, e) -> handleUnexpectedThrowable(src, e.getCause())); + (ctx, e) -> handleUnexpectedThrowable(ctx.sender(), e.getCause())); } - private void registerExceptionHandler(Class type, BiConsumer handler) { - controller.registerHandler(type, context -> handler.accept(context.context().sender(), context.exception())); + private void registerExceptionHandler(Class type, BiConsumer, E> handler) { + controller.registerHandler(type, context -> handler.accept(context.context(), context.exception())); } - private static void handleNoPermission(GeyserCommandSource source, NoPermissionException exception) { + private static void handleNoPermission(CommandContext context, NoPermissionException exception) { + GeyserCommandSource source = context.sender(); + + // Let backend server receive & handle the command + if (CommandRegistry.STANDALONE_COMMAND_MANAGER && source instanceof GeyserSession session) { + session.sendCommand(context.rawInput().input()); + return; + } + // custom handling if the source can't use the command because of additional requirements if (exception.permissionResult() instanceof GeyserPermission.Result result) { if (result.meta() == GeyserPermission.Result.Meta.NOT_BEDROCK) { diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockCommandRequestTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockCommandRequestTranslator.java index 1e84f032e..27d18183d 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockCommandRequestTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockCommandRequestTranslator.java @@ -27,7 +27,6 @@ package org.geysermc.geyser.translator.protocol.bedrock; import org.cloudburstmc.protocol.bedrock.packet.CommandRequestPacket; import org.geysermc.geyser.GeyserImpl; -import org.geysermc.geyser.api.util.PlatformType; import org.geysermc.geyser.command.CommandRegistry; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; @@ -44,10 +43,12 @@ public class BedrockCommandRequestTranslator extends PacketTranslator 0) { String root = args[0]; @@ -55,15 +56,13 @@ public class BedrockCommandRequestTranslator extends PacketTranslator