Skip to content

update entity_teleport packet on 1.21.3+ - #1154

Open
TheSharkyOfficial wants to merge 3 commits into
PrismarineJS:masterfrom
TheSharkyOfficial:patch-1
Open

update entity_teleport packet on 1.21.3+#1154
TheSharkyOfficial wants to merge 3 commits into
PrismarineJS:masterfrom
TheSharkyOfficial:patch-1

Conversation

@TheSharkyOfficial

Copy link
Copy Markdown

Updated teleport_entity packet according to https://minecraft.wiki/w/Java_Edition_protocol/Packets#Synchronize_Vehicle_Position
Should fix partial packet errors for this packet.

@extremeheat

Copy link
Copy Markdown
Member

Do you have link to relevant vanilla source code for this?

@atiweb

atiweb commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Re: the vanilla source — here's the relevant code, decompiled from the server jar (ClientboundTeleportEntityPacket):

public record ClientboundTeleportEntityPacket(int id, PositionMoveRotation change, Set<Relative> relatives, boolean onGround) {
    public static final StreamCodec<FriendlyByteBuf, ClientboundTeleportEntityPacket> STREAM_CODEC = StreamCodec.composite(
        ByteBufCodecs.VAR_INT,             ClientboundTeleportEntityPacket::id,
        PositionMoveRotation.STREAM_CODEC, ClientboundTeleportEntityPacket::change,
        Relative.SET_STREAM_CODEC,         ClientboundTeleportEntityPacket::relatives,
        ByteBufCodecs.BOOL,                ClientboundTeleportEntityPacket::onGround,
        ClientboundTeleportEntityPacket::new);
}
public record PositionMoveRotation(Vec3 position, Vec3 deltaMovement, float yRot, float xRot) { /* Vec3, Vec3, FLOAT, FLOAT */ }

So the wire layout is id(varint), position x/y/z (f64), deltaMovement x/y/z (f64), yRot/xRot (f32), relatives, onGround(bool). The position / velocity / f32-rotation / onGround part of this PR matches. I checked the codec is byte-for-byte the same in 1.21.3, 1.21.11 and 26.2, so it's been stable since the 1.21.2 rework.

Two things worth fixing:

1. flags is a 4-byte int, not a 9-bit bitfield. Relative.SET_STREAM_CODEC is:

public enum Relative { X(0), Y(1), Z(2), Y_ROT(3), X_ROT(4), DELTA_X(5), DELTA_Y(6), DELTA_Z(7), ROTATE_DELTA(8); }
public static final StreamCodec<ByteBuf, Set<Relative>> SET_STREAM_CODEC = ByteBufCodecs.INT.map(Relative::unpack, Relative::pack);

— a 4-byte int with bits 0–8. The inline bitfield of 9×1 bits here only consumes 2 bytes (and reads MSB-first), so it would still desync. minecraft-data already has the right type for this exact Set<Relative>PositionUpdateRelatives (bitflags over u32), used by packet_position:

"PositionUpdateRelatives": ["bitflags", { "type": "u32", "flags": ["x","y","z","yaw","pitch","dx","dy","dz","yawDelta"] }]

So "type": "PositionUpdateRelatives" is a drop-in fix (correct width + reuses the existing type instead of a new inline bitfield).

