1
0
mirror of https://github.com/GeyserMC/Geyser.git synced 2025-12-19 23:09:29 +00:00

Refactor GameProtocol to remove version slash-combinations (#4979)

* Refactor GameProtocol

* Document 1.21.22 as a supported version, update MinecraftVersion javadoc

* Only expose latest Bedrock protocol & version, ensure latest version in ping

* Also indicate 1.21.8 Java edition support in the geyser api

---------

Co-authored-by: onebeastchris <github@onechris.mozmail.com>
This commit is contained in:
Konicai
2025-07-27 14:37:51 -04:00
committed by GitHub
parent a6f707fb10
commit 70bdb7f66a
9 changed files with 102 additions and 94 deletions

View File

@@ -34,7 +34,7 @@ public interface MinecraftVersion {
/**
* Gets the Minecraft version as a String.
* Example: "1.20.2", or "1.20.40/1.20.41"
* Example formats: "1.21", "1.21.1", "1.21.22"
*
* @return the version string
*/

View File

@@ -57,14 +57,6 @@ repositories {
name = "viaversion"
}
// BungeeCord
// maven("https://oss.sonatype.org/content/repositories/snapshots") {
// mavenContent { snapshotsOnly() }
// }
// For Adventure snapshots
//maven("https://s01.oss.sonatype.org/content/repositories/snapshots/")
// Jitpack for e.g. MCPL
maven("https://jitpack.io") {
content { includeGroupByRegex("com\\.github\\..*") }

View File

@@ -41,7 +41,6 @@ import net.kyori.adventure.text.format.NamedTextColor;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.cloudburstmc.protocol.bedrock.codec.BedrockCodec;
import org.cloudburstmc.protocol.bedrock.util.EncryptionUtils;
import org.geysermc.api.Geyser;
import org.geysermc.cumulus.form.Form;
@@ -111,7 +110,6 @@ import java.net.UnknownHostException;
import java.nio.file.Path;
import java.security.Key;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
@@ -792,11 +790,7 @@ public class GeyserImpl implements GeyserApi, EventRegistrar {
@Override
public @NonNull List<MinecraftVersion> supportedBedrockVersions() {
ArrayList<MinecraftVersion> versions = new ArrayList<>();
for (BedrockCodec codec : GameProtocol.SUPPORTED_BEDROCK_CODECS) {
versions.add(new MinecraftVersionImpl(codec.getMinecraftVersion(), codec.getProtocolVersion()));
}
return Collections.unmodifiableList(versions);
return Collections.unmodifiableList(GameProtocol.SUPPORTED_BEDROCK_VERSIONS);
}
@Override

View File

@@ -26,8 +26,8 @@
package org.geysermc.geyser.command.defaults;
import com.fasterxml.jackson.databind.JsonNode;
import org.cloudburstmc.protocol.bedrock.codec.BedrockCodec;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.api.util.MinecraftVersion;
import org.geysermc.geyser.api.util.PlatformType;
import org.geysermc.geyser.api.util.TriState;
import org.geysermc.geyser.command.GeyserCommand;
@@ -43,6 +43,25 @@ import java.util.List;
public class VersionCommand extends GeyserCommand {
private static final String SUPPORTED_BEDROCK_RANGE;
private static final String SUPPORTED_JAVA_RANGE;
static {
List<MinecraftVersion> bedrockVersions = GameProtocol.SUPPORTED_BEDROCK_VERSIONS;
if (bedrockVersions.size() > 1) {
SUPPORTED_BEDROCK_RANGE = bedrockVersions.get(0).versionString() + " - " + bedrockVersions.get(bedrockVersions.size() - 1).versionString();
} else {
SUPPORTED_BEDROCK_RANGE = bedrockVersions.get(0).versionString();
}
List<String> javaVersions = GameProtocol.getJavaVersions();
if (javaVersions.size() > 1) {
SUPPORTED_JAVA_RANGE = javaVersions.get(0) + " - " + javaVersions.get(javaVersions.size() - 1);
} else {
SUPPORTED_JAVA_RANGE = javaVersions.get(0);
}
}
private final GeyserImpl geyser;
public VersionCommand(GeyserImpl geyser, String name, String description, String permission) {
@@ -54,23 +73,8 @@ public class VersionCommand extends GeyserCommand {
public void execute(CommandContext<GeyserCommandSource> context) {
GeyserCommandSource source = context.sender();
String bedrockVersions;
List<BedrockCodec> supportedCodecs = GameProtocol.SUPPORTED_BEDROCK_CODECS;
if (supportedCodecs.size() > 1) {
bedrockVersions = supportedCodecs.get(0).getMinecraftVersion() + " - " + supportedCodecs.get(supportedCodecs.size() - 1).getMinecraftVersion();
} else {
bedrockVersions = GameProtocol.SUPPORTED_BEDROCK_CODECS.get(0).getMinecraftVersion();
}
String javaVersions;
List<String> supportedJavaVersions = GameProtocol.getJavaVersions();
if (supportedJavaVersions.size() > 1) {
javaVersions = supportedJavaVersions.get(0) + " - " + supportedJavaVersions.get(supportedJavaVersions.size() - 1);
} else {
javaVersions = supportedJavaVersions.get(0);
}
source.sendMessage(GeyserLocale.getPlayerLocaleString("geyser.commands.version.version", source.locale(),
GeyserImpl.NAME, GeyserImpl.VERSION, javaVersions, bedrockVersions));
GeyserImpl.NAME, GeyserImpl.VERSION, SUPPORTED_JAVA_RANGE, SUPPORTED_BEDROCK_RANGE));
// Disable update checking in dev mode and for players in Geyser Standalone
if (!GeyserImpl.getInstance().isProductionEnvironment() || (!source.isConsole() && geyser.getPlatformType() == PlatformType.STANDALONE)) {

View File

@@ -34,12 +34,12 @@ import com.google.common.io.Files;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import lombok.Getter;
import org.cloudburstmc.protocol.bedrock.codec.BedrockCodec;
import org.geysermc.floodgate.util.DeviceOs;
import org.geysermc.floodgate.util.FloodgateInfoHolder;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.api.GeyserApi;
import org.geysermc.geyser.api.extension.Extension;
import org.geysermc.geyser.api.util.MinecraftVersion;
import org.geysermc.geyser.configuration.GeyserConfiguration;
import org.geysermc.geyser.network.GameProtocol;
import org.geysermc.geyser.session.GeyserSession;
@@ -224,9 +224,9 @@ public class DumpInfo {
private final int javaProtocol;
MCInfo() {
this.bedrockVersions = GameProtocol.SUPPORTED_BEDROCK_CODECS.stream().map(BedrockCodec::getMinecraftVersion).toList();
this.bedrockProtocols = GameProtocol.SUPPORTED_BEDROCK_CODECS.stream().map(BedrockCodec::getProtocolVersion).toList();
this.defaultBedrockProtocol = GameProtocol.DEFAULT_BEDROCK_CODEC.getProtocolVersion();
this.bedrockVersions = GameProtocol.SUPPORTED_BEDROCK_VERSIONS.stream().map(MinecraftVersion::versionString).toList();
this.bedrockProtocols = GameProtocol.SUPPORTED_BEDROCK_PROTOCOLS;
this.defaultBedrockProtocol = GameProtocol.DEFAULT_BEDROCK_PROTOCOL;
this.javaVersions = GameProtocol.getJavaVersions();
this.javaProtocol = GameProtocol.getJavaProtocolVersion();
}

View File

@@ -25,6 +25,8 @@
package org.geysermc.geyser.network;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import it.unimi.dsi.fastutil.ints.IntList;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.cloudburstmc.protocol.bedrock.codec.BedrockCodec;
import org.cloudburstmc.protocol.bedrock.codec.v786.Bedrock_v786;
@@ -32,13 +34,15 @@ import org.cloudburstmc.protocol.bedrock.codec.v800.Bedrock_v800;
import org.cloudburstmc.protocol.bedrock.codec.v818.Bedrock_v818;
import org.cloudburstmc.protocol.bedrock.codec.v819.Bedrock_v819;
import org.cloudburstmc.protocol.bedrock.netty.codec.packet.BedrockPacketCodec;
import org.geysermc.geyser.api.util.MinecraftVersion;
import org.geysermc.geyser.impl.MinecraftVersionImpl;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.mcprotocollib.protocol.codec.MinecraftCodec;
import org.geysermc.mcprotocollib.protocol.codec.PacketCodec;
import java.util.ArrayList;
import java.util.List;
import java.util.StringJoiner;
import java.util.stream.Collectors;
/**
* Contains information about the supported protocols in Geyser.
@@ -46,17 +50,30 @@ import java.util.StringJoiner;
public final class GameProtocol {
/**
* Default Bedrock codec that should act as a fallback. Should represent the latest available
* release of the game that Geyser supports.
* All Bedrock protocol codecs that Geyser uses
*/
public static final BedrockCodec DEFAULT_BEDROCK_CODEC = CodecProcessor.processCodec(Bedrock_v819.CODEC.toBuilder()
.minecraftVersion("1.21.93")
.build());
private static final List<BedrockCodec> SUPPORTED_BEDROCK_CODECS = new ArrayList<>();
/**
* A list of all supported Bedrock versions that can join Geyser
* All bedrock protocol versions that Geyser supports
*/
public static final List<BedrockCodec> SUPPORTED_BEDROCK_CODECS = new ArrayList<>();
public static final IntList SUPPORTED_BEDROCK_PROTOCOLS = new IntArrayList();
/**
* All bedrock minecraft versions that Geyser supports.
* There may be multiple MinecraftVersions with the same protocol version.
*/
public static final List<MinecraftVersion> SUPPORTED_BEDROCK_VERSIONS = new ArrayList<>();
/**
* The latest Bedrock protocol version that Geyser supports.
*/
public static final int DEFAULT_BEDROCK_PROTOCOL;
/**
* The latest Bedrock Minecraft version that Geyser supports.
*/
public static final String DEFAULT_BEDROCK_VERSION;
/**
* Java codec that is supported. We only ever support one version for
@@ -65,16 +82,44 @@ public final class GameProtocol {
private static final PacketCodec DEFAULT_JAVA_CODEC = MinecraftCodec.CODEC;
static {
SUPPORTED_BEDROCK_CODECS.add(CodecProcessor.processCodec(Bedrock_v786.CODEC.toBuilder()
.minecraftVersion("1.21.70 - 1.21.73")
.build()));
SUPPORTED_BEDROCK_CODECS.add(CodecProcessor.processCodec(Bedrock_v800.CODEC.toBuilder()
.minecraftVersion("1.21.80 - 1.21.84")
.build()));
SUPPORTED_BEDROCK_CODECS.add((CodecProcessor.processCodec(Bedrock_v818.CODEC.toBuilder()
.minecraftVersion("1.21.90 - 1.21.92")
.build())));
SUPPORTED_BEDROCK_CODECS.add(DEFAULT_BEDROCK_CODEC);
// Strict ordering
register(Bedrock_v786.CODEC, "1.21.70", "1.21.71", "1.21.72", "1.21.73");
register(Bedrock_v800.CODEC, "1.21.80", "1.21.81", "1.21.82", "1.21.83", "1.21.84");
register(Bedrock_v818.CODEC, "1.21.90", "1.21.91", "1.21.92");
register(Bedrock_v819.CODEC, "1.21.93", "1.21.94");
MinecraftVersion latestBedrock = SUPPORTED_BEDROCK_VERSIONS.get(SUPPORTED_BEDROCK_VERSIONS.size() - 1);
DEFAULT_BEDROCK_VERSION = latestBedrock.versionString();
DEFAULT_BEDROCK_PROTOCOL = latestBedrock.protocolVersion();
}
/**
* Registers a bedrock codec, along with its protocol version and minecraft version(s).
* This method must be called in ascending order in terms of protocol version.
*
* @param codec the codec to register
* @param minecraftVersions all versions the codec supports, in ascending order
*/
private static void register(BedrockCodec codec, String... minecraftVersions) {
// modify packet serializers to better fit our use
codec = CodecProcessor.processCodec(codec);
SUPPORTED_BEDROCK_CODECS.add(codec);
SUPPORTED_BEDROCK_PROTOCOLS.add(codec.getProtocolVersion());
for (String version : minecraftVersions) {
SUPPORTED_BEDROCK_VERSIONS.add(new MinecraftVersionImpl(version, codec.getProtocolVersion()));
}
}
/**
* Registers a bedrock codec, its protocol version, and a single minecraft version which is taken from the codec.
* This method must be called in ascending order in terms of protocol version.
*
* @param codec the codec to register
*/
private static void register(BedrockCodec codec) {
register(codec, codec.getMinecraftVersion());
}
/**
@@ -109,22 +154,13 @@ public final class GameProtocol {
return session.protocolVersion() == Bedrock_v800.CODEC.getProtocolVersion();
}
/**
* Gets the {@link PacketCodec} for Minecraft: Java Edition.
*
* @return the packet codec for Minecraft: Java Edition
*/
public static PacketCodec getJavaCodec() {
return DEFAULT_JAVA_CODEC;
}
/**
* Gets the supported Minecraft: Java Edition version names.
*
* @return the supported Minecraft: Java Edition version names
*/
public static List<String> getJavaVersions() {
return List.of(DEFAULT_JAVA_CODEC.getMinecraftVersion());
return List.of(DEFAULT_JAVA_CODEC.getMinecraftVersion(), "1.21.8");
}
/**
@@ -142,31 +178,23 @@ public final class GameProtocol {
* @return the supported Minecraft: Java Edition version
*/
public static String getJavaMinecraftVersion() {
return DEFAULT_JAVA_CODEC.getMinecraftVersion();
return "1.21.8";
}
/**
* @return a string showing all supported Bedrock versions for this Geyser instance
*/
public static String getAllSupportedBedrockVersions() {
StringJoiner joiner = new StringJoiner(", ");
for (BedrockCodec packetCodec : SUPPORTED_BEDROCK_CODECS) {
joiner.add(packetCodec.getMinecraftVersion());
}
return joiner.toString();
return SUPPORTED_BEDROCK_VERSIONS.stream()
.map(MinecraftVersion::versionString)
.collect(Collectors.joining(", "));
}
/**
* @return a string showing all supported Java versions for this Geyser instance
*/
public static String getAllSupportedJavaVersions() {
StringJoiner joiner = new StringJoiner(", ");
for (String version : getJavaVersions()) {
joiner.add(version);
}
return joiner.toString();
return String.join(", ", getJavaVersions());
}
private GameProtocol() {

View File

@@ -120,8 +120,9 @@ public class UpstreamPacketHandler extends LoggingPacketHandler {
private boolean setCorrectCodec(int protocolVersion) {
BedrockCodec packetCodec = GameProtocol.getBedrockCodec(protocolVersion);
if (packetCodec == null) {
// None of our Bedrock codecs support this client version, so we can simply compare it to our default protocol.
String supportedVersions = GameProtocol.getAllSupportedBedrockVersions();
if (protocolVersion > GameProtocol.DEFAULT_BEDROCK_CODEC.getProtocolVersion()) {
if (protocolVersion > GameProtocol.DEFAULT_BEDROCK_PROTOCOL) {
// Too early to determine session locale
String disconnectMessage = GeyserLocale.getLocaleStringLog("geyser.network.outdated.server", supportedVersions);
// If the latest release matches this version, then let the user know.
@@ -132,7 +133,7 @@ public class UpstreamPacketHandler extends LoggingPacketHandler {
}
session.disconnect(disconnectMessage);
return false;
} else if (protocolVersion < GameProtocol.DEFAULT_BEDROCK_CODEC.getProtocolVersion()) {
} else if (protocolVersion < GameProtocol.DEFAULT_BEDROCK_PROTOCOL) {
// A note on the following line: various older client versions have different forms of DisconnectPacket.
// Using only the latest BedrockCompat for such clients leads to inaccurate disconnect messages: https://github.com/GeyserMC/Geyser/issues/4378
// This updates the BedrockCompat protocol if necessary:

View File

@@ -78,7 +78,7 @@ public final class GeyserServer {
/*
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 String PING_VERSION = pingVersion();
private static final String PING_VERSION = GameProtocol.DEFAULT_BEDROCK_VERSION;
private static final int PING_VERSION_BYTES_LENGTH = PING_VERSION.getBytes(StandardCharsets.UTF_8).length;
private static final int BRAND_BYTES_LENGTH = GeyserImpl.NAME.getBytes(StandardCharsets.UTF_8).length;
/**
@@ -311,7 +311,7 @@ public final class GeyserServer {
.edition("MCPE")
.gameType("Survival") // Can only be Survival or Creative as of 1.16.210.59
.nintendoLimited(false)
.protocolVersion(GameProtocol.DEFAULT_BEDROCK_CODEC.getProtocolVersion())
.protocolVersion(GameProtocol.DEFAULT_BEDROCK_PROTOCOL)
.version(PING_VERSION)
.ipv4Port(this.broadcastPort)
.ipv6Port(this.broadcastPort)
@@ -386,17 +386,6 @@ public final class GeyserServer {
return pong;
}
private static String pingVersion() {
// BedrockPong version is required to not be empty as of 1.16.210.59.
// Can only contain . and numbers, so use the latest version instead of sending all
var version = GameProtocol.DEFAULT_BEDROCK_CODEC.getMinecraftVersion();
var versionSplit = version.split("/");
if (versionSplit.length > 1) {
version = versionSplit[versionSplit.length - 1];
}
return version;
}
/**
* @return the throwable from the given supplier, or the throwable caught while calling the supplier.
*/

View File

@@ -89,7 +89,7 @@ public final class AssetUtils {
// Get the url for the latest version of the games manifest
String latestInfoURL = "";
for (Version version : versionManifest.getVersions()) {
if (version.getId().equals(GameProtocol.getJavaCodec().getMinecraftVersion())) {
if (version.getId().equals(GameProtocol.getJavaMinecraftVersion())) {
latestInfoURL = version.getUrl();
break;
}