Ensure we send commands/chat the same way a Java client would (#4703)

* Ensure we send commands/chat the same way a Java client would

* yeet static import, move blank check
This commit is contained in:
chris 2024-05-29 23:43:39 +02:00 committed by GitHub
parent 0fcf0f9b4f
commit 66f30a2cb6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 50 additions and 6 deletions

View file

@ -26,8 +26,8 @@
package org.geysermc.geyser.translator.protocol.bedrock;
import org.cloudburstmc.protocol.bedrock.packet.CommandRequestPacket;
import org.geysermc.geyser.api.util.PlatformType;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.api.util.PlatformType;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.protocol.PacketTranslator;
import org.geysermc.geyser.translator.protocol.Translator;
@ -39,15 +39,17 @@ public class BedrockCommandRequestTranslator extends PacketTranslator<CommandReq
@Override
public void translate(GeyserSession session, CommandRequestPacket packet) {
String command = MessageTranslator.convertToPlainText(packet.getCommand());
handleCommand(session, MessageTranslator.normalizeSpace(command).substring(1));
}
static void handleCommand(GeyserSession session, String command) {
if (!(session.getGeyser().getPlatformType() == PlatformType.STANDALONE
&& GeyserImpl.getInstance().commandManager().runCommand(session, command.substring(1)))) {
&& GeyserImpl.getInstance().commandManager().runCommand(session, command))) {
if (MessageTranslator.isTooLong(command, session)) {
return;
}
// running commands via Bedrock's command select menu adds a trailing whitespace which Java doesn't like
// https://github.com/GeyserMC/Geyser/issues/3877
session.sendCommand(command.substring(1).stripTrailing());
session.sendCommand(command);
}
}
}

View file

@ -36,13 +36,22 @@ public class BedrockTextTranslator extends PacketTranslator<TextPacket> {
@Override
public void translate(GeyserSession session, TextPacket packet) {
String message = MessageTranslator.convertToPlainText(packet.getMessage());
// Java trims all messages, and then checks for the leading slash
String message = MessageTranslator.convertToPlainText(
MessageTranslator.normalizeSpace(packet.getMessage())
);
if (message.isBlank()) {
// Java Edition (as of 1.17.1) just doesn't pass on these messages, so... we won't either!
return;
}
if (message.startsWith("/")) {
// Yes, Java actually allows whitespaces before commands and will still see those as valid
BedrockCommandRequestTranslator.handleCommand(session, message.substring(1));
return;
}
if (MessageTranslator.isTooLong(message, session)) {
return;
}

View file

@ -387,6 +387,39 @@ public class MessageTranslator {
return false;
}
/**
* Normalizes whitespaces - a thing a vanilla client apparently does with commands and chat messages.
*/
public static String normalizeSpace(String string) {
if (string == null || string.isEmpty()) {
return string;
}
final int size = string.length();
final char[] newChars = new char[size];
int count = 0;
int whitespacesCount = 0;
boolean startWhitespaces = true;
for (int i = 0; i < size; i++) {
final char actualChar = string.charAt(i);
final boolean isWhitespace = Character.isWhitespace(actualChar);
if (isWhitespace) {
if (whitespacesCount == 0 && !startWhitespaces) {
newChars[count++] = ' ';
}
whitespacesCount++;
} else {
startWhitespaces = false;
// Replace non-breaking spaces with regular spaces for normalization
newChars[count++] = (actualChar == '\u00A0' ? ' ' : actualChar);
whitespacesCount = 0;
}
}
if (startWhitespaces) {
return "";
}
return new String(newChars, 0, count - (whitespacesCount > 0 ? 1 : 0)).trim();
}
public static void init() {
// no-op
}