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 1 commit
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
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
6 changes: 3 additions & 3 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,8 +225,8 @@ 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.bedrockVersions = GameProtocol.SUPPORTED_BEDROCK_VERSIONS.stream().map(MinecraftVersion::versionString).toList();
this.bedrockProtocols = GameProtocol.SUPPORTED_BEDROCK_PROTOCOLS;
this.defaultBedrockProtocol = GameProtocol.DEFAULT_BEDROCK_CODEC.getProtocolVersion();
this.javaVersions = GameProtocol.getJavaVersions();
this.javaProtocol = GameProtocol.getJavaProtocolVersion();
Expand Down
100 changes: 61 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,50 @@

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 codec in use
*/
public static final BedrockCodec DEFAULT_BEDROCK_CODEC;

/**
* Java codec that is supported. We only ever support one version for
Expand All @@ -65,16 +77,43 @@ 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);
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");

DEFAULT_BEDROCK_CODEC = SUPPORTED_BEDROCK_CODECS.get(SUPPORTED_BEDROCK_CODECS.size() - 1);
}

/**
* Registers the given BedrockCodec, along with its protocol version and minecraft version(s)
*
* @param codec the codec to register
* @param minecraftVersions all versions the codec supports
*/
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 codec, its protocol version,
* and a single minecraft version which is taken from the codec
*
* @param codec the codec to register
*/
private static void register(BedrockCodec codec) {
register(codec, codec.getMinecraftVersion());
}

/**
Expand All @@ -101,15 +140,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 +171,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 @@ -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_CODEC.getMinecraftVersion();
Copy link
Member

@Tim203 Tim203 Aug 24, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not against this, but one thing that should be noted here is that because we no longer override minecraftVersion the ping version will now become 1.21.20 instead of 1.21.21 (which was the version that'd show in the ping before this PR)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good catch

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 @@ -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