2. This affects every 1.21.2+ version, not only 1.21.3. entity_teleport is still the old yaw/pitch: i8 form in 1.21.3, 1.21.6, 1.21.9 and 1.21.11 (and in the generated 26.2 data in #1198), and the jar structure is identical across all of them — so the same fix is needed everywhere from 1.21.2 onward.

@DatArnoGuy

Copy link
Copy Markdown

Is this ready to be merged? My console is again full of this spam :D

Chunk size is 64 but only 30 was read ; partial packet : {"name":"entity_teleport","params":{"entityId":791,"x":48.97947009945363,"y":60,"z":133.125,"yaw":21,"pitch":-72,"onGround":true}}; buffer :7b970640487d5f46b64817404e0000000000004060a4000000000015b82325d210bf270000000000000000000000000000000040f3e0ee000000000000000001

@extremeheat

Copy link
Copy Markdown
Member

@copilot Please correct the changes made per atiweb comment with PositionUpdateRelatives and also apply this to all subsequent versions

@AnonymoDGH

Copy link
Copy Markdown
Contributor

I verified this fix against the actual packet buffers from mineflayer#3759 (entity_teleport errors on 1.21.8) and it works. Decoding with your new format:

entityId: 1073741824 ✓
x/y/z: -194.5, 76, 61.5 ✓ (matches the partial packet from the issue)
velocity x/y/z: 0, 0, 0
yaw/pitch: -177.15, 1.90 (f32)
flags: 0
onGround: false

However, 2 bytes remain unread in both buffers from that issue (00 01 at the end) — the last byte is a VarInt vehicleId (value 1 in both samples). Per minecraft.wiki Synchronize Vehicle Position, there's a final Vehicle ID: VarInt field. Could you add it?

Also, this same bug affects all versions from 1.21.2+ (1.21.4, 1.21.5, 1.21.6, 1.21.8, 1.21.9, 1.21.11, 26.1) — the current PR only updates 1.21.3. Worth extending if you have the bandwidth, otherwise I can open a follow-up.

@atiweb

atiweb commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

@AnonymoDGH the leftover bytes are an off-by-one, there is no vehicleId field.

The buffer in DatArnoGuy's report above is 64 bytes and the first byte is the packet id (0x7b). If you start decoding at byte 0, entityId lands at the wrong offset and you end up 2 bytes short at the end, which is exactly what you are seeing. Starting at byte 1:

entityId  varint   = 791                          <- matches the reported entityId
x y z     f64 x3   = 48.979470, 60, 133.125       <- matches the reported x/y/z
velocity  f64 x3
yaw pitch f32 x2   = 7.6212, 0
flags     i32      = 0
onGround  bool     = 1                            <- matches the reported onGround
                     consumed 64 of 64, nothing left over

Three of those values match what mineflayer printed in the same error, and the total lands exactly on the buffer length. The 00 01 you read as a VarInt vehicleId is the tail of the correct fields shifted by one byte.

The jar agrees. 1.21.8 ClientboundTeleportEntityPacket:

public record ClientboundTeleportEntityPacket(int id, PositionMoveRotation change, Set<Relative> relatives, boolean onGround) {
    public static final StreamCodec<FriendlyByteBuf, ClientboundTeleportEntityPacket> STREAM_CODEC = StreamCodec.composite(
        ByteBufCodecs.VAR_INT,             ClientboundTeleportEntityPacket::id,
        PositionMoveRotation.STREAM_CODEC, ClientboundTeleportEntityPacket::change,
        Relative.SET_STREAM_CODEC,         ClientboundTeleportEntityPacket::relatives,
        ByteBufCodecs.BOOL,                ClientboundTeleportEntityPacket::onGround,
        ClientboundTeleportEntityPacket::new);
}

No vehicle id, and nothing after onGround.

The wiki page you linked is a different packet. ClientboundEntityPositionSyncPacket is id + PositionMoveRotation + onGround, with no relatives field at all, and it is its own entry rather than a variant of this one:

public record ClientboundEntityPositionSyncPacket(int id, PositionMoveRotation values, boolean onGround) { ... }

One caveat on that sample: velocityX decodes to 4.8e-204, which is not a plausible velocity, so a hex character probably got mangled when it was pasted. It does not change the byte accounting, the other five fields and the total are exact.

Your second point is right and still open. This needs to go to every 1.21.2+ version, not only 1.21.3.

Also still open: flags in this PR is the inline 9 x 1 bit bitfield, which reads 2 bytes MSB first, while Relative.SET_STREAM_CODEC is a 4 byte int. Verified in 1.21.8 too:

public enum Relative { X(0), Y(1), Z(2), Y_ROT(3), X_ROT(4), DELTA_X(5), DELTA_Y(6), DELTA_Z(7), ROTATE_DELTA(8); }
public static final StreamCodec<ByteBuf, Set<Relative>> SET_STREAM_CODEC = ByteBufCodecs.INT.map(Relative::unpack, Relative::pack);

So "type": "PositionUpdateRelatives" is still needed, as @extremeheat asked for in July. As far as I can tell that was never pushed, the branch is still 1.21.3 only with the bitfield.

@TheSharkyOfficial @extremeheat if Sharky does not have the bandwidth, I am happy to open the complete fix as a separate PR: PositionUpdateRelatives for the flags plus the same change across all 1.21.2+ versions, jar verified per version and rebuilt with npm run build so protocol.json stays in sync. Say the word and I will put it up, otherwise I will stay out of the way.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants