SchemaSerializer error

I'm trying to migrate an existing project to version 0.11 so I resolved to start from scratch because it was yielding an error but the error remains. Here's the code:

index.ts

import http from 'http';
import express from 'express';
import { Server } from 'colyseus';
import cors from 'cors';

import { StateHandlerRoom } from './rooms/room';

const port = Number(process.env.PORT || 2567);
const app = express();

app.use(cors());
app.use(express.json());

const server = http.createServer(app);
const gameServer = new Server({ server });

gameServer.define('room', StateHandlerRoom);

gameServer.listen(port);
console.log(`Listening on ws://localhost:${ port }`);

room.ts

import { Room, Client } from 'colyseus';
import { Schema, type, MapSchema } from '@colyseus/schema';

export class Player extends Schema {
    @type("number")
    x = Math.floor(Math.random() * 400);

    @type("number")
    y = Math.floor(Math.random() * 400);
}

export class State extends Schema {
    @type({ map: Player })
    players = new MapSchema<Player>();

    something = "This attribute won't be sent to the client-side";

    createPlayer (id: string) {
        this.players[ id ] = new Player();
    }

    removePlayer (id: string) {
        delete this.players[ id ];
    }

    movePlayer (id: string, movement: any) {
        if (movement.x) {
            this.players[ id ].x += movement.x * 10;

        } else if (movement.y) {
            this.players[ id ].y += movement.y * 10;
        }
    }
}

export class StateHandlerRoom extends Room<State> {
    maxClients = 4;

    onCreate (options) {
        console.log("StateHandlerRoom created!", options);

        this.setState(new State());
    }

    onJoin (client: Client) {
        this.state.createPlayer(client.sessionId);
    }

    onLeave (client) {
        this.state.removePlayer(client.sessionId);
    }

    onMessage (client, data) {
        console.log("StateHandlerRoom received message from", client.sessionId, ":", data);
        this.state.movePlayer(client.sessionId, data);
    }

    onDispose () {
        console.log("Dispose StateHandlerRoom");
    }

}

and in React I'm doing:

this.client = new Client("ws://localhost:2567");
this.room = this.client.joinOrCreate('room').then(room => {
    console.log('---> JOIN BATTLE: ', this.room);
}).catch(e => {
    console.log('---> JOIN BATTLE FAILED!!!: ', e);
});

can't seem to get past this error:

Error: SchemaSerializer error. See: https://docs.colyseus.io/migrating/0.10/#new-default-serializer
    at SchemaSerializer.reset (/SERVER/node_modules/colyseus/lib/serializer/SchemaSerializer.js:13:19)
    at StateHandlerRoom.setState (/SERVER/node_modules/colyseus/lib/Room.js:109:26)
    at StateHandlerRoom.onCreate (/SERVER/rooms/room.ts:42:14)
    at /SERVER/node_modules/colyseus/lib/MatchMaker.js:215:28

Hi @hlarcher, this error is most likely to happen when having a previous version of @colyseus/schema listed under your package-lock.json. Please remove your package-lock.json + node_modules, and run npm install again. It should get rid of this error. Cheers!

Great, that was exactly it!

However after migrating now every joinOrCreate creates a new room, I have this:

gameServer.define('room', BattleRoom);

and this:

onJoin(client: Client, options: any) {
    console.log('onJoin', Object.keys(this.state.teams).length);
    if (Object.keys(this.state.teams).length === 2) {
        this.lock();
    }
}

debug is always "onJoin 0".

it seems it is not a server side problem but rather a client one.

the server is implemented like this:

onJoin(client: Client, options: any) {
    if (Object.keys(this.state.teams).length === 2) {
        this.lock();
    } else {
        // add team
        this.state.addTeam(client.sessionId, options.team);

        // start if we have both teams
        if (this.state.teamCount === 2) {
            this.state.startBattle();

            // broadcast new team
            this.broadcast({
                type: 'STARTED',
                state: this.state,
            });
        }
    }
}

and the client is implemented like this:

this.room = this.client.joinOrCreate('battle', {team}).then(room => {
    room.onJoin(() => this.onRoomJoin(team));
    room.onStateChange((state) => this.onRoomStateChange(state));
    room.onMessage((message) => this.onRoomMessage(message));
    room.onError(() => this.onRoomError());
    room.onLeave(() => this.onRoomLeave());
}).catch(e => {
    console.log('---> JOIN BATTLE FAILED!!!: ', e);
});

onRoomMessage = message => {
        console.log('---> ON MESSAGE: ', this.client.id, this.room.name, message);
}

but the onRoomMessage method is never called

Hi @hlarcher,

Here's a modified version to work on v0.11:

// no assignment, as the return value is Promise
this.client.joinOrCreate('battle', {team}).then(room => {
    this.room = room; // here's the room instance!

    // on join has been successful already!
    this.onRoomJoin(team)
    // room.onJoin(() => this.onRoomJoin(team));

    room.onStateChange((state) => this.onRoomStateChange(state));
    room.onMessage((message) => this.onRoomMessage(message));
    room.onError(() => this.onRoomError());
    room.onLeave(() => this.onRoomLeave());
}).catch(e => {
    console.log('---> JOIN BATTLE FAILED!!!: ', e);
});

Awesome, thanks :)