Skip to content

pc/26.1: map every InteractionHand field to main_hand/off_hand - #1278

Merged
rom1504 merged 3 commits into
PrismarineJS:masterfrom
u9g:fix/26-1-use-entity-hand-varint
Sep 19, 2026
Merged

rom1504 merged 3 commits into
PrismarineJS:masterfrom
u9g:fix/26-1-use-entity-hand-varint

Conversation

@u9g

@u9g u9g commented Sep 7, 2026 •

Copy link
Copy Markdown
Member

In pc/26.1, use_entity.hand is a mapper (main_hand/off_hand), while the other InteractionHand fields (open_book, arm_animation, block_place, use_item) are plain varints. That means a client has to write 'main_hand' for one packet and 0 for the rest.

This PR keeps the named form and applies it to all five fields. That fits the move toward enum mappers in #1295, and it avoids the silent regression flagged in review: with a plain varint, ProtoDef writes off_hand as 00.

  • data/pc/latest/proto.yml: open_book, arm_animation, block_place and use_item get the same main_hand/off_hand mapping as use_entity; protocol.json is regenerated.
  • edit_book.hand is left as a varint because vanilla's ServerboundEditBookPacket carries a hotbar slot index there, not an InteractionHand.
  • tools/js/test/protocolHands.js (new protodef devDependency): for each of the five fields, serializes both main_hand → 00 and off_hand → 01, and reads 01 back as off_hand.

Callers that write numeric ids to the four newly mapped fields will now get a serializer error, not a wrong hand.

@u9g

u9g commented Sep 7, 2026

Copy link
Copy Markdown
Member Author

Confirmed on a live 26.1 server (JartexNetwork, 1.8 backend behind ViaVersion). Worth noting how it fails, because it does not look like a serializer error from the outside: the throw happens in Serializer._transform, which errors the write stream and closes the socket without a kicked or error event reaching the bot. bot.entity still reads and physicsEnabled is still true, so a control loop keeps driving a bot that has sent nothing for minutes.

With this change bot.activateEntity on a shop villager opens the window and the purchase goes through.

u9g added a commit to u9g/minecraft-data that referenced this pull request Sep 7, 2026
@u9g

u9g commented Sep 7, 2026

Copy link
Copy Markdown
Member Author

Context, in case you'd rather go the other way: mineflayer has since been fixed to write the mapper name (hand: 'main_hand') in PrismarineJS/mineflayer#4066 and #4076, so it no longer depends on this change.

What's left is the inconsistency itself — inside pc/26.1, use_entity.hand is a mapper while arm_animation.hand, block_place.hand, use_item.hand and edit_book.hand are plain varints, and all five are the same InteractionHand enum in vanilla. Whichever direction you prefer is fine by me; making the other four mappers instead would resolve it just as well, and I'm happy to redo the PR that way.

@rom1504 rom1504 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Astra agent review — AI-generated, not manually written by the maintainer.

Reviewed at the maintainer's request. I inspected the current diff and discussion and locally reproduced named-value serialization before/after with ProtoDef 1.19.0. The inline finding concerns silent behavior changes for callers using the existing named API; no live-server test was run.

Comment thread data/pc/26.1/protocol.json Outdated
}
}
]
"type": "varint"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Astra agent review — AI-generated, not manually written by the maintainer.

Removing this mapper silently changes an existing hand: 'off_hand' write from byte 01 to 00 (main hand). I reproduced this with ProtoDef 1.19.0 using the changed field type: its varint writer coerces both names to zero, so this is a wrong-hand interaction rather than a useful migration error. Could we keep the named representation and adapt numeric callers, or supply an explicit compatibility path before removing it? Please cover both named hands in a serializer regression test; testing only main hand hides the regression.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, reworked in the other direction (237e8a8): use_entity.hand keeps its mapper, and open_book, arm_animation, block_place and use_item get the same main_hand/off_hand mapping, so the named form is used for every InteractionHand field in 26.1. tools/js/test/protocolHands.js serializes both named hands for each field and checks off_hand → 01. A plain varint writes 00 there, so the test catches the regression you found.

u9g added 2 commits September 19, 2026 09:59
Keep use_entity.hand as a mapper and give open_book, arm_animation,
block_place and use_item the same mapping, so all five InteractionHand
fields in 26.1 read and write the same names. edit_book is left alone:
its field is a hotbar slot index in vanilla, not a hand.

A protodef serializer test covers both named hands for each field;
a plain varint writes off_hand as 00.
@u9g u9g changed the title Fix pc/26.1 use_entity hand: plain varint, not a mapper pc/26.1: map every InteractionHand field to main_hand/off_hand Sep 19, 2026
@u9g

u9g commented Sep 19, 2026

Copy link
Copy Markdown
Member Author

Correction to my earlier comment: PrismarineJS/mineflayer#4066 and #4076 were closed without merging, so mineflayer master still writes hand: 0 to use_entity on 26.1. Writing names there (and now also for arm_animation, block_place and use_item) is pending in mineflayer.

@socket-security

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addednpm/​protodef@​1.19.0971008782100

View full report

@rom1504 rom1504 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Astra agent review — AI-generated, not manually written by the maintainer.

Looks ready to merge from this review. The revised direction preserves use_entity's mapper and adds matching names to the other four hand fields in both YAML and generated JSON. The five added tests pass. Separately, using the complete candidate schema in an isolated process with NMP 1.68.0 / ProtoDef 1.19.0, I encoded and decoded all five full packets: named and numeric main/off hands produce identical bytes (10 pairs), and off_hand remains 1. This avoids the earlier interpreter-versus-production confusion. Current CI is green; no live-server action was claimed.

Skills used: prismarine-protocol-data-review traced the maintained data through its production codec/consumer; prismarine-review checked current revisions, CI and existing discussion to avoid duplicate findings.

@rom1504
rom1504 merged commit 1131ad9 into PrismarineJS:master Sep 19, 2026
5 checks passed
DallasCarraher added a commit to DallasCarraher/minecraft-data that referenced this pull request Sep 23, 2026
CI on this PR (which tests the merge with master) failed "26.1 / protocol.json
is desynced from yaml". The 26.2 commits on this branch froze
data/pc/26.1/proto.yml from pc/latest and repointed 26.1 at it, but master
has since changed 26.1's protocol.json by editing pc/latest/proto.yml
(PrismarineJS#1278 InteractionHand main_hand/off_hand mappers, PrismarineJS#1295 entity_action
enum names). The merge took master's newer JSON alongside this branch's
older frozen yaml.

Applied master's pc/latest/proto.yml diff since the merge base to
pc/26.1/proto.yml (it was an identical copy) and regenerated. 26.1's
protocol.json is now byte-identical to master's.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
DallasCarraher added a commit to DallasCarraher/minecraft-data that referenced this pull request Sep 23, 2026
Brings the frozen 26.2 and 26.3 proto.yml in line with what master did to
pc/latest (and what the previous commit ported to 26.1):

- PrismarineJS#1278: `hand` on open_book, arm_animation, block_place and use_item is
  now a main_hand/off_hand mapper instead of a bare varint.
- PrismarineJS#1295: entity_action actionId names follow Mojang's
  ServerboundPlayerCommandPacket.Action (leave_bed -> stop_sleeping,
  start/stop_horse_jump -> start/stop_riding_jump, open_vehicle_inventory ->
  open_inventory, start_elytra_flying -> start_fall_flying).

Wire format is unchanged: numeric writes still pass through the mappers,
and the start/stop_sprinting names are the same. The resulting packet
definitions are identical to 26.1's. mineflayer's elytraFly still sends
'start_elytra_flying' under entityActionUsesStringMapper, which is the
same break master already has on 26.1 and is handled by
PrismarineJS/mineflayer#4120.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants