Can anyone help with an error I'm getting when trying ot access my presences?

{I am getting an error when writing an entity to state.presences[presence.userId].
I have a suspicion that this is because of the UserId format. I tried assigning state.presences[“1”] and it worked, but when I tried to do state.presences[“abs”] instead it gave an error. That is, when assigning letters, it gives an error. What to do?}

  1. Versions: Nakama {3.7.0}, {Docker}, {Unity SDK 3.1.1}
  2. Server Framework Runtime language (If relevant) {TS/JS}
{"level":"debug","ts":"2021-10-05T15:51:00.351Z","caller":"server/tracker.go:842","msg":"Processing presence event","joins":0,"leaves":1}
nakama_1    | {"level":"info","ts":"2021-10-05T15:51:00.351Z","caller":"server/session_ws.go:458","msg":"Cleaned up closed connection session registry","uid":"06144aeb-b520-4fb5-bf70-0b9c9213c0b0","sid":"090b4d1e-25f4-11ec-b97e-688e25b5a5ca"}
nakama_1    | {"level":"info","ts":"2021-10-05T15:51:00.351Z","caller":"server/session_ws.go:475","msg":"Closed client connection","uid":"06144aeb-b520-4fb5-bf70-0b9c9213c0b0","sid":"090b4d1e-25f4-11ec-b97e-688e25b5a5ca"}
nakama_1    | {"level":"warn","ts":"2021-10-05T15:51:00.352Z","caller":"server/match_handler.go:462","msg":"Stopping match after error from match_join execution","mid":"b2ddb5af-edc3-4a45-a0f2-7e7017c3930c","tick":0,"error":"TypeError: Can't set property '06144aeb-b520-4fb5-bf70-0b9c9213c0b0' on Go slice at index.js:34:40(6)"}

code:

export const matchInit = (ctx: nkruntime.Context, logger: nkruntime.Logger, nk: nkruntime.Nakama, params: { [key: string]: string }): { state: nkruntime.MatchState, tickRate: number, label: string } => {
    logger.debug('Lobby match created');

    const presences: nkruntime.Presence[] = [];
    const state: nkruntime.MatchState = {presences};
    return {
        state,
        tickRate: 1,
        label: ''
    };
};

export const matchJoinAttempt = (ctx: nkruntime.Context, logger: nkruntime.Logger, nk: nkruntime.Nakama, dispatcher: nkruntime.MatchDispatcher, tick: number, state: nkruntime.MatchState, presence: nkruntime.Presence, metadata: { [key: string]: any }): { state: nkruntime.MatchState, accept: boolean, rejectMessage?: string | undefined } | null => {
    logger.debug('%q attempted to join Lobby match', ctx.userId);

    return {
        state,
        accept: true
    };
}

export const matchJoin = (ctx: nkruntime.Context, logger: nkruntime.Logger, nk: nkruntime.Nakama, dispatcher: nkruntime.MatchDispatcher, tick: number, state: nkruntime.MatchState, presences: nkruntime.Presence[]): { state: nkruntime.MatchState } | null => {
    logger.debug('%q joined Lobby match', ctx.userId);
    
    presences.forEach(presence => {
        state.presences[presence.userId] = presence;
    });

    return {
        state
    };
}

export const matchLeave = (ctx: nkruntime.Context, logger: nkruntime.Logger, nk: nkruntime.Nakama, dispatcher: nkruntime.MatchDispatcher, tick: number, state: nkruntime.MatchState, presences: nkruntime.Presence[]): { state: nkruntime.MatchState } | null => {
    logger.debug('%q left Lobby match', ctx.userId);

    presences.forEach(presence => {
        delete (state.presences[presence.userId]);
    });

    return {
        state
    };
}

export const matchLoop = (ctx: nkruntime.Context, logger: nkruntime.Logger, nk: nkruntime.Nakama, dispatcher: nkruntime.MatchDispatcher, tick: number, state: nkruntime.MatchState, messages: nkruntime.MatchMessage[]): { state: nkruntime.MatchState } | null => {
    logger.debug('Lobby match loop executed');

    Object.keys(state.presences).forEach(key => {
        const presence = state.presences[key];
        logger.info('Presence %v name $v', presence.userId, presence.username);
    });

    messages.forEach(message => {
        logger.info('Received %v from %v', message.data, message.sender.userId);
        dispatcher.broadcastMessage(1, message.data, [message.sender], null);
    });

    return {
        state
    };
}

export const matchTerminate = (ctx: nkruntime.Context, logger: nkruntime.Logger, nk: nkruntime.Nakama, dispatcher: nkruntime.MatchDispatcher, tick: number, state: nkruntime.MatchState, graceSeconds: number): { state: nkruntime.MatchState } | null => {
    logger.debug('Lobby match terminated');

    const message = `Server shutting down in ${graceSeconds} seconds.`;
    dispatcher.broadcastMessage(2, message, null, null);

    return {
        state
    };
}

:tv: Media:

Hi @BlueXT, welcome to the forum.

It looks like you’re trying to index the presences variable as though it were an object, however it is an array and should therefore only be indexed using integers.

If you wish to map your presence objects to their associated User Id you could use an any type object as shown below:

const presences : any = {};

Alternatively, you could define an interface so that you can guarantee your object only ever contains nkruntime.Presence objects indexed by a string:

interface PresenceMap {
    [index: string]: nkruntime.Presence;
}

const presences : PresenceMap = {};

For a more thorough example please see the sample code in the Nakama project template repository, specifically: nakama-project-template/match_handler.ts at master · heroiclabs/nakama-project-template · GitHub

Hope this helps.