Don't allow the sub-MOTD to be empty (#1933)

As of 1.16.210.59, the sub-MOTD cannot be blank: https://bugs.mojang.com/browse/MCPE-117979

This workaround will be implemented now so the widest range of Geyser versions will properly show a ping in 1.16.210 - better an 'outdated server' message than 'unable to connect to world.'
This commit is contained in:
Camotoy 2021-02-15 21:41:11 -05:00 committed by GitHub
parent 93a74d669d
commit 1f1d94aa81
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 29 additions and 13 deletions

View file

@ -42,6 +42,15 @@ import java.net.InetSocketAddress;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
public class ConnectorServerEventHandler implements BedrockServerEventHandler { public class ConnectorServerEventHandler implements BedrockServerEventHandler {
/*
The following constants are all used to ensure the ping does not reach a length where it is unparsable by the Bedrock client
*/
private static final int MINECRAFT_VERSION_BYTES_LENGTH = BedrockProtocol.DEFAULT_BEDROCK_CODEC.getMinecraftVersion().getBytes(StandardCharsets.UTF_8).length;
private static final int BRAND_BYTES_LENGTH = GeyserConnector.NAME.getBytes(StandardCharsets.UTF_8).length;
/**
* The MOTD, sub-MOTD and Minecraft version ({@link #MINECRAFT_VERSION_BYTES_LENGTH}) combined cannot reach this length.
*/
private static final int MAGIC_RAKNET_LENGTH = 338;
private final GeyserConnector connector; private final GeyserConnector connector;
@ -72,13 +81,13 @@ public class ConnectorServerEventHandler implements BedrockServerEventHandler {
pong.setGameType("Survival"); // Can only be Survival or Creative as of 1.16.210.59 pong.setGameType("Survival"); // Can only be Survival or Creative as of 1.16.210.59
pong.setNintendoLimited(false); pong.setNintendoLimited(false);
pong.setProtocolVersion(BedrockProtocol.DEFAULT_BEDROCK_CODEC.getProtocolVersion()); pong.setProtocolVersion(BedrockProtocol.DEFAULT_BEDROCK_CODEC.getProtocolVersion());
pong.setVersion(BedrockProtocol.DEFAULT_BEDROCK_CODEC.getMinecraftVersion()); // Required to not be empty as of 1.16.210.59 pong.setVersion(BedrockProtocol.DEFAULT_BEDROCK_CODEC.getMinecraftVersion()); // Required to not be empty as of 1.16.210.59. Can only contain . and numbers.
pong.setIpv4Port(config.getBedrock().getPort()); pong.setIpv4Port(config.getBedrock().getPort());
if (config.isPassthroughMotd() && pingInfo != null && pingInfo.getDescription() != null) { if (config.isPassthroughMotd() && pingInfo != null && pingInfo.getDescription() != null) {
String[] motd = MessageTranslator.convertMessageLenient(pingInfo.getDescription()).split("\n"); String[] motd = MessageTranslator.convertMessageLenient(pingInfo.getDescription()).split("\n");
String mainMotd = motd[0]; // First line of the motd. String mainMotd = motd[0]; // First line of the motd.
String subMotd = (motd.length != 1) ? motd[1] : ""; // Second line of the motd if present, otherwise blank. String subMotd = (motd.length != 1) ? motd[1] : GeyserConnector.NAME; // Second line of the motd if present, otherwise default.
pong.setMotd(mainMotd.trim()); pong.setMotd(mainMotd.trim());
pong.setSubMotd(subMotd.trim()); // Trimmed to shift it to the left, prevents the universe from collapsing on us just because we went 2 characters over the text box's limit. pong.setSubMotd(subMotd.trim()); // Trimmed to shift it to the left, prevents the universe from collapsing on us just because we went 2 characters over the text box's limit.
@ -95,22 +104,28 @@ public class ConnectorServerEventHandler implements BedrockServerEventHandler {
pong.setMaximumPlayerCount(config.getMaxPlayers()); pong.setMaximumPlayerCount(config.getMaxPlayers());
} }
if (pong.getMotd() == null) { // Fallbacks to prevent errors and allow Bedrock to see the server
pong.setMotd(""); if (pong.getMotd() == null || pong.getMotd().trim().isEmpty()) {
pong.setMotd(GeyserConnector.NAME);
} }
if (pong.getSubMotd() == null) { if (pong.getSubMotd() == null || pong.getSubMotd().trim().isEmpty()) {
pong.setSubMotd(""); // Sub-MOTD cannot be empty as of 1.16.210.59
pong.setSubMotd(GeyserConnector.NAME);
} }
// The ping will not appear if the MOTD + sub-MOTD is of a certain length. // The ping will not appear if the MOTD + sub-MOTD is of a certain length.
// We don't know why, though // We don't know why, though
byte[] motdArray = pong.getMotd().getBytes(StandardCharsets.UTF_8); byte[] motdArray = pong.getMotd().getBytes(StandardCharsets.UTF_8);
if (motdArray.length + pong.getSubMotd().getBytes(StandardCharsets.UTF_8).length > 338) { int subMotdLength = pong.getSubMotd().getBytes(StandardCharsets.UTF_8).length;
// Remove the sub-MOTD first since that only appears locally if (motdArray.length + subMotdLength > (MAGIC_RAKNET_LENGTH - MINECRAFT_VERSION_BYTES_LENGTH)) {
pong.setSubMotd(""); // Shorten the sub-MOTD first since that only appears locally
if (motdArray.length > 338) { if (subMotdLength > BRAND_BYTES_LENGTH) {
pong.setSubMotd(GeyserConnector.NAME);
subMotdLength = BRAND_BYTES_LENGTH;
}
if (motdArray.length > (MAGIC_RAKNET_LENGTH - MINECRAFT_VERSION_BYTES_LENGTH - subMotdLength)) {
// If the top MOTD is still too long, we chop it down // If the top MOTD is still too long, we chop it down
byte[] newMotdArray = new byte[339]; byte[] newMotdArray = new byte[MAGIC_RAKNET_LENGTH - MINECRAFT_VERSION_BYTES_LENGTH - subMotdLength];
System.arraycopy(motdArray, 0, newMotdArray, 0, newMotdArray.length); System.arraycopy(motdArray, 0, newMotdArray, 0, newMotdArray.length);
pong.setMotd(new String(newMotdArray, StandardCharsets.UTF_8)); pong.setMotd(new String(newMotdArray, StandardCharsets.UTF_8));
} }

View file

@ -18,8 +18,9 @@ bedrock:
# This option is for the plugin version only. # This option is for the plugin version only.
clone-remote-port: false clone-remote-port: false
# The MOTD that will be broadcasted to Minecraft: Bedrock Edition clients. This is irrelevant if "passthrough-motd" is set to true # The MOTD that will be broadcasted to Minecraft: Bedrock Edition clients. This is irrelevant if "passthrough-motd" is set to true
motd1: "GeyserMC" # If either of these are empty, the respective string will default to "Geyser"
motd2: "Another GeyserMC forced host." motd1: "Geyser"
motd2: "Another Geyser server."
# The Server Name that will be sent to Minecraft: Bedrock Edition clients. This is visible in both the pause menu and the settings menu. # The Server Name that will be sent to Minecraft: Bedrock Edition clients. This is visible in both the pause menu and the settings menu.
server-name: "Geyser" server-name: "Geyser"
remote: remote: