1
0
mirror of https://github.com/GeyserMC/Geyser.git synced 2025-12-19 14:59:27 +00:00

Introduce sendCommand API method (#5582)

* Introduce sendCommand API method

* Ensure Geyser/extension commands are caught

* Remove handleCommand from the translator, use executeCommand directly

* Relocate the command handling logic again, using the new one this time

* Fix up the javadocs

* Rename back to sendCommand, rename the packet method

* Also change the bedrock command translator

* And another one...

* Ensure we forward commands directly when catching exceptions during command execution

---------

Co-authored-by: onebeastchris <github@onechris.mozmail.com>
This commit is contained in:
Aurorawr
2025-06-25 23:21:40 +01:00
committed by GitHub
parent 0f857c69a4
commit 2ca4ea7652
7 changed files with 46 additions and 33 deletions

View File

@@ -107,6 +107,13 @@ public interface GeyserConnection extends Connection, CommandSource {
*/ */
void openQuickActions(); void openQuickActions();
/**
* Sends a command as if the player had executed it.
*
* @param command the command without the leading forward-slash
*/
void sendCommand(String command);
/** /**
* @param javaId the Java entity ID to look up. * @param javaId the Java entity ID to look up.
* @return a {@link GeyserEntity} if present in this connection's entity tracker. * @return a {@link GeyserEntity} if present in this connection's entity tracker.

View File

@@ -287,7 +287,7 @@ public class CommandRegistry implements EventRegistrar {
help.execute(source); help.execute(source);
} else if (STANDALONE_COMMAND_MANAGER && source instanceof GeyserSession session) { } else if (STANDALONE_COMMAND_MANAGER && source instanceof GeyserSession session) {
// If we are on an appropriate platform, forward the command to the backend // If we are on an appropriate platform, forward the command to the backend
session.sendCommand(context.rawInput().input()); session.sendCommandPacket(context.rawInput().input());
} else { } else {
source.sendLocaleString(ExceptionHandlers.PERMISSION_FAIL_LANG_KEY); source.sendLocaleString(ExceptionHandlers.PERMISSION_FAIL_LANG_KEY);
} }

View File

@@ -89,7 +89,7 @@ final class ExceptionHandlers {
(ctx, e) -> { (ctx, e) -> {
// Let backend server receive & handle the command // Let backend server receive & handle the command
if (CommandRegistry.STANDALONE_COMMAND_MANAGER && ctx.sender() instanceof GeyserSession session) { if (CommandRegistry.STANDALONE_COMMAND_MANAGER && ctx.sender() instanceof GeyserSession session) {
session.sendCommand(ctx.rawInput().input()); session.sendCommandPacket(ctx.rawInput().input());
} else { } else {
ctx.sender().sendLocaleString("geyser.command.not_found"); ctx.sender().sendLocaleString("geyser.command.not_found");
} }
@@ -114,7 +114,7 @@ final class ExceptionHandlers {
// Let backend server receive & handle the command // Let backend server receive & handle the command
if (CommandRegistry.STANDALONE_COMMAND_MANAGER && source instanceof GeyserSession session) { if (CommandRegistry.STANDALONE_COMMAND_MANAGER && source instanceof GeyserSession session) {
session.sendCommand(context.rawInput().input()); session.sendCommandPacket(context.rawInput().input());
return; return;
} }

View File

@@ -126,7 +126,7 @@ public abstract class WorldManager {
* @param value The new value for the gamerule * @param value The new value for the gamerule
*/ */
public void setGameRule(GeyserSession session, String name, Object value) { public void setGameRule(GeyserSession session, String name, Object value) {
session.sendCommand("gamerule " + name + " " + value); session.sendCommandPacket("gamerule " + name + " " + value);
} }
/** /**
@@ -162,7 +162,7 @@ public abstract class WorldManager {
* @param gameMode the new default game mode * @param gameMode the new default game mode
*/ */
public void setDefaultGameMode(GeyserSession session, GameMode gameMode) { public void setDefaultGameMode(GeyserSession session, GameMode gameMode) {
session.sendCommand("defaultgamemode " + gameMode.name().toLowerCase(Locale.ROOT)); session.sendCommandPacket("defaultgamemode " + gameMode.name().toLowerCase(Locale.ROOT));
} }
/** /**
@@ -172,7 +172,7 @@ public abstract class WorldManager {
* @param difficulty The difficulty to change to * @param difficulty The difficulty to change to
*/ */
public void setDifficulty(GeyserSession session, Difficulty difficulty) { public void setDifficulty(GeyserSession session, Difficulty difficulty) {
session.sendCommand("difficulty " + difficulty.name().toLowerCase(Locale.ROOT)); session.sendCommandPacket("difficulty " + difficulty.name().toLowerCase(Locale.ROOT));
} }
/** /**

View File

@@ -120,6 +120,7 @@ import org.geysermc.geyser.api.entity.type.player.GeyserPlayerEntity;
import org.geysermc.geyser.api.event.bedrock.SessionDisconnectEvent; import org.geysermc.geyser.api.event.bedrock.SessionDisconnectEvent;
import org.geysermc.geyser.api.event.bedrock.SessionLoginEvent; import org.geysermc.geyser.api.event.bedrock.SessionLoginEvent;
import org.geysermc.geyser.api.network.RemoteServer; import org.geysermc.geyser.api.network.RemoteServer;
import org.geysermc.geyser.command.CommandRegistry;
import org.geysermc.geyser.command.GeyserCommandSource; import org.geysermc.geyser.command.GeyserCommandSource;
import org.geysermc.geyser.configuration.EmoteOffhandWorkaroundOption; import org.geysermc.geyser.configuration.EmoteOffhandWorkaroundOption;
import org.geysermc.geyser.configuration.GeyserConfiguration; import org.geysermc.geyser.configuration.GeyserConfiguration;
@@ -1510,10 +1511,39 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
/** /**
* Sends a command to the Java server. * Sends a command to the Java server.
*/ */
public void sendCommand(String command) { public void sendCommandPacket(String command) {
sendDownstreamGamePacket(new ServerboundChatCommandSignedPacket(command, Instant.now().toEpochMilli(), 0L, Collections.emptyList(), 0, new BitSet(), (byte) 0)); sendDownstreamGamePacket(new ServerboundChatCommandSignedPacket(command, Instant.now().toEpochMilli(), 0L, Collections.emptyList(), 0, new BitSet(), (byte) 0));
} }
/**
* Runs the command through platform specific command registries if applicable
* else, it sends the command to the server.
*/
@Override
public void sendCommand(String command) {
if (MessageTranslator.isTooLong(command, this)) {
return;
}
if (CommandRegistry.STANDALONE_COMMAND_MANAGER) {
// try to handle the command within the standalone/viaproxy command manager
String[] args = command.split(" ");
if (args.length > 0) {
String root = args[0];
CommandRegistry registry = GeyserImpl.getInstance().commandRegistry();
if (registry.rootCommands().contains(root)) {
registry.runCommand(this, command);
// don't pass the command to the java server here
// will pass it through later if the user lacks permission
return;
}
}
}
this.sendCommandPacket(command);
}
@Override @Override
public void openPauseScreenAdditions() { public void openPauseScreenAdditions() {
List<Dialog> additions = tagCache.get(DialogTag.PAUSE_SCREEN_ADDITIONS); List<Dialog> additions = tagCache.get(DialogTag.PAUSE_SCREEN_ADDITIONS);

View File

@@ -39,30 +39,6 @@ public class BedrockCommandRequestTranslator extends PacketTranslator<CommandReq
@Override @Override
public void translate(GeyserSession session, CommandRequestPacket packet) { public void translate(GeyserSession session, CommandRequestPacket packet) {
String command = MessageTranslator.convertToPlainText(packet.getCommand()); String command = MessageTranslator.convertToPlainText(packet.getCommand());
handleCommand(session, MessageTranslator.normalizeSpace(command).substring(1)); session.sendCommand(MessageTranslator.normalizeSpace(command).substring(1));
}
static void handleCommand(GeyserSession session, String command) {
if (MessageTranslator.isTooLong(command, session)) {
return;
}
if (CommandRegistry.STANDALONE_COMMAND_MANAGER) {
// try to handle the command within the standalone/viaproxy command manager
String[] args = command.split(" ");
if (args.length > 0) {
String root = args[0];
CommandRegistry registry = GeyserImpl.getInstance().commandRegistry();
if (registry.rootCommands().contains(root)) {
registry.runCommand(session, command);
// don't pass the command to the java server here
// will pass it through later if the user lacks permission
return;
}
}
}
session.sendCommand(command);
} }
} }

View File

@@ -48,7 +48,7 @@ public class BedrockTextTranslator extends PacketTranslator<TextPacket> {
if (message.startsWith("/")) { if (message.startsWith("/")) {
// Yes, Java actually allows whitespaces before commands and will still see those as valid // Yes, Java actually allows whitespaces before commands and will still see those as valid
BedrockCommandRequestTranslator.handleCommand(session, message.substring(1)); session.sendCommand(message.substring(1));
return; return;
} }