This commit is contained in:
Nassim Jahnke committed 2025-10-03 13:46:19 +02:00
1 parent 556560a0f3
commit 98d1d2cb49
14 files changed
+270 -4

No files matched your search

@@ -0,0 +1,28 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* 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.
*/
package com.viaversion.viaversion.api.minecraft;
public record Vector3d(double x, double y, double z) {
public static final Vector3d ZERO = new Vector3d(0, 0, 0);
}
@@ -91,7 +91,7 @@ public class ProtocolVersion implements Comparable<ProtocolVersion> {
public static final ProtocolVersion v1_21_5 = register(770, "1.21.5");
public static final ProtocolVersion v1_21_6 = register(771, "1.21.6");
public static final ProtocolVersion v1_21_7 = register(772, "1.21.7-1.21.8", new SubVersionRange("1.21", 7, 8));
public static final ProtocolVersion v1_21_9 = register(773, 260, "1.21.9");
public static final ProtocolVersion v1_21_9 = register(773, 261, "1.21.9");
public static final ProtocolVersion unknown = new ProtocolVersion(VersionType.SPECIAL, -1, -1, "UNKNOWN", null);
static {
@@ -38,6 +38,7 @@ import com.viaversion.viaversion.api.minecraft.Quaternion;
import com.viaversion.viaversion.api.minecraft.RegistryEntry;
import com.viaversion.viaversion.api.minecraft.SoundEvent;
import com.viaversion.viaversion.api.minecraft.Vector;
import com.viaversion.viaversion.api.minecraft.Vector3d;
import com.viaversion.viaversion.api.minecraft.Vector3f;
import com.viaversion.viaversion.api.minecraft.VillagerData;
import com.viaversion.viaversion.api.minecraft.blockentity.BlockEntity;
@@ -70,6 +71,7 @@ import com.viaversion.viaversion.api.type.types.ShortType;
import com.viaversion.viaversion.api.type.types.StringType;
import com.viaversion.viaversion.api.type.types.UUIDType;
import com.viaversion.viaversion.api.type.types.UnsignedByteType;
import com.viaversion.viaversion.api.type.types.UnsignedIntType;
import com.viaversion.viaversion.api.type.types.UnsignedShortType;
import com.viaversion.viaversion.api.type.types.VarIntArrayType;
import com.viaversion.viaversion.api.type.types.VarIntType;
@@ -100,6 +102,7 @@ import com.viaversion.viaversion.api.type.types.math.BlockPositionType1_8;
import com.viaversion.viaversion.api.type.types.math.ChunkPositionType;
import com.viaversion.viaversion.api.type.types.math.EulerAngleType;
import com.viaversion.viaversion.api.type.types.math.GlobalBlockPositionType;
import com.viaversion.viaversion.api.type.types.math.MovementVectorType;
import com.viaversion.viaversion.api.type.types.math.QuaternionType;
import com.viaversion.viaversion.api.type.types.math.Vector3fType;
import com.viaversion.viaversion.api.type.types.math.VectorType;
@@ -144,6 +147,7 @@ public final class Types {
public static final IntType INT = new IntType();
public static final Type<int[]> INT_ARRAY_PRIMITIVE = new IntArrayType();
public static final UnsignedIntType UNSIGNED_INT = new UnsignedIntType();
public static final FloatType FLOAT = new FloatType();
public static final FloatType.OptionalFloatType OPTIONAL_FLOAT = new FloatType.OptionalFloatType();
@@ -192,6 +196,7 @@ public final class Types {
public static final Type<Vector> VECTOR = new VectorType();
public static final Type<Vector3f> VECTOR3F = new Vector3fType();
public static final Type<Quaternion> QUATERNION = new QuaternionType();
public static final Type<Vector3d> MOVEMENT_VECTOR = new MovementVectorType();
public static final Type<CompoundTag> NAMED_COMPOUND_TAG = new NamedCompoundTagType();
public static final Type<CompoundTag> OPTIONAL_NAMED_COMPOUND_TAG = new NamedCompoundTagType.OptionalNamedCompoundTagType();
@@ -0,0 +1,61 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* 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.
*/
package com.viaversion.viaversion.api.type.types;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.TypeConverter;
import io.netty.buffer.ByteBuf;
public class UnsignedIntType extends Type<Long> implements TypeConverter<Long> {
public UnsignedIntType() {
super(Long.class);
}
@Override
public Long read(ByteBuf buffer) {
return buffer.readUnsignedInt();
}
public long readPrimitive(ByteBuf buffer) {
return buffer.readUnsignedInt();
}
@Override
public void write(ByteBuf buffer, Long l) {
buffer.writeInt(l.intValue());
}
public void writePrimitive(ByteBuf buffer, long l) {
buffer.writeInt((int) l);
}
@Override
public Long from(Object o) {
if (o instanceof Number number) {
return number.longValue();
} else if (o instanceof Boolean boo) {
return boo ? 1L : 0L;
}
throw new UnsupportedOperationException();
}
}
@@ -0,0 +1,100 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* 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.
*/
package com.viaversion.viaversion.api.type.types.math;
import com.viaversion.viaversion.api.minecraft.Vector3d;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.util.MathUtil;
import io.netty.buffer.ByteBuf;
public class MovementVectorType extends Type<Vector3d> {
private static final int MAPPED_MAX_VALUE = Short.MAX_VALUE >> 1;
private static final int SCALE_BITS_MASK = 3; // first 2 bits for the scale
private static final int CONTINUATION_BIT_MASK = 1 << 2; // 3rd bit to indicate more scale data
public MovementVectorType() {
super(Vector3d.class);
}
@Override
public Vector3d read(final ByteBuf buffer) {
// Pack values back into a single long
final int first = Types.UNSIGNED_BYTE.read(buffer);
if (first == 0) {
return Vector3d.ZERO;
}
final int second = Types.UNSIGNED_BYTE.read(buffer);
final long third = Types.UNSIGNED_INT.read(buffer);
final long packed = third << 16 | second << 8 | first;
// 15 bits for each part after removing the scale bits
final double encodedX = packed >> (0 + SCALE_BITS_MASK) & Short.MAX_VALUE;
final double encodedY = packed >> (15 + SCALE_BITS_MASK) & Short.MAX_VALUE;
final double encodedZ = packed >> (30 + SCALE_BITS_MASK) & Short.MAX_VALUE;
int scale = first & SCALE_BITS_MASK;
if ((first & CONTINUATION_BIT_MASK) != 0) {
// Read the remaining bits and add them to the first two
scale |= Types.VAR_INT.readPrimitive(buffer) << 2;
}
return new Vector3d(
(encodedX / MAPPED_MAX_VALUE - 1) * scale,
(encodedY / MAPPED_MAX_VALUE - 1) * scale,
(encodedZ / MAPPED_MAX_VALUE - 1) * scale
);
}
@Override
public void write(final ByteBuf buffer, final Vector3d vec) {
final double maxPart = Math.max(Math.abs(vec.x()), Math.max(Math.abs(vec.y()), Math.abs(vec.z())));
if (maxPart < MathUtil.EPSILON) {
buffer.writeByte(0);
return;
}
final int scale = (int) Math.ceil(maxPart);
final double quantizationFactor = 0.5 / scale;
final long encodedX = (long) ((vec.x() * quantizationFactor + 0.5) * Short.MAX_VALUE);
final long encodedY = (long) ((vec.y() * quantizationFactor + 0.5) * Short.MAX_VALUE);
final long encodedZ = (long) ((vec.z() * quantizationFactor + 0.5) * Short.MAX_VALUE);
final boolean scaleTooLargeForBits = scale > 3;
final int scaleBits = scaleTooLargeForBits ? (scale & SCALE_BITS_MASK) | CONTINUATION_BIT_MASK : scale;
final long packed = scaleBits
| (encodedX << (0 + SCALE_BITS_MASK))
| (encodedY << (15 + SCALE_BITS_MASK))
| (encodedZ << (30 + SCALE_BITS_MASK));
buffer.writeByte((byte) packed);
buffer.writeByte((byte) (packed >> 8));
buffer.writeInt((int) (packed >> 16));
if (scaleTooLargeForBits) {
// First two bits have already been written
Types.VAR_INT.writePrimitive(buffer, scale >> 2);
}
}
}
@@ -24,6 +24,11 @@ package com.viaversion.viaversion.util;
public final class MathUtil {
/**
* Miniscule value below which positive floats are considered zero
*/
public static final float EPSILON = 1.0E-5F;
/**
* Returns the ceiled integer value of the given float.
*
@@ -19,6 +19,7 @@ tasks {
compileJava {
options.encoding = Charsets.UTF_8.name()
options.compilerArgs.addAll(listOf("-nowarn", "-Xlint:-unchecked", "-Xlint:-deprecation"))
options.isFork = true
}
test {
useJUnitPlatform()
+1 -1
View File
@@ -26,7 +26,7 @@ tasks.named<Jar>("sourcesJar") {
val prepareViaProxyFiles by tasks.registering(Copy::class) {
dependsOn(project.tasks.shadowJar)
from(project.tasks.shadowJar.get().archiveFile.get().asFile)
from(project.tasks.shadowJar.map { it.archiveFile.get().asFile })
into(layout.projectDirectory.dir("run/jars"))
val projectName = project.name
@@ -38,7 +38,7 @@ final class EntityPacketRewriter1_99 extends EntityRewriter<ClientboundPacket1_2
@Override
public void registerPackets() {
// Tracks entities, applies entity data rewrites registered below, untracks entities
registerTrackerWithData1_19(ClientboundPackets1_21_6.ADD_ENTITY, EntityTypes1_21_9.FALLING_BLOCK);
registerTrackerWithData1_21_9(ClientboundPackets1_21_6.ADD_ENTITY, EntityTypes1_21_9.FALLING_BLOCK);
registerSetEntityData(ClientboundPackets1_21_6.SET_ENTITY_DATA);
registerRemoveEntities(ClientboundPackets1_21_6.REMOVE_ENTITIES);
registerPlayerAbilities(ClientboundPackets1_21_6.PLAYER_ABILITIES);
@@ -17,9 +17,12 @@
*/
package com.viaversion.viaversion.protocols.v1_21_7to1_21_9.rewriter;
import com.viaversion.viaversion.api.minecraft.Vector3d;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_21_9;
import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes1_21_9;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.protocols.v1_21_5to1_21_6.packet.ClientboundConfigurationPackets1_21_6;
import com.viaversion.viaversion.protocols.v1_21_5to1_21_6.packet.ClientboundPacket1_21_6;
import com.viaversion.viaversion.protocols.v1_21_5to1_21_6.packet.ClientboundPackets1_21_6;
@@ -35,7 +38,6 @@ public final class EntityPacketRewriter1_21_9 extends EntityRewriter<Clientbound
@Override
public void registerPackets() {
registerTrackerWithData1_19(ClientboundPackets1_21_6.ADD_ENTITY, EntityTypes1_21_9.FALLING_BLOCK);
registerSetEntityData(ClientboundPackets1_21_6.SET_ENTITY_DATA);
registerRemoveEntities(ClientboundPackets1_21_6.REMOVE_ENTITIES);
registerPlayerAbilities(ClientboundPackets1_21_6.PLAYER_ABILITIES);
@@ -43,10 +45,52 @@ public final class EntityPacketRewriter1_21_9 extends EntityRewriter<Clientbound
registerLogin1_20_5(ClientboundPackets1_21_6.LOGIN);
registerRespawn1_20_5(ClientboundPackets1_21_6.RESPAWN);
protocol.registerClientbound(ClientboundPackets1_21_6.ADD_ENTITY, wrapper -> {
final int entityId = wrapper.passthrough(Types.VAR_INT);
wrapper.passthrough(Types.UUID); // Entity UUID
final int entityTypeId = wrapper.passthrough(Types.VAR_INT);
wrapper.passthrough(Types.DOUBLE); // X
wrapper.passthrough(Types.DOUBLE); // Y
wrapper.passthrough(Types.DOUBLE); // Z
wrapper.write(Types.MOVEMENT_VECTOR, Vector3d.ZERO); // Set at the end
wrapper.passthrough(Types.BYTE); // Pitch
wrapper.passthrough(Types.BYTE); // Yaw
wrapper.passthrough(Types.BYTE); // Head yaw
final int data = wrapper.passthrough(Types.VAR_INT);
final EntityType entityType = trackAndRewrite(wrapper, entityTypeId, entityId);
if (protocol.getMappingData() != null && entityType == EntityTypes1_21_9.FALLING_BLOCK) {
final int mappedBlockStateId = protocol.getMappingData().getNewBlockStateId(data);
wrapper.set(Types.VAR_INT, 2, mappedBlockStateId);
}
wrapper.set(Types.MOVEMENT_VECTOR, 0, readRelativeMovement(wrapper));
});
protocol.registerClientbound(ClientboundPackets1_21_6.SET_ENTITY_MOTION, wrapper -> {
wrapper.passthrough(Types.VAR_INT); // Entity ID
wrapper.write(Types.MOVEMENT_VECTOR, readRelativeMovement(wrapper));
});
protocol.registerClientbound(ClientboundPackets1_21_6.PLAYER_ROTATION, wrapper -> {
wrapper.passthrough(Types.FLOAT); // Y rotation
wrapper.write(Types.BOOLEAN, false); // Relative Y rotation
wrapper.passthrough(Types.FLOAT); // X rotation
wrapper.write(Types.BOOLEAN, false); // Relative X rotation
});
final RegistryDataRewriter registryDataRewriter = new RegistryDataRewriter(protocol);
protocol.registerClientbound(ClientboundConfigurationPackets1_21_6.REGISTRY_DATA, registryDataRewriter::handle);
}
private Vector3d readRelativeMovement(final PacketWrapper wrapper) {
final double movementX = wrapper.read(Types.SHORT) / 8000D;
final double movementY = wrapper.read(Types.SHORT) / 8000D;
final double movementZ = wrapper.read(Types.SHORT) / 8000D;
return new Vector3d(movementX, movementY, movementZ);
}
@Override
protected void registerRewrites() {
final EntityDataTypes1_21_9 entityDataTypes = protocol.mappedTypes().entityDataTypes();
@@ -32,6 +32,7 @@ import com.viaversion.viaversion.api.data.entity.EntityTracker;
import com.viaversion.viaversion.api.data.entity.TrackedEntity;
import com.viaversion.viaversion.api.minecraft.GameMode;
import com.viaversion.viaversion.api.minecraft.Particle;
import com.viaversion.viaversion.api.minecraft.Vector3d;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.entitydata.EntityData;
import com.viaversion.viaversion.api.minecraft.entitydata.EntityDataType;
@@ -313,6 +314,27 @@ public abstract class EntityRewriter<C extends ClientboundPacketType, T extends
});
}
public void registerTrackerWithData1_21_9(C packetType, EntityType fallingBlockType) {
protocol.registerClientbound(packetType, wrapper -> {
final int entityId = wrapper.passthrough(Types.VAR_INT);
wrapper.passthrough(Types.UUID); // Entity UUID
final int entityTypeId = wrapper.passthrough(Types.VAR_INT);
wrapper.passthrough(Types.DOUBLE); // X
wrapper.passthrough(Types.DOUBLE); // Y
wrapper.passthrough(Types.DOUBLE); // Z
wrapper.passthrough(Types.MOVEMENT_VECTOR); // Movement
wrapper.passthrough(Types.BYTE); // Pitch
wrapper.passthrough(Types.BYTE); // Yaw
wrapper.passthrough(Types.BYTE); // Head yaw
final int data = wrapper.passthrough(Types.VAR_INT);
final EntityType entityType = trackAndRewrite(wrapper, entityTypeId, entityId);
if (protocol.getMappingData() != null && entityType == fallingBlockType) {
final int mappedBlockStateId = protocol.getMappingData().getNewBlockStateId(data);
wrapper.set(Types.VAR_INT, 2, mappedBlockStateId);
}
});
}
/**
* Registers an entity tracker for the extra spawn packets like player, painting, or xp orb spawns.
*