diff --git a/src/main/java/net/elytrium/limbofilter/LimboFilter.java b/src/main/java/net/elytrium/limbofilter/LimboFilter.java index b781900..362b4d0 100644 --- a/src/main/java/net/elytrium/limbofilter/LimboFilter.java +++ b/src/main/java/net/elytrium/limbofilter/LimboFilter.java @@ -317,6 +317,7 @@ public void reload() { new PacketMapping(0x58, ProtocolVersion.MINECRAFT_1_20_5, true), new PacketMapping(0x5D, ProtocolVersion.MINECRAFT_1_21_2, true), new PacketMapping(0x5C, ProtocolVersion.MINECRAFT_1_21_5, true), + new PacketMapping(0x61, ProtocolVersion.MINECRAFT_1_21_9, true), }) .registerPacket(PacketDirection.CLIENTBOUND, SpawnEntity.class, null, new PacketMapping[]{ new PacketMapping(0x0E, ProtocolVersion.MINIMUM_VERSION, true), diff --git a/src/main/java/net/elytrium/limbofilter/protocol/data/ItemFrame.java b/src/main/java/net/elytrium/limbofilter/protocol/data/ItemFrame.java index 77b2ca2..9cd0fb8 100644 --- a/src/main/java/net/elytrium/limbofilter/protocol/data/ItemFrame.java +++ b/src/main/java/net/elytrium/limbofilter/protocol/data/ItemFrame.java @@ -51,8 +51,12 @@ public static int getID(ProtocolVersion protocolVersion) { return 71; } else if (protocolVersion.compareTo(ProtocolVersion.MINECRAFT_1_21_5) <= 0) { return 70; - } else { + } else if (protocolVersion.compareTo(ProtocolVersion.MINECRAFT_1_21_7) <= 0) { return 71; + } else if (protocolVersion.compareTo(ProtocolVersion.MINECRAFT_1_21_9) <= 0) { + return 72; + } else { + return 73; } } diff --git a/src/main/java/net/elytrium/limbofilter/protocol/data/PackedVector.java b/src/main/java/net/elytrium/limbofilter/protocol/data/PackedVector.java new file mode 100644 index 0000000..c44029c --- /dev/null +++ b/src/main/java/net/elytrium/limbofilter/protocol/data/PackedVector.java @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2021 - 2025 Elytrium + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package net.elytrium.limbofilter.protocol.data; + +import com.velocitypowered.proxy.protocol.ProtocolUtils; +import io.netty.buffer.ByteBuf; + +public record PackedVector(double x, double y, double z) { + + public static PackedVector read(ByteBuf buffer) { + int first = buffer.readUnsignedByte(); + if (first == 0) { + return new PackedVector(0, 0, 0); + } else { + int second = buffer.readUnsignedByte(); + long third = buffer.readUnsignedInt(); + long result = third << 16 | (long) (second << 8) | (long) first; + long multiplier = first & 3; + if ((first & 4) == 4) { + multiplier |= ((long) ProtocolUtils.readVarInt(buffer) & 4094967295L) << 2L; + } + + return new PackedVector(unpack(result >> 3) * (double) multiplier, + unpack(result >> 18) * (double) multiplier, + unpack(result >> 33) * (double) multiplier); + } + } + + public static void write(ByteBuf buffer, double x, double y, double z) { + double sx = sanitize(x); + double sy = sanitize(y); + double sz = sanitize(z); + double maxValue = Math.max(Math.abs(sx), Math.max(Math.abs(sy), Math.abs(sz))); + if (maxValue < 3.051944088384301E-5) { + buffer.writeByte(0); + return; + } + + long result = (long) maxValue; + long max = maxValue > (double) result ? result + 1L : result; + + boolean continuation = (max & 3) != max; + long px = pack(sx / (double) max) << 3; + long py = pack(sy / (double) max) << 18; + long pz = pack(sz / (double) max) << 33; + long packed = (continuation ? max & 3 | 4 : max) | px | py | pz; + buffer.writeByte((byte) ((int) packed)); + buffer.writeByte((byte) ((int) (packed >> 8))); + buffer.writeInt((int) (packed >> 16)); + if (continuation) { + ProtocolUtils.writeVarInt(buffer, (int) (max >> 2)); + } + } + + private static long pack(double value) { + return Math.round((value * 0.5 + 0.5) * 32766.0); + } + + private static double unpack(long value) { + return Math.min((double) (value & (long) 32767), 32766.0) * 2.0 / 32766.0 - 1.0; + } + + private static double sanitize(double value) { + if (Double.isNaN(value)) { + return 0.0; + } else { + return value < -1.7179869183E10 ? -1.7179869183E10 : Math.min(value, 1.7179869183E10); + } + } +} diff --git a/src/main/java/net/elytrium/limbofilter/protocol/packets/SpawnEntity.java b/src/main/java/net/elytrium/limbofilter/protocol/packets/SpawnEntity.java index 12c194f..378bdac 100644 --- a/src/main/java/net/elytrium/limbofilter/protocol/packets/SpawnEntity.java +++ b/src/main/java/net/elytrium/limbofilter/protocol/packets/SpawnEntity.java @@ -24,6 +24,7 @@ import io.netty.buffer.ByteBuf; import java.util.UUID; import java.util.function.Function; +import net.elytrium.limbofilter.protocol.data.PackedVector; public class SpawnEntity implements MinecraftPacket { @@ -76,6 +77,10 @@ public void encode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersi buf.writeDouble(this.positionX); buf.writeDouble(this.positionY); buf.writeDouble(this.positionZ); + + if (protocolVersion.noLessThan(ProtocolVersion.MINECRAFT_1_21_9)) { + PackedVector.write(buf, this.velocityX, this.velocityY, this.velocityZ); + } } else { buf.writeByte(this.type.apply(protocolVersion)); buf.writeInt((int) (this.positionX * 32.0)); @@ -90,9 +95,12 @@ public void encode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersi } else { buf.writeInt(this.data); } - buf.writeShort((int) (this.velocityX * 8000.0F)); - buf.writeShort((int) (this.velocityY * 8000.0F)); - buf.writeShort((int) (this.velocityZ * 8000.0F)); + + if (protocolVersion.lessThan(ProtocolVersion.MINECRAFT_1_21_9)) { + buf.writeShort((int) (this.velocityX * 8000.0F)); + buf.writeShort((int) (this.velocityY * 8000.0F)); + buf.writeShort((int) (this.velocityZ * 8000.0F)); + } } @Override