Skip to content

custom_click_action packet - incorrect nbt buffer size? #1484

@MayorLeon20

Description

@MayorLeon20

[+] 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)
//      })

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions