diff --git a/src/main/java/org/geysermc/connect/MasterServer.java b/src/main/java/org/geysermc/connect/MasterServer.java index 9c34169..2cbdeb4 100644 --- a/src/main/java/org/geysermc/connect/MasterServer.java +++ b/src/main/java/org/geysermc/connect/MasterServer.java @@ -29,6 +29,7 @@ import com.nukkitx.protocol.bedrock.*; import com.nukkitx.protocol.bedrock.v408.Bedrock_v408; import lombok.Getter; import lombok.Setter; +import org.geysermc.connector.network.BedrockProtocol; import org.geysermc.connector.utils.FileUtils; import org.geysermc.connect.proxy.GeyserProxyBootstrap; import org.geysermc.connect.storage.AbstractStorageManager; @@ -47,8 +48,6 @@ import java.util.concurrent.ScheduledExecutorService; public class MasterServer { - public static final BedrockPacketCodec CODEC = Bedrock_v408.V408_CODEC; - private final Timer timer; private BedrockServer bdServer; private BedrockPong bdPong; @@ -134,7 +133,7 @@ public class MasterServer { bdPong.setMaximumPlayerCount(geyserConnectConfig.getMaxPlayers()); bdPong.setGameType("Survival"); bdPong.setIpv4Port(port); - bdPong.setProtocolVersion(MasterServer.CODEC.getProtocolVersion()); + bdPong.setProtocolVersion(BedrockProtocol.DEFAULT_BEDROCK_CODEC.getProtocolVersion()); bdPong.setVersion(null); // Server tries to connect either way and it looks better bdServer.setHandler(new BedrockServerEventHandler() { diff --git a/src/main/java/org/geysermc/connect/PacketHandler.java b/src/main/java/org/geysermc/connect/PacketHandler.java index 8150113..f8acce9 100644 --- a/src/main/java/org/geysermc/connect/PacketHandler.java +++ b/src/main/java/org/geysermc/connect/PacketHandler.java @@ -32,6 +32,7 @@ import com.fasterxml.jackson.databind.node.JsonNodeType; import com.nimbusds.jose.JWSObject; import com.nimbusds.jose.crypto.factories.DefaultJWSVerifierFactory; import com.nukkitx.network.util.DisconnectReason; +import com.nukkitx.protocol.bedrock.BedrockPacketCodec; import com.nukkitx.protocol.bedrock.BedrockServerSession; import com.nukkitx.protocol.bedrock.data.AttributeData; import com.nukkitx.protocol.bedrock.handler.BedrockPacketHandler; @@ -44,7 +45,9 @@ import org.geysermc.connect.ui.FormID; import org.geysermc.connect.ui.UIHandler; import org.geysermc.connect.utils.Player; import org.geysermc.connector.entity.attribute.AttributeType; +import org.geysermc.connector.network.BedrockProtocol; import org.geysermc.connector.utils.AttributeUtils; +import org.geysermc.connector.utils.LanguageUtils; import java.io.IOException; import java.security.interfaces.ECPublicKey; @@ -83,20 +86,20 @@ public class PacketHandler implements BedrockPacketHandler { public boolean handle(LoginPacket packet) { masterServer.getLogger().debug("Login: " + packet.toString()); - // Check the protocol version is correct - int protocol = packet.getProtocolVersion(); - if (protocol != MasterServer.CODEC.getProtocolVersion()) { + BedrockPacketCodec packetCodec = BedrockProtocol.getBedrockCodec(packet.getProtocolVersion()); + if (packetCodec == null) { + session.setPacketCodec(BedrockProtocol.DEFAULT_BEDROCK_CODEC); PlayStatusPacket status = new PlayStatusPacket(); - if (protocol > MasterServer.CODEC.getProtocolVersion()) { + if (packet.getProtocolVersion() > BedrockProtocol.DEFAULT_BEDROCK_CODEC.getProtocolVersion()) { status.setStatus(PlayStatusPacket.Status.LOGIN_FAILED_SERVER_OLD); - } else { + } else if (packet.getProtocolVersion() < BedrockProtocol.DEFAULT_BEDROCK_CODEC.getProtocolVersion()) { status.setStatus(PlayStatusPacket.Status.LOGIN_FAILED_CLIENT_OLD); } session.sendPacket(status); } // Set the session codec - session.setPacketCodec(MasterServer.CODEC); + session.setPacketCodec(packetCodec); // Read the raw chain data JsonNode rawChainData; diff --git a/src/main/java/org/geysermc/connect/utils/Logger.java b/src/main/java/org/geysermc/connect/utils/Logger.java index 72479ef..faa7c4e 100644 --- a/src/main/java/org/geysermc/connect/utils/Logger.java +++ b/src/main/java/org/geysermc/connect/utils/Logger.java @@ -28,8 +28,8 @@ package org.geysermc.connect.utils; import lombok.extern.log4j.Log4j2; import net.minecrell.terminalconsole.SimpleTerminalConsole; import org.apache.logging.log4j.core.config.Configurator; -import org.geysermc.connector.GeyserLogger; import org.geysermc.connect.MasterServer; +import org.geysermc.connector.GeyserLogger; import org.geysermc.connector.common.ChatColor; @Log4j2 diff --git a/src/main/java/org/geysermc/connect/utils/PaletteManger.java b/src/main/java/org/geysermc/connect/utils/PaletteManger.java index c2ec344..26360d4 100644 --- a/src/main/java/org/geysermc/connect/utils/PaletteManger.java +++ b/src/main/java/org/geysermc/connect/utils/PaletteManger.java @@ -31,36 +31,59 @@ import org.geysermc.connector.utils.FileUtils; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; /** * This class is mostly copied from core Geyser */ public class PaletteManger { - public static final NbtList BLOCK_PALLETE; - public static final NbtMap BIOMES_PALLETE; + public static final NbtList BLOCK_PALETTE; + public static final NbtMap BIOMES_PALETTE; public static final byte[] EMPTY_LEVEL_CHUNK_DATA; private static final NbtMap EMPTY_TAG = NbtMap.EMPTY; static { /* Load block palette */ - InputStream stream = FileUtils.getResource("bedrock/runtime_block_states.dat"); + // Build the air block entry + NbtMapBuilder mainBuilder = NbtMap.builder(); + mainBuilder.putShort("id", (short) 0); - try (NBTInputStream nbtInputStream = NbtUtils.createNetworkReader(stream)) { - BLOCK_PALLETE = (NbtList) nbtInputStream.readTag(); - } catch (Exception e) { - throw new AssertionError("Unable to get blocks from runtime block states", e); - } + NbtMapBuilder blockBuilder = NbtMap.builder(); + blockBuilder.putString("name", "minecraft:air"); + blockBuilder.putInt("version", 17825806); + blockBuilder.put("states", NbtMap.EMPTY); + + mainBuilder.put("block", blockBuilder.build()); + + // Build the block list with the entry + List blocks = new ArrayList<>(); + blocks.add(mainBuilder.build()); + + BLOCK_PALETTE = new NbtList<>(NbtType.COMPOUND, blocks); /* Load biomes */ - stream = FileUtils.getResource("bedrock/biome_definitions.dat"); + // Build a fake plains biome entry + NbtMapBuilder plainsBuilder = NbtMap.builder(); + plainsBuilder.putFloat("blue_spores", 0f); + plainsBuilder.putFloat("white_ash", 0f); + plainsBuilder.putFloat("ash", 0f); + plainsBuilder.putFloat("temperature", 0f); + plainsBuilder.putFloat("red_spores", 0f); + plainsBuilder.putFloat("downfall", 0f); - try (NBTInputStream nbtInputStream = NbtUtils.createNetworkReader(stream)){ - BIOMES_PALLETE = (NbtMap) nbtInputStream.readTag(); - } catch (Exception e) { - throw new AssertionError("Failed to get biomes from biome definitions", e); - } + plainsBuilder.put("minecraft:overworld_generation_rules", NbtMap.EMPTY); + plainsBuilder.put("minecraft:climate", NbtMap.EMPTY); + plainsBuilder.put("tags", NbtList.EMPTY); + + // Add the fake plains to the map + NbtMapBuilder biomesBuilder = NbtMap.builder(); + biomesBuilder.put("plains", plainsBuilder.build()); + + // Build the biomes palette + BIOMES_PALETTE = biomesBuilder.build(); /* Create empty chunk data */ try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) { diff --git a/src/main/java/org/geysermc/connect/utils/Player.java b/src/main/java/org/geysermc/connect/utils/Player.java index e0ce170..cf3ac12 100644 --- a/src/main/java/org/geysermc/connect/utils/Player.java +++ b/src/main/java/org/geysermc/connect/utils/Player.java @@ -128,7 +128,7 @@ public class Player { startGamePacket.setCurrentTick(0); startGamePacket.setEnchantmentSeed(0); startGamePacket.setMultiplayerCorrelationId(""); - startGamePacket.setBlockPalette(PaletteManger.BLOCK_PALLETE); + startGamePacket.setBlockPalette(PaletteManger.BLOCK_PALETTE); startGamePacket.setVanillaVersion("*"); session.sendPacket(startGamePacket); @@ -143,7 +143,7 @@ public class Player { // Send the biomes BiomeDefinitionListPacket biomeDefinitionListPacket = new BiomeDefinitionListPacket(); - biomeDefinitionListPacket.setDefinitions(PaletteManger.BIOMES_PALLETE); + biomeDefinitionListPacket.setDefinitions(PaletteManger.BIOMES_PALETTE); session.sendPacket(biomeDefinitionListPacket); // Let the client know the player can spawn