From b34b198064780481f669f53960180d39de0254e2 Mon Sep 17 00:00:00 2001 From: Andrew Steinborn Date: Thu, 6 Aug 2020 15:08:50 -0400 Subject: [PATCH] 1.16.2-pre3 --- .../api/network/ProtocolVersion.java | 2 +- .../client/ClientPlaySessionHandler.java | 9 +-- .../connection/registry/DimensionData.java | 72 ++++++++++++++----- .../connection/registry/DimensionInfo.java | 20 +++--- .../registry/DimensionRegistry.java | 2 +- .../proxy/protocol/packet/JoinGame.java | 24 +++++-- .../proxy/protocol/packet/Respawn.java | 29 ++++++-- 7 files changed, 114 insertions(+), 44 deletions(-) diff --git a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java index fa09d7502..fa4319cb3 100644 --- a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java +++ b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java @@ -39,7 +39,7 @@ public enum ProtocolVersion { MINECRAFT_1_15_2(578, "1.15.2"), MINECRAFT_1_16(735, "1.16"), MINECRAFT_1_16_1(736, "1.16.1"), - MINECRAFT_1_16_2(746, "1.16.2"); + MINECRAFT_1_16_2(748, "1.16.2"); private final int protocol; private final String name; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientPlaySessionHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientPlaySessionHandler.java index d72b0ef46..fe1a63b9c 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientPlaySessionHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientPlaySessionHandler.java @@ -336,15 +336,16 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler { int tempDim = joinGame.getDimension() == 0 ? -1 : 0; player.getConnection().delayedWrite( new Respawn(tempDim, joinGame.getPartialHashedSeed(), joinGame.getDifficulty(), - joinGame.getGamemode(), joinGame.getLevelType(), - false, joinGame.getDimensionInfo(), joinGame.getPreviousGamemode())); + joinGame.getGamemode(), joinGame.getLevelType(), + false, joinGame.getDimensionInfo(), joinGame.getPreviousGamemode(), + joinGame.getCurrentDimensionData())); } player.getConnection().delayedWrite( new Respawn(joinGame.getDimension(), joinGame.getPartialHashedSeed(), joinGame.getDifficulty(), joinGame.getGamemode(), joinGame.getLevelType(), - false, joinGame.getDimensionInfo(), joinGame.getPreviousGamemode())); - + false, joinGame.getDimensionInfo(), joinGame.getPreviousGamemode(), + joinGame.getCurrentDimensionData())); destination.setActiveDimensionRegistry(joinGame.getDimensionRegistry()); // 1.16 } 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 a18724f67..a34149802 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 @@ -6,6 +6,8 @@ import net.kyori.nbt.CompoundTag; import org.checkerframework.checker.nullness.qual.Nullable; public final class DimensionData { + private static final String UNKNOWN_DIMENSION_ID = "velocity:unknown_dimension"; + private final String registryIdentifier; private final @Nullable Integer dimensionId; private final boolean isNatural; @@ -151,22 +153,34 @@ public final class DimensionData { } /** - * Parses a given CompoundTag to a DimensionData instance. - * @param dimTag the compound from the registry to read - * @param version the protocol version from the registry + * Returns a fresh {@link DimensionData} with the specified {@code registryIdentifier} + * and {@code dimensionId}. + * + * @param registryIdentifier the identifier for the dimension from the registry + * @param dimensionId optional, dimension ID + * @return a new {@link DimensionData} + */ + public DimensionData annotateWith(String registryIdentifier, + @Nullable Integer dimensionId) { + return new DimensionData(registryIdentifier, dimensionId, isNatural, ambientLight, isShrunk, + isUltrawarm, hasCeiling, hasSkylight, isPiglinSafe, doBedsWork, doRespawnAnchorsWork, + hasRaids, logicalHeight, burningBehaviourIdentifier, fixedTime, createDragonFight, + coordinateScale); + } + + public boolean isUnannotated() { + return this.registryIdentifier.equalsIgnoreCase(UNKNOWN_DIMENSION_ID); + } + + /** + * Parses a given CompoundTag to a DimensionData instance. Assumes the data only contains + * dimension details. + * + * @param details the compound from the registry to read + * @param version the protocol version * @return game dimension data */ - public static DimensionData decodeCompoundTag(CompoundTag dimTag, ProtocolVersion version) { - Preconditions.checkNotNull(dimTag, "CompoundTag cannot be null"); - String registryIdentifier = dimTag.getString("name"); - CompoundTag details; - Integer dimensionId = null; - if (version.compareTo(ProtocolVersion.MINECRAFT_1_16_2) >= 0) { - dimensionId = dimTag.getInt("id"); - details = dimTag.getCompound("element"); - } else { - details = dimTag; - } + public static DimensionData decodeBaseCompoundTag(CompoundTag details, ProtocolVersion version) { boolean isNatural = details.getBoolean("natural"); float ambientLight = details.getFloat("ambient_light"); boolean isShrunk = details.getBoolean("shrunk"); @@ -186,12 +200,34 @@ public final class DimensionData { Double coordinateScale = details.contains("coordinate_scale") ? details.getDouble("coordinate_scale") : null; return new DimensionData( - registryIdentifier, dimensionId, isNatural, ambientLight, isShrunk, + UNKNOWN_DIMENSION_ID, null, isNatural, ambientLight, isShrunk, isUltrawarm, hasCeiling, hasSkylight, isPiglinSafe, doBedsWork, doRespawnAnchorsWork, hasRaids, logicalHeight, burningBehaviourIdentifier, fixedTime, hasEnderdragonFight, coordinateScale); } + /** + * Parses a given CompoundTag to a DimensionData instance. Assumes the data is part of a + * dimension registry. + * @param dimTag the compound from the registry to read + * @param version the protocol version + * @return game dimension data + */ + public static DimensionData decodeRegistryEntry(CompoundTag dimTag, ProtocolVersion version) { + String registryIdentifier = dimTag.getString("name"); + CompoundTag details; + Integer dimensionId = null; + if (version.compareTo(ProtocolVersion.MINECRAFT_1_16_2) >= 0) { + dimensionId = dimTag.getInt("id"); + details = dimTag.getCompound("element"); + } else { + details = dimTag; + } + + DimensionData deserializedDetails = decodeBaseCompoundTag(details, version); + return deserializedDetails.annotateWith(registryIdentifier, dimensionId); + } + /** * Encodes the Dimension data as CompoundTag. * @param version the version to serialize as @@ -215,7 +251,11 @@ public final class DimensionData { } } - private CompoundTag serializeDimensionDetails() { + /** + * Serializes details of this dimension. + * @return serialized details of this dimension + */ + public CompoundTag serializeDimensionDetails() { CompoundTag ret = new CompoundTag(); ret.putBoolean("natural", isNatural); ret.putFloat("ambient_light", ambientLight); diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/registry/DimensionInfo.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/registry/DimensionInfo.java index a06426cce..54c833d12 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/registry/DimensionInfo.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/registry/DimensionInfo.java @@ -1,6 +1,7 @@ package com.velocitypowered.proxy.connection.registry; import com.google.common.base.Preconditions; +import org.checkerframework.checker.nullness.qual.Nullable; public final class DimensionInfo { @@ -16,18 +17,13 @@ public final class DimensionInfo { * @param isFlat if true will set world lighting below surface-level to not display fog * @param isDebugType if true constrains the world to the very limited debug-type world */ - public DimensionInfo(String registryIdentifier, String levelName, - boolean isFlat, boolean isDebugType) { + public DimensionInfo(String registryIdentifier, @Nullable String levelName, + boolean isFlat, boolean isDebugType) { this.registryIdentifier = Preconditions.checkNotNull( - registryIdentifier, "registryIdentifier cannot be null"); - Preconditions.checkArgument( - registryIdentifier.length() > 0, - "registryIdentifier cannot be empty"); - this.levelName = Preconditions.checkNotNull( - levelName, "levelName cannot be null"); - Preconditions.checkArgument( - levelName.length() > 0, - "registryIdentifier cannot be empty"); + registryIdentifier, "registryIdentifier cannot be null"); + Preconditions.checkArgument(registryIdentifier.length() > 0, + "registryIdentifier cannot be empty"); + this.levelName = levelName; this.isFlat = isFlat; this.isDebugType = isDebugType; } @@ -40,7 +36,7 @@ public final class DimensionInfo { return isFlat; } - public String getLevelName() { + public @Nullable String getLevelName() { return levelName; } 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 aa5844498..5cc07f8d4 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 @@ -97,7 +97,7 @@ public final class DimensionRegistry { ImmutableSet.Builder mappings = ImmutableSet.builder(); for (Tag iter : toParse) { if (iter instanceof CompoundTag) { - mappings.add(DimensionData.decodeCompoundTag((CompoundTag) iter, version)); + mappings.add(DimensionData.decodeRegistryEntry((CompoundTag) iter, version)); } } return mappings.build(); 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 2c0b63c90..845845c46 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 @@ -28,6 +28,7 @@ public class JoinGame implements MinecraftPacket { private boolean showRespawnScreen; private DimensionRegistry dimensionRegistry; // 1.16+ private DimensionInfo dimensionInfo; // 1.16+ + private DimensionData currentDimensionData; // 1.16.2+ private short previousGamemode; // 1.16+ private CompoundTag biomeRegistry; // 1.16.2+ @@ -139,6 +140,9 @@ public class JoinGame implements MinecraftPacket { this.biomeRegistry = biomeRegistry; } + public DimensionData getCurrentDimensionData() { + return currentDimensionData; + } @Override public String toString() { @@ -186,8 +190,15 @@ public class JoinGame implements MinecraftPacket { ImmutableSet readData = DimensionRegistry.fromGameData(dimensionRegistryContainer, version); this.dimensionRegistry = new DimensionRegistry(readData, levelNames); - dimensionIdentifier = ProtocolUtils.readString(buf); - levelName = ProtocolUtils.readString(buf); + if (version.compareTo(ProtocolVersion.MINECRAFT_1_16_2) >= 0) { + CompoundTag currentDimDataTag = ProtocolUtils.readCompoundTag(buf); + dimensionIdentifier = ProtocolUtils.readString(buf); + this.currentDimensionData = DimensionData.decodeBaseCompoundTag(currentDimDataTag, version) + .annotateWith(dimensionIdentifier, null); + } else { + dimensionIdentifier = ProtocolUtils.readString(buf); + levelName = ProtocolUtils.readString(buf); + } } else if (version.compareTo(ProtocolVersion.MINECRAFT_1_9_1) >= 0) { this.dimension = buf.readInt(); } else { @@ -248,8 +259,13 @@ public class JoinGame implements MinecraftPacket { registryContainer.put("dimension", encodedDimensionRegistry); } ProtocolUtils.writeCompoundTag(buf, registryContainer); - ProtocolUtils.writeString(buf, dimensionInfo.getRegistryIdentifier()); - ProtocolUtils.writeString(buf, dimensionInfo.getLevelName()); + if (version.compareTo(ProtocolVersion.MINECRAFT_1_16_2) >= 0) { + ProtocolUtils.writeCompoundTag(buf, currentDimensionData.serializeDimensionDetails()); + ProtocolUtils.writeString(buf, dimensionInfo.getRegistryIdentifier()); + } else { + ProtocolUtils.writeString(buf, dimensionInfo.getRegistryIdentifier()); + ProtocolUtils.writeString(buf, dimensionInfo.getLevelName()); + } } else if (version.compareTo(ProtocolVersion.MINECRAFT_1_9_1) >= 0) { buf.writeInt(dimension); } else { 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 d14e9f8c8..33ec66196 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 @@ -2,10 +2,12 @@ package com.velocitypowered.proxy.protocol.packet; import com.velocitypowered.api.network.ProtocolVersion; import com.velocitypowered.proxy.connection.MinecraftSessionHandler; +import com.velocitypowered.proxy.connection.registry.DimensionData; 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; public class Respawn implements MinecraftPacket { @@ -15,15 +17,16 @@ public class Respawn implements MinecraftPacket { private short gamemode; private String levelType = ""; private boolean shouldKeepPlayerData; // 1.16+ - private DimensionInfo dimensionInfo; // 1.16+ + private DimensionInfo dimensionInfo; // 1.16-1.16.1 private short previousGamemode; // 1.16+ + private DimensionData currentDimensionData; // 1.16.2+ public Respawn() { } public Respawn(int dimension, long partialHashedSeed, short difficulty, short gamemode, String levelType, boolean shouldKeepPlayerData, DimensionInfo dimensionInfo, - short previousGamemode) { + short previousGamemode, DimensionData currentDimensionData) { this.dimension = dimension; this.partialHashedSeed = partialHashedSeed; this.difficulty = difficulty; @@ -100,7 +103,9 @@ public class Respawn implements MinecraftPacket { + ", levelType='" + levelType + '\'' + ", shouldKeepPlayerData=" + shouldKeepPlayerData + ", dimensionRegistryName='" + dimensionInfo.toString() + '\'' + + ", dimensionInfo=" + dimensionInfo + ", previousGamemode=" + previousGamemode + + ", dimensionData=" + currentDimensionData + '}'; } @@ -109,8 +114,15 @@ public class Respawn implements MinecraftPacket { String dimensionIdentifier = null; String levelName = null; if (version.compareTo(ProtocolVersion.MINECRAFT_1_16) >= 0) { - dimensionIdentifier = ProtocolUtils.readString(buf); - levelName = ProtocolUtils.readString(buf); + if (version.compareTo(ProtocolVersion.MINECRAFT_1_16_2) >= 0) { + CompoundTag dimDataTag = ProtocolUtils.readCompoundTag(buf); + dimensionIdentifier = ProtocolUtils.readString(buf); + this.currentDimensionData = DimensionData.decodeBaseCompoundTag(dimDataTag, version) + .annotateWith(dimensionIdentifier, null); + } else { + dimensionIdentifier = ProtocolUtils.readString(buf); + levelName = ProtocolUtils.readString(buf); + } } else { this.dimension = buf.readInt(); } @@ -135,8 +147,13 @@ public class Respawn implements MinecraftPacket { @Override public void encode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion version) { if (version.compareTo(ProtocolVersion.MINECRAFT_1_16) >= 0) { - ProtocolUtils.writeString(buf, dimensionInfo.getRegistryIdentifier()); - ProtocolUtils.writeString(buf, dimensionInfo.getLevelName()); + if (version.compareTo(ProtocolVersion.MINECRAFT_1_16_2) >= 0) { + ProtocolUtils.writeCompoundTag(buf, currentDimensionData.serializeDimensionDetails()); + ProtocolUtils.writeString(buf, dimensionInfo.getRegistryIdentifier()); + } else { + ProtocolUtils.writeString(buf, dimensionInfo.getRegistryIdentifier()); + ProtocolUtils.writeString(buf, dimensionInfo.getLevelName()); + } } else { buf.writeInt(dimension); }