Skip to content

Commit

Permalink
Merge branch '0.9.0'
Browse files Browse the repository at this point in the history
Conflicts:
	package.json
  • Loading branch information
endel committed Mar 30, 2018
2 parents f5d8a91 + b2be3ff commit 51c577e
Show file tree
Hide file tree
Showing 16 changed files with 415 additions and 257 deletions.
1 change: 1 addition & 0 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
/test
/dist
src
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ room.listen("entities/:id/:attribute", (change) => {
Room state has been updated:

```ts
room.onUpdate.add(function(state) {
room.onStateChange.add(function(state) {
console.log(room.name, "has new state:", state)
})
```
Expand Down
2 changes: 1 addition & 1 deletion dist/colyseus.js

Large diffs are not rendered by default.

37 changes: 33 additions & 4 deletions dist/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@

<div id="messages"></div>

<button onclick="join()">Join</button>
<button onclick="create()">Create</button>
<button onclick="joinByLastId()">Join by last id</button>
<button onclick="getAvailableRooms()">List avaiable rooms</button>

<script>
var host = window.document.location.host.replace(/:.*/, '');
var client = new Colyseus.Client('ws://' + host + ':8080');
Expand Down Expand Up @@ -43,7 +48,9 @@
client.onOpen.add(function() {
console.log("onOpen")

room = client.join('chat');
});

function addListeners (room) {
room.onJoin.add(function() {
console.log(room.id);
console.log('joined!');
Expand All @@ -53,10 +60,32 @@
console.log("LEFT ROOM", arguments);
});

room.onUpdate.add(function(data) {
console.log("chat update: ", data)
room.onStateChange.add(function(state) {
console.log("chat update: ", state)
});
});
}

function join () {
room = client.join('chat');
addListeners(room);
}

function create () {
room = client.join('chat', { create: true });
addListeners(room);
}

function joinByLastId () {
room = client.join(room.id);
addListeners(room);
}

function getAvailableRooms() {
client.getAvailableRooms('chat', function(rooms, err) {
console.log(rooms);
});
}


document.getElementById('form').onsubmit = function(e) {
e.preventDefault()
Expand Down
13 changes: 7 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "colyseus.js",
"version": "0.8.4",
"version": "0.9.0",
"description": "Multiplayer Game Client for the Browser",
"keywords": [
"multiplayer",
Expand All @@ -16,11 +16,11 @@
"typings": "lib/index.d.ts",
"scripts": {
"start": "npm run build && node --harmony ./examples/server.js",
"build-dist": "webpack --env.production",
"build": "tsc && npm run build-dist",
"watch": "tsc -w",
"prepublish": "npm run build",
"test": "mocha test/*.ts --require ts-node/register",
"build": "webpack --env.production",
"watch": "tsc -w",
"prepublish": "tsc && npm run build",
"tslint": "tslint --project .",
"postinstall": "npm run -s donate",
"donate": "echo \"\u001b[35m\u001b[1mLove Colyseus? Support its development by becoming a backer:\u001b[22m\u001b[39m\n > \u001b[34mhttps://www.patreon.com/endel\u001b[39m\""
},
Expand All @@ -30,7 +30,7 @@
"dependencies": {
"@gamestdio/clock": "^1.1.0",
"@gamestdio/websocket": "^0.2.3",
"delta-listener": "^2.1.2",
"@gamestdio/state-listener": "^3.0.0",
"fossil-delta": "^1.0.0",
"notepack.io": "^2.1.2",
"signals.js": "^1.0.0"
Expand All @@ -48,6 +48,7 @@
"nodemon": "^1.7.1",
"ts-loader": "^2.3.7",
"ts-node": "^3.3.0",
"tslint": "^5.9.1",
"typescript": "^2.5.3",
"uglify-js": "^2.6.1",
"watchify": "^3.6.1",
Expand Down
127 changes: 87 additions & 40 deletions src/Client.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import * as msgpack from "notepack.io";
import { Signal } from "signals.js";
import * as msgpack from 'notepack.io';
import { Signal } from 'signals.js';

import { Protocol } from "./Protocol";
import { Room } from "./Room";
import { Connection } from "./Connection";
import { Connection } from './Connection';
import { Protocol } from './Protocol';
import { Room, RoomAvailable } from './Room';

export class Client {
public id?: string;
Expand All @@ -18,32 +18,75 @@ export class Client {

protected rooms: {[id: string]: Room} = {};
protected connectingRooms: {[id: string]: Room} = {};
protected joinRequestId = 0;
protected requestId = 0;

protected hostname: string;
protected storage: Storage = window.localStorage;

constructor (url: string) {
protected roomsAvailableRequests: {[requestId: number]: (value?: RoomAvailable[]) => void} = {};

constructor(url: string) {
this.hostname = url;
let colyseusid: any = this.storage.getItem('colyseusid');
const colyseusid: any = this.storage.getItem('colyseusid');

if (
typeof(Promise) === "undefined" || // old browsers
typeof(Promise) === 'undefined' || // old browsers
!(colyseusid instanceof Promise)
) {
// browser has synchronous return
this.createConnection(colyseusid);
this.connect(colyseusid);

} else {
// react-native is asynchronous
colyseusid.then(id => this.createConnection(id));
colyseusid.then((id) => this.connect(id));
}
}

protected createConnection (colyseusid: string) {
this.id = colyseusid || "";
public join<T>(roomName: string, options: any = {}): Room<T> {
options.requestId = ++this.requestId;

const room = new Room<T>(roomName, options);

// remove references on leaving
room.onLeave.addOnce(() => {
delete this.rooms[room.id];
delete this.connectingRooms[options.requestId];
});

this.connectingRooms[ options.requestId ] = room;

this.connection.send([Protocol.JOIN_ROOM, roomName, options]);

return room;
}

public getAvailableRooms(roomName: string, callback: (rooms: RoomAvailable[], err?: string) => void) {
// reject this promise after 10 seconds.
const requestId = ++this.requestId;
const removeRequest = () => delete this.roomsAvailableRequests[requestId];
const rejectionTimeout = setTimeout(() => {
removeRequest();
callback([], "timeout");
}, 10000);

// send the request to the server.
this.connection.send([Protocol.ROOM_LIST, requestId, roomName]);

this.roomsAvailableRequests[requestId] = (roomsAvailable) => {
removeRequest();
clearTimeout(rejectionTimeout);
callback(roomsAvailable);
};
}

public close () {
this.connection.close();
}

this.connection = new Connection(`${ this.hostname }/?colyseusid=${ this.id }`);
protected connect(colyseusid: string) {
this.id = colyseusid || '';

this.connection = this.createConnection();
this.connection.onmessage = this.onMessageCallback.bind(this);
this.connection.onclose = (e) => this.onClose.dispatch();
this.connection.onerror = (e) => this.onError.dispatch();
Expand All @@ -53,62 +96,66 @@ export class Client {
if (this.id) {
this.onOpen.dispatch();
}
}
};
}

join<T> (roomName: string, options: any = {}): Room<T> {
options.requestId = ++this.joinRequestId;

const room = new Room<T>(roomName);

// remove references on leaving
room.onLeave.addOnce(() => {
delete this.rooms[room.id];
delete this.connectingRooms[options.requestId];
});

this.connectingRooms[ options.requestId ] = room;
protected createConnection(path: string = '', options: any = {}) {
// append colyseusid to connection string.
const params = [`colyseusid=${this.id}`];

this.connection.send([Protocol.JOIN_ROOM, roomName, options]);
for (const name in options) {
if (!options.hasOwnProperty(name)) {
continue;
}
params.push(`${name}=${options[name]}`);
}

return room;
return new Connection(`${this.hostname}/${path}?${params.join('&')}`);
}

/**
* @override
*/
protected onMessageCallback (event) {
let message = msgpack.decode( new Uint8Array(event.data) );
let code = message[0];
protected onMessageCallback(event) {
const message = msgpack.decode( new Uint8Array(event.data) );
const code = message[0];

if (code == Protocol.USER_ID) {
if (code === Protocol.USER_ID) {
this.storage.setItem('colyseusid', message[1]);

this.id = message[1];
this.onOpen.dispatch();

} else if (code == Protocol.JOIN_ROOM) {
let requestId = message[2];
let room = this.connectingRooms[ requestId ];
} else if (code === Protocol.JOIN_ROOM) {
const requestId = message[2];
const room = this.connectingRooms[ requestId ];

if (!room) {
console.warn("colyseus.js: client left room before receiving session id.");
console.warn('colyseus.js: client left room before receiving session id.');
return;
}

this.rooms[room.id] = room;

room.id = message[1];
room.connect(new Connection(`${ this.hostname }/${ room.id }?colyseusid=${ this.id }`));
room.connect(this.createConnection(room.id, room.options));

delete this.connectingRooms[ requestId ];

} else if (code == Protocol.JOIN_ERROR) {
console.error("colyseus.js: server error:", message[2]);
} else if (code === Protocol.JOIN_ERROR) {
console.error('colyseus.js: server error:', message[2]);

// general error
this.onError.dispatch(message[2]);

} else if (code === Protocol.ROOM_LIST) {
if (this.roomsAvailableRequests[message[1]]) {
this.roomsAvailableRequests[message[1]](message[2]);

} else {
console.warn('receiving ROOM_LIST after timeout:', message[2]);
}

} else {
this.onMessage.dispatch(message);
}
Expand Down
23 changes: 11 additions & 12 deletions src/Connection.ts
Original file line number Diff line number Diff line change
@@ -1,37 +1,36 @@
import WebSocketClient from "@gamestdio/websocket";
import * as msgpack from "notepack.io";
import WebSocketClient from '@gamestdio/websocket';
import * as msgpack from 'notepack.io';

export class Connection extends WebSocketClient {

private _enqueuedCalls: any[] = [];

constructor (url, query: any = {}) {
constructor(url, query: any = {}) {
super(url);

this.binaryType = "arraybuffer";
this.binaryType = 'arraybuffer';
}

onOpenCallback (event) {
public onOpenCallback(event) {
super.onOpenCallback();

if (this._enqueuedCalls.length > 0) {
for (let i=0; i<this._enqueuedCalls.length; i++) {
let [ method, args ] = this._enqueuedCalls[i];
this[ method ].apply(this, args);
for (const [method, args] of this._enqueuedCalls) {
this[method].apply(this, args);
}
}
}

send (data: any): void {
if (this.ws.readyState == WebSocket.OPEN) {
return super.send( msgpack.encode(data) )
public send(data: any): void {
if (this.ws.readyState === WebSocket.OPEN) {
return super.send( msgpack.encode(data) );

} else {
console.warn(`colyseus.js: trying to send data while in ${ this.ws.readyState } state`);

// WebSocket not connected.
// Enqueue data to be sent when readyState == OPEN
this._enqueuedCalls.push(['send', [data]])
this._enqueuedCalls.push(['send', [data]]);
}
}

Expand Down
3 changes: 3 additions & 0 deletions src/Protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ export enum Protocol {
ROOM_STATE = 14,
ROOM_STATE_PATCH = 15,

// Match-making related (20~29)
ROOM_LIST = 20,

// Generic messages (50~60)
BAD_REQUEST = 50,

Expand Down
Loading

0 comments on commit 51c577e

Please sign in to comment.