Nakama-js-protobuf WebSocket adapter not working

When I receive broadcasted messages from Nakama to the JavaScript Client SDK, I get this which is a protobuf:

{
  match_id: '5160bac8-bd5d-4319-a9e9-4075bd5f1ecc.nakama',
  op_code: 1,
  data: Uint8Array(1239) [
    123, 34, 110, 101, 120, 116,  71,  97, 109, 101,  82, 101,
    109, 97, 105, 110, 105, 110, 103,  84, 105,  99, 107, 115,
     34, 58,  48,  44,  34, 100, 101,  99, 107, 115,  34,  58,
    123, 34, 115, 112, 101, 101, 100,  34,  58,  91,  49,  49,
     44, 51,  44,  50,  44,  54,  44,  55,  44,  52,  44,  57,
     44, 49,  50,  44,  49,  51,  44,  53,  44,  49,  52,  93,
     44, 34,  97, 116, 116,  97,  99, 107,  34,  58,  91,  51,
     44, 49,  51,  44,  56,  44,  52,  44,  49,  52,  44,  49,
     50, 44,  57,  44,
    ... 1139 more items
  ],
  reliable: true
}

I want to make the data into a JavaScript Object, so I thought maybe I could use the nakama-js-protobuf package but the instructions on that README: nakama-js/packages/nakama-js-protobuf at master · heroiclabs/nakama-js · GitHub don’t work:

import { WebSocketAdapterPb } from "@heroiclabs/nakama-js-protobuf"
...

const socket = client.createSocket(false, false, new WebSocketAdapterPb())

I get the following typescript error:

Argument of type 'WebSocketAdapterPb' is not assignable to parameter of type 'WebSocketAdapter'.  Property 'isOpen' is missing in type 'WebSocketAdapterPb' but required in type 'WebSocketAdapter'. typescript (2345) [36, 44]

If I try to run it anyway, it tells me isOpen() is missing from WebSocketAdapterPb:

test-client.ts:36:44 - error TS2345: Argument of type 'WebSocketAdapterPb' is not assignable to parameter of type 'WebSocketAdapter'.
  Property 'isOpen' is missing in type 'WebSocketAdapterPb' but required in type 'WebSocketAdapter'.

36         s1 = c1.createSocket(false, false, new WebSocketAdapterPb())
                                              ~~~~~~~~~~~~~~~~~~~~~~~~

  node_modules/.pnpm/@heroiclabs+nakama-js@2.6.1/node_modules/@heroiclabs/nakama-js/dist/web_socket_adapter.d.ts:36:5
    36     isOpen(): boolean;
           ~~~~~~~~~~~~~~~~~~
    'isOpen' is declared here.

I’m wondering if I am doing this correctly? At the moment this I use TextDecoder to deserialize:

const data = JSON.parse(new TextDecoder().decode(result.data))

This works but I don’t think this is the intended way to do this, could someone help thank you!

  1. Versions: Nakama 3.15.0 Docker, nakama-js 2.6.1, nakama-js-protobuf 1.2.1
  2. Server Framework Runtime language: TS

I noticed that the published package to npm for nakama-js-protobuf is 1.2.1 is an outdated one where isConnected is defined instead of isOpen where as the github version is 1.3.0 - so i tried installing 1.3.0 manually:

dependencies

"@heroiclabs/nakama-js-protobuf": "https://gitpkg.now.sh/heroiclabs/nakama-js/packages/nakama-js-protobuf?master"

But I still get the same error - isOpen doesn’t seem to be there when I instantiate new WebSocketAdapterPb()

Edit: I stopped getting the error, but it seems that my data still shows up like this:

{
  match_id: 'f1ab3f05-352a-45bf-a669-fe9581880155.nakama',
  op_code: 1,
  reliable: true,
  data: Uint8Array(1235) [
    123,  34, 108,  97,  98, 101, 108,  34,  58, 123,  34, 111,
    112, 101, 110,  34,  58, 102,  97, 108, 115, 101, 125,  44,
     34, 112, 108,  97, 121, 105, 110, 103,  34,  58, 116, 114,
    117, 101,  44,  34, 100,  97, 109,  97, 103, 101,  34,  58,
    123,  34,  51, 100,  49,  53,  51,  52,  50,  98,  45,  49,
     51, 102, 100,  45,  52,  53,  56,  98,  45,  97, 101,  50,
     57,  45,  98,  52, 101,  54,  97,  99,  52, 100,  99,  56,
     51, 100,  34,  58,  48,  44,  34,  52,  56,  55,  98,  48,
     55,  57,  99,  45,
    ... 1135 more items
  ]
}

which is the same as if it were the text websocket adapter

Hey @dragonlobster – the data you receive will be a Uint8Array regardless of whether you use the text or protobuf adapter. If you are using the text adapter you can decode it with the TextDecoder class.

If you send a string as match data using the protobuf adapter, you’ll also have to parse it with the TextDecoder class, but it sounds like you just want to use the text adapter anyway.

We’ll release the latest protobuf adapter to fix that isOpen error.

Thank you @lugehorsam based on the source code I understand the difference between the two websocket adapters is using js-base64 vs TextEncoder which is fine.

I just have one more question - if I am using TypeScript on server side how should I decode the data from either when sending match state? I think because the server side is not actually a Node runtime it won’t have access to TextDecoder class, or js-base64 class to run atob or am I wrong on that - thank you.

Hey @dragonlobster the server will automatically handle the base64 encoding/decoding for your match handler.

@lugehorsam however on server side i am getting an ArrayBuffer (whether I’m using WebSocketAdapterText or WebSocketAdapterPB), for example if i try:

logger.info(`${message.data}`)

I get

{..."msg":"[object ArrayBuffer]"}

how to deserialize this into javascript object? do i need to polyfill TextDecoder - thank you.

Edit: I solved it with this:

const data = String.fromCharCode.apply(null, new Uint8Array(message.data))
const dataObj = JSON.parse(data)

but not sure if this is the right way to do it

Hello @dragonlobster

This is how we advise to deserialize into a JS object, using the binaryToString utility function exposed in the Nakama module:

JSON.parse(nk.binaryToString(message.data));

Hope this helps.

1 Like

@sesposito thank you sir, works perfectly