3
0
Mirror von https://github.com/PaperMC/Velocity.git synchronisiert 2024-09-29 06:30:16 +02:00

Remove registry decoding (#979)

Dieser Commit ist enthalten in:
Gero 2023-03-29 09:21:01 +02:00 committet von GitHub
Ursprung 36cc2bde23
Commit 93b6376b38
Es konnte kein GPG-Schlüssel zu dieser Signatur gefunden werden
GPG-Schlüssel-ID: 4AEE18F83AFDEB23
6 geänderte Dateien mit 33 neuen und 609 gelöschten Zeilen

Datei anzeigen

@ -35,7 +35,6 @@ import com.velocitypowered.proxy.connection.ConnectionTypes;
import com.velocitypowered.proxy.connection.MinecraftConnection; import com.velocitypowered.proxy.connection.MinecraftConnection;
import com.velocitypowered.proxy.connection.MinecraftConnectionAssociation; import com.velocitypowered.proxy.connection.MinecraftConnectionAssociation;
import com.velocitypowered.proxy.connection.client.ConnectedPlayer; import com.velocitypowered.proxy.connection.client.ConnectedPlayer;
import com.velocitypowered.proxy.connection.registry.DimensionRegistry;
import com.velocitypowered.proxy.connection.util.ConnectionRequestResults.Impl; import com.velocitypowered.proxy.connection.util.ConnectionRequestResults.Impl;
import com.velocitypowered.proxy.protocol.StateRegistry; import com.velocitypowered.proxy.protocol.StateRegistry;
import com.velocitypowered.proxy.protocol.packet.Handshake; import com.velocitypowered.proxy.protocol.packet.Handshake;
@ -52,6 +51,7 @@ import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.function.UnaryOperator; import java.util.function.UnaryOperator;
import net.kyori.adventure.nbt.CompoundBinaryTag;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
@ -69,7 +69,7 @@ public class VelocityServerConnection implements MinecraftConnectionAssociation,
private boolean gracefulDisconnect = false; private boolean gracefulDisconnect = false;
private BackendConnectionPhase connectionPhase = BackendConnectionPhases.UNKNOWN; private BackendConnectionPhase connectionPhase = BackendConnectionPhases.UNKNOWN;
private final Map<Long, Long> pendingPings = new HashMap<>(); private final Map<Long, Long> pendingPings = new HashMap<>();
private @MonotonicNonNull DimensionRegistry activeDimensionRegistry; private @MonotonicNonNull CompoundBinaryTag activeDimensionRegistry;
/** /**
* Initializes a new server connection. * Initializes a new server connection.
@ -344,11 +344,11 @@ public class VelocityServerConnection implements MinecraftConnectionAssociation,
return hasCompletedJoin; return hasCompletedJoin;
} }
public DimensionRegistry getActiveDimensionRegistry() { public CompoundBinaryTag getActiveDimensionRegistry() {
return activeDimensionRegistry; return activeDimensionRegistry;
} }
public void setActiveDimensionRegistry(DimensionRegistry activeDimensionRegistry) { public void setActiveDimensionRegistry(CompoundBinaryTag activeDimensionRegistry) {
this.activeDimensionRegistry = activeDimensionRegistry; this.activeDimensionRegistry = activeDimensionRegistry;
} }
} }

Datei anzeigen

@ -473,7 +473,7 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler {
} }
} }
destination.setActiveDimensionRegistry(joinGame.getDimensionRegistry()); // 1.16 destination.setActiveDimensionRegistry(joinGame.getRegistry()); // 1.16
// Remove previous boss bars. These don't get cleared when sending JoinGame, thus the need to // Remove previous boss bars. These don't get cleared when sending JoinGame, thus the need to
// track them. // track them.

Datei anzeigen

@ -1,388 +0,0 @@
/*
* Copyright (C) 2020-2023 Velocity Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.velocitypowered.proxy.connection.registry;
import com.google.common.base.Preconditions;
import com.velocitypowered.api.network.ProtocolVersion;
import net.kyori.adventure.nbt.CompoundBinaryTag;
import org.checkerframework.checker.nullness.qual.Nullable;
/**
* Represents a dimension sent to the client by the server.
*/
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;
private final float ambientLight;
private final boolean isShrunk;
private final boolean isUltrawarm;
private final boolean hasCeiling;
private final boolean hasSkylight;
private final boolean isPiglinSafe;
private final boolean doBedsWork;
private final boolean doRespawnAnchorsWork;
private final boolean hasRaids;
private final int logicalHeight;
private final String burningBehaviourIdentifier;
private final @Nullable Long fixedTime;
private final @Nullable Boolean createDragonFight;
private final @Nullable Double coordinateScale;
private final @Nullable String effects;
private final @Nullable Integer minY; // Required and added by 1.17
private final @Nullable Integer height; // Required and added by 1.17
private final @Nullable Integer monsterSpawnBlockLightLimit; // Required and added by 1.19
private final @Nullable Integer monsterSpawnLightLevel; // Required and added by 1.19
/**
* Initializes a new {@link DimensionData} instance.
*
* @param registryIdentifier the identifier for the dimension from the registry.
* @param dimensionId the dimension ID contained in the registry (the "id" tag)
* @param isNatural indicates if the dimension use natural world generation
* (e.g. overworld)
* @param ambientLight the light level the client sees without external lighting
* @param isShrunk indicates if the world is shrunk, aka not the full 256
* blocks (e.g. nether)
* @param isUltrawarm internal dimension warmth flag
* @param hasCeiling indicates if the dimension has a ceiling layer
* @param hasSkylight indicates if the dimension should display the sun
* @param isPiglinSafe indicates if piglins should naturally zombify in this
* dimension
* @param doBedsWork indicates if players should be able to sleep in beds in this
* dimension
* @param doRespawnAnchorsWork indicates if player respawn points can be used in this
* dimension
* @param hasRaids indicates if raids can be spawned in the dimension
* @param logicalHeight the natural max height for the given dimension
* @param burningBehaviourIdentifier the identifier for how burning blocks work in the dimension
* @param fixedTime optional. If set to any game daytime value will deactivate
* time cycle
* @param createDragonFight optional. Internal flag used in the end dimension
* @param coordinateScale optional, unknown purpose
* @param effects optional, unknown purpose
* @param minY the world effective lowest build-level
* @param height the world height above zero
* @param monsterSpawnBlockLightLimit an integer controlling the block light needed to prevent
* monster spawns.
* @param monsterSpawnLightLevel an int provider which is evaluated to find a value to
* compare the current overall brightness with to determine if
* a monster should be allowed to spawn.
*/
public DimensionData(String registryIdentifier,
@Nullable Integer dimensionId,
boolean isNatural,
float ambientLight, boolean isShrunk, boolean isUltrawarm,
boolean hasCeiling, boolean hasSkylight,
boolean isPiglinSafe, boolean doBedsWork,
boolean doRespawnAnchorsWork, boolean hasRaids,
int logicalHeight, String burningBehaviourIdentifier,
@Nullable Long fixedTime, @Nullable Boolean createDragonFight,
@Nullable Double coordinateScale,
@Nullable String effects,
@Nullable Integer minY, @Nullable Integer height,
@Nullable Integer monsterSpawnBlockLightLimit,
@Nullable Integer monsterSpawnLightLevel) {
this.monsterSpawnBlockLightLimit = monsterSpawnBlockLightLimit;
this.monsterSpawnLightLevel = monsterSpawnLightLevel;
Preconditions.checkNotNull(
registryIdentifier, "registryIdentifier cannot be null");
Preconditions.checkArgument(registryIdentifier.length() > 0,
"registryIdentifier cannot be empty");
Preconditions.checkArgument(logicalHeight >= 0, "localHeight must be >= 0");
Preconditions.checkNotNull(
burningBehaviourIdentifier, "burningBehaviourIdentifier cannot be null");
Preconditions.checkArgument(burningBehaviourIdentifier.length() > 0,
"burningBehaviourIdentifier cannot be empty");
this.registryIdentifier = registryIdentifier;
this.dimensionId = dimensionId;
this.isNatural = isNatural;
this.ambientLight = ambientLight;
this.isShrunk = isShrunk;
this.isUltrawarm = isUltrawarm;
this.hasCeiling = hasCeiling;
this.hasSkylight = hasSkylight;
this.isPiglinSafe = isPiglinSafe;
this.doBedsWork = doBedsWork;
this.doRespawnAnchorsWork = doRespawnAnchorsWork;
this.hasRaids = hasRaids;
this.logicalHeight = logicalHeight;
this.burningBehaviourIdentifier = burningBehaviourIdentifier;
this.fixedTime = fixedTime;
this.createDragonFight = createDragonFight;
this.coordinateScale = coordinateScale;
this.effects = effects;
this.minY = minY;
this.height = height;
}
public String getRegistryIdentifier() {
return registryIdentifier;
}
public @Nullable Integer getDimensionId() {
return dimensionId;
}
public boolean isNatural() {
return isNatural;
}
public float getAmbientLight() {
return ambientLight;
}
public boolean isShrunk() {
return isShrunk;
}
public boolean isUltrawarm() {
return isUltrawarm;
}
public boolean hasCeiling() {
return hasCeiling;
}
public boolean hasSkylight() {
return hasSkylight;
}
public boolean isPiglinSafe() {
return isPiglinSafe;
}
public boolean doBedsWork() {
return doBedsWork;
}
public boolean doRespawnAnchorsWork() {
return doRespawnAnchorsWork;
}
public boolean hasRaids() {
return hasRaids;
}
public int getLogicalHeight() {
return logicalHeight;
}
public String getBurningBehaviourIdentifier() {
return burningBehaviourIdentifier;
}
public @Nullable Long getFixedTime() {
return fixedTime;
}
public @Nullable Boolean getCreateDragonFight() {
return createDragonFight;
}
public @Nullable Double getCoordinateScale() {
return coordinateScale;
}
public @Nullable Integer getMinY() {
return minY;
}
public @Nullable Integer getHeight() {
return height;
}
/**
* 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, effects, minY, height, monsterSpawnBlockLightLimit,
monsterSpawnLightLevel);
}
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 decodeBaseCompoundTag(CompoundBinaryTag details,
ProtocolVersion version) {
boolean isNatural = details.getBoolean("natural");
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");
int logicalHeight = details.getInt("logical_height");
String burningBehaviourIdentifier = details.getString("infiniburn");
Long fixedTime = details.keySet().contains("fixed_time")
? details.getLong("fixed_time") : null;
Boolean hasEnderdragonFight = details.keySet().contains("has_enderdragon_fight")
? details.getBoolean("has_enderdragon_fight") : null;
Double coordinateScale = details.keySet().contains("coordinate_scale")
? details.getDouble("coordinate_scale") : null;
String effects = details.keySet().contains("effects") ? details.getString("effects")
: null;
Integer minY = details.keySet().contains("min_y") ? details.getInt("min_y") : null;
Integer height = details.keySet().contains("height") ? details.getInt("height") : null;
Integer monsterSpawnBlockLightLimit =
details.keySet().contains("monster_spawn_block_light_limit")
? details.getInt("monster_spawn_block_light_limit") : null;
Integer monsterSpawnLightLevel =
details.keySet().contains("monster_spawn_light_level") ? details.getInt(
"monster_spawn_block_light_limit") :
null;
if (version.compareTo(ProtocolVersion.MINECRAFT_1_17) >= 0) {
Preconditions.checkNotNull(height,
"DimensionData requires 'height' to be present for this version");
Preconditions.checkNotNull(minY,
"DimensionData requires 'minY' to be present for this version");
}
if (version.compareTo(ProtocolVersion.MINECRAFT_1_19) >= 0) {
Preconditions.checkNotNull(monsterSpawnBlockLightLimit,
"DimensionData requires 'monster_spawn_block_light_limit' to be present"
+ " for this version.");
Preconditions.checkNotNull(monsterSpawnLightLevel,
"DimensionData requires 'monster_spawn_light_level' to be present"
+ " for this version.");
}
return new DimensionData(
UNKNOWN_DIMENSION_ID, null, isNatural, ambientLight, isShrunk,
isUltrawarm, hasCeiling, hasSkylight, isPiglinSafe, doBedsWork, doRespawnAnchorsWork,
hasRaids, logicalHeight, burningBehaviourIdentifier, fixedTime, hasEnderdragonFight,
coordinateScale, effects, minY, height, monsterSpawnBlockLightLimit,
monsterSpawnLightLevel);
}
/**
* 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(CompoundBinaryTag dimTag,
ProtocolVersion version) {
String registryIdentifier = dimTag.getString("name");
CompoundBinaryTag 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
* @return compound containing the dimension data
*/
public CompoundBinaryTag encodeAsCompoundTag(ProtocolVersion version) {
CompoundBinaryTag details = serializeDimensionDetails();
if (version.compareTo(ProtocolVersion.MINECRAFT_1_16_2) >= 0) {
if (dimensionId == null) {
throw new IllegalStateException("Tried to serialize a 1.16.2+ dimension registry entry "
+ "without an ID");
}
return CompoundBinaryTag.builder()
.putString("name", registryIdentifier)
.putInt("id", dimensionId)
.put("element", details)
.build();
} else {
return details.putString("name", registryIdentifier);
}
}
/**
* Serializes details of this dimension.
*
* @return serialized details of this dimension
*/
public CompoundBinaryTag serializeDimensionDetails() {
CompoundBinaryTag.Builder ret = CompoundBinaryTag.builder();
ret.putBoolean("natural", isNatural);
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.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);
}
if (coordinateScale != null) {
ret.putDouble("coordinate_scale", coordinateScale);
}
if (effects != null) {
ret.putString("effects", effects);
}
if (minY != null) {
ret.putInt("min_y", minY);
}
if (height != null) {
ret.putInt("height", height);
}
if (monsterSpawnBlockLightLimit != null) {
ret.putInt("monster_spawn_block_light_limit", monsterSpawnBlockLightLimit);
}
if (monsterSpawnLightLevel != null) {
ret.putInt("monster_spawn_light_level", monsterSpawnLightLevel);
}
return ret.build();
}
}

