Can't move babylon.js

Hi!

I've been experimenting with the babylon.js boilerplate (thanks @endel for the update!)

I'm trying to have the playing move locally, send their position to the server, which sends it out to the other clients. But for some reason, I can't move with the current code. wasd to move and mouse locks to look. you control the free camera.

It comes down to this error:
0_1559938997019_error.PNG

Here is my code:
index.ts:

import "./index.css";

import * as BABYLON from "babylonjs";
import Keycode from "keycode.js";

import { client } from "./game/network";

// Re-using server-side types for networking
// This is optional, but highly recommended
import { StateHandler } from "../../server/src/rooms/StateHandler";
import { PressedKeys } from "../../server/src/entities/Player";
import { CamPos } from "../../server/src/entities/Player";

const canvas = document.getElementById('game') as HTMLCanvasElement;
const engine = new BABYLON.Engine(canvas, true);

// This creates a basic Babylon Scene object (non-mesh)
var scene = new BABYLON.Scene(engine);



// This creates and positions a free camera (non-mesh)
var camera = new BABYLON.FreeCamera("camera1", new BABYLON.Vector3(0, 5, -10), scene);
camera.keysUp = [87];
camera.keysDown = [83];
camera.keysLeft = [65];
camera.keysRight = [68];

// This targets the camera to scene origin
camera.setTarget(BABYLON.Vector3.Zero());

// This attaches the camera to the canvas
camera.attachControl(canvas, true);

// This creates a light, aiming 0,1,0 - to the sky (non-mesh)
var light = new BABYLON.HemisphericLight("light1", new BABYLON.Vector3(0, 1, 0), scene);

// Default intensity is 1. Let's dim the light a small amount
light.intensity = 0.7;

// Our built-in 'ground' shape. Params: name, width, depth, subdivs, scene
var ground = BABYLON.Mesh.CreateGround("ground1", 6, 6, 2, scene);

// Attach default camera mouse navigation
// camera.attachControl(canvas);

// Colyseus / Join Room
const room = client.join<StateHandler>("game");
room.onJoin.add(() => {
    const playerViews: {[id: string]: BABYLON.Mesh} = {};

    room.state.players.onAdd = function(player, key) {
		if (key != room.sessionId) {
            playerViews[key] = BABYLON.Mesh.CreateSphere("sphere1", 16, 2, scene);
			playerViews[key].position.set(player.position.x, player.position.y, player.position.z);
        }
    };

    room.state.players.onChange = function(player, key) {
		if (key != room.sessionId) {
        playerViews[key].position.set(player.position.x, player.position.y, player.position.z);
		}
    };

    room.state.players.onRemove = function(player, key) {
		if (key != room.sessionId) {
        scene.removeMesh(playerViews[key]);
        delete playerViews[key];
		}
    };
	
	

})

room.onStateChange.add((state) => {
    console.log("New room state:", state.toJSON());
})


const camposition: CamPos = { x: 0, y: 1, z:0 };
scene.registerAfterRender(function() {
	camposition.x = camera.position.x;
	camposition.y = camera.position.y;
	camposition.z = camera.position.z;
	room.send(['pos', camposition]);
});

// Scene render loop
engine.runRenderLoop(function() {
    scene.render();
});

// Keyboard listeners
const keyboard: PressedKeys = { x: 0, y: 0 };
window.addEventListener("keydown", function(e) {
    if (e.which === Keycode.LEFT) {
        keyboard.x = -1;
    } else if (e.which === Keycode.RIGHT) {
        keyboard.x = 1;
    } else if (e.which === Keycode.UP) {
        keyboard.y = -1;
    } else if (e.which === Keycode.DOWN) {
        keyboard.y = 1;
    }
    //room.send(['key', keyboard]);
});

window.addEventListener("keyup", function(e) {
    if (e.which === Keycode.LEFT) {
        keyboard.x = 0;
    } else if (e.which === Keycode.RIGHT) {
        keyboard.x = 0;
    } else if (e.which === Keycode.UP) {
        keyboard.y = 0;
    } else if (e.which === Keycode.DOWN) {
        keyboard.y = 0;
    }
    //room.send(['key', keyboard]);
});

// Resize the engine on window resize
window.addEventListener('resize', function() {
    engine.resize();
});

gameroom.ts

import { Room, Client } from "colyseus";

import { StateHandler } from "./StateHandler";
import { Player } from "../entities/Player";

export class GameRoom extends Room<StateHandler> {
    maxClients = 8;

    onInit (options) {
        this.setSimulationInterval(() => this.onUpdate());
        this.setState(new StateHandler());
    }

    requestJoin (options) {
        return true;
    }

    onJoin (client) {
        const player = new Player();
        player.name = `Player ${ this.clients.length }`;

        this.state.players[client.sessionId] = player;
    }

    onMessage (client: Client, message: any) {
        const [event, data] = message;
        const player: Player = this.state.players[client.sessionId];

        if (event === "pos") {
            player.camPos = data;
        }
    }

    onUpdate () {
        for (const sessionId in this.state.players) {
            const player: Player = this.state.players[sessionId];
            player.position.x = player.camPos.x;
			player.position.y = player.camPos.y;
            player.position.z = player.camPos.z;
			console.log(player.camPos.x + " " + player.camPos.y + " " + player.camPos.z);
        }
    }

    onLeave (client: Client) {
        delete this.state.players[client.sessionId];
    }

    onDispose () {
    }

}

player.ts

import { Schema, type } from "@colyseus/schema";

export interface PressedKeys {
    x: number;
    y: number;
}

export interface CamPos {
    x: number;
    y: number;
	z: number;
}

export class Position extends Schema {
    @type("number") x: number = 0;
    @type("number") y: number = 0;
    @type("number") z: number = 0;
}

export class Player extends Schema {
    @type("string") name: string;
    @type(Position) position = new Position();

    pressedKeys: PressedKeys = { x: 0, y: 0 };
	camPos: CamPos = { x: 0, y: 1, z: 0 };

    constructor () {
        super();
    }
}

thanks for any help, Givo.

Or, if it helps, here is a zip file of the whole project: https://drive.google.com/file/d/1pKI-eLp6JQhMwCfH6Qb1XWlnK-2EsKbU/view?usp=sharing

I was able to fix it! Babylon.js was loading a lot faster than colyseus, so using the scene.registerAfterRender(function() {} was calling room.send before the client had even connected. I now use the pointer lock canvas.click function to start the position updates!

demo at https://boilerplate-fps-works.herokuapp.com/

WASD moving, mouse look