From cab6919a46516026c731e56654bdc6f527bb2540 Mon Sep 17 00:00:00 2001 From: Andrew Steinborn Date: Thu, 6 Aug 2020 17:38:52 -0400 Subject: [PATCH] Switch to adventure-nbt and fix server switching on 1.16.2-pre3 --- proxy/build.gradle | 2 +- .../connection/registry/DimensionData.java | 80 ++++++++++--------- .../registry/DimensionRegistry.java | 27 ++++--- .../proxy/protocol/ProtocolUtils.java | 16 ++-- .../proxy/protocol/packet/JoinGame.java | 33 ++++---- .../proxy/protocol/packet/Respawn.java | 5 +- 6 files changed, 84 insertions(+), 79 deletions(-) diff --git a/proxy/build.gradle b/proxy/build.gradle index 3b975e84d..1bfa281e6 100644 --- a/proxy/build.gradle +++ b/proxy/build.gradle @@ -63,7 +63,7 @@ dependencies { compile 'it.unimi.dsi:fastutil:8.2.3' compile 'net.kyori:event-method-asm:4.0.0-SNAPSHOT' - compile 'net.kyori:nbt:1.12-1.0.0-SNAPSHOT' + compile 'net.kyori:adventure-nbt:4.0.0-SNAPSHOT' compile 'com.mojang:brigadier:1.0.17' diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/registry/DimensionData.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/registry/DimensionData.java index a34149802..b3824975d 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/registry/DimensionData.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/registry/DimensionData.java @@ -2,7 +2,7 @@ package com.velocitypowered.proxy.connection.registry; import com.google.common.base.Preconditions; import com.velocitypowered.api.network.ProtocolVersion; -import net.kyori.nbt.CompoundTag; +import net.kyori.adventure.nbt.CompoundBinaryTag; import org.checkerframework.checker.nullness.qual.Nullable; public final class DimensionData { @@ -180,24 +180,25 @@ public final class DimensionData { * @param version the protocol version * @return game dimension data */ - public static DimensionData decodeBaseCompoundTag(CompoundTag details, ProtocolVersion version) { - boolean isNatural = details.getBoolean("natural"); + public static DimensionData decodeBaseCompoundTag(CompoundBinaryTag details, + ProtocolVersion version) { + boolean isNatural = details.getByte("natural") >= 1; float ambientLight = details.getFloat("ambient_light"); - boolean isShrunk = details.getBoolean("shrunk"); - boolean isUltrawarm = details.getBoolean("ultrawarm"); - boolean hasCeiling = details.getBoolean("has_ceiling"); - boolean hasSkylight = details.getBoolean("has_skylight"); - boolean isPiglinSafe = details.getBoolean("piglin_safe"); - boolean doBedsWork = details.getBoolean("bed_works"); - boolean doRespawnAnchorsWork = details.getBoolean("respawn_anchor_works"); - boolean hasRaids = details.getBoolean("has_raids"); + boolean isShrunk = details.getByte("shrunk") >= 1; + boolean isUltrawarm = details.getByte("ultrawarm") >= 1; + boolean hasCeiling = details.getByte("has_ceiling") >= 1; + boolean hasSkylight = details.getByte("has_skylight") >= 1; + boolean isPiglinSafe = details.getByte("piglin_safe") >= 1; + boolean doBedsWork = details.getByte("bed_works") >= 1; + boolean doRespawnAnchorsWork = details.getByte("respawn_anchor_works") >= 1; + boolean hasRaids = details.getByte("has_raids") >= 1; int logicalHeight = details.getInt("logical_height"); String burningBehaviourIdentifier = details.getString("infiniburn"); - Long fixedTime = details.contains("fixed_time") + Long fixedTime = details.keySet().contains("fixed_time") ? details.getLong("fixed_time") : null; - Boolean hasEnderdragonFight = details.contains("has_enderdragon_fight") - ? details.getBoolean("has_enderdragon_fight") : null; - Double coordinateScale = details.contains("coordinate_scale") + Boolean hasEnderdragonFight = details.keySet().contains("has_enderdragon_fight") + ? details.getByte("has_enderdragon_fight") >= 1 : null; + Double coordinateScale = details.keySet().contains("coordinate_scale") ? details.getDouble("coordinate_scale") : null; return new DimensionData( UNKNOWN_DIMENSION_ID, null, isNatural, ambientLight, isShrunk, @@ -213,9 +214,10 @@ public final class DimensionData { * @param version the protocol version * @return game dimension data */ - public static DimensionData decodeRegistryEntry(CompoundTag dimTag, ProtocolVersion version) { + public static DimensionData decodeRegistryEntry(CompoundBinaryTag dimTag, + ProtocolVersion version) { String registryIdentifier = dimTag.getString("name"); - CompoundTag details; + CompoundBinaryTag details; Integer dimensionId = null; if (version.compareTo(ProtocolVersion.MINECRAFT_1_16_2) >= 0) { dimensionId = dimTag.getInt("id"); @@ -233,21 +235,21 @@ public final class DimensionData { * @param version the version to serialize as * @return compound containing the dimension data */ - public CompoundTag encodeAsCompoundTag(ProtocolVersion version) { - CompoundTag details = serializeDimensionDetails(); + public CompoundBinaryTag encodeAsCompoundTag(ProtocolVersion version) { + CompoundBinaryTag details = serializeDimensionDetails(); if (version.compareTo(ProtocolVersion.MINECRAFT_1_16_2) >= 0) { - CompoundTag parent = new CompoundTag(); - parent.putString("name", registryIdentifier); if (dimensionId == null) { throw new IllegalStateException("Tried to serialize a 1.16.2+ dimension registry entry " + "without an ID"); } - parent.putInt("id", dimensionId); - parent.put("element", details); - return parent; + + return CompoundBinaryTag.builder() + .putString("name", registryIdentifier) + .putInt("id", dimensionId) + .put("element", details) + .build(); } else { - details.putString("name", registryIdentifier); - return details; + return details.putString("name", registryIdentifier); } } @@ -255,29 +257,29 @@ public final class DimensionData { * Serializes details of this dimension. * @return serialized details of this dimension */ - public CompoundTag serializeDimensionDetails() { - CompoundTag ret = new CompoundTag(); - ret.putBoolean("natural", isNatural); + public CompoundBinaryTag serializeDimensionDetails() { + CompoundBinaryTag.Builder ret = CompoundBinaryTag.builder(); + ret.putByte("natural", (byte) (isNatural ? 1 : 0)); ret.putFloat("ambient_light", ambientLight); - ret.putBoolean("shrunk", isShrunk); - ret.putBoolean("ultrawarm", isUltrawarm); - ret.putBoolean("has_ceiling", hasCeiling); - ret.putBoolean("has_skylight", hasSkylight); - ret.putBoolean("piglin_safe", isPiglinSafe); - ret.putBoolean("bed_works", doBedsWork); - ret.putBoolean("respawn_anchor_works", doRespawnAnchorsWork); - ret.putBoolean("has_raids", hasRaids); + ret.putByte("shrunk", (byte) (isShrunk ? 1 : 0)); + ret.putByte("ultrawarm", (byte) (isUltrawarm ? 1 : 0)); + ret.putByte("has_ceiling", (byte) (hasCeiling ? 1 : 0)); + ret.putByte("has_skylight", (byte) (hasSkylight ? 1 : 0)); + ret.putByte("piglin_safe", (byte) (isPiglinSafe ? 1 : 0)); + ret.putByte("bed_works", (byte) (doBedsWork ? 1 : 0)); + ret.putByte("respawn_anchor_works", (byte) (doBedsWork ? 1 : 0)); + ret.putByte("has_raids", (byte) (hasRaids ? 1 : 0)); ret.putInt("logical_height", logicalHeight); ret.putString("infiniburn", burningBehaviourIdentifier); if (fixedTime != null) { ret.putLong("fixed_time", fixedTime); } if (createDragonFight != null) { - ret.putBoolean("has_enderdragon_fight", createDragonFight); + ret.putByte("has_enderdragon_fight", (byte) (createDragonFight ? 1 : 0)); } if (coordinateScale != null) { ret.putDouble("coordinate_scale", coordinateScale); } - return ret; + return ret.build(); } } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/registry/DimensionRegistry.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/registry/DimensionRegistry.java index 5cc07f8d4..36a902b63 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/registry/DimensionRegistry.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/registry/DimensionRegistry.java @@ -8,13 +8,12 @@ import com.velocitypowered.api.network.ProtocolVersion; import java.util.Map; import java.util.Set; -import net.kyori.nbt.CompoundTag; -import net.kyori.nbt.ListTag; -import net.kyori.nbt.Tag; -import net.kyori.nbt.TagType; +import net.kyori.adventure.nbt.BinaryTag; +import net.kyori.adventure.nbt.BinaryTagTypes; +import net.kyori.adventure.nbt.CompoundBinaryTag; +import net.kyori.adventure.nbt.ListBinaryTag; import org.checkerframework.checker.nullness.qual.Nullable; - public final class DimensionRegistry { private final Map registeredDimensions; @@ -80,24 +79,26 @@ public final class DimensionRegistry { * Encodes the stored Dimension registry as CompoundTag. * @return the CompoundTag containing identifier:type mappings */ - public ListTag encodeRegistry(ProtocolVersion version) { - ListTag list = new ListTag(TagType.COMPOUND); + public ListBinaryTag encodeRegistry(ProtocolVersion version) { + ListBinaryTag.Builder listBuilder = ListBinaryTag + .builder(BinaryTagTypes.COMPOUND); for (DimensionData iter : registeredDimensions.values()) { - list.add(iter.encodeAsCompoundTag(version)); + listBuilder.add(iter.encodeAsCompoundTag(version)); } - return list; + return listBuilder.build(); } /** * Decodes a CompoundTag storing a dimension registry. * @param toParse CompoundTag containing a dimension registry */ - public static ImmutableSet fromGameData(ListTag toParse, ProtocolVersion version) { + public static ImmutableSet fromGameData(ListBinaryTag toParse, + ProtocolVersion version) { Preconditions.checkNotNull(toParse, "ListTag cannot be null"); ImmutableSet.Builder mappings = ImmutableSet.builder(); - for (Tag iter : toParse) { - if (iter instanceof CompoundTag) { - mappings.add(DimensionData.decodeRegistryEntry((CompoundTag) iter, version)); + for (BinaryTag iter : toParse) { + if (iter instanceof CompoundBinaryTag) { + mappings.add(DimensionData.decodeRegistryEntry((CompoundBinaryTag) iter, version)); } } return mappings.build(); diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/ProtocolUtils.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/ProtocolUtils.java index 8ad0e1980..e9b98b33e 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/ProtocolUtils.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/ProtocolUtils.java @@ -22,9 +22,9 @@ import java.util.ArrayList; import java.util.List; import java.util.UUID; +import net.kyori.adventure.nbt.BinaryTagIO; +import net.kyori.adventure.nbt.CompoundBinaryTag; import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; -import net.kyori.nbt.CompoundTag; -import net.kyori.nbt.TagIO; public enum ProtocolUtils { ; @@ -219,11 +219,11 @@ public enum ProtocolUtils { } /** - * Reads a {@link net.kyori.nbt.CompoundTag} from the {@code buf}. + * Reads a {@link net.kyori.adventure.nbt.CompoundBinaryTag} from the {@code buf}. * @param buf the buffer to read from - * @return {@link net.kyori.nbt.CompoundTag} the CompoundTag from the buffer + * @return {@link net.kyori.adventure.nbt.CompoundBinaryTag} the CompoundTag from the buffer */ - public static CompoundTag readCompoundTag(ByteBuf buf) { + public static CompoundBinaryTag readCompoundTag(ByteBuf buf) { int indexBefore = buf.readerIndex(); byte startType = buf.readByte(); if (startType == 0) { @@ -231,7 +231,7 @@ public enum ProtocolUtils { } buf.readerIndex(indexBefore); try { - return TagIO.readDataInput(new ByteBufInputStream(buf)); + return BinaryTagIO.readDataInput(new ByteBufInputStream(buf)); } catch (IOException thrown) { throw new DecoderException( "Unable to parse NBT CompoundTag, full error: " + thrown.getMessage()); @@ -243,13 +243,13 @@ public enum ProtocolUtils { * @param buf the buffer to write to * @param compoundTag the CompoundTag to write */ - public static void writeCompoundTag(ByteBuf buf, CompoundTag compoundTag) { + public static void writeCompoundTag(ByteBuf buf, CompoundBinaryTag compoundTag) { if (compoundTag == null) { buf.writeByte(0); return; } try { - TagIO.writeDataOutput(compoundTag, new ByteBufOutputStream(buf)); + BinaryTagIO.writeDataOutput(compoundTag, new ByteBufOutputStream(buf)); } catch (IOException e) { throw new EncoderException("Unable to encode NBT CompoundTag"); } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/JoinGame.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/JoinGame.java index 845845c46..bd4001cf1 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/JoinGame.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/JoinGame.java @@ -8,9 +8,9 @@ import com.velocitypowered.proxy.connection.registry.DimensionInfo; import com.velocitypowered.proxy.connection.registry.DimensionRegistry; import com.velocitypowered.proxy.protocol.*; import io.netty.buffer.ByteBuf; -import net.kyori.nbt.CompoundTag; -import net.kyori.nbt.ListTag; -import net.kyori.nbt.TagType; +import net.kyori.adventure.nbt.BinaryTagTypes; +import net.kyori.adventure.nbt.CompoundBinaryTag; +import net.kyori.adventure.nbt.ListBinaryTag; import org.checkerframework.checker.nullness.qual.Nullable; public class JoinGame implements MinecraftPacket { @@ -30,7 +30,7 @@ public class JoinGame implements MinecraftPacket { private DimensionInfo dimensionInfo; // 1.16+ private DimensionData currentDimensionData; // 1.16.2+ private short previousGamemode; // 1.16+ - private CompoundTag biomeRegistry; // 1.16.2+ + private CompoundBinaryTag biomeRegistry; // 1.16.2+ public int getEntityId() { return entityId; @@ -132,11 +132,11 @@ public class JoinGame implements MinecraftPacket { this.isHardcore = isHardcore; } - public CompoundTag getBiomeRegistry() { + public CompoundBinaryTag getBiomeRegistry() { return biomeRegistry; } - public void setBiomeRegistry(CompoundTag biomeRegistry) { + public void setBiomeRegistry(CompoundBinaryTag biomeRegistry) { this.biomeRegistry = biomeRegistry; } @@ -178,20 +178,21 @@ public class JoinGame implements MinecraftPacket { if (version.compareTo(ProtocolVersion.MINECRAFT_1_16) >= 0) { this.previousGamemode = buf.readByte(); ImmutableSet levelNames = ImmutableSet.copyOf(ProtocolUtils.readStringArray(buf)); - CompoundTag registryContainer = ProtocolUtils.readCompoundTag(buf); - ListTag dimensionRegistryContainer = null; + CompoundBinaryTag registryContainer = ProtocolUtils.readCompoundTag(buf); + ListBinaryTag dimensionRegistryContainer = null; if (version.compareTo(ProtocolVersion.MINECRAFT_1_16_2) >= 0) { dimensionRegistryContainer = registryContainer.getCompound("minecraft:dimension_type") - .getList("value", TagType.COMPOUND); + .getList("value", BinaryTagTypes.COMPOUND); this.biomeRegistry = registryContainer.getCompound("minecraft:worldgen/biome"); } else { - dimensionRegistryContainer = registryContainer.getList("dimension", TagType.COMPOUND); + dimensionRegistryContainer = registryContainer.getList("dimension", + BinaryTagTypes.COMPOUND); } ImmutableSet readData = DimensionRegistry.fromGameData(dimensionRegistryContainer, version); this.dimensionRegistry = new DimensionRegistry(readData, levelNames); if (version.compareTo(ProtocolVersion.MINECRAFT_1_16_2) >= 0) { - CompoundTag currentDimDataTag = ProtocolUtils.readCompoundTag(buf); + CompoundBinaryTag currentDimDataTag = ProtocolUtils.readCompoundTag(buf); dimensionIdentifier = ProtocolUtils.readString(buf); this.currentDimensionData = DimensionData.decodeBaseCompoundTag(currentDimDataTag, version) .annotateWith(dimensionIdentifier, null); @@ -247,18 +248,18 @@ public class JoinGame implements MinecraftPacket { buf.writeByte(previousGamemode); ProtocolUtils.writeStringArray(buf, dimensionRegistry.getLevelNames().toArray( new String[dimensionRegistry.getLevelNames().size()])); - CompoundTag registryContainer = new CompoundTag(); - ListTag encodedDimensionRegistry = dimensionRegistry.encodeRegistry(version); + CompoundBinaryTag.Builder registryContainer = CompoundBinaryTag.builder(); + ListBinaryTag encodedDimensionRegistry = dimensionRegistry.encodeRegistry(version); if (version.compareTo(ProtocolVersion.MINECRAFT_1_16_2) >= 0) { - CompoundTag dimensionRegistryDummy = new CompoundTag(); + CompoundBinaryTag.Builder dimensionRegistryDummy = CompoundBinaryTag.builder(); dimensionRegistryDummy.putString("type", "minecraft:dimension_type"); dimensionRegistryDummy.put("value", encodedDimensionRegistry); - registryContainer.put("minecraft:dimension_type", dimensionRegistryDummy); + registryContainer.put("minecraft:dimension_type", dimensionRegistryDummy.build()); registryContainer.put("minecraft:worldgen/biome", biomeRegistry); } else { registryContainer.put("dimension", encodedDimensionRegistry); } - ProtocolUtils.writeCompoundTag(buf, registryContainer); + ProtocolUtils.writeCompoundTag(buf, registryContainer.build()); if (version.compareTo(ProtocolVersion.MINECRAFT_1_16_2) >= 0) { ProtocolUtils.writeCompoundTag(buf, currentDimensionData.serializeDimensionDetails()); ProtocolUtils.writeString(buf, dimensionInfo.getRegistryIdentifier()); diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/Respawn.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/Respawn.java index 33ec66196..9a5aee432 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/Respawn.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/Respawn.java @@ -7,7 +7,7 @@ import com.velocitypowered.proxy.connection.registry.DimensionInfo; import com.velocitypowered.proxy.protocol.MinecraftPacket; import com.velocitypowered.proxy.protocol.ProtocolUtils; import io.netty.buffer.ByteBuf; -import net.kyori.nbt.CompoundTag; +import net.kyori.adventure.nbt.CompoundBinaryTag; public class Respawn implements MinecraftPacket { @@ -35,6 +35,7 @@ public class Respawn implements MinecraftPacket { this.shouldKeepPlayerData = shouldKeepPlayerData; this.dimensionInfo = dimensionInfo; this.previousGamemode = previousGamemode; + this.currentDimensionData = currentDimensionData; } public int getDimension() { @@ -115,7 +116,7 @@ public class Respawn implements MinecraftPacket { String levelName = null; if (version.compareTo(ProtocolVersion.MINECRAFT_1_16) >= 0) { if (version.compareTo(ProtocolVersion.MINECRAFT_1_16_2) >= 0) { - CompoundTag dimDataTag = ProtocolUtils.readCompoundTag(buf); + CompoundBinaryTag dimDataTag = ProtocolUtils.readCompoundTag(buf); dimensionIdentifier = ProtocolUtils.readString(buf); this.currentDimensionData = DimensionData.decodeBaseCompoundTag(dimDataTag, version) .annotateWith(dimensionIdentifier, null);