Datei anzeigen

@ -1,128 +0,0 @@
/*
* Copyright (C) 2020-2023 Velocity Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.velocitypowered.proxy.connection.registry;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import com.velocitypowered.api.network.ProtocolVersion;
import java.util.Map;
import java.util.Set;
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;
/**
* Represents a registry of dimensions sent to the client by the server.
*/
public final class DimensionRegistry {
private final Map<String, DimensionData> registeredDimensions;
private final ImmutableSet<String> levelNames;
/**
* Initializes a new {@link DimensionRegistry} instance. This registry is required for 1.16+
* clients/servers to communicate, it constrains the dimension types and names the client can be
* sent in a Respawn action (dimension change). This WILL raise an IllegalArgumentException if the
* following is not met: - At least one valid DimensionData instance is provided - At least one
* valid world name is provided
*
* @param registeredDimensions a populated {@link ImmutableSet} containing dimension data types
* @param levelNames a populated {@link ImmutableSet} of the level (world) names the
* server offers
*/
public DimensionRegistry(ImmutableSet<DimensionData> registeredDimensions,
ImmutableSet<String> levelNames) {
Preconditions.checkNotNull(registeredDimensions,
"registeredDimensions cannot be null");
Preconditions.checkNotNull(levelNames,
"levelNames cannot be null");
Preconditions.checkArgument(registeredDimensions.size() > 0,
"registeredDimensions needs to be populated");
Preconditions.checkArgument(levelNames.size() > 0,
"levelNames needs to populated");
this.registeredDimensions = Maps.uniqueIndex(
registeredDimensions, DimensionData::getRegistryIdentifier);
this.levelNames = levelNames;
}
public Map<String, DimensionData> getRegisteredDimensions() {
return registeredDimensions;
}
public Set<String> getLevelNames() {
return levelNames;
}
/**
* Returns the internal dimension data type as used by the game.
*
* @param dimensionIdentifier how the dimension is identified by the connection
* @return game dimension data or null if not registered
*/
public @Nullable DimensionData getDimensionData(String dimensionIdentifier) {
return registeredDimensions.get(dimensionIdentifier);
}
/**
* Checks a {@link DimensionInfo} against this registry.
*
* @param toValidate the {@link DimensionInfo} to validate
* @return true: the dimension information is valid for this registry
*/
public boolean isValidFor(DimensionInfo toValidate) {
if (toValidate == null) {
return false;
}
return registeredDimensions.containsKey(toValidate.getRegistryIdentifier())
&& levelNames.contains(toValidate.getLevelName());
}
/**
* Encodes the stored Dimension registry as CompoundTag.
*
* @return the CompoundTag containing identifier:type mappings
*/
public ListBinaryTag encodeRegistry(ProtocolVersion version) {
ListBinaryTag.Builder<CompoundBinaryTag> listBuilder = ListBinaryTag
.builder(BinaryTagTypes.COMPOUND);
for (DimensionData iter : registeredDimensions.values()) {
listBuilder.add(iter.encodeAsCompoundTag(version));
}
return listBuilder.build();
}
/**
* Decodes a CompoundTag storing a dimension registry.
*
* @param toParse CompoundTag containing a dimension registry
*/
public static ImmutableSet<DimensionData> fromGameData(ListBinaryTag toParse,
ProtocolVersion version) {
Preconditions.checkNotNull(toParse, "ListTag cannot be null");
ImmutableSet.Builder<DimensionData> mappings = ImmutableSet.builder();
for (BinaryTag iter : toParse) {
if (iter instanceof CompoundBinaryTag) {
mappings.add(DimensionData.decodeRegistryEntry((CompoundBinaryTag) iter, version));
}
}
return mappings.build();
}
}

