Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor GameProtocol to remove version slash-combinations #4979

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ The ultimate goal of this project is to allow Minecraft: Bedrock Edition users t
Special thanks to the DragonProxy project for being a trailblazer in protocol translation and for all the team members who have joined us here!

## Supported Versions
Geyser is currently supporting Minecraft Bedrock 1.20.80 - 1.21.21 and Minecraft Java 1.21/1.21.1. For more information, please see [here](https://geysermc.org/wiki/geyser/supported-versions/).
Geyser is currently supporting Minecraft Bedrock 1.20.80 - 1.21.22 and Minecraft Java 1.21/1.21.1. For more information, please see [here](https://geysermc.org/wiki/geyser/supported-versions/).

## Setting Up
Take a look [here](https://geysermc.org/wiki/geyser/setup/) for how to set up Geyser.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
*/
Expand Down
8 changes: 1 addition & 7 deletions core/src/main/java/org/geysermc/geyser/GeyserImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@
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.geysermc.api.Geyser;
import org.geysermc.cumulus.form.Form;
import org.geysermc.cumulus.form.util.FormBuilder;
Expand Down Expand Up @@ -112,7 +111,6 @@
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;
Expand Down Expand Up @@ -826,11 +824,7 @@ public PlatformType platformType() {

@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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -43,6 +43,25 @@

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) {
Expand All @@ -54,23 +73,8 @@ public VersionCommand(GeyserImpl geyser, String name, String description, String
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)) {
Expand Down
8 changes: 4 additions & 4 deletions core/src/main/java/org/geysermc/geyser/dump/DumpInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,12 @@
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;
Expand Down Expand Up @@ -225,9 +225,9 @@ public static class MCInfo {
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();
}
Expand Down
109 changes: 70 additions & 39 deletions core/src/main/java/org/geysermc/geyser/network/GameProtocol.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,38 +25,55 @@

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.v671.Bedrock_v671;
import org.cloudburstmc.protocol.bedrock.codec.v685.Bedrock_v685;
import org.cloudburstmc.protocol.bedrock.codec.v686.Bedrock_v686;
import org.cloudburstmc.protocol.bedrock.codec.v712.Bedrock_v712;
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.
*/
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_v712.CODEC.toBuilder()
.minecraftVersion("1.21.20/1.21.21")
.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
Expand All @@ -65,16 +82,47 @@ public final class GameProtocol {
private static final PacketCodec DEFAULT_JAVA_CODEC = MinecraftCodec.CODEC;

static {
SUPPORTED_BEDROCK_CODECS.add(CodecProcessor.processCodec(Bedrock_v671.CODEC.toBuilder()
.minecraftVersion("1.20.80/1.20.81")
.build()));
SUPPORTED_BEDROCK_CODECS.add(CodecProcessor.processCodec(Bedrock_v685.CODEC.toBuilder()
.minecraftVersion("1.21.0/1.21.1")
.build()));
SUPPORTED_BEDROCK_CODECS.add(CodecProcessor.processCodec(Bedrock_v686.CODEC.toBuilder()
.minecraftVersion("1.21.2/1.21.3")
.build()));
SUPPORTED_BEDROCK_CODECS.add(DEFAULT_BEDROCK_CODEC);
// Strict ordering
register(Bedrock_v671.CODEC, "1.20.80", "1.20.81");
register(Bedrock_v685.CODEC, "1.21.0", "1.21.1");
register(Bedrock_v686.CODEC, "1.21.2", "1.21.3");
register(Bedrock_v712.CODEC, "1.21.20", "1.21.21", "1.21.22");

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());

if (minecraftVersions.length < 1) {
throw new IllegalArgumentException("Must provide a minecraft version");
}
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());
}

/**
Expand All @@ -101,15 +149,6 @@ public static boolean isPre1_21_2(GeyserSession session) {
return session.getUpstream().getProtocolVersion() < Bedrock_v686.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.
*
Expand Down Expand Up @@ -141,24 +180,16 @@ public static String getJavaMinecraftVersion() {
* @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() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,9 @@ PacketSignal defaultHandler(BedrockPacket packet) {
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.
Expand All @@ -118,7 +119,7 @@ private boolean setCorrectCodec(int protocolVersion) {
}
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:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,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;
/**
Expand Down Expand Up @@ -316,7 +316,7 @@ public BedrockPong onQuery(Channel channel, InetSocketAddress inetSocketAddress)
.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)
Expand Down Expand Up @@ -391,17 +391,6 @@ public BedrockPong onQuery(Channel channel, InetSocketAddress inetSocketAddress)
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.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ public static CompletableFuture<Void> generateAssetCache() {
// 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;
}
Expand Down