I have been following the Colyseus Multiplayer Server tutorial and have run into a roadblock when creating a new room. Please see the image below which contains a screenshot of the error thrown from my PlayCanvas app and the logs from the Colyseus Arena server. It does seem as if things are working correctly on the Arena server-side, as both the ‘create’ and ‘join’ functions print their logs without errors. However, the asynchronous function call client.joinOrCreate
is throwing an error when the callback resolves. Namely, the error is
Uncaught Error: Invalid byte 81
at utf8Read (Protocol.ts:64:11)
at Room.onMessageCallback (Room.ts:167:33)
I have been trying to troubleshoot this issue, however I can’t even really tell if the issue is being generated in the external scripts provided by Arena, the PlayCanvas framework, the code I have written in both PlayCanvas and node.js, or some combination of all of the above. The utf8Read
seems to be under-the-hood in PlayCanvas, but Room.onMessage
is definitely a Colyseus function. Now if I do something like provide an incorrect room name, the try/catch statement executes and something like Network Controller Error: Name 'bad-name' not found in server
is printed to the console, but when I provide the correct name I get the Uncaught Error shown below. So the function call and try statement seem to generally work on both the client-side and server-side, but something is going wrong assigning the function return to the local variable? I’m not sure. Here is the code snippet from my app. I’ve changed it a few times and had the same result so I’ve reverted the code to use the async function suggested by the tutorial, and the Colyseus server code is the barebones npm init colyseus-app
with a couple added message handlers:
var NetworkController = pc.createScript('networkController');
NetworkController.attributes.add('interval', { type: 'number' });
NetworkController.prototype.initialize = function () {
this.session = {
client: null,
room: null,
roomName: 'my_room'
};
this.session.client = new Colyseus.Client('wss:ycixrc.colyseus.dev');
};
NetworkController.prototype.update = function (dt) {
let keys = this.app.keyboard;
if (keys.wasPressed(pc.KEY_1)) { this.sessionManager('join-or-create'); }
if (this.session.room) {
if (keys.wasPressed(pc.KEY_2)) { this.sessionManager('update-interval'); }
if (keys.wasPressed(pc.KEY_3)) { this.sessionManager('toggle-on'); }
if (keys.wasPressed(pc.KEY_4)) { this.sessionManager('toggle-off'); }
if (keys.wasPressed(pc.KEY_5)) { this.sessionManager('leave'); }
this.session.room.state.onChange = (changes) => {
console.log('=============================');
changes.forEach(change => {
console.log('-------------------------------');
console.log(change.field);
console.log(change.value);
console.log(change.previousValue);
console.log('-------------------------------');
});
};
}
};
NetworkController.prototype.sessionManager = async function (action) {
try {
switch (action) {
case 'join-or-create':
console.log('here before create');
this.session.room = await this.session.client.joinOrCreate(this.session.roomName);
console.log('here after create');
console.log(this.session.room);
break;
case 'update-interval':
console.log('here before update');
this.session.room.send('updateInterval', { newInterval: this.interval });
console.log('here after update');
break;
case 'toggle-on':
console.log('here before toggle on');
this.session.room.send('toggleRun', { run: true });
console.log('here after toggle on');
break;
case 'toggle-off':
console.log('here before toggle off');
this.session.room.send('toggleRun', { run: false });
console.log('here after toggle off');
break;
case 'leave':
console.log('here before leave');
this.session.room.leave();
console.log('here after leave');
break;
}
} catch (err) {
console.log(`Network Controller Error: ${err.message}`);
}
};