Datei anzeigen

@ -20,16 +20,12 @@ package com.velocitypowered.proxy.protocol.packet;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.velocitypowered.api.network.ProtocolVersion; import com.velocitypowered.api.network.ProtocolVersion;
import com.velocitypowered.proxy.connection.MinecraftSessionHandler; import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
import com.velocitypowered.proxy.connection.registry.DimensionData;
import com.velocitypowered.proxy.connection.registry.DimensionInfo; import com.velocitypowered.proxy.connection.registry.DimensionInfo;
import com.velocitypowered.proxy.connection.registry.DimensionRegistry;
import com.velocitypowered.proxy.protocol.*; import com.velocitypowered.proxy.protocol.*;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import it.unimi.dsi.fastutil.Pair; import it.unimi.dsi.fastutil.Pair;
import net.kyori.adventure.nbt.BinaryTagIO; import net.kyori.adventure.nbt.BinaryTagIO;
import net.kyori.adventure.nbt.BinaryTagTypes;
import net.kyori.adventure.nbt.CompoundBinaryTag; import net.kyori.adventure.nbt.CompoundBinaryTag;
import net.kyori.adventure.nbt.ListBinaryTag;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
public class JoinGame implements MinecraftPacket { public class JoinGame implements MinecraftPacket {
@ -46,15 +42,13 @@ public class JoinGame implements MinecraftPacket {
private int viewDistance; // 1.14+ private int viewDistance; // 1.14+
private boolean reducedDebugInfo; private boolean reducedDebugInfo;
private boolean showRespawnScreen; private boolean showRespawnScreen;
private DimensionRegistry dimensionRegistry; // 1.16+ private ImmutableSet<String> levelNames; // 1.16+
private CompoundBinaryTag registry; // 1.16+
private DimensionInfo dimensionInfo; // 1.16+ private DimensionInfo dimensionInfo; // 1.16+
private DimensionData currentDimensionData; // 1.16.2+ private CompoundBinaryTag currentDimensionData; // 1.16.2+
private short previousGamemode; // 1.16+ private short previousGamemode; // 1.16+
private CompoundBinaryTag biomeRegistry; // 1.16.2+
private int simulationDistance; // 1.18+ private int simulationDistance; // 1.18+
private @Nullable Pair<String, Long> lastDeathPosition; private @Nullable Pair<String, Long> lastDeathPosition; // 1.19+
private CompoundBinaryTag chatTypeRegistry; // placeholder, 1.19+
private @Nullable CompoundBinaryTag originalRegistryContainerTag;
public int getEntityId() { public int getEntityId() {
return entityId; return entityId;
@ -132,14 +126,6 @@ public class JoinGame implements MinecraftPacket {
this.dimensionInfo = dimensionInfo; this.dimensionInfo = dimensionInfo;
} }
public DimensionRegistry getDimensionRegistry() {
return dimensionRegistry;
}
public void setDimensionRegistry(DimensionRegistry dimensionRegistry) {
this.dimensionRegistry = dimensionRegistry;
}
public short getPreviousGamemode() { public short getPreviousGamemode() {
return previousGamemode; return previousGamemode;
} }
@ -156,15 +142,7 @@ public class JoinGame implements MinecraftPacket {
this.isHardcore = isHardcore; this.isHardcore = isHardcore;
} }
public CompoundBinaryTag getBiomeRegistry() { public CompoundBinaryTag getCurrentDimensionData() {
return biomeRegistry;
}
public void setBiomeRegistry(CompoundBinaryTag biomeRegistry) {
this.biomeRegistry = biomeRegistry;
}
public DimensionData getCurrentDimensionData() {
return currentDimensionData; return currentDimensionData;
} }
@ -184,12 +162,8 @@ public class JoinGame implements MinecraftPacket {
this.lastDeathPosition = lastDeathPosition; this.lastDeathPosition = lastDeathPosition;
} }
public CompoundBinaryTag getChatTypeRegistry() { public CompoundBinaryTag getRegistry() {
return chatTypeRegistry; return registry;
}
public void setChatTypeRegistry(CompoundBinaryTag chatTypeRegistry) {
this.chatTypeRegistry = chatTypeRegistry;
} }
@Override @Override
@ -200,12 +174,16 @@ public class JoinGame implements MinecraftPacket {
+ ", dimension=" + dimension + ", dimension=" + dimension
+ ", partialHashedSeed=" + partialHashedSeed + ", partialHashedSeed=" + partialHashedSeed
+ ", difficulty=" + difficulty + ", difficulty=" + difficulty
+ ", isHardcore=" + isHardcore
+ ", maxPlayers=" + maxPlayers + ", maxPlayers=" + maxPlayers
+ ", levelType='" + levelType + '\'' + ", levelType='" + levelType + '\''
+ ", viewDistance=" + viewDistance + ", viewDistance=" + viewDistance
+ ", reducedDebugInfo=" + reducedDebugInfo + ", reducedDebugInfo=" + reducedDebugInfo
+ ", dimensionRegistry='" + dimensionRegistry + '\'' + ", showRespawnScreen=" + showRespawnScreen
+ ", levelNames=" + levelNames
+ ", registry='" + registry + '\''
+ ", dimensionInfo='" + dimensionInfo + '\'' + ", dimensionInfo='" + dimensionInfo + '\''
+ ", currentDimensionData='" + currentDimensionData + '\''
+ ", previousGamemode=" + previousGamemode + ", previousGamemode=" + previousGamemode
+ ", simulationDistance=" + simulationDistance + ", simulationDistance=" + simulationDistance
+ ", lastDeathPosition='" + lastDeathPosition + '\'' + ", lastDeathPosition='" + lastDeathPosition + '\''
@ -263,39 +241,16 @@ public class JoinGame implements MinecraftPacket {
this.isHardcore = (this.gamemode & 0x08) != 0; this.isHardcore = (this.gamemode & 0x08) != 0;
this.gamemode &= ~0x08; this.gamemode &= ~0x08;
} }
this.previousGamemode = buf.readByte(); this.previousGamemode = buf.readByte();
ImmutableSet<String> levelNames = ImmutableSet.copyOf(ProtocolUtils.readStringArray(buf)); this.levelNames = ImmutableSet.copyOf(ProtocolUtils.readStringArray(buf));
this.registry = ProtocolUtils.readCompoundTag(buf, JOINGAME_READER);
CompoundBinaryTag registryContainer = ProtocolUtils.readCompoundTag(buf, JOINGAME_READER);
ListBinaryTag dimensionRegistryContainer;
if (version.compareTo(ProtocolVersion.MINECRAFT_1_16_2) >= 0) {
dimensionRegistryContainer = registryContainer.getCompound("minecraft:dimension_type")
.getList("value", BinaryTagTypes.COMPOUND);
this.biomeRegistry = registryContainer.getCompound("minecraft:worldgen/biome");
if (version.compareTo(ProtocolVersion.MINECRAFT_1_19) >= 0) {
this.chatTypeRegistry = registryContainer.getCompound("minecraft:chat_type");
} else {
this.chatTypeRegistry = CompoundBinaryTag.empty();
}
} else {
dimensionRegistryContainer = registryContainer.getList("dimension",
BinaryTagTypes.COMPOUND);
}
ImmutableSet<DimensionData> readData =
DimensionRegistry.fromGameData(dimensionRegistryContainer, version);
this.dimensionRegistry = new DimensionRegistry(readData, levelNames);
this.originalRegistryContainerTag = registryContainer;
String dimensionIdentifier; String dimensionIdentifier;
String levelName = null; String levelName = null;
if (version.compareTo(ProtocolVersion.MINECRAFT_1_16_2) >= 0 if (version.compareTo(ProtocolVersion.MINECRAFT_1_16_2) >= 0
&& version.compareTo(ProtocolVersion.MINECRAFT_1_19) < 0) { && version.compareTo(ProtocolVersion.MINECRAFT_1_19) < 0) {
CompoundBinaryTag currentDimDataTag = ProtocolUtils.readCompoundTag(buf, JOINGAME_READER); this.currentDimensionData = ProtocolUtils.readCompoundTag(buf, JOINGAME_READER);
dimensionIdentifier = ProtocolUtils.readString(buf); dimensionIdentifier = ProtocolUtils.readString(buf);
this.currentDimensionData = DimensionData.decodeBaseCompoundTag(currentDimDataTag, version)
.annotateWith(dimensionIdentifier, null);
} else { } else {
dimensionIdentifier = ProtocolUtils.readString(buf); dimensionIdentifier = ProtocolUtils.readString(buf);
levelName = ProtocolUtils.readString(buf); levelName = ProtocolUtils.readString(buf);
@ -315,9 +270,11 @@ public class JoinGame implements MinecraftPacket {
this.reducedDebugInfo = buf.readBoolean(); this.reducedDebugInfo = buf.readBoolean();
this.showRespawnScreen = buf.readBoolean(); this.showRespawnScreen = buf.readBoolean();
boolean isDebug = buf.readBoolean(); boolean isDebug = buf.readBoolean();
boolean isFlat = buf.readBoolean(); boolean isFlat = buf.readBoolean();
this.dimensionInfo = new DimensionInfo(dimensionIdentifier, levelName, isFlat, isDebug); this.dimensionInfo = new DimensionInfo(dimensionIdentifier, levelName, isFlat, isDebug);
// optional death location // optional death location
if (version.compareTo(ProtocolVersion.MINECRAFT_1_19) >= 0 && buf.readBoolean()) { if (version.compareTo(ProtocolVersion.MINECRAFT_1_19) >= 0 && buf.readBoolean()) {
this.lastDeathPosition = Pair.of(ProtocolUtils.readString(buf), buf.readLong()); this.lastDeathPosition = Pair.of(ProtocolUtils.readString(buf), buf.readLong());
@ -379,40 +336,25 @@ public class JoinGame implements MinecraftPacket {
buf.writeByte(isHardcore ? gamemode | 0x8 : gamemode); buf.writeByte(isHardcore ? gamemode | 0x8 : gamemode);
} }
buf.writeByte(previousGamemode); buf.writeByte(previousGamemode);
ProtocolUtils.writeStringArray(buf, dimensionRegistry.getLevelNames().toArray(new String[0]));
if (this.originalRegistryContainerTag != null) { ProtocolUtils.writeStringArray(buf, levelNames.toArray(String[]::new));
ProtocolUtils.writeCompoundTag(buf, this.originalRegistryContainerTag); ProtocolUtils.writeCompoundTag(buf, this.registry);
} else {
CompoundBinaryTag.Builder registryContainer = CompoundBinaryTag.builder();
ListBinaryTag encodedDimensionRegistry = dimensionRegistry.encodeRegistry(version);
if (version.compareTo(ProtocolVersion.MINECRAFT_1_16_2) >= 0) {
CompoundBinaryTag.Builder dimensionRegistryEntry = CompoundBinaryTag.builder();
dimensionRegistryEntry.putString("type", "minecraft:dimension_type");
dimensionRegistryEntry.put("value", encodedDimensionRegistry);
registryContainer.put("minecraft:dimension_type", dimensionRegistryEntry.build());
registryContainer.put("minecraft:worldgen/biome", biomeRegistry);
if (version.compareTo(ProtocolVersion.MINECRAFT_1_19) >= 0) {
registryContainer.put("minecraft:chat_type", chatTypeRegistry);
}
} else {
registryContainer.put("dimension", encodedDimensionRegistry);
}
ProtocolUtils.writeCompoundTag(buf, registryContainer.build());
}
if (version.compareTo(ProtocolVersion.MINECRAFT_1_16_2) >= 0 if (version.compareTo(ProtocolVersion.MINECRAFT_1_16_2) >= 0
&& version.compareTo(ProtocolVersion.MINECRAFT_1_19) < 0) { && version.compareTo(ProtocolVersion.MINECRAFT_1_19) < 0) {
ProtocolUtils.writeCompoundTag(buf, currentDimensionData.serializeDimensionDetails()); ProtocolUtils.writeCompoundTag(buf, currentDimensionData);
ProtocolUtils.writeString(buf, dimensionInfo.getRegistryIdentifier()); ProtocolUtils.writeString(buf, dimensionInfo.getRegistryIdentifier());
} else { } else {
ProtocolUtils.writeString(buf, dimensionInfo.getRegistryIdentifier()); ProtocolUtils.writeString(buf, dimensionInfo.getRegistryIdentifier());
ProtocolUtils.writeString(buf, dimensionInfo.getLevelName()); ProtocolUtils.writeString(buf, dimensionInfo.getLevelName());
} }
buf.writeLong(partialHashedSeed); buf.writeLong(partialHashedSeed);
if (version.compareTo(ProtocolVersion.MINECRAFT_1_16_2) >= 0) { if (version.compareTo(ProtocolVersion.MINECRAFT_1_16_2) >= 0) {
ProtocolUtils.writeVarInt(buf, maxPlayers); ProtocolUtils.writeVarInt(buf, maxPlayers);
} else { } else {
buf.writeByte(maxPlayers); buf.writeByte(maxPlayers);
} }
ProtocolUtils.writeVarInt(buf, viewDistance); ProtocolUtils.writeVarInt(buf, viewDistance);
if (version.compareTo(ProtocolVersion.MINECRAFT_1_18) >= 0) { if (version.compareTo(ProtocolVersion.MINECRAFT_1_18) >= 0) {
ProtocolUtils.writeVarInt(buf, simulationDistance); ProtocolUtils.writeVarInt(buf, simulationDistance);
@ -420,6 +362,7 @@ public class JoinGame implements MinecraftPacket {
buf.writeBoolean(reducedDebugInfo); buf.writeBoolean(reducedDebugInfo);
buf.writeBoolean(showRespawnScreen); buf.writeBoolean(showRespawnScreen);
buf.writeBoolean(dimensionInfo.isDebugType()); buf.writeBoolean(dimensionInfo.isDebugType());
buf.writeBoolean(dimensionInfo.isFlat()); buf.writeBoolean(dimensionInfo.isFlat());

Datei anzeigen

@ -19,7 +19,6 @@ package com.velocitypowered.proxy.protocol.packet;
import com.velocitypowered.api.network.ProtocolVersion; import com.velocitypowered.api.network.ProtocolVersion;
import com.velocitypowered.proxy.connection.MinecraftSessionHandler; import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
import com.velocitypowered.proxy.connection.registry.DimensionData;
import com.velocitypowered.proxy.connection.registry.DimensionInfo; import com.velocitypowered.proxy.connection.registry.DimensionInfo;
import com.velocitypowered.proxy.protocol.MinecraftPacket; import com.velocitypowered.proxy.protocol.MinecraftPacket;
import com.velocitypowered.proxy.protocol.ProtocolUtils; import com.velocitypowered.proxy.protocol.ProtocolUtils;
@ -39,7 +38,7 @@ public class Respawn implements MinecraftPacket {
private byte dataToKeep; // 1.16+ private byte dataToKeep; // 1.16+
private DimensionInfo dimensionInfo; // 1.16-1.16.1 private DimensionInfo dimensionInfo; // 1.16-1.16.1
private short previousGamemode; // 1.16+ private short previousGamemode; // 1.16+
private DimensionData currentDimensionData; // 1.16.2+ private CompoundBinaryTag currentDimensionData; // 1.16.2+
private @Nullable Pair<String, Long> lastDeathPosition; // 1.19+ private @Nullable Pair<String, Long> lastDeathPosition; // 1.19+
public Respawn() { public Respawn() {
@ -47,7 +46,7 @@ public class Respawn implements MinecraftPacket {
public Respawn(int dimension, long partialHashedSeed, short difficulty, short gamemode, public Respawn(int dimension, long partialHashedSeed, short difficulty, short gamemode,
String levelType, byte dataToKeep, DimensionInfo dimensionInfo, String levelType, byte dataToKeep, DimensionInfo dimensionInfo,
short previousGamemode, DimensionData currentDimensionData, short previousGamemode, CompoundBinaryTag currentDimensionData,
@Nullable Pair<String, Long> lastDeathPosition) { @Nullable Pair<String, Long> lastDeathPosition) {
this.dimension = dimension; this.dimension = dimension;
this.partialHashedSeed = partialHashedSeed; this.partialHashedSeed = partialHashedSeed;
@ -155,10 +154,8 @@ public class Respawn implements MinecraftPacket {
if (version.compareTo(ProtocolVersion.MINECRAFT_1_16) >= 0) { if (version.compareTo(ProtocolVersion.MINECRAFT_1_16) >= 0) {
if (version.compareTo(ProtocolVersion.MINECRAFT_1_16_2) >= 0 if (version.compareTo(ProtocolVersion.MINECRAFT_1_16_2) >= 0
&& version.compareTo(ProtocolVersion.MINECRAFT_1_19) < 0) { && version.compareTo(ProtocolVersion.MINECRAFT_1_19) < 0) {
CompoundBinaryTag dimDataTag = ProtocolUtils.readCompoundTag(buf, BinaryTagIO.reader()); this.currentDimensionData = ProtocolUtils.readCompoundTag(buf, BinaryTagIO.reader());
dimensionIdentifier = ProtocolUtils.readString(buf); dimensionIdentifier = ProtocolUtils.readString(buf);
this.currentDimensionData = DimensionData.decodeBaseCompoundTag(dimDataTag, version)
.annotateWith(dimensionIdentifier, null);
} else { } else {
dimensionIdentifier = ProtocolUtils.readString(buf); dimensionIdentifier = ProtocolUtils.readString(buf);
levelName = ProtocolUtils.readString(buf); levelName = ProtocolUtils.readString(buf);
@ -198,7 +195,7 @@ public class Respawn implements MinecraftPacket {
if (version.compareTo(ProtocolVersion.MINECRAFT_1_16) >= 0) { if (version.compareTo(ProtocolVersion.MINECRAFT_1_16) >= 0) {
if (version.compareTo(ProtocolVersion.MINECRAFT_1_16_2) >= 0 if (version.compareTo(ProtocolVersion.MINECRAFT_1_16_2) >= 0
&& version.compareTo(ProtocolVersion.MINECRAFT_1_19) < 0) { && version.compareTo(ProtocolVersion.MINECRAFT_1_19) < 0) {
ProtocolUtils.writeCompoundTag(buf, currentDimensionData.serializeDimensionDetails()); ProtocolUtils.writeCompoundTag(buf, currentDimensionData);
ProtocolUtils.writeString(buf, dimensionInfo.getRegistryIdentifier()); ProtocolUtils.writeString(buf, dimensionInfo.getRegistryIdentifier());
} else { } else {
ProtocolUtils.writeString(buf, dimensionInfo.getRegistryIdentifier()); ProtocolUtils.writeString(buf, dimensionInfo.getRegistryIdentifier());