Skip to content

Match the vanilla client in the login/configuration handshake: cookies, brand, per-login chat session, known packs - #1522

Open
u9g wants to merge 5 commits into
PrismarineJS:masterfrom
u9g:fix/vanilla-config-parity
Open

Match the vanilla client in the login/configuration handshake: cookies, brand, per-login chat session, known packs#1522
u9g wants to merge 5 commits into
PrismarineJS:masterfrom
u9g:fix/vanilla-config-parity

Conversation

@u9g

@u9g u9g commented Sep 6, 2026

Copy link
Copy Markdown
Member

Audit of nmp's client against the vanilla 1.21.4 client (ClientHandshakePacketListenerImpl, ClientCommonPacketListenerImpl, ClientPacketListener, KnownPacksManager, Options) turned up four places where nmp diverges in ways that servers and proxies notice. One commit each:

  • Answer cookie_request (1.20.5+). nmp never replied, so any server or proxy that sends one (Velocity/Bungee modern forwarding, transfer flows) hangs the connection. A new src/client/cookies.js keeps client._cookies, fills it from store_cookie, and answers cookie_request in login, configuration and play with the stored value or an absent one, exactly like vanilla. A cookies option seeds the map so a consumer following a transfer packet can carry cookies over like vanilla's TransferState.
  • Brand then Client Information, once. Vanilla answers login_acknowledged with custom_payload minecraft:brand followed by Client Information, and does not repeat either when a server sends it back to configuration (only configuration_acknowledged). nmp sent no brand, re-sent the settings on every configuration entry, and used view distance 10 where vanilla's default is 12. New brand option (default 'vanilla'; mineflayer's options.brand flows through), clientSettings defaults are now the vanilla ones.
  • Fresh chat session on every login packet. After a proxy server switch the second login packet left the old session in place; vanilla discards it and announces a new session (new UUID, index 0) with the same key pair. client.once('login')client.on('login').
  • select_known_packs. Vanilla replies with the packs from the server's list it has locally. New knownPacks option ([{ namespace, id, version }]) answered with the intersection; the default stays [] so servers keep sending full registry data, which mineflayer/prismarine-registry rely on.

Docs updated in docs/API.md. In-process tests added in test/serverTest.js for cookie replies in all three states (including a stored-cookie echo and an absent reply), brand-then-settings sent exactly once across a start_configuration round trip, and the known-packs intersection.

Note: minecraft-data's 1.21.8 protocol.json declares cookie_response.value as a non-optional ByteArray (the 1.21.8 client writes it nullable like every other version). The absent reply is still wire-correct there (an empty ByteArray and an absent option both serialize as a single 0x00), but echoing a stored cookie needs a minecraft-data fix; the stored-cookie test is gated on the schema having the option wrapper.

u9g added 4 commits September 6, 2026 16:03
A server or proxy that sends cookie_request (1.20.5+) in the login,
configuration or play state never got a reply, so the connection hung.
Keep a per-connection cookie map on client._cookies, fill it from
store_cookie packets and from the new `cookies` option (for carrying
cookies over a transfer), and answer every cookie_request with the stored
value or an absent one, as vanilla does.
…e vanilla

The vanilla client answers login_acknowledged with a minecraft:brand
custom_payload followed by Client Information, and sends neither again
when a server moves it back to configuration from play: it only replies
with configuration_acknowledged. nmp sent no brand, re-sent the settings
on every configuration entry and defaulted the view distance to 10 where
vanilla uses 12. Send the brand (`brand` option, default 'vanilla') and
the settings on the first entry only, with the vanilla defaults.
The chat session was only created for the first login packet. After a
server switch through re-configuration the next login packet left the
old session in place, while the vanilla client discards its session on
every login and announces a new one (fresh session UUID, index 0) with
the same profile key pair. Do the same.
The vanilla client answers select_known_packs with the packs from the
server's list that it has locally (minecraft:core at its own version on a
vanilla server), and the server then omits the registry entries of those
packs. nmp always replied with no packs. Add a `knownPacks` option listing
the client's local packs and reply with their intersection with the
server's list. It defaults to [] so the server keeps sending its full
registry data, which consumers such as mineflayer depend on.
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.

1 participant