Nakama weird match state gotcha's

Hi All,

Just here to inform something weird happening with states…

Now i start a match like this in TS:

createWorld: (worldId: number, nk: nkruntime.Nakama) => {
        return nk.matchCreate("worlds", {
            worldId
        });
    }

initializer.registerMatch<WorldState>('worlds', {
        matchInit,
        matchJoinAttempt,
        matchJoin,
        matchLeave,
        matchLoop,
        matchTerminate,
        matchSignal
    });
    WorldService.createWorld(1, nk);

For the match state i have:

import * as Collections from 'typescript-collections';

export interface WorldState extends nkruntime.MatchState {
    encodes?: Collections.Dictionary<RegionCoordinates, Collections.Set<RegionUpdateMessage>>;    
    worldId: number
}

Now for my matchInit function i have this:

const matchInit = function (ctx: nkruntime.Context, logger: nkruntime.Logger, nk: nkruntime.Nakama, params: { [key: string]: string }): { state: WorldState, tickRate: number, label: string } {
      return {
        state: {
             encodes: new Collections.Dictionary<RegionCoordinates, Collections.Set<RegionUpdateMessage>>();
        },
        tickRate: SERVER_CONSTANTS.gameTicksPerSecond,
        label: 'World ' + params.worldId
     }
}

Now you expect state.encodes to be a Dictionary object inside the match loop… but no, it seems to be not. The object has lost its type and you cannot call size anymore.

const matchLoop = function (ctx: nkruntime.Context, logger: nkruntime.Logger, nk: nkruntime.Nakama, dispatcher: nkruntime.MatchDispatcher, tick: number, state: WorldState, messages: nkruntime.MatchMessage[]): { state: WorldState } | null {
     state.encodes.size();

}

For some reason it works if i make a wrapper class for the dictionary and use the wrapper encodeRepository inside the state then use state.encodeRepository.getEncodes() inside my match loop:

import * as Collections from 'typescript-collections';
import { RegionUpdateMessage } from '../messages/RegionUpdateMessage';
import { RegionCoordinates } from '../region/RegionCoordinates';

export class EncodeRepository {
    private readonly encodes: Collections.Dictionary<RegionCoordinates, Collections.Set<RegionUpdateMessage>>;

    constructor() {
        this.encodes = new Collections.Dictionary<RegionCoordinates, Collections.Set<RegionUpdateMessage>>(e => e.hash());
    }

    getEncodes = function(): Collections.Dictionary<RegionCoordinates, Collections.Set<RegionUpdateMessage>> {
        return this.encodes;
    }.bind(this);
}

Is there anything i am doing wrong or is this just a issue with mapping in the core code?

Hello,

To clarify, are you getting a runtime error in matchLoop with the

(...)
 state: {
             encodes: new Collections.Dictionary<RegionCoordinates, Collections.Set<RegionUpdateMessage>>();
        },
(...)

initialization?

The initialization works fine. My matchInit method has no errors and creates the dictionary perfectly.
However yes, get the error inside the matchLoop when trying to call any of the functions for state.encodes .e.g. state.encodes.size() it will not be able to find the function.

If i wrap the Dictionary inside a class it works. i can access state.myClass.getEncodes().size()

I think this is similar if not the exact same issue as this: