From 6ccf629a8ae9f5c573a60379c775f7282ead4951 Mon Sep 17 00:00:00 2001 From: DoctorMacc Date: Tue, 11 Aug 2020 10:00:14 -0400 Subject: [PATCH] Update to 1.16.2-rc2; add multiversion support --- connector/pom.xml | 2 +- .../geysermc/connector/GeyserConnector.java | 4 -- .../command/defaults/VersionCommand.java | 3 +- .../org/geysermc/connector/dump/DumpInfo.java | 5 +- .../connector/network/BedrockProtocol.java | 66 +++++++++++++++++++ .../network/ConnectorServerEventHandler.java | 3 +- .../connector/network/QueryPacketHandler.java | 2 +- .../network/UpstreamPacketHandler.java | 20 ++++-- 8 files changed, 87 insertions(+), 18 deletions(-) create mode 100644 connector/src/main/java/org/geysermc/connector/network/BedrockProtocol.java diff --git a/connector/pom.xml b/connector/pom.xml index 3d5c098ae..dd1ad1921 100644 --- a/connector/pom.xml +++ b/connector/pom.xml @@ -111,7 +111,7 @@ com.github.GeyserMC MCProtocolLib - 2ee53b72d1 + 82dcf31d03 compile diff --git a/connector/src/main/java/org/geysermc/connector/GeyserConnector.java b/connector/src/main/java/org/geysermc/connector/GeyserConnector.java index 693244799..103faf791 100644 --- a/connector/src/main/java/org/geysermc/connector/GeyserConnector.java +++ b/connector/src/main/java/org/geysermc/connector/GeyserConnector.java @@ -28,9 +28,7 @@ package org.geysermc.connector; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.nukkitx.network.raknet.RakNetConstants; -import com.nukkitx.protocol.bedrock.BedrockPacketCodec; import com.nukkitx.protocol.bedrock.BedrockServer; -import com.nukkitx.protocol.bedrock.v409.Bedrock_v409; import lombok.Getter; import lombok.Setter; import org.geysermc.connector.bootstrap.GeyserBootstrap; @@ -75,8 +73,6 @@ public class GeyserConnector { public static final ObjectMapper JSON_MAPPER = new ObjectMapper().disable(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES); - public static final BedrockPacketCodec BEDROCK_PACKET_CODEC = Bedrock_v409.V409_CODEC; - public static final String NAME = "Geyser"; public static final String VERSION = "DEV"; // A fallback for running in IDEs diff --git a/connector/src/main/java/org/geysermc/connector/command/defaults/VersionCommand.java b/connector/src/main/java/org/geysermc/connector/command/defaults/VersionCommand.java index 50527968d..681474a98 100644 --- a/connector/src/main/java/org/geysermc/connector/command/defaults/VersionCommand.java +++ b/connector/src/main/java/org/geysermc/connector/command/defaults/VersionCommand.java @@ -30,6 +30,7 @@ import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.command.CommandSender; import org.geysermc.connector.command.GeyserCommand; import org.geysermc.connector.common.ChatColor; +import org.geysermc.connector.network.BedrockProtocol; import org.geysermc.connector.utils.FileUtils; import org.geysermc.connector.utils.LanguageUtils; import org.geysermc.connector.utils.WebUtils; @@ -50,7 +51,7 @@ public class VersionCommand extends GeyserCommand { @Override public void execute(CommandSender sender, String[] args) { - sender.sendMessage(LanguageUtils.getLocaleStringLog("geyser.commands.version.version", GeyserConnector.NAME, GeyserConnector.VERSION, MinecraftConstants.GAME_VERSION, GeyserConnector.BEDROCK_PACKET_CODEC.getMinecraftVersion())); + sender.sendMessage(LanguageUtils.getLocaleStringLog("geyser.commands.version.version", GeyserConnector.NAME, GeyserConnector.VERSION, MinecraftConstants.GAME_VERSION, BedrockProtocol.DEFAULT_BEDROCK_CODEC.getMinecraftVersion())); // Disable update checking in dev mode //noinspection ConstantConditions - changes in production diff --git a/connector/src/main/java/org/geysermc/connector/dump/DumpInfo.java b/connector/src/main/java/org/geysermc/connector/dump/DumpInfo.java index 9c4928414..9d91cde6b 100644 --- a/connector/src/main/java/org/geysermc/connector/dump/DumpInfo.java +++ b/connector/src/main/java/org/geysermc/connector/dump/DumpInfo.java @@ -32,6 +32,7 @@ import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import lombok.Getter; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.configuration.GeyserConfiguration; +import org.geysermc.connector.network.BedrockProtocol; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.utils.DockerCheck; import org.geysermc.connector.utils.FileUtils; @@ -136,8 +137,8 @@ public class DumpInfo { private final int javaProtocol; MCInfo() { - this.bedrockVersion = GeyserConnector.BEDROCK_PACKET_CODEC.getMinecraftVersion(); - this.bedrockProtocol = GeyserConnector.BEDROCK_PACKET_CODEC.getProtocolVersion(); + this.bedrockVersion = BedrockProtocol.DEFAULT_BEDROCK_CODEC.getMinecraftVersion(); + this.bedrockProtocol = BedrockProtocol.DEFAULT_BEDROCK_CODEC.getProtocolVersion(); this.javaVersion = MinecraftConstants.GAME_VERSION; this.javaProtocol = MinecraftConstants.PROTOCOL_VERSION; } diff --git a/connector/src/main/java/org/geysermc/connector/network/BedrockProtocol.java b/connector/src/main/java/org/geysermc/connector/network/BedrockProtocol.java new file mode 100644 index 000000000..734bea436 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/BedrockProtocol.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network; + +import com.nukkitx.protocol.bedrock.BedrockPacketCodec; +import com.nukkitx.protocol.bedrock.v407.Bedrock_v407; +import com.nukkitx.protocol.bedrock.v409.Bedrock_v409; + +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +/** + * Contains information about the supported Bedrock protocols in Geyser. + */ +public class BedrockProtocol { + /** + * Default Bedrock codec that should act as a fallback and as the version shown in /geyser version + */ + public static final BedrockPacketCodec DEFAULT_BEDROCK_CODEC = Bedrock_v409.V409_CODEC; + /** + * A list of all supported Bedrock versions that can join Geyser + */ + public static final Set SUPPORTED_BEDROCK_CODECS = ConcurrentHashMap.newKeySet(); + + static { + SUPPORTED_BEDROCK_CODECS.add(DEFAULT_BEDROCK_CODEC); + SUPPORTED_BEDROCK_CODECS.add(Bedrock_v407.V407_CODEC); + } + + /** + * Gets the {@link BedrockPacketCodec} of the given protocol version. + * @param protocolVersion The protocol version to attempt to find + * @return The packet codec, or null if the client's protocol is unsupported + */ + public static BedrockPacketCodec getBedrockCodec(int protocolVersion) { + for (BedrockPacketCodec packetCodec : SUPPORTED_BEDROCK_CODECS) { + if (packetCodec.getProtocolVersion() == protocolVersion) { + return packetCodec; + } + } + return null; + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/ConnectorServerEventHandler.java b/connector/src/main/java/org/geysermc/connector/network/ConnectorServerEventHandler.java index 6ca9063c2..c850fc4ab 100644 --- a/connector/src/main/java/org/geysermc/connector/network/ConnectorServerEventHandler.java +++ b/connector/src/main/java/org/geysermc/connector/network/ConnectorServerEventHandler.java @@ -71,7 +71,7 @@ public class ConnectorServerEventHandler implements BedrockServerEventHandler { pong.setEdition("MCPE"); pong.setGameType("Default"); pong.setNintendoLimited(false); - pong.setProtocolVersion(GeyserConnector.BEDROCK_PACKET_CODEC.getProtocolVersion()); + pong.setProtocolVersion(BedrockProtocol.DEFAULT_BEDROCK_CODEC.getProtocolVersion()); pong.setVersion(null); // Server tries to connect either way and it looks better pong.setIpv4Port(config.getBedrock().getPort()); @@ -108,7 +108,6 @@ public class ConnectorServerEventHandler implements BedrockServerEventHandler { public void onSessionCreation(BedrockServerSession bedrockServerSession) { bedrockServerSession.setLogging(true); bedrockServerSession.setPacketHandler(new UpstreamPacketHandler(connector, new GeyserSession(connector, bedrockServerSession))); - bedrockServerSession.setPacketCodec(GeyserConnector.BEDROCK_PACKET_CODEC); } @Override diff --git a/connector/src/main/java/org/geysermc/connector/network/QueryPacketHandler.java b/connector/src/main/java/org/geysermc/connector/network/QueryPacketHandler.java index 7854f14c0..bd67fd1b5 100644 --- a/connector/src/main/java/org/geysermc/connector/network/QueryPacketHandler.java +++ b/connector/src/main/java/org/geysermc/connector/network/QueryPacketHandler.java @@ -167,7 +167,7 @@ public class QueryPacketHandler { gameData.put("hostname", motd); gameData.put("gametype", "SMP"); gameData.put("game_id", "MINECRAFT"); - gameData.put("version", GeyserConnector.BEDROCK_PACKET_CODEC.getMinecraftVersion()); + gameData.put("version", BedrockProtocol.DEFAULT_BEDROCK_CODEC.getMinecraftVersion()); gameData.put("plugins", ""); gameData.put("map", GeyserConnector.NAME); gameData.put("numplayers", currentPlayerCount); diff --git a/connector/src/main/java/org/geysermc/connector/network/UpstreamPacketHandler.java b/connector/src/main/java/org/geysermc/connector/network/UpstreamPacketHandler.java index 357e870f6..f65b3ef1a 100644 --- a/connector/src/main/java/org/geysermc/connector/network/UpstreamPacketHandler.java +++ b/connector/src/main/java/org/geysermc/connector/network/UpstreamPacketHandler.java @@ -26,6 +26,7 @@ package org.geysermc.connector.network; import com.nukkitx.protocol.bedrock.BedrockPacket; +import com.nukkitx.protocol.bedrock.BedrockPacketCodec; import com.nukkitx.protocol.bedrock.packet.*; import org.geysermc.connector.common.AuthType; import org.geysermc.connector.configuration.GeyserConfiguration; @@ -48,15 +49,20 @@ public class UpstreamPacketHandler extends LoggingPacketHandler { @Override public boolean handle(LoginPacket loginPacket) { - if (loginPacket.getProtocolVersion() > GeyserConnector.BEDROCK_PACKET_CODEC.getProtocolVersion()) { - // Too early to determine session locale - session.disconnect(LanguageUtils.getLocaleStringLog("geyser.network.outdated.server", GeyserConnector.BEDROCK_PACKET_CODEC.getMinecraftVersion())); - return true; - } else if (loginPacket.getProtocolVersion() < GeyserConnector.BEDROCK_PACKET_CODEC.getProtocolVersion()) { - session.disconnect(LanguageUtils.getLocaleStringLog("geyser.network.outdated.client", GeyserConnector.BEDROCK_PACKET_CODEC.getMinecraftVersion())); - return true; + BedrockPacketCodec packetCodec = BedrockProtocol.getBedrockCodec(loginPacket.getProtocolVersion()); + if (packetCodec == null) { + if (loginPacket.getProtocolVersion() > BedrockProtocol.DEFAULT_BEDROCK_CODEC.getProtocolVersion()) { + // Too early to determine session locale + session.disconnect(LanguageUtils.getLocaleStringLog("geyser.network.outdated.server", BedrockProtocol.DEFAULT_BEDROCK_CODEC.getMinecraftVersion())); + return true; + } else if (loginPacket.getProtocolVersion() < BedrockProtocol.DEFAULT_BEDROCK_CODEC.getProtocolVersion()) { + session.disconnect(LanguageUtils.getLocaleStringLog("geyser.network.outdated.client", BedrockProtocol.DEFAULT_BEDROCK_CODEC.getMinecraftVersion())); + return true; + } } + session.getUpstream().getSession().setPacketCodec(packetCodec); + LoginEncryptionUtils.encryptPlayerConnection(connector, session, loginPacket); PlayStatusPacket playStatus = new PlayStatusPacket();