PrismarineJS / PrismarineJS/node-minecraft-protocol

custom_click_action packet - incorrect nbt buffer size?

Open
#1,484 4 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

possible bug
Dominant language
JavaScript
Stars
1.4k
Forks
290
Avg merge
4d 8h
Merged PRs (30d)
7

Description

[+] The FAQ doesn't contain a resolution to my issue

Versions

  • minecraft-protocol: 1.64.0
  • server: paper 1.21.8
  • node: 24.6.0

Detailed description of a problem

The Dialog API was added in 1.21.6. The dialog can be called during the configuration state. When the button is clicked, the custom_click_action packet is sent. I tried sending this packet, but it always returns an error about an invalid value.

What did you try yet?

I wrote code to manually send this packet using AI, and it worked. As far as I understand, the nbt buffer length is being calculated incorrectly. The code, as I've verified, is presented below.

Correct buffer: <Buffer 00 08 10 6e 6c 6f 67 69 6e 3a 6c 6f 67 69 6e 2f 79 65 73 1a 0a 08 00 08 70 61 73 73 77 6f 72 64 00 0b 68 65 6c 6c 6f 20 77 6f 72 6c 64 00>

Incorrect buffer: <Buffer 00 08 10 6e 6c 6f 67 69 6e 3a 6c 6f 67 69 6e 2f 79 65 73 01 0a 08 00 08 70 61 73 73 77 6f 72 64 00 0b 68 65 6c 6c 6f 20 77 6f 72 6c 64 00>

The difference here is in 1 number.

packetParts value is: [
<Buffer 08>,
<Buffer 10 6e 6c 6f 67 69 6e 3a 6c 6f 67 69 6e 2f 79 65 73>,
<Buffer 1a>,
<Buffer 0a 08 00 08 70 61 73 73 77 6f 72 64 00 0b 68 65 6c 6c 6f 20 77 6f 72 6c 64 00>
]

As far as I understand, the server sees that the nbt is short and does not read it completely.

Your current code

bot._client.on('packet', async (data, meta) => {
    if (meta.name === 'show_dialog') {
        // manual sending (works correctly)
        const packetParts = [];

        packetParts.push(encodeVarInt(0x08)); // packet id
        packetParts.push(encodeString("nlogin:login/yes")); // The identifier for the click action

        const keyBytes = Buffer.from('password', 'utf8'); 
        const passBytes = Buffer.from('hello world', 'utf8');

        const nbtSize = 1 + 1 + 2 + keyBytes.length + 2 + passBytes.length + 1;
        const nbtBuffer = Buffer.alloc(nbtSize);

        let offset = 0;

        nbtBuffer.writeUInt8(0x0A, offset++);
        nbtBuffer.writeUInt8(0x08, offset++);

        nbtBuffer.writeUInt16BE(keyBytes.length, offset);
        offset += 2;
        keyBytes.copy(nbtBuffer, offset);
        offset += keyBytes.length;

        nbtBuffer.writeUInt16BE(passBytes.length, offset);
        offset += 2;
        passBytes.copy(nbtBuffer, offset);
        offset += passBytes.length;

        nbtBuffer.writeUInt8(0x00, offset++);

        packetParts.push(encodeVarInt(nbtBuffer.length)); // nbt buffer size
        packetParts.push(nbtBuffer); // nbt buffer data

        const rawBuffer = Buffer.concat(packetParts);

        bot._client.writeRaw(rawBuffer);
        
         // sending using write (not working correctly)
        bot._client.write('custom_click_action', { id: 'nlogin:login/yes', nbt: nbt.comp({ password: nbt.string('hello world')}, ) });
    } 
});

function encodeVarInt(value) {
    const bytes = [];
    do {
        let temp = value & 0x7f;
        value >>>= 7;
        if (value !== 0) {
            temp |= 0x80;
        }
        bytes.push(temp);
    } while (value !== 0);
    return Buffer.from(bytes);
}

function encodeString(text) {
    const stringBuffer = Buffer.from(text, 'utf8');
    const lengthBuffer = encodeVarInt(stringBuffer.length);
    return Buffer.concat([lengthBuffer, stringBuffer]);
}

// I also added code to track the buffer of the sent packet.
//  this.compressor.on('data', (buffer) => {
//          console.log(buffer)
//      })

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the custom_click_action packet serialization and compare the write() output with the manually constructed buffer shown in the issue. Check how the nbt field length is encoded, then verify that the emitted packet contains the expected 0x1a length and is accepted by the server.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript
Domain
networking
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
50/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.