Cannot send Uint8Array to Client

Hi,

I am using the server to send messages to client. Specifically i am using the this.matchDispatcher.broadcastMessage

        /**
         * Broadcast a message to match presences.
         *
         * @param opcode - Numeric message op code.
         * @param data - Opt. Data payload string, or null.
         * @param presences - Opt. List of presences (a subset of match participants) to use as message targets, or null to send to the whole match. Defaults to null.
         * @param sender - Opt. A presence to tag on the message as the 'sender', or null.
         * @param reliable - Opt. Broadcast the message with delivery guarantees or not. Defaults to true.
         * @throws {TypeError, GoError}
         */
        broadcastMessage(opcode: number, data?: Uint8Array | string | null, presences?: Presence[] | null, sender?: Presence | null, reliable?: boolean): void;

However when i use this where data is a UInt8Array i get this error:

{"level":"error","ts":"2022-07-14T18:38:23.452Z","caller":"server/runtime_javascript_logger.go:94","msg":"Error%!(EXTRA string=TypeError\n\tat github.com/heroiclabs/nakama/v3/server.(*RuntimeJavaScriptMatchCore).broadcastMessage.func1 (native)\n\tat index.js:7791:76(61)\n\tat github.com/dop251/goja.(*Runtime).boundCallable.func1 (native)\n\tat index.js:8550:45(62)\n\tat github.com/dop251/goja.(*Runtime).boundCallable.func1 (native)\n\tat matchLoop (index.js:8792:63(32))\n\tat native\n)","mid":"506c5ae9-9b7f-49d3-a0a3-87926b5e77a8"}

Here is the transpiled JS code it is erroring on:

Here is the TS code:

It works if i use strings like this:

Is it not possible to send bytes through the socket directly?

Hi JayArrow

It seems to be a problem on the Typescript runtime binding to the underlying Go code that we need to investigate and improve. Meanwhile, you will have to convert the data to string as you said.

Thank you for pointing it out.

@JayArrowz what version of the server are you using?

Hi @flavio @sesposito thanks for the quick responses.

My server version is as follows:

FROM registry.heroiclabs.com/heroiclabs/nakama:3.12.0

My Nakama Runtime Dep:

    "nakama-runtime": "git+https://github.com/heroiclabs/nakama-common.git",

Rollup config incase you need it:

import resolve, { nodeResolve } from '@rollup/plugin-node-resolve';
import commonJS from '@rollup/plugin-commonjs';
import json from '@rollup/plugin-json';
import babel from '@rollup/plugin-babel';
import typescript from '@rollup/plugin-typescript';
import pkg from './package.json';
import multiInput from 'rollup-plugin-multi-input';
import nodePolyfills from 'rollup-plugin-node-polyfills';

const extensions = ['.mjs', '.js', '.ts', '.json'];

export default {
    input: "./src/index.ts",
    external: ['nakama-runtime'],
    plugins: [
        // Allows node_modules resolution
        
       // nodeResolve(),
        nodePolyfills(),
        resolve({ extensions }),
        // Compile TypeScript
        typescript({
            noImplicitReturns: true,
            moduleResolution: "node",
            experimentalDecorators: true,
            esModuleInterop: true,
            noUnusedLocals: false,
            noUnusedParameters: false,
            removeComments: true,
            target: "es5",
            module: "ESNext",
            strict: false,
            downlevelIteration: true
        }),

        json(),

        // Resolve CommonJS modules
        commonJS({ extensions }),
        
    ],
    output: {
        dir: 'build',
    },
}

For now i will convert it to a string, but ideally when this is fixed we can remove this conversion. Thanks :slight_smile:

The downside to also doing text decoding is atleast four times the bytes are sent over the wire. This is not ideal :.

The TextDecoder i am using is this one:
text-encoding-polyfill - npm (npmjs.com)
I have tried both ascii and utf8 options.

What server side sends:

Opcode 81 buffer normal size is 4

game-server-nakama-1    | {"level":"info","ts":"2022-07-16T15:18:19.842Z","caller":"server/runtime_javascript_logger.go:74","msg":"Sending Var Message opcode: 81 size: 4","mid":"67f029da-d50d-458b-8e28-685e1c1d0f05"}

When buffer is text decoded and sent the size becomes 6:

game-server-nakama-1    | {"level":"info","ts":"2022-07-16T15:18:19.843Z","caller":"server/runtime_javascript_logger.go:74","msg":"\u0000\u0000È‘\u0000\u0000 variable buffer LEN %!s(int64=6)","mid":"67f029da-d50d-458b-8e28-685e1c1d0f05"}```

Server sends Opcode 64 originally 2 bytes:

game-server-nakama-1    | {"level":"info","ts":"2022-07-16T15:14:48.222Z","caller":"server/runtime_javascript_logger.go:74","msg":"Sending Var Message opcode: 64 size: 2","mid":"56393fdf-7632-4ff6-b929-689bd66f8de1"}   

buffer decoded Opcode 64 becomes 16 bytes:

game-server-nakama-1    | {"level":"info","ts":"2022-07-16T15:14:48.222Z","caller":"server/runtime_javascript_logger.go:74","msg":"ÎN\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000 fixed buffer LEN %!s(int64=16)","mid":"56393fdf-7632-4ff6-b929-689bd66f8de1"}

Client gets back (mismatch something is happening on the golang side of things to cause this?):

Opcode: 64
Data: [195,142,78,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
Opcode: 81
Data: [0,0,195,136,226,128,152,0,0]

String.fromCharCode seems to produce the same results of the bytes inflating in size

Edit:
Have figured this out, hex encoding works best

@JayArrowz we’ve updated the TypeScript definitions, could you please try to send your data in the broadcastMessage function as an ArrayBuffer instead and let us know how that goes?

1 Like

Can confirm this has been fixed and accepting array buffer now, thank you :smiley:

1 Like