UNPKG

colyseus

Version:

Multiplayer Game Server for Node.js.

125 lines (95 loc) 3.68 kB
import { merge, spliceOne } from "./Utils"; import { Room } from "./Room"; import { Client } from "./index"; export class MatchMaker { private handlers: {[id: string]: any[]} = {}; private availableRooms: {[name: string]: Room<any>[]} = {}; private roomsById: {[name: number]: Room<any>} = {}; private roomCount: number = 0; public addHandler (name: string, handler: Function, options: any = {}): void { this.handlers[ name ] = [handler, options]; this.availableRooms[ name ] = []; } public hasHandler (roomName: string): boolean { return this.handlers[ roomName ] !== undefined; } public hasAvailableRoom (roomName: string): boolean { return (this.availableRooms[ roomName ] && this.availableRooms[ roomName ].length > 0) } public getRoomById (roomId: number): Room<any> { return this.roomsById[ roomId ]; } public joinById (client: Client, roomId: number, clientOptions: any): Room<any> { let room = this.roomsById[ roomId ]; if (!room) { console.error(`Error: trying to join non-existant room "${ roomId }"`); } else if (!room.requestJoin(clientOptions)) { console.error(`Error can't join "${ clientOptions.roomName }" with options: ${ JSON.stringify(clientOptions) }`); room = undefined; } return room; } public joinOrCreateByName (client: Client, roomName: string, clientOptions: any): Room<any> { if (!this.hasHandler(roomName)) { console.error(`Error: no available handler for "${ roomName }"`); } else { return this.requestJoin( client, roomName, clientOptions ) || this.create( client, roomName, clientOptions ); } } public requestJoin (client: Client, roomName: string, clientOptions: any): Room<any> { let room: Room<any>; if ( this.hasAvailableRoom( roomName ) ) { for ( var i=0; i < this.availableRooms[ roomName ].length; i++ ) { let availableRoom = this.availableRooms[ roomName ][ i ]; if ( availableRoom.requestJoin(clientOptions) ) { room = availableRoom; break; } } } return room; } public create (client: Client, roomName: string, clientOptions: any): Room<any> { let room = null , handler = this.handlers[ roomName ][0] , options = this.handlers[ roomName ][1]; // TODO: // keep track of available roomId's // try to use 0~127 in order to have lesser Buffer size options.roomId = this.roomCount++; options.roomName = roomName; room = new handler(merge(clientOptions, options)); // imediatelly ask client to join the room if ( room.requestJoin(clientOptions) ) { room.on('lock', this.lockRoom.bind(this, roomName, room)); room.on('unlock', this.unlockRoom.bind(this, roomName, room)); room.once('dispose', this.disposeRoom.bind(this, roomName, room)); this.roomsById[ room.roomId ] = room; // room always start unlocked this.unlockRoom(roomName, room); } else { room = null; } return room; } private lockRoom (roomName: string, room: Room<any>): void { if (this.hasAvailableRoom(roomName)) { let index = this.availableRooms[roomName].indexOf(room); if (index !== -1) { spliceOne(this.availableRooms[roomName], index); } } } private unlockRoom (roomName: string, room: Room<any>) { if (this.availableRooms[ roomName ].indexOf(room) === -1) { this.availableRooms[ roomName ].push(room) } } private disposeRoom(roomName: string, room: Room<any>): void { delete this.roomsById[ room.roomId ] // remove from available rooms this.lockRoom(roomName, room) } }