@colyseus/core 0.14.32 → 0.14.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/Logger.js.map +1 -1
- package/build/Logger.mjs.map +1 -1
- package/build/Room.js +1 -1
- package/build/Room.js.map +1 -1
- package/build/Room.mjs +1 -1
- package/build/Room.mjs.map +1 -1
- package/build/Server.d.ts +6 -0
- package/build/Server.js +9 -1
- package/build/Server.js.map +1 -1
- package/build/Server.mjs +9 -1
- package/build/Server.mjs.map +1 -1
- package/build/matchmaker/driver/interfaces.js.map +1 -1
- package/build/presence/Presence.js.map +1 -1
- package/build/utils/DevMode.js +9 -2
- package/build/utils/DevMode.js.map +2 -2
- package/build/utils/DevMode.mjs +5 -1
- package/build/utils/DevMode.mjs.map +1 -1
- package/build/utils/Utils.js +4 -1
- package/build/utils/Utils.js.map +2 -2
- package/build/utils/Utils.mjs.map +1 -1
- package/package.json +3 -2
package/build/Logger.js.map
CHANGED
|
@@ -2,6 +2,6 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/Logger.ts"],
|
|
4
4
|
"sourcesContent": ["//\n// Abstract logging adaptor\n//\nexport class Logger {\n debug(...args) {\n logger.debug(...args);\n }\n\n error(...args) {\n logger.error(...args);\n }\n\n info(...args) {\n logger.info(...args);\n }\n\n trace(...args) {\n logger.trace(...args);\n }\n\n warn(...args) {\n logger.warn(...args);\n }\n}\n\nexport let logger: Logger = console;\n\nexport function setLogger(instance: Logger) {\n logger = instance;\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAGO,MAAM,OAAO;AAAA,EAClB,SAAS,MAAM;AACb,WAAO,MAAM,GAAG,IAAI;AAAA,EACtB;AAAA,EAEA,SAAS,MAAM;AACb,WAAO,MAAM,GAAG,IAAI;AAAA,EACtB;AAAA,EAEA,QAAQ,MAAM;AACZ,WAAO,KAAK,GAAG,IAAI;AAAA,EACrB;AAAA,EAEA,SAAS,MAAM;AACb,WAAO,MAAM,GAAG,IAAI;AAAA,EACtB;AAAA,EAEA,QAAQ,MAAM;AACZ,WAAO,KAAK,GAAG,IAAI;AAAA,EACrB;AACF;AAEO,IAAI,SAAiB;AAErB,
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAGO,MAAM,OAAO;AAAA,EAClB,SAAS,MAAM;AACb,WAAO,MAAM,GAAG,IAAI;AAAA,EACtB;AAAA,EAEA,SAAS,MAAM;AACb,WAAO,MAAM,GAAG,IAAI;AAAA,EACtB;AAAA,EAEA,QAAQ,MAAM;AACZ,WAAO,KAAK,GAAG,IAAI;AAAA,EACrB;AAAA,EAEA,SAAS,MAAM;AACb,WAAO,MAAM,GAAG,IAAI;AAAA,EACtB;AAAA,EAEA,QAAQ,MAAM;AACZ,WAAO,KAAK,GAAG,IAAI;AAAA,EACrB;AACF;AAEO,IAAI,SAAiB;AAErB,SAAS,UAAU,UAAkB;AAC1C,WAAS;AACX;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/build/Logger.mjs.map
CHANGED
|
@@ -2,6 +2,6 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/Logger.ts"],
|
|
4
4
|
"sourcesContent": ["//\n// Abstract logging adaptor\n//\nexport class Logger {\n debug(...args) {\n logger.debug(...args);\n }\n\n error(...args) {\n logger.error(...args);\n }\n\n info(...args) {\n logger.info(...args);\n }\n\n trace(...args) {\n logger.trace(...args);\n }\n\n warn(...args) {\n logger.warn(...args);\n }\n}\n\nexport let logger: Logger = console;\n\nexport function setLogger(instance: Logger) {\n logger = instance;\n}\n"],
|
|
5
|
-
"mappings": "AAGO,MAAM,OAAO;AAAA,EAClB,SAAS,MAAM;AACb,WAAO,MAAM,GAAG,IAAI;AAAA,EACtB;AAAA,EAEA,SAAS,MAAM;AACb,WAAO,MAAM,GAAG,IAAI;AAAA,EACtB;AAAA,EAEA,QAAQ,MAAM;AACZ,WAAO,KAAK,GAAG,IAAI;AAAA,EACrB;AAAA,EAEA,SAAS,MAAM;AACb,WAAO,MAAM,GAAG,IAAI;AAAA,EACtB;AAAA,EAEA,QAAQ,MAAM;AACZ,WAAO,KAAK,GAAG,IAAI;AAAA,EACrB;AACF;AAEO,IAAI,SAAiB;AAErB,
|
|
5
|
+
"mappings": "AAGO,MAAM,OAAO;AAAA,EAClB,SAAS,MAAM;AACb,WAAO,MAAM,GAAG,IAAI;AAAA,EACtB;AAAA,EAEA,SAAS,MAAM;AACb,WAAO,MAAM,GAAG,IAAI;AAAA,EACtB;AAAA,EAEA,QAAQ,MAAM;AACZ,WAAO,KAAK,GAAG,IAAI;AAAA,EACrB;AAAA,EAEA,SAAS,MAAM;AACb,WAAO,MAAM,GAAG,IAAI;AAAA,EACtB;AAAA,EAEA,QAAQ,MAAM;AACZ,WAAO,KAAK,GAAG,IAAI;AAAA,EACrB;AACF;AAEO,IAAI,SAAiB;AAErB,SAAS,UAAU,UAAkB;AAC1C,WAAS;AACX;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/build/Room.js
CHANGED
|
@@ -459,7 +459,7 @@ class Room {
|
|
|
459
459
|
Debug.debugAndPrintError(`onMessage for "${messageType}" not registered.`);
|
|
460
460
|
}
|
|
461
461
|
}
|
|
462
|
-
else if (code === Protocol.Protocol.JOIN_ROOM) {
|
|
462
|
+
else if (code === Protocol.Protocol.JOIN_ROOM && client.state === Transport.ClientState.JOINING) {
|
|
463
463
|
// join room has been acknowledged by the client
|
|
464
464
|
client.state = Transport.ClientState.JOINED;
|
|
465
465
|
// send current state when new client joins the room
|
package/build/Room.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Room.js","sources":["../src/Room.ts"],"sourcesContent":["import http from 'http';\nimport msgpack from 'notepack.io';\n\nimport { decode, Iterator, Schema } from '@colyseus/schema';\n\nimport Clock from '@gamestdio/timer';\nimport { EventEmitter } from 'events';\n\nimport { Presence } from './presence/Presence';\n\nimport { Serializer } from './serializer/Serializer';\nimport { NoneSerializer } from './serializer/NoneSerializer';\nimport { SchemaSerializer } from './serializer/SchemaSerializer';\n\nimport { ErrorCode, getMessageBytes, Protocol } from './Protocol';\nimport { Deferred, spliceOne } from './Utils';\n\nimport { debugAndPrintError, debugPatch } from './Debug';\nimport { ServerError } from './errors/ServerError';\nimport { Client, ClientState, ISendOptions } from './Transport';\nimport { RoomListingData } from './matchmaker/driver';\n\nconst DEFAULT_PATCH_RATE = 1000 / 20; // 20fps (50ms)\nconst DEFAULT_SIMULATION_INTERVAL = 1000 / 60; // 60fps (16.66ms)\nconst noneSerializer = new NoneSerializer();\n\nexport const DEFAULT_SEAT_RESERVATION_TIME = Number(process.env.COLYSEUS_SEAT_RESERVATION_TIME || 15);\n\nexport type SimulationCallback = (deltaTime: number) => void;\n\nexport type RoomConstructor<T= any> = new (presence?: Presence) => Room<T>;\n\nexport interface IBroadcastOptions extends ISendOptions {\n except?: Client;\n}\n\nexport enum RoomInternalState {\n CREATING = 0,\n CREATED = 1,\n DISCONNECTING = 2,\n}\n\nexport abstract class Room<State= any, Metadata= any> {\n\n public get locked() {\n return this._locked;\n }\n\n public get metadata() {\n return this.listing.metadata;\n }\n\n public listing: RoomListingData<Metadata>;\n public clock: Clock = new Clock();\n\n public roomId: string;\n public roomName: string;\n\n public maxClients: number = Infinity;\n public patchRate: number = DEFAULT_PATCH_RATE;\n public autoDispose: boolean = true;\n\n public state: State;\n public presence: Presence;\n\n public clients: Client[] = [];\n public internalState: RoomInternalState = RoomInternalState.CREATING;\n\n /** @internal */\n public _events = new EventEmitter();\n\n // seat reservation & reconnection\n protected seatReservationTime: number = DEFAULT_SEAT_RESERVATION_TIME;\n protected reservedSeats: { [sessionId: string]: any } = {};\n protected reservedSeatTimeouts: { [sessionId: string]: NodeJS.Timer } = {};\n\n protected reconnections: { [sessionId: string]: Deferred } = {};\n\n private onMessageHandlers: {[id: string]: (client: Client, message: any) => void} = {};\n\n private _serializer: Serializer<State> = noneSerializer;\n private _afterNextPatchQueue: Array<[string | Client, IArguments]> = [];\n\n private _simulationInterval: NodeJS.Timer;\n private _patchInterval: NodeJS.Timer;\n\n private _locked: boolean = false;\n private _lockedExplicitly: boolean = false;\n private _maxClientsReached: boolean = false;\n\n // this timeout prevents rooms that are created by one process, but no client\n // ever had success joining into it on the specified interval.\n private _autoDisposeTimeout: NodeJS.Timer;\n\n constructor(presence?: Presence) {\n this.presence = presence;\n\n this._events.once('dispose', async () => {\n try {\n await this._dispose();\n\n } catch (e) {\n debugAndPrintError(`onDispose error: ${(e && e.message || e || 'promise rejected')}`);\n }\n this._events.emit('disconnect');\n });\n\n this.setPatchRate(this.patchRate);\n // set default _autoDisposeTimeout\n this.resetAutoDisposeTimeout(this.seatReservationTime);\n }\n\n // Optional abstract methods\n public onCreate?(options: any): void | Promise<any>;\n public onJoin?(client: Client, options?: any, auth?: any): void | Promise<any>;\n public onLeave?(client: Client, consented?: boolean): void | Promise<any>;\n public onDispose?(): void | Promise<any>;\n public onAuth(client: Client, options: any, request?: http.IncomingMessage): any | Promise<any> {\n return true;\n }\n\n public hasReachedMaxClients(): boolean {\n return (this.clients.length + Object.keys(this.reservedSeats).length) >= this.maxClients;\n }\n\n public setSeatReservationTime(seconds: number) {\n this.seatReservationTime = seconds;\n return this;\n }\n\n public hasReservedSeat(sessionId: string): boolean {\n return this.reservedSeats[sessionId] !== undefined;\n }\n\n public setSimulationInterval(onTickCallback?: SimulationCallback, delay: number = DEFAULT_SIMULATION_INTERVAL): void {\n // clear previous interval in case called setSimulationInterval more than once\n if (this._simulationInterval) { clearInterval(this._simulationInterval); }\n\n if (onTickCallback) {\n this._simulationInterval = setInterval(() => {\n this.clock.tick();\n onTickCallback(this.clock.deltaTime);\n }, delay);\n }\n }\n\n public setPatchRate(milliseconds: number): void {\n this.patchRate = milliseconds;\n\n // clear previous interval in case called setPatchRate more than once\n if (this._patchInterval) {\n clearInterval(this._patchInterval);\n this._patchInterval = undefined;\n }\n\n if (milliseconds !== null && milliseconds !== 0) {\n this._patchInterval = setInterval(() => this.broadcastPatch(), milliseconds);\n }\n }\n\n public setState(newState: State) {\n this.clock.start();\n\n if ('_definition' in newState) {\n this.setSerializer(new SchemaSerializer());\n }\n\n this._serializer.reset(newState);\n\n this.state = newState;\n }\n\n public setSerializer(serializer: Serializer<State>) {\n this._serializer = serializer;\n }\n\n public async setMetadata(meta: Partial<Metadata>) {\n if (!this.listing.metadata) {\n this.listing.metadata = meta as Metadata;\n\n } else {\n for (const field in meta) {\n if (!meta.hasOwnProperty(field)) { continue; }\n this.listing.metadata[field] = meta[field];\n }\n\n // `MongooseDriver` workaround: persit metadata mutations\n if ('markModified' in this.listing) {\n (this.listing as any).markModified('metadata');\n }\n }\n\n if (this.internalState === RoomInternalState.CREATED) {\n await this.listing.save();\n }\n }\n\n public async setPrivate(bool: boolean = true) {\n this.listing.private = bool;\n\n if (this.internalState === RoomInternalState.CREATED) {\n await this.listing.save();\n }\n }\n\n public async lock() {\n // rooms locked internally aren't explicit locks.\n this._lockedExplicitly = (arguments[0] === undefined);\n\n // skip if already locked.\n if (this._locked) { return; }\n\n this._locked = true;\n\n await this.listing.updateOne({\n $set: { locked: this._locked },\n });\n\n this._events.emit('lock');\n }\n\n public async unlock() {\n // only internal usage passes arguments to this function.\n if (arguments[0] === undefined) {\n this._lockedExplicitly = false;\n }\n\n // skip if already locked\n if (!this._locked) { return; }\n\n this._locked = false;\n\n await this.listing.updateOne({\n $set: { locked: this._locked },\n });\n\n this._events.emit('unlock');\n }\n\n public send(client: Client, type: string | number, message: any, options?: ISendOptions): void;\n public send(client: Client, message: Schema, options?: ISendOptions): void;\n public send(client: Client, messageOrType: any, messageOrOptions?: any | ISendOptions, options?: ISendOptions): void {\n console.warn('DEPRECATION WARNING: use client.send(...) instead of this.send(client, ...)');\n client.send(messageOrType, messageOrOptions, options);\n }\n\n public broadcast(type: string | number, message?: any, options?: IBroadcastOptions);\n public broadcast<T extends Schema>(message: T, options?: IBroadcastOptions);\n public broadcast(\n typeOrSchema: string | number | Schema,\n messageOrOptions?: any | IBroadcastOptions,\n options?: IBroadcastOptions,\n ) {\n const isSchema = (typeof(typeOrSchema) === 'object');\n const opts: IBroadcastOptions = ((isSchema) ? messageOrOptions : options);\n\n if (opts && opts.afterNextPatch) {\n delete opts.afterNextPatch;\n this._afterNextPatchQueue.push(['broadcast', arguments]);\n return;\n }\n\n if (isSchema) {\n this.broadcastMessageSchema(typeOrSchema as Schema, opts);\n\n } else {\n this.broadcastMessageType(typeOrSchema as string, messageOrOptions, opts);\n }\n }\n\n public broadcastPatch() {\n if (!this._simulationInterval) {\n this.clock.tick();\n }\n\n if (!this.state) {\n return false;\n }\n\n const hasChanges = this._serializer.applyPatches(this.clients, this.state);\n\n // broadcast messages enqueued for \"after patch\"\n this._dequeueAfterPatchMessages();\n\n return hasChanges;\n }\n\n public onMessage<T = any>(messageType: '*', callback: (client: Client, type: string | number, message: T) => void);\n public onMessage<T = any>(messageType: string | number, callback: (client: Client, message: T) => void);\n public onMessage<T = any>(messageType: '*' | string | number, callback: (...args: any[]) => void) {\n this.onMessageHandlers[messageType] = callback;\n // returns a method to unbind the callback\n return () => delete this.onMessageHandlers[messageType];\n }\n\n public async disconnect(): Promise<any> {\n this.internalState = RoomInternalState.DISCONNECTING;\n await this.listing.remove();\n\n this.autoDispose = true;\n\n const delayedDisconnection = new Promise<void>((resolve) =>\n this._events.once('disconnect', () => resolve()));\n\n for (const reconnection of Object.values(this.reconnections)) {\n reconnection.reject();\n }\n\n let numClients = this.clients.length;\n if (numClients > 0) {\n // clients may have `async onLeave`, room will be disposed after they're fulfilled\n while (numClients--) {\n this._forciblyCloseClient(this.clients[numClients], Protocol.WS_CLOSE_CONSENTED);\n }\n } else {\n // no clients connected, dispose immediately.\n this._events.emit('dispose');\n }\n\n return await delayedDisconnection;\n }\n\n public async ['_onJoin'](client: Client, req?: http.IncomingMessage) {\n const sessionId = client.sessionId;\n\n if (this.reservedSeatTimeouts[sessionId]) {\n clearTimeout(this.reservedSeatTimeouts[sessionId]);\n delete this.reservedSeatTimeouts[sessionId];\n }\n\n // clear auto-dispose timeout.\n if (this._autoDisposeTimeout) {\n clearTimeout(this._autoDisposeTimeout);\n this._autoDisposeTimeout = undefined;\n }\n\n // get seat reservation options and clear it\n const options = this.reservedSeats[sessionId];\n delete this.reservedSeats[sessionId];\n\n // share \"after next patch queue\" reference with every client.\n client._afterNextPatchQueue = this._afterNextPatchQueue;\n\n // bind clean-up callback when client connection closes\n client.ref['onleave'] = this._onLeave.bind(this, client);\n client.ref.once('close', client.ref['onleave']);\n\n this.clients.push(client);\n\n const reconnection = this.reconnections[sessionId];\n if (reconnection) {\n reconnection.resolve(client);\n\n } else {\n try {\n client.auth = await this.onAuth(client, options, req);\n\n if (!client.auth) {\n throw new ServerError(ErrorCode.AUTH_FAILED, 'onAuth failed');\n }\n\n if (this.onJoin) {\n await this.onJoin(client, options, client.auth);\n }\n } catch (e) {\n spliceOne(this.clients, this.clients.indexOf(client));\n\n // make sure an error code is provided.\n if (!e.code) {\n e.code = ErrorCode.APPLICATION_ERROR;\n }\n\n throw e;\n\n } finally {\n // remove seat reservation\n delete this.reservedSeats[sessionId];\n }\n }\n\n // emit 'join' to room handler\n this._events.emit('join', client);\n\n // allow client to send messages after onJoin has succeeded.\n client.ref.on('message', this._onMessage.bind(this, client));\n\n // confirm room id that matches the room name requested to join\n client.raw(getMessageBytes[Protocol.JOIN_ROOM](\n this._serializer.id,\n this._serializer.handshake && this._serializer.handshake(),\n ));\n }\n\n public allowReconnection(previousClient: Client, seconds: number = Infinity): Deferred<Client> {\n if (this.internalState === RoomInternalState.DISCONNECTING) {\n this._disposeIfEmpty(); // gracefully shutting down\n throw new Error('disconnecting');\n }\n\n const sessionId = previousClient.sessionId;\n this._reserveSeat(sessionId, true, seconds, true);\n\n // keep reconnection reference in case the user reconnects into this room.\n const reconnection = new Deferred<Client>();\n this.reconnections[sessionId] = reconnection;\n\n if (seconds !== Infinity) {\n // expire seat reservation after timeout\n this.reservedSeatTimeouts[sessionId] = setTimeout(() =>\n reconnection.reject(false), seconds * 1000);\n }\n\n const cleanup = () => {\n delete this.reservedSeats[sessionId];\n delete this.reconnections[sessionId];\n delete this.reservedSeatTimeouts[sessionId];\n };\n\n reconnection.\n then((newClient) => {\n newClient.auth = previousClient.auth;\n newClient.userData = previousClient.userData;\n previousClient.ref = newClient.ref; // swap \"ref\" for convenience\n previousClient.state = ClientState.RECONNECTED;\n clearTimeout(this.reservedSeatTimeouts[sessionId]);\n cleanup();\n }).\n catch(() => {\n cleanup();\n this.resetAutoDisposeTimeout();\n });\n\n return reconnection;\n }\n\n protected resetAutoDisposeTimeout(timeoutInSeconds: number = 1) {\n clearTimeout(this._autoDisposeTimeout);\n\n if (!this.autoDispose) {\n return;\n }\n\n this._autoDisposeTimeout = setTimeout(() => {\n this._autoDisposeTimeout = undefined;\n this._disposeIfEmpty();\n }, timeoutInSeconds * 1000);\n }\n\n private broadcastMessageSchema<T extends Schema>(message: T, options: IBroadcastOptions = {}) {\n const encodedMessage = getMessageBytes[Protocol.ROOM_DATA_SCHEMA](message);\n\n let numClients = this.clients.length;\n while (numClients--) {\n const client = this.clients[numClients];\n\n if (options.except !== client) {\n client.enqueueRaw(encodedMessage);\n }\n }\n }\n\n private broadcastMessageType(type: string, message?: any, options: IBroadcastOptions = {}) {\n const encodedMessage = getMessageBytes[Protocol.ROOM_DATA](type, message);\n\n let numClients = this.clients.length;\n while (numClients--) {\n const client = this.clients[numClients];\n\n if (options.except !== client) {\n client.enqueueRaw(encodedMessage);\n }\n }\n }\n\n private sendFullState(client: Client): void {\n client.enqueueRaw(getMessageBytes[Protocol.ROOM_STATE](this._serializer.getFullState(client)));\n }\n\n private _dequeueAfterPatchMessages() {\n const length = this._afterNextPatchQueue.length;\n\n if (length > 0) {\n for (let i = 0; i < length; i++) {\n const [target, args] = this._afterNextPatchQueue[i];\n\n if (target === \"broadcast\") {\n this.broadcast.apply(this, args);\n\n } else {\n (target as Client).raw.apply(target, args);\n }\n }\n\n // new messages may have been added in the meantime,\n // let's splice the ones that have been processed\n this._afterNextPatchQueue.splice(0, length);\n }\n }\n\n private async _reserveSeat(\n sessionId: string,\n joinOptions: any = true,\n seconds: number = this.seatReservationTime,\n allowReconnection: boolean = false,\n ) {\n if (!allowReconnection && this.hasReachedMaxClients()) {\n return false;\n }\n\n this.reservedSeats[sessionId] = joinOptions;\n\n if (!allowReconnection) {\n await this._incrementClientCount();\n\n this.reservedSeatTimeouts[sessionId] = setTimeout(async () => {\n delete this.reservedSeats[sessionId];\n delete this.reservedSeatTimeouts[sessionId];\n await this._decrementClientCount();\n }, seconds * 1000);\n\n this.resetAutoDisposeTimeout(seconds);\n }\n\n return true;\n }\n\n private _disposeIfEmpty() {\n const willDispose = (\n this.autoDispose &&\n this._autoDisposeTimeout === undefined &&\n this.clients.length === 0 &&\n Object.keys(this.reservedSeats).length === 0\n );\n\n if (willDispose) {\n this._events.emit('dispose');\n }\n\n return willDispose;\n }\n\n private async _dispose(): Promise<any> {\n let userReturnData;\n\n if (this.onDispose) {\n userReturnData = this.onDispose();\n }\n\n if (this._patchInterval) {\n clearInterval(this._patchInterval);\n this._patchInterval = undefined;\n }\n\n if (this._simulationInterval) {\n clearInterval(this._simulationInterval);\n this._simulationInterval = undefined;\n }\n\n if (this._autoDisposeTimeout) {\n clearInterval(this._autoDisposeTimeout);\n this._autoDisposeTimeout = undefined;\n }\n\n // clear all timeouts/intervals + force to stop ticking\n this.clock.clear();\n this.clock.stop();\n\n return await (userReturnData || Promise.resolve());\n }\n\n private _onMessage(client: Client, bytes: number[]) {\n // skip if client is on LEAVING state.\n if (client.state === ClientState.LEAVING) { return; }\n\n const it: Iterator = { offset: 0 };\n const code = decode.uint8(bytes, it);\n\n if (!bytes) {\n debugAndPrintError(`${this.roomName} (${this.roomId}), couldn't decode message: ${bytes}`);\n return;\n }\n\n if (code === Protocol.ROOM_DATA) {\n const messageType = (decode.stringCheck(bytes, it))\n ? decode.string(bytes, it)\n : decode.number(bytes, it);\n\n let message;\n try {\n message = (bytes.length > it.offset)\n ? msgpack.decode(bytes.slice(it.offset, bytes.length))\n : undefined;\n } catch (e) {\n debugAndPrintError(e);\n return;\n }\n\n if (this.onMessageHandlers[messageType]) {\n this.onMessageHandlers[messageType](client, message);\n\n } else if (this.onMessageHandlers['*']) {\n (this.onMessageHandlers['*'] as any)(client, messageType, message);\n\n } else {\n debugAndPrintError(`onMessage for \"${messageType}\" not registered.`);\n }\n\n } else if (code === Protocol.JOIN_ROOM) {\n // join room has been acknowledged by the client\n client.state = ClientState.JOINED;\n\n // send current state when new client joins the room\n if (this.state) {\n this.sendFullState(client);\n }\n\n // dequeue messages sent before client has joined effectively (on user-defined `onJoin`)\n if (client._enqueuedMessages.length > 0) {\n client._enqueuedMessages.forEach((enqueued) => client.raw(enqueued));\n }\n delete client._enqueuedMessages;\n\n } else if (code === Protocol.LEAVE_ROOM) {\n this._forciblyCloseClient(client, Protocol.WS_CLOSE_CONSENTED);\n }\n\n }\n\n private _forciblyCloseClient(client: Client, closeCode: number) {\n // stop receiving messages from this client\n client.ref.removeAllListeners('message');\n\n // prevent \"onLeave\" from being called twice if player asks to leave\n client.ref.removeListener('close', client.ref['onleave']);\n\n // only effectively close connection when \"onLeave\" is fulfilled\n this._onLeave(client, closeCode).then(() => client.leave(Protocol.WS_CLOSE_NORMAL));\n }\n\n private async _onLeave(client: Client, code?: number): Promise<any> {\n const success = spliceOne(this.clients, this.clients.indexOf(client));\n\n // call 'onLeave' method only if the client has been successfully accepted.\n if (success && this.onLeave) {\n try {\n client.state = ClientState.LEAVING;\n await this.onLeave(client, (code === Protocol.WS_CLOSE_CONSENTED));\n\n } catch (e) {\n debugAndPrintError(`onLeave error: ${(e && e.message || e || 'promise rejected')}`);\n }\n }\n\n if (client.state !== ClientState.RECONNECTED) {\n // try to dispose immediatelly if client reconnection isn't set up.\n const willDispose = await this._decrementClientCount();\n\n this._events.emit('leave', client, willDispose);\n }\n }\n\n private async _incrementClientCount() {\n // lock automatically when maxClients is reached\n if (!this._locked && this.hasReachedMaxClients()) {\n this._maxClientsReached = true;\n this.lock.call(this, true);\n }\n\n await this.listing.updateOne({\n $inc: { clients: 1 },\n $set: { locked: this._locked },\n });\n }\n\n private async _decrementClientCount() {\n const willDispose = this._disposeIfEmpty();\n\n if (this.internalState === RoomInternalState.DISCONNECTING) {\n return;\n }\n\n // unlock if room is available for new connections\n if (!willDispose) {\n if (this._maxClientsReached && !this._lockedExplicitly) {\n this._maxClientsReached = false;\n this.unlock.call(this, true);\n }\n\n // update room listing cache\n await this.listing.updateOne({\n $inc: { clients: -1 },\n $set: { locked: this._locked },\n });\n }\n\n return willDispose;\n }\n\n}\n"],"names":["NoneSerializer","RoomInternalState","Clock","EventEmitter","debugAndPrintError","SchemaSerializer","Protocol","ServerError","ErrorCode","spliceOne","getMessageBytes","Deferred","ClientState","decode","msgpack"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Room.js","sources":["../src/Room.ts"],"sourcesContent":["import http from 'http';\nimport msgpack from 'notepack.io';\n\nimport { decode, Iterator, Schema } from '@colyseus/schema';\n\nimport Clock from '@gamestdio/timer';\nimport { EventEmitter } from 'events';\n\nimport { Presence } from './presence/Presence';\n\nimport { Serializer } from './serializer/Serializer';\nimport { NoneSerializer } from './serializer/NoneSerializer';\nimport { SchemaSerializer } from './serializer/SchemaSerializer';\n\nimport { ErrorCode, getMessageBytes, Protocol } from './Protocol';\nimport { Deferred, spliceOne } from './Utils';\n\nimport { debugAndPrintError, debugPatch } from './Debug';\nimport { ServerError } from './errors/ServerError';\nimport { Client, ClientState, ISendOptions } from './Transport';\nimport { RoomListingData } from './matchmaker/driver';\n\nconst DEFAULT_PATCH_RATE = 1000 / 20; // 20fps (50ms)\nconst DEFAULT_SIMULATION_INTERVAL = 1000 / 60; // 60fps (16.66ms)\nconst noneSerializer = new NoneSerializer();\n\nexport const DEFAULT_SEAT_RESERVATION_TIME = Number(process.env.COLYSEUS_SEAT_RESERVATION_TIME || 15);\n\nexport type SimulationCallback = (deltaTime: number) => void;\n\nexport type RoomConstructor<T= any> = new (presence?: Presence) => Room<T>;\n\nexport interface IBroadcastOptions extends ISendOptions {\n except?: Client;\n}\n\nexport enum RoomInternalState {\n CREATING = 0,\n CREATED = 1,\n DISCONNECTING = 2,\n}\n\nexport abstract class Room<State= any, Metadata= any> {\n\n public get locked() {\n return this._locked;\n }\n\n public get metadata() {\n return this.listing.metadata;\n }\n\n public listing: RoomListingData<Metadata>;\n public clock: Clock = new Clock();\n\n public roomId: string;\n public roomName: string;\n\n public maxClients: number = Infinity;\n public patchRate: number = DEFAULT_PATCH_RATE;\n public autoDispose: boolean = true;\n\n public state: State;\n public presence: Presence;\n\n public clients: Client[] = [];\n public internalState: RoomInternalState = RoomInternalState.CREATING;\n\n /** @internal */\n public _events = new EventEmitter();\n\n // seat reservation & reconnection\n protected seatReservationTime: number = DEFAULT_SEAT_RESERVATION_TIME;\n protected reservedSeats: { [sessionId: string]: any } = {};\n protected reservedSeatTimeouts: { [sessionId: string]: NodeJS.Timer } = {};\n\n protected reconnections: { [sessionId: string]: Deferred } = {};\n\n private onMessageHandlers: {[id: string]: (client: Client, message: any) => void} = {};\n\n private _serializer: Serializer<State> = noneSerializer;\n private _afterNextPatchQueue: Array<[string | Client, IArguments]> = [];\n\n private _simulationInterval: NodeJS.Timer;\n private _patchInterval: NodeJS.Timer;\n\n private _locked: boolean = false;\n private _lockedExplicitly: boolean = false;\n private _maxClientsReached: boolean = false;\n\n // this timeout prevents rooms that are created by one process, but no client\n // ever had success joining into it on the specified interval.\n private _autoDisposeTimeout: NodeJS.Timer;\n\n constructor(presence?: Presence) {\n this.presence = presence;\n\n this._events.once('dispose', async () => {\n try {\n await this._dispose();\n\n } catch (e) {\n debugAndPrintError(`onDispose error: ${(e && e.message || e || 'promise rejected')}`);\n }\n this._events.emit('disconnect');\n });\n\n this.setPatchRate(this.patchRate);\n // set default _autoDisposeTimeout\n this.resetAutoDisposeTimeout(this.seatReservationTime);\n }\n\n // Optional abstract methods\n public onCreate?(options: any): void | Promise<any>;\n public onJoin?(client: Client, options?: any, auth?: any): void | Promise<any>;\n public onLeave?(client: Client, consented?: boolean): void | Promise<any>;\n public onDispose?(): void | Promise<any>;\n public onAuth(client: Client, options: any, request?: http.IncomingMessage): any | Promise<any> {\n return true;\n }\n\n public hasReachedMaxClients(): boolean {\n return (this.clients.length + Object.keys(this.reservedSeats).length) >= this.maxClients;\n }\n\n public setSeatReservationTime(seconds: number) {\n this.seatReservationTime = seconds;\n return this;\n }\n\n public hasReservedSeat(sessionId: string): boolean {\n return this.reservedSeats[sessionId] !== undefined;\n }\n\n public setSimulationInterval(onTickCallback?: SimulationCallback, delay: number = DEFAULT_SIMULATION_INTERVAL): void {\n // clear previous interval in case called setSimulationInterval more than once\n if (this._simulationInterval) { clearInterval(this._simulationInterval); }\n\n if (onTickCallback) {\n this._simulationInterval = setInterval(() => {\n this.clock.tick();\n onTickCallback(this.clock.deltaTime);\n }, delay);\n }\n }\n\n public setPatchRate(milliseconds: number): void {\n this.patchRate = milliseconds;\n\n // clear previous interval in case called setPatchRate more than once\n if (this._patchInterval) {\n clearInterval(this._patchInterval);\n this._patchInterval = undefined;\n }\n\n if (milliseconds !== null && milliseconds !== 0) {\n this._patchInterval = setInterval(() => this.broadcastPatch(), milliseconds);\n }\n }\n\n public setState(newState: State) {\n this.clock.start();\n\n if ('_definition' in newState) {\n this.setSerializer(new SchemaSerializer());\n }\n\n this._serializer.reset(newState);\n\n this.state = newState;\n }\n\n public setSerializer(serializer: Serializer<State>) {\n this._serializer = serializer;\n }\n\n public async setMetadata(meta: Partial<Metadata>) {\n if (!this.listing.metadata) {\n this.listing.metadata = meta as Metadata;\n\n } else {\n for (const field in meta) {\n if (!meta.hasOwnProperty(field)) { continue; }\n this.listing.metadata[field] = meta[field];\n }\n\n // `MongooseDriver` workaround: persit metadata mutations\n if ('markModified' in this.listing) {\n (this.listing as any).markModified('metadata');\n }\n }\n\n if (this.internalState === RoomInternalState.CREATED) {\n await this.listing.save();\n }\n }\n\n public async setPrivate(bool: boolean = true) {\n this.listing.private = bool;\n\n if (this.internalState === RoomInternalState.CREATED) {\n await this.listing.save();\n }\n }\n\n public async lock() {\n // rooms locked internally aren't explicit locks.\n this._lockedExplicitly = (arguments[0] === undefined);\n\n // skip if already locked.\n if (this._locked) { return; }\n\n this._locked = true;\n\n await this.listing.updateOne({\n $set: { locked: this._locked },\n });\n\n this._events.emit('lock');\n }\n\n public async unlock() {\n // only internal usage passes arguments to this function.\n if (arguments[0] === undefined) {\n this._lockedExplicitly = false;\n }\n\n // skip if already locked\n if (!this._locked) { return; }\n\n this._locked = false;\n\n await this.listing.updateOne({\n $set: { locked: this._locked },\n });\n\n this._events.emit('unlock');\n }\n\n public send(client: Client, type: string | number, message: any, options?: ISendOptions): void;\n public send(client: Client, message: Schema, options?: ISendOptions): void;\n public send(client: Client, messageOrType: any, messageOrOptions?: any | ISendOptions, options?: ISendOptions): void {\n console.warn('DEPRECATION WARNING: use client.send(...) instead of this.send(client, ...)');\n client.send(messageOrType, messageOrOptions, options);\n }\n\n public broadcast(type: string | number, message?: any, options?: IBroadcastOptions);\n public broadcast<T extends Schema>(message: T, options?: IBroadcastOptions);\n public broadcast(\n typeOrSchema: string | number | Schema,\n messageOrOptions?: any | IBroadcastOptions,\n options?: IBroadcastOptions,\n ) {\n const isSchema = (typeof(typeOrSchema) === 'object');\n const opts: IBroadcastOptions = ((isSchema) ? messageOrOptions : options);\n\n if (opts && opts.afterNextPatch) {\n delete opts.afterNextPatch;\n this._afterNextPatchQueue.push(['broadcast', arguments]);\n return;\n }\n\n if (isSchema) {\n this.broadcastMessageSchema(typeOrSchema as Schema, opts);\n\n } else {\n this.broadcastMessageType(typeOrSchema as string, messageOrOptions, opts);\n }\n }\n\n public broadcastPatch() {\n if (!this._simulationInterval) {\n this.clock.tick();\n }\n\n if (!this.state) {\n return false;\n }\n\n const hasChanges = this._serializer.applyPatches(this.clients, this.state);\n\n // broadcast messages enqueued for \"after patch\"\n this._dequeueAfterPatchMessages();\n\n return hasChanges;\n }\n\n public onMessage<T = any>(messageType: '*', callback: (client: Client, type: string | number, message: T) => void);\n public onMessage<T = any>(messageType: string | number, callback: (client: Client, message: T) => void);\n public onMessage<T = any>(messageType: '*' | string | number, callback: (...args: any[]) => void) {\n this.onMessageHandlers[messageType] = callback;\n // returns a method to unbind the callback\n return () => delete this.onMessageHandlers[messageType];\n }\n\n public async disconnect(): Promise<any> {\n this.internalState = RoomInternalState.DISCONNECTING;\n await this.listing.remove();\n\n this.autoDispose = true;\n\n const delayedDisconnection = new Promise<void>((resolve) =>\n this._events.once('disconnect', () => resolve()));\n\n for (const reconnection of Object.values(this.reconnections)) {\n reconnection.reject();\n }\n\n let numClients = this.clients.length;\n if (numClients > 0) {\n // clients may have `async onLeave`, room will be disposed after they're fulfilled\n while (numClients--) {\n this._forciblyCloseClient(this.clients[numClients], Protocol.WS_CLOSE_CONSENTED);\n }\n } else {\n // no clients connected, dispose immediately.\n this._events.emit('dispose');\n }\n\n return await delayedDisconnection;\n }\n\n public async ['_onJoin'](client: Client, req?: http.IncomingMessage) {\n const sessionId = client.sessionId;\n\n if (this.reservedSeatTimeouts[sessionId]) {\n clearTimeout(this.reservedSeatTimeouts[sessionId]);\n delete this.reservedSeatTimeouts[sessionId];\n }\n\n // clear auto-dispose timeout.\n if (this._autoDisposeTimeout) {\n clearTimeout(this._autoDisposeTimeout);\n this._autoDisposeTimeout = undefined;\n }\n\n // get seat reservation options and clear it\n const options = this.reservedSeats[sessionId];\n delete this.reservedSeats[sessionId];\n\n // share \"after next patch queue\" reference with every client.\n client._afterNextPatchQueue = this._afterNextPatchQueue;\n\n // bind clean-up callback when client connection closes\n client.ref['onleave'] = this._onLeave.bind(this, client);\n client.ref.once('close', client.ref['onleave']);\n\n this.clients.push(client);\n\n const reconnection = this.reconnections[sessionId];\n if (reconnection) {\n reconnection.resolve(client);\n\n } else {\n try {\n client.auth = await this.onAuth(client, options, req);\n\n if (!client.auth) {\n throw new ServerError(ErrorCode.AUTH_FAILED, 'onAuth failed');\n }\n\n if (this.onJoin) {\n await this.onJoin(client, options, client.auth);\n }\n } catch (e) {\n spliceOne(this.clients, this.clients.indexOf(client));\n\n // make sure an error code is provided.\n if (!e.code) {\n e.code = ErrorCode.APPLICATION_ERROR;\n }\n\n throw e;\n\n } finally {\n // remove seat reservation\n delete this.reservedSeats[sessionId];\n }\n }\n\n // emit 'join' to room handler\n this._events.emit('join', client);\n\n // allow client to send messages after onJoin has succeeded.\n client.ref.on('message', this._onMessage.bind(this, client));\n\n // confirm room id that matches the room name requested to join\n client.raw(getMessageBytes[Protocol.JOIN_ROOM](\n this._serializer.id,\n this._serializer.handshake && this._serializer.handshake(),\n ));\n }\n\n public allowReconnection(previousClient: Client, seconds: number = Infinity): Deferred<Client> {\n if (this.internalState === RoomInternalState.DISCONNECTING) {\n this._disposeIfEmpty(); // gracefully shutting down\n throw new Error('disconnecting');\n }\n\n const sessionId = previousClient.sessionId;\n this._reserveSeat(sessionId, true, seconds, true);\n\n // keep reconnection reference in case the user reconnects into this room.\n const reconnection = new Deferred<Client>();\n this.reconnections[sessionId] = reconnection;\n\n if (seconds !== Infinity) {\n // expire seat reservation after timeout\n this.reservedSeatTimeouts[sessionId] = setTimeout(() =>\n reconnection.reject(false), seconds * 1000);\n }\n\n const cleanup = () => {\n delete this.reservedSeats[sessionId];\n delete this.reconnections[sessionId];\n delete this.reservedSeatTimeouts[sessionId];\n };\n\n reconnection.\n then((newClient) => {\n newClient.auth = previousClient.auth;\n newClient.userData = previousClient.userData;\n previousClient.ref = newClient.ref; // swap \"ref\" for convenience\n previousClient.state = ClientState.RECONNECTED;\n clearTimeout(this.reservedSeatTimeouts[sessionId]);\n cleanup();\n }).\n catch(() => {\n cleanup();\n this.resetAutoDisposeTimeout();\n });\n\n return reconnection;\n }\n\n protected resetAutoDisposeTimeout(timeoutInSeconds: number = 1) {\n clearTimeout(this._autoDisposeTimeout);\n\n if (!this.autoDispose) {\n return;\n }\n\n this._autoDisposeTimeout = setTimeout(() => {\n this._autoDisposeTimeout = undefined;\n this._disposeIfEmpty();\n }, timeoutInSeconds * 1000);\n }\n\n private broadcastMessageSchema<T extends Schema>(message: T, options: IBroadcastOptions = {}) {\n const encodedMessage = getMessageBytes[Protocol.ROOM_DATA_SCHEMA](message);\n\n let numClients = this.clients.length;\n while (numClients--) {\n const client = this.clients[numClients];\n\n if (options.except !== client) {\n client.enqueueRaw(encodedMessage);\n }\n }\n }\n\n private broadcastMessageType(type: string, message?: any, options: IBroadcastOptions = {}) {\n const encodedMessage = getMessageBytes[Protocol.ROOM_DATA](type, message);\n\n let numClients = this.clients.length;\n while (numClients--) {\n const client = this.clients[numClients];\n\n if (options.except !== client) {\n client.enqueueRaw(encodedMessage);\n }\n }\n }\n\n private sendFullState(client: Client): void {\n client.enqueueRaw(getMessageBytes[Protocol.ROOM_STATE](this._serializer.getFullState(client)));\n }\n\n private _dequeueAfterPatchMessages() {\n const length = this._afterNextPatchQueue.length;\n\n if (length > 0) {\n for (let i = 0; i < length; i++) {\n const [target, args] = this._afterNextPatchQueue[i];\n\n if (target === \"broadcast\") {\n this.broadcast.apply(this, args);\n\n } else {\n (target as Client).raw.apply(target, args);\n }\n }\n\n // new messages may have been added in the meantime,\n // let's splice the ones that have been processed\n this._afterNextPatchQueue.splice(0, length);\n }\n }\n\n private async _reserveSeat(\n sessionId: string,\n joinOptions: any = true,\n seconds: number = this.seatReservationTime,\n allowReconnection: boolean = false,\n ) {\n if (!allowReconnection && this.hasReachedMaxClients()) {\n return false;\n }\n\n this.reservedSeats[sessionId] = joinOptions;\n\n if (!allowReconnection) {\n await this._incrementClientCount();\n\n this.reservedSeatTimeouts[sessionId] = setTimeout(async () => {\n delete this.reservedSeats[sessionId];\n delete this.reservedSeatTimeouts[sessionId];\n await this._decrementClientCount();\n }, seconds * 1000);\n\n this.resetAutoDisposeTimeout(seconds);\n }\n\n return true;\n }\n\n private _disposeIfEmpty() {\n const willDispose = (\n this.autoDispose &&\n this._autoDisposeTimeout === undefined &&\n this.clients.length === 0 &&\n Object.keys(this.reservedSeats).length === 0\n );\n\n if (willDispose) {\n this._events.emit('dispose');\n }\n\n return willDispose;\n }\n\n private async _dispose(): Promise<any> {\n let userReturnData;\n\n if (this.onDispose) {\n userReturnData = this.onDispose();\n }\n\n if (this._patchInterval) {\n clearInterval(this._patchInterval);\n this._patchInterval = undefined;\n }\n\n if (this._simulationInterval) {\n clearInterval(this._simulationInterval);\n this._simulationInterval = undefined;\n }\n\n if (this._autoDisposeTimeout) {\n clearInterval(this._autoDisposeTimeout);\n this._autoDisposeTimeout = undefined;\n }\n\n // clear all timeouts/intervals + force to stop ticking\n this.clock.clear();\n this.clock.stop();\n\n return await (userReturnData || Promise.resolve());\n }\n\n private _onMessage(client: Client, bytes: number[]) {\n // skip if client is on LEAVING state.\n if (client.state === ClientState.LEAVING) { return; }\n\n const it: Iterator = { offset: 0 };\n const code = decode.uint8(bytes, it);\n\n if (!bytes) {\n debugAndPrintError(`${this.roomName} (${this.roomId}), couldn't decode message: ${bytes}`);\n return;\n }\n\n if (code === Protocol.ROOM_DATA) {\n const messageType = (decode.stringCheck(bytes, it))\n ? decode.string(bytes, it)\n : decode.number(bytes, it);\n\n let message;\n try {\n message = (bytes.length > it.offset)\n ? msgpack.decode(bytes.slice(it.offset, bytes.length))\n : undefined;\n } catch (e) {\n debugAndPrintError(e);\n return;\n }\n\n if (this.onMessageHandlers[messageType]) {\n this.onMessageHandlers[messageType](client, message);\n\n } else if (this.onMessageHandlers['*']) {\n (this.onMessageHandlers['*'] as any)(client, messageType, message);\n\n } else {\n debugAndPrintError(`onMessage for \"${messageType}\" not registered.`);\n }\n\n } else if (code === Protocol.JOIN_ROOM && client.state === ClientState.JOINING) {\n // join room has been acknowledged by the client\n client.state = ClientState.JOINED;\n\n // send current state when new client joins the room\n if (this.state) {\n this.sendFullState(client);\n }\n\n // dequeue messages sent before client has joined effectively (on user-defined `onJoin`)\n if (client._enqueuedMessages.length > 0) {\n client._enqueuedMessages.forEach((enqueued) => client.raw(enqueued));\n }\n delete client._enqueuedMessages;\n\n } else if (code === Protocol.LEAVE_ROOM) {\n this._forciblyCloseClient(client, Protocol.WS_CLOSE_CONSENTED);\n }\n\n }\n\n private _forciblyCloseClient(client: Client, closeCode: number) {\n // stop receiving messages from this client\n client.ref.removeAllListeners('message');\n\n // prevent \"onLeave\" from being called twice if player asks to leave\n client.ref.removeListener('close', client.ref['onleave']);\n\n // only effectively close connection when \"onLeave\" is fulfilled\n this._onLeave(client, closeCode).then(() => client.leave(Protocol.WS_CLOSE_NORMAL));\n }\n\n private async _onLeave(client: Client, code?: number): Promise<any> {\n const success = spliceOne(this.clients, this.clients.indexOf(client));\n\n // call 'onLeave' method only if the client has been successfully accepted.\n if (success && this.onLeave) {\n try {\n client.state = ClientState.LEAVING;\n await this.onLeave(client, (code === Protocol.WS_CLOSE_CONSENTED));\n\n } catch (e) {\n debugAndPrintError(`onLeave error: ${(e && e.message || e || 'promise rejected')}`);\n }\n }\n\n if (client.state !== ClientState.RECONNECTED) {\n // try to dispose immediatelly if client reconnection isn't set up.\n const willDispose = await this._decrementClientCount();\n\n this._events.emit('leave', client, willDispose);\n }\n }\n\n private async _incrementClientCount() {\n // lock automatically when maxClients is reached\n if (!this._locked && this.hasReachedMaxClients()) {\n this._maxClientsReached = true;\n this.lock.call(this, true);\n }\n\n await this.listing.updateOne({\n $inc: { clients: 1 },\n $set: { locked: this._locked },\n });\n }\n\n private async _decrementClientCount() {\n const willDispose = this._disposeIfEmpty();\n\n if (this.internalState === RoomInternalState.DISCONNECTING) {\n return;\n }\n\n // unlock if room is available for new connections\n if (!willDispose) {\n if (this._maxClientsReached && !this._lockedExplicitly) {\n this._maxClientsReached = false;\n this.unlock.call(this, true);\n }\n\n // update room listing cache\n await this.listing.updateOne({\n $inc: { clients: -1 },\n $set: { locked: this._locked },\n });\n }\n\n return willDispose;\n }\n\n}\n"],"names":["NoneSerializer","RoomInternalState","Clock","EventEmitter","debugAndPrintError","SchemaSerializer","Protocol","ServerError","ErrorCode","spliceOne","getMessageBytes","Deferred","ClientState","decode","msgpack"],"mappings":"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"}
|
package/build/Room.mjs
CHANGED
|
@@ -450,7 +450,7 @@ class Room {
|
|
|
450
450
|
debugAndPrintError(`onMessage for "${messageType}" not registered.`);
|
|
451
451
|
}
|
|
452
452
|
}
|
|
453
|
-
else if (code === Protocol.JOIN_ROOM) {
|
|
453
|
+
else if (code === Protocol.JOIN_ROOM && client.state === ClientState.JOINING) {
|
|
454
454
|
// join room has been acknowledged by the client
|
|
455
455
|
client.state = ClientState.JOINED;
|
|
456
456
|
// send current state when new client joins the room
|
package/build/Room.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Room.mjs","sources":["../src/Room.ts"],"sourcesContent":["import http from 'http';\nimport msgpack from 'notepack.io';\n\nimport { decode, Iterator, Schema } from '@colyseus/schema';\n\nimport Clock from '@gamestdio/timer';\nimport { EventEmitter } from 'events';\n\nimport { Presence } from './presence/Presence';\n\nimport { Serializer } from './serializer/Serializer';\nimport { NoneSerializer } from './serializer/NoneSerializer';\nimport { SchemaSerializer } from './serializer/SchemaSerializer';\n\nimport { ErrorCode, getMessageBytes, Protocol } from './Protocol';\nimport { Deferred, spliceOne } from './Utils';\n\nimport { debugAndPrintError, debugPatch } from './Debug';\nimport { ServerError } from './errors/ServerError';\nimport { Client, ClientState, ISendOptions } from './Transport';\nimport { RoomListingData } from './matchmaker/driver';\n\nconst DEFAULT_PATCH_RATE = 1000 / 20; // 20fps (50ms)\nconst DEFAULT_SIMULATION_INTERVAL = 1000 / 60; // 60fps (16.66ms)\nconst noneSerializer = new NoneSerializer();\n\nexport const DEFAULT_SEAT_RESERVATION_TIME = Number(process.env.COLYSEUS_SEAT_RESERVATION_TIME || 15);\n\nexport type SimulationCallback = (deltaTime: number) => void;\n\nexport type RoomConstructor<T= any> = new (presence?: Presence) => Room<T>;\n\nexport interface IBroadcastOptions extends ISendOptions {\n except?: Client;\n}\n\nexport enum RoomInternalState {\n CREATING = 0,\n CREATED = 1,\n DISCONNECTING = 2,\n}\n\nexport abstract class Room<State= any, Metadata= any> {\n\n public get locked() {\n return this._locked;\n }\n\n public get metadata() {\n return this.listing.metadata;\n }\n\n public listing: RoomListingData<Metadata>;\n public clock: Clock = new Clock();\n\n public roomId: string;\n public roomName: string;\n\n public maxClients: number = Infinity;\n public patchRate: number = DEFAULT_PATCH_RATE;\n public autoDispose: boolean = true;\n\n public state: State;\n public presence: Presence;\n\n public clients: Client[] = [];\n public internalState: RoomInternalState = RoomInternalState.CREATING;\n\n /** @internal */\n public _events = new EventEmitter();\n\n // seat reservation & reconnection\n protected seatReservationTime: number = DEFAULT_SEAT_RESERVATION_TIME;\n protected reservedSeats: { [sessionId: string]: any } = {};\n protected reservedSeatTimeouts: { [sessionId: string]: NodeJS.Timer } = {};\n\n protected reconnections: { [sessionId: string]: Deferred } = {};\n\n private onMessageHandlers: {[id: string]: (client: Client, message: any) => void} = {};\n\n private _serializer: Serializer<State> = noneSerializer;\n private _afterNextPatchQueue: Array<[string | Client, IArguments]> = [];\n\n private _simulationInterval: NodeJS.Timer;\n private _patchInterval: NodeJS.Timer;\n\n private _locked: boolean = false;\n private _lockedExplicitly: boolean = false;\n private _maxClientsReached: boolean = false;\n\n // this timeout prevents rooms that are created by one process, but no client\n // ever had success joining into it on the specified interval.\n private _autoDisposeTimeout: NodeJS.Timer;\n\n constructor(presence?: Presence) {\n this.presence = presence;\n\n this._events.once('dispose', async () => {\n try {\n await this._dispose();\n\n } catch (e) {\n debugAndPrintError(`onDispose error: ${(e && e.message || e || 'promise rejected')}`);\n }\n this._events.emit('disconnect');\n });\n\n this.setPatchRate(this.patchRate);\n // set default _autoDisposeTimeout\n this.resetAutoDisposeTimeout(this.seatReservationTime);\n }\n\n // Optional abstract methods\n public onCreate?(options: any): void | Promise<any>;\n public onJoin?(client: Client, options?: any, auth?: any): void | Promise<any>;\n public onLeave?(client: Client, consented?: boolean): void | Promise<any>;\n public onDispose?(): void | Promise<any>;\n public onAuth(client: Client, options: any, request?: http.IncomingMessage): any | Promise<any> {\n return true;\n }\n\n public hasReachedMaxClients(): boolean {\n return (this.clients.length + Object.keys(this.reservedSeats).length) >= this.maxClients;\n }\n\n public setSeatReservationTime(seconds: number) {\n this.seatReservationTime = seconds;\n return this;\n }\n\n public hasReservedSeat(sessionId: string): boolean {\n return this.reservedSeats[sessionId] !== undefined;\n }\n\n public setSimulationInterval(onTickCallback?: SimulationCallback, delay: number = DEFAULT_SIMULATION_INTERVAL): void {\n // clear previous interval in case called setSimulationInterval more than once\n if (this._simulationInterval) { clearInterval(this._simulationInterval); }\n\n if (onTickCallback) {\n this._simulationInterval = setInterval(() => {\n this.clock.tick();\n onTickCallback(this.clock.deltaTime);\n }, delay);\n }\n }\n\n public setPatchRate(milliseconds: number): void {\n this.patchRate = milliseconds;\n\n // clear previous interval in case called setPatchRate more than once\n if (this._patchInterval) {\n clearInterval(this._patchInterval);\n this._patchInterval = undefined;\n }\n\n if (milliseconds !== null && milliseconds !== 0) {\n this._patchInterval = setInterval(() => this.broadcastPatch(), milliseconds);\n }\n }\n\n public setState(newState: State) {\n this.clock.start();\n\n if ('_definition' in newState) {\n this.setSerializer(new SchemaSerializer());\n }\n\n this._serializer.reset(newState);\n\n this.state = newState;\n }\n\n public setSerializer(serializer: Serializer<State>) {\n this._serializer = serializer;\n }\n\n public async setMetadata(meta: Partial<Metadata>) {\n if (!this.listing.metadata) {\n this.listing.metadata = meta as Metadata;\n\n } else {\n for (const field in meta) {\n if (!meta.hasOwnProperty(field)) { continue; }\n this.listing.metadata[field] = meta[field];\n }\n\n // `MongooseDriver` workaround: persit metadata mutations\n if ('markModified' in this.listing) {\n (this.listing as any).markModified('metadata');\n }\n }\n\n if (this.internalState === RoomInternalState.CREATED) {\n await this.listing.save();\n }\n }\n\n public async setPrivate(bool: boolean = true) {\n this.listing.private = bool;\n\n if (this.internalState === RoomInternalState.CREATED) {\n await this.listing.save();\n }\n }\n\n public async lock() {\n // rooms locked internally aren't explicit locks.\n this._lockedExplicitly = (arguments[0] === undefined);\n\n // skip if already locked.\n if (this._locked) { return; }\n\n this._locked = true;\n\n await this.listing.updateOne({\n $set: { locked: this._locked },\n });\n\n this._events.emit('lock');\n }\n\n public async unlock() {\n // only internal usage passes arguments to this function.\n if (arguments[0] === undefined) {\n this._lockedExplicitly = false;\n }\n\n // skip if already locked\n if (!this._locked) { return; }\n\n this._locked = false;\n\n await this.listing.updateOne({\n $set: { locked: this._locked },\n });\n\n this._events.emit('unlock');\n }\n\n public send(client: Client, type: string | number, message: any, options?: ISendOptions): void;\n public send(client: Client, message: Schema, options?: ISendOptions): void;\n public send(client: Client, messageOrType: any, messageOrOptions?: any | ISendOptions, options?: ISendOptions): void {\n console.warn('DEPRECATION WARNING: use client.send(...) instead of this.send(client, ...)');\n client.send(messageOrType, messageOrOptions, options);\n }\n\n public broadcast(type: string | number, message?: any, options?: IBroadcastOptions);\n public broadcast<T extends Schema>(message: T, options?: IBroadcastOptions);\n public broadcast(\n typeOrSchema: string | number | Schema,\n messageOrOptions?: any | IBroadcastOptions,\n options?: IBroadcastOptions,\n ) {\n const isSchema = (typeof(typeOrSchema) === 'object');\n const opts: IBroadcastOptions = ((isSchema) ? messageOrOptions : options);\n\n if (opts && opts.afterNextPatch) {\n delete opts.afterNextPatch;\n this._afterNextPatchQueue.push(['broadcast', arguments]);\n return;\n }\n\n if (isSchema) {\n this.broadcastMessageSchema(typeOrSchema as Schema, opts);\n\n } else {\n this.broadcastMessageType(typeOrSchema as string, messageOrOptions, opts);\n }\n }\n\n public broadcastPatch() {\n if (!this._simulationInterval) {\n this.clock.tick();\n }\n\n if (!this.state) {\n return false;\n }\n\n const hasChanges = this._serializer.applyPatches(this.clients, this.state);\n\n // broadcast messages enqueued for \"after patch\"\n this._dequeueAfterPatchMessages();\n\n return hasChanges;\n }\n\n public onMessage<T = any>(messageType: '*', callback: (client: Client, type: string | number, message: T) => void);\n public onMessage<T = any>(messageType: string | number, callback: (client: Client, message: T) => void);\n public onMessage<T = any>(messageType: '*' | string | number, callback: (...args: any[]) => void) {\n this.onMessageHandlers[messageType] = callback;\n // returns a method to unbind the callback\n return () => delete this.onMessageHandlers[messageType];\n }\n\n public async disconnect(): Promise<any> {\n this.internalState = RoomInternalState.DISCONNECTING;\n await this.listing.remove();\n\n this.autoDispose = true;\n\n const delayedDisconnection = new Promise<void>((resolve) =>\n this._events.once('disconnect', () => resolve()));\n\n for (const reconnection of Object.values(this.reconnections)) {\n reconnection.reject();\n }\n\n let numClients = this.clients.length;\n if (numClients > 0) {\n // clients may have `async onLeave`, room will be disposed after they're fulfilled\n while (numClients--) {\n this._forciblyCloseClient(this.clients[numClients], Protocol.WS_CLOSE_CONSENTED);\n }\n } else {\n // no clients connected, dispose immediately.\n this._events.emit('dispose');\n }\n\n return await delayedDisconnection;\n }\n\n public async ['_onJoin'](client: Client, req?: http.IncomingMessage) {\n const sessionId = client.sessionId;\n\n if (this.reservedSeatTimeouts[sessionId]) {\n clearTimeout(this.reservedSeatTimeouts[sessionId]);\n delete this.reservedSeatTimeouts[sessionId];\n }\n\n // clear auto-dispose timeout.\n if (this._autoDisposeTimeout) {\n clearTimeout(this._autoDisposeTimeout);\n this._autoDisposeTimeout = undefined;\n }\n\n // get seat reservation options and clear it\n const options = this.reservedSeats[sessionId];\n delete this.reservedSeats[sessionId];\n\n // share \"after next patch queue\" reference with every client.\n client._afterNextPatchQueue = this._afterNextPatchQueue;\n\n // bind clean-up callback when client connection closes\n client.ref['onleave'] = this._onLeave.bind(this, client);\n client.ref.once('close', client.ref['onleave']);\n\n this.clients.push(client);\n\n const reconnection = this.reconnections[sessionId];\n if (reconnection) {\n reconnection.resolve(client);\n\n } else {\n try {\n client.auth = await this.onAuth(client, options, req);\n\n if (!client.auth) {\n throw new ServerError(ErrorCode.AUTH_FAILED, 'onAuth failed');\n }\n\n if (this.onJoin) {\n await this.onJoin(client, options, client.auth);\n }\n } catch (e) {\n spliceOne(this.clients, this.clients.indexOf(client));\n\n // make sure an error code is provided.\n if (!e.code) {\n e.code = ErrorCode.APPLICATION_ERROR;\n }\n\n throw e;\n\n } finally {\n // remove seat reservation\n delete this.reservedSeats[sessionId];\n }\n }\n\n // emit 'join' to room handler\n this._events.emit('join', client);\n\n // allow client to send messages after onJoin has succeeded.\n client.ref.on('message', this._onMessage.bind(this, client));\n\n // confirm room id that matches the room name requested to join\n client.raw(getMessageBytes[Protocol.JOIN_ROOM](\n this._serializer.id,\n this._serializer.handshake && this._serializer.handshake(),\n ));\n }\n\n public allowReconnection(previousClient: Client, seconds: number = Infinity): Deferred<Client> {\n if (this.internalState === RoomInternalState.DISCONNECTING) {\n this._disposeIfEmpty(); // gracefully shutting down\n throw new Error('disconnecting');\n }\n\n const sessionId = previousClient.sessionId;\n this._reserveSeat(sessionId, true, seconds, true);\n\n // keep reconnection reference in case the user reconnects into this room.\n const reconnection = new Deferred<Client>();\n this.reconnections[sessionId] = reconnection;\n\n if (seconds !== Infinity) {\n // expire seat reservation after timeout\n this.reservedSeatTimeouts[sessionId] = setTimeout(() =>\n reconnection.reject(false), seconds * 1000);\n }\n\n const cleanup = () => {\n delete this.reservedSeats[sessionId];\n delete this.reconnections[sessionId];\n delete this.reservedSeatTimeouts[sessionId];\n };\n\n reconnection.\n then((newClient) => {\n newClient.auth = previousClient.auth;\n newClient.userData = previousClient.userData;\n previousClient.ref = newClient.ref; // swap \"ref\" for convenience\n previousClient.state = ClientState.RECONNECTED;\n clearTimeout(this.reservedSeatTimeouts[sessionId]);\n cleanup();\n }).\n catch(() => {\n cleanup();\n this.resetAutoDisposeTimeout();\n });\n\n return reconnection;\n }\n\n protected resetAutoDisposeTimeout(timeoutInSeconds: number = 1) {\n clearTimeout(this._autoDisposeTimeout);\n\n if (!this.autoDispose) {\n return;\n }\n\n this._autoDisposeTimeout = setTimeout(() => {\n this._autoDisposeTimeout = undefined;\n this._disposeIfEmpty();\n }, timeoutInSeconds * 1000);\n }\n\n private broadcastMessageSchema<T extends Schema>(message: T, options: IBroadcastOptions = {}) {\n const encodedMessage = getMessageBytes[Protocol.ROOM_DATA_SCHEMA](message);\n\n let numClients = this.clients.length;\n while (numClients--) {\n const client = this.clients[numClients];\n\n if (options.except !== client) {\n client.enqueueRaw(encodedMessage);\n }\n }\n }\n\n private broadcastMessageType(type: string, message?: any, options: IBroadcastOptions = {}) {\n const encodedMessage = getMessageBytes[Protocol.ROOM_DATA](type, message);\n\n let numClients = this.clients.length;\n while (numClients--) {\n const client = this.clients[numClients];\n\n if (options.except !== client) {\n client.enqueueRaw(encodedMessage);\n }\n }\n }\n\n private sendFullState(client: Client): void {\n client.enqueueRaw(getMessageBytes[Protocol.ROOM_STATE](this._serializer.getFullState(client)));\n }\n\n private _dequeueAfterPatchMessages() {\n const length = this._afterNextPatchQueue.length;\n\n if (length > 0) {\n for (let i = 0; i < length; i++) {\n const [target, args] = this._afterNextPatchQueue[i];\n\n if (target === \"broadcast\") {\n this.broadcast.apply(this, args);\n\n } else {\n (target as Client).raw.apply(target, args);\n }\n }\n\n // new messages may have been added in the meantime,\n // let's splice the ones that have been processed\n this._afterNextPatchQueue.splice(0, length);\n }\n }\n\n private async _reserveSeat(\n sessionId: string,\n joinOptions: any = true,\n seconds: number = this.seatReservationTime,\n allowReconnection: boolean = false,\n ) {\n if (!allowReconnection && this.hasReachedMaxClients()) {\n return false;\n }\n\n this.reservedSeats[sessionId] = joinOptions;\n\n if (!allowReconnection) {\n await this._incrementClientCount();\n\n this.reservedSeatTimeouts[sessionId] = setTimeout(async () => {\n delete this.reservedSeats[sessionId];\n delete this.reservedSeatTimeouts[sessionId];\n await this._decrementClientCount();\n }, seconds * 1000);\n\n this.resetAutoDisposeTimeout(seconds);\n }\n\n return true;\n }\n\n private _disposeIfEmpty() {\n const willDispose = (\n this.autoDispose &&\n this._autoDisposeTimeout === undefined &&\n this.clients.length === 0 &&\n Object.keys(this.reservedSeats).length === 0\n );\n\n if (willDispose) {\n this._events.emit('dispose');\n }\n\n return willDispose;\n }\n\n private async _dispose(): Promise<any> {\n let userReturnData;\n\n if (this.onDispose) {\n userReturnData = this.onDispose();\n }\n\n if (this._patchInterval) {\n clearInterval(this._patchInterval);\n this._patchInterval = undefined;\n }\n\n if (this._simulationInterval) {\n clearInterval(this._simulationInterval);\n this._simulationInterval = undefined;\n }\n\n if (this._autoDisposeTimeout) {\n clearInterval(this._autoDisposeTimeout);\n this._autoDisposeTimeout = undefined;\n }\n\n // clear all timeouts/intervals + force to stop ticking\n this.clock.clear();\n this.clock.stop();\n\n return await (userReturnData || Promise.resolve());\n }\n\n private _onMessage(client: Client, bytes: number[]) {\n // skip if client is on LEAVING state.\n if (client.state === ClientState.LEAVING) { return; }\n\n const it: Iterator = { offset: 0 };\n const code = decode.uint8(bytes, it);\n\n if (!bytes) {\n debugAndPrintError(`${this.roomName} (${this.roomId}), couldn't decode message: ${bytes}`);\n return;\n }\n\n if (code === Protocol.ROOM_DATA) {\n const messageType = (decode.stringCheck(bytes, it))\n ? decode.string(bytes, it)\n : decode.number(bytes, it);\n\n let message;\n try {\n message = (bytes.length > it.offset)\n ? msgpack.decode(bytes.slice(it.offset, bytes.length))\n : undefined;\n } catch (e) {\n debugAndPrintError(e);\n return;\n }\n\n if (this.onMessageHandlers[messageType]) {\n this.onMessageHandlers[messageType](client, message);\n\n } else if (this.onMessageHandlers['*']) {\n (this.onMessageHandlers['*'] as any)(client, messageType, message);\n\n } else {\n debugAndPrintError(`onMessage for \"${messageType}\" not registered.`);\n }\n\n } else if (code === Protocol.JOIN_ROOM) {\n // join room has been acknowledged by the client\n client.state = ClientState.JOINED;\n\n // send current state when new client joins the room\n if (this.state) {\n this.sendFullState(client);\n }\n\n // dequeue messages sent before client has joined effectively (on user-defined `onJoin`)\n if (client._enqueuedMessages.length > 0) {\n client._enqueuedMessages.forEach((enqueued) => client.raw(enqueued));\n }\n delete client._enqueuedMessages;\n\n } else if (code === Protocol.LEAVE_ROOM) {\n this._forciblyCloseClient(client, Protocol.WS_CLOSE_CONSENTED);\n }\n\n }\n\n private _forciblyCloseClient(client: Client, closeCode: number) {\n // stop receiving messages from this client\n client.ref.removeAllListeners('message');\n\n // prevent \"onLeave\" from being called twice if player asks to leave\n client.ref.removeListener('close', client.ref['onleave']);\n\n // only effectively close connection when \"onLeave\" is fulfilled\n this._onLeave(client, closeCode).then(() => client.leave(Protocol.WS_CLOSE_NORMAL));\n }\n\n private async _onLeave(client: Client, code?: number): Promise<any> {\n const success = spliceOne(this.clients, this.clients.indexOf(client));\n\n // call 'onLeave' method only if the client has been successfully accepted.\n if (success && this.onLeave) {\n try {\n client.state = ClientState.LEAVING;\n await this.onLeave(client, (code === Protocol.WS_CLOSE_CONSENTED));\n\n } catch (e) {\n debugAndPrintError(`onLeave error: ${(e && e.message || e || 'promise rejected')}`);\n }\n }\n\n if (client.state !== ClientState.RECONNECTED) {\n // try to dispose immediatelly if client reconnection isn't set up.\n const willDispose = await this._decrementClientCount();\n\n this._events.emit('leave', client, willDispose);\n }\n }\n\n private async _incrementClientCount() {\n // lock automatically when maxClients is reached\n if (!this._locked && this.hasReachedMaxClients()) {\n this._maxClientsReached = true;\n this.lock.call(this, true);\n }\n\n await this.listing.updateOne({\n $inc: { clients: 1 },\n $set: { locked: this._locked },\n });\n }\n\n private async _decrementClientCount() {\n const willDispose = this._disposeIfEmpty();\n\n if (this.internalState === RoomInternalState.DISCONNECTING) {\n return;\n }\n\n // unlock if room is available for new connections\n if (!willDispose) {\n if (this._maxClientsReached && !this._lockedExplicitly) {\n this._maxClientsReached = false;\n this.unlock.call(this, true);\n }\n\n // update room listing cache\n await this.listing.updateOne({\n $inc: { clients: -1 },\n $set: { locked: this._locked },\n });\n }\n\n return willDispose;\n }\n\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Room.mjs","sources":["../src/Room.ts"],"sourcesContent":["import http from 'http';\nimport msgpack from 'notepack.io';\n\nimport { decode, Iterator, Schema } from '@colyseus/schema';\n\nimport Clock from '@gamestdio/timer';\nimport { EventEmitter } from 'events';\n\nimport { Presence } from './presence/Presence';\n\nimport { Serializer } from './serializer/Serializer';\nimport { NoneSerializer } from './serializer/NoneSerializer';\nimport { SchemaSerializer } from './serializer/SchemaSerializer';\n\nimport { ErrorCode, getMessageBytes, Protocol } from './Protocol';\nimport { Deferred, spliceOne } from './Utils';\n\nimport { debugAndPrintError, debugPatch } from './Debug';\nimport { ServerError } from './errors/ServerError';\nimport { Client, ClientState, ISendOptions } from './Transport';\nimport { RoomListingData } from './matchmaker/driver';\n\nconst DEFAULT_PATCH_RATE = 1000 / 20; // 20fps (50ms)\nconst DEFAULT_SIMULATION_INTERVAL = 1000 / 60; // 60fps (16.66ms)\nconst noneSerializer = new NoneSerializer();\n\nexport const DEFAULT_SEAT_RESERVATION_TIME = Number(process.env.COLYSEUS_SEAT_RESERVATION_TIME || 15);\n\nexport type SimulationCallback = (deltaTime: number) => void;\n\nexport type RoomConstructor<T= any> = new (presence?: Presence) => Room<T>;\n\nexport interface IBroadcastOptions extends ISendOptions {\n except?: Client;\n}\n\nexport enum RoomInternalState {\n CREATING = 0,\n CREATED = 1,\n DISCONNECTING = 2,\n}\n\nexport abstract class Room<State= any, Metadata= any> {\n\n public get locked() {\n return this._locked;\n }\n\n public get metadata() {\n return this.listing.metadata;\n }\n\n public listing: RoomListingData<Metadata>;\n public clock: Clock = new Clock();\n\n public roomId: string;\n public roomName: string;\n\n public maxClients: number = Infinity;\n public patchRate: number = DEFAULT_PATCH_RATE;\n public autoDispose: boolean = true;\n\n public state: State;\n public presence: Presence;\n\n public clients: Client[] = [];\n public internalState: RoomInternalState = RoomInternalState.CREATING;\n\n /** @internal */\n public _events = new EventEmitter();\n\n // seat reservation & reconnection\n protected seatReservationTime: number = DEFAULT_SEAT_RESERVATION_TIME;\n protected reservedSeats: { [sessionId: string]: any } = {};\n protected reservedSeatTimeouts: { [sessionId: string]: NodeJS.Timer } = {};\n\n protected reconnections: { [sessionId: string]: Deferred } = {};\n\n private onMessageHandlers: {[id: string]: (client: Client, message: any) => void} = {};\n\n private _serializer: Serializer<State> = noneSerializer;\n private _afterNextPatchQueue: Array<[string | Client, IArguments]> = [];\n\n private _simulationInterval: NodeJS.Timer;\n private _patchInterval: NodeJS.Timer;\n\n private _locked: boolean = false;\n private _lockedExplicitly: boolean = false;\n private _maxClientsReached: boolean = false;\n\n // this timeout prevents rooms that are created by one process, but no client\n // ever had success joining into it on the specified interval.\n private _autoDisposeTimeout: NodeJS.Timer;\n\n constructor(presence?: Presence) {\n this.presence = presence;\n\n this._events.once('dispose', async () => {\n try {\n await this._dispose();\n\n } catch (e) {\n debugAndPrintError(`onDispose error: ${(e && e.message || e || 'promise rejected')}`);\n }\n this._events.emit('disconnect');\n });\n\n this.setPatchRate(this.patchRate);\n // set default _autoDisposeTimeout\n this.resetAutoDisposeTimeout(this.seatReservationTime);\n }\n\n // Optional abstract methods\n public onCreate?(options: any): void | Promise<any>;\n public onJoin?(client: Client, options?: any, auth?: any): void | Promise<any>;\n public onLeave?(client: Client, consented?: boolean): void | Promise<any>;\n public onDispose?(): void | Promise<any>;\n public onAuth(client: Client, options: any, request?: http.IncomingMessage): any | Promise<any> {\n return true;\n }\n\n public hasReachedMaxClients(): boolean {\n return (this.clients.length + Object.keys(this.reservedSeats).length) >= this.maxClients;\n }\n\n public setSeatReservationTime(seconds: number) {\n this.seatReservationTime = seconds;\n return this;\n }\n\n public hasReservedSeat(sessionId: string): boolean {\n return this.reservedSeats[sessionId] !== undefined;\n }\n\n public setSimulationInterval(onTickCallback?: SimulationCallback, delay: number = DEFAULT_SIMULATION_INTERVAL): void {\n // clear previous interval in case called setSimulationInterval more than once\n if (this._simulationInterval) { clearInterval(this._simulationInterval); }\n\n if (onTickCallback) {\n this._simulationInterval = setInterval(() => {\n this.clock.tick();\n onTickCallback(this.clock.deltaTime);\n }, delay);\n }\n }\n\n public setPatchRate(milliseconds: number): void {\n this.patchRate = milliseconds;\n\n // clear previous interval in case called setPatchRate more than once\n if (this._patchInterval) {\n clearInterval(this._patchInterval);\n this._patchInterval = undefined;\n }\n\n if (milliseconds !== null && milliseconds !== 0) {\n this._patchInterval = setInterval(() => this.broadcastPatch(), milliseconds);\n }\n }\n\n public setState(newState: State) {\n this.clock.start();\n\n if ('_definition' in newState) {\n this.setSerializer(new SchemaSerializer());\n }\n\n this._serializer.reset(newState);\n\n this.state = newState;\n }\n\n public setSerializer(serializer: Serializer<State>) {\n this._serializer = serializer;\n }\n\n public async setMetadata(meta: Partial<Metadata>) {\n if (!this.listing.metadata) {\n this.listing.metadata = meta as Metadata;\n\n } else {\n for (const field in meta) {\n if (!meta.hasOwnProperty(field)) { continue; }\n this.listing.metadata[field] = meta[field];\n }\n\n // `MongooseDriver` workaround: persit metadata mutations\n if ('markModified' in this.listing) {\n (this.listing as any).markModified('metadata');\n }\n }\n\n if (this.internalState === RoomInternalState.CREATED) {\n await this.listing.save();\n }\n }\n\n public async setPrivate(bool: boolean = true) {\n this.listing.private = bool;\n\n if (this.internalState === RoomInternalState.CREATED) {\n await this.listing.save();\n }\n }\n\n public async lock() {\n // rooms locked internally aren't explicit locks.\n this._lockedExplicitly = (arguments[0] === undefined);\n\n // skip if already locked.\n if (this._locked) { return; }\n\n this._locked = true;\n\n await this.listing.updateOne({\n $set: { locked: this._locked },\n });\n\n this._events.emit('lock');\n }\n\n public async unlock() {\n // only internal usage passes arguments to this function.\n if (arguments[0] === undefined) {\n this._lockedExplicitly = false;\n }\n\n // skip if already locked\n if (!this._locked) { return; }\n\n this._locked = false;\n\n await this.listing.updateOne({\n $set: { locked: this._locked },\n });\n\n this._events.emit('unlock');\n }\n\n public send(client: Client, type: string | number, message: any, options?: ISendOptions): void;\n public send(client: Client, message: Schema, options?: ISendOptions): void;\n public send(client: Client, messageOrType: any, messageOrOptions?: any | ISendOptions, options?: ISendOptions): void {\n console.warn('DEPRECATION WARNING: use client.send(...) instead of this.send(client, ...)');\n client.send(messageOrType, messageOrOptions, options);\n }\n\n public broadcast(type: string | number, message?: any, options?: IBroadcastOptions);\n public broadcast<T extends Schema>(message: T, options?: IBroadcastOptions);\n public broadcast(\n typeOrSchema: string | number | Schema,\n messageOrOptions?: any | IBroadcastOptions,\n options?: IBroadcastOptions,\n ) {\n const isSchema = (typeof(typeOrSchema) === 'object');\n const opts: IBroadcastOptions = ((isSchema) ? messageOrOptions : options);\n\n if (opts && opts.afterNextPatch) {\n delete opts.afterNextPatch;\n this._afterNextPatchQueue.push(['broadcast', arguments]);\n return;\n }\n\n if (isSchema) {\n this.broadcastMessageSchema(typeOrSchema as Schema, opts);\n\n } else {\n this.broadcastMessageType(typeOrSchema as string, messageOrOptions, opts);\n }\n }\n\n public broadcastPatch() {\n if (!this._simulationInterval) {\n this.clock.tick();\n }\n\n if (!this.state) {\n return false;\n }\n\n const hasChanges = this._serializer.applyPatches(this.clients, this.state);\n\n // broadcast messages enqueued for \"after patch\"\n this._dequeueAfterPatchMessages();\n\n return hasChanges;\n }\n\n public onMessage<T = any>(messageType: '*', callback: (client: Client, type: string | number, message: T) => void);\n public onMessage<T = any>(messageType: string | number, callback: (client: Client, message: T) => void);\n public onMessage<T = any>(messageType: '*' | string | number, callback: (...args: any[]) => void) {\n this.onMessageHandlers[messageType] = callback;\n // returns a method to unbind the callback\n return () => delete this.onMessageHandlers[messageType];\n }\n\n public async disconnect(): Promise<any> {\n this.internalState = RoomInternalState.DISCONNECTING;\n await this.listing.remove();\n\n this.autoDispose = true;\n\n const delayedDisconnection = new Promise<void>((resolve) =>\n this._events.once('disconnect', () => resolve()));\n\n for (const reconnection of Object.values(this.reconnections)) {\n reconnection.reject();\n }\n\n let numClients = this.clients.length;\n if (numClients > 0) {\n // clients may have `async onLeave`, room will be disposed after they're fulfilled\n while (numClients--) {\n this._forciblyCloseClient(this.clients[numClients], Protocol.WS_CLOSE_CONSENTED);\n }\n } else {\n // no clients connected, dispose immediately.\n this._events.emit('dispose');\n }\n\n return await delayedDisconnection;\n }\n\n public async ['_onJoin'](client: Client, req?: http.IncomingMessage) {\n const sessionId = client.sessionId;\n\n if (this.reservedSeatTimeouts[sessionId]) {\n clearTimeout(this.reservedSeatTimeouts[sessionId]);\n delete this.reservedSeatTimeouts[sessionId];\n }\n\n // clear auto-dispose timeout.\n if (this._autoDisposeTimeout) {\n clearTimeout(this._autoDisposeTimeout);\n this._autoDisposeTimeout = undefined;\n }\n\n // get seat reservation options and clear it\n const options = this.reservedSeats[sessionId];\n delete this.reservedSeats[sessionId];\n\n // share \"after next patch queue\" reference with every client.\n client._afterNextPatchQueue = this._afterNextPatchQueue;\n\n // bind clean-up callback when client connection closes\n client.ref['onleave'] = this._onLeave.bind(this, client);\n client.ref.once('close', client.ref['onleave']);\n\n this.clients.push(client);\n\n const reconnection = this.reconnections[sessionId];\n if (reconnection) {\n reconnection.resolve(client);\n\n } else {\n try {\n client.auth = await this.onAuth(client, options, req);\n\n if (!client.auth) {\n throw new ServerError(ErrorCode.AUTH_FAILED, 'onAuth failed');\n }\n\n if (this.onJoin) {\n await this.onJoin(client, options, client.auth);\n }\n } catch (e) {\n spliceOne(this.clients, this.clients.indexOf(client));\n\n // make sure an error code is provided.\n if (!e.code) {\n e.code = ErrorCode.APPLICATION_ERROR;\n }\n\n throw e;\n\n } finally {\n // remove seat reservation\n delete this.reservedSeats[sessionId];\n }\n }\n\n // emit 'join' to room handler\n this._events.emit('join', client);\n\n // allow client to send messages after onJoin has succeeded.\n client.ref.on('message', this._onMessage.bind(this, client));\n\n // confirm room id that matches the room name requested to join\n client.raw(getMessageBytes[Protocol.JOIN_ROOM](\n this._serializer.id,\n this._serializer.handshake && this._serializer.handshake(),\n ));\n }\n\n public allowReconnection(previousClient: Client, seconds: number = Infinity): Deferred<Client> {\n if (this.internalState === RoomInternalState.DISCONNECTING) {\n this._disposeIfEmpty(); // gracefully shutting down\n throw new Error('disconnecting');\n }\n\n const sessionId = previousClient.sessionId;\n this._reserveSeat(sessionId, true, seconds, true);\n\n // keep reconnection reference in case the user reconnects into this room.\n const reconnection = new Deferred<Client>();\n this.reconnections[sessionId] = reconnection;\n\n if (seconds !== Infinity) {\n // expire seat reservation after timeout\n this.reservedSeatTimeouts[sessionId] = setTimeout(() =>\n reconnection.reject(false), seconds * 1000);\n }\n\n const cleanup = () => {\n delete this.reservedSeats[sessionId];\n delete this.reconnections[sessionId];\n delete this.reservedSeatTimeouts[sessionId];\n };\n\n reconnection.\n then((newClient) => {\n newClient.auth = previousClient.auth;\n newClient.userData = previousClient.userData;\n previousClient.ref = newClient.ref; // swap \"ref\" for convenience\n previousClient.state = ClientState.RECONNECTED;\n clearTimeout(this.reservedSeatTimeouts[sessionId]);\n cleanup();\n }).\n catch(() => {\n cleanup();\n this.resetAutoDisposeTimeout();\n });\n\n return reconnection;\n }\n\n protected resetAutoDisposeTimeout(timeoutInSeconds: number = 1) {\n clearTimeout(this._autoDisposeTimeout);\n\n if (!this.autoDispose) {\n return;\n }\n\n this._autoDisposeTimeout = setTimeout(() => {\n this._autoDisposeTimeout = undefined;\n this._disposeIfEmpty();\n }, timeoutInSeconds * 1000);\n }\n\n private broadcastMessageSchema<T extends Schema>(message: T, options: IBroadcastOptions = {}) {\n const encodedMessage = getMessageBytes[Protocol.ROOM_DATA_SCHEMA](message);\n\n let numClients = this.clients.length;\n while (numClients--) {\n const client = this.clients[numClients];\n\n if (options.except !== client) {\n client.enqueueRaw(encodedMessage);\n }\n }\n }\n\n private broadcastMessageType(type: string, message?: any, options: IBroadcastOptions = {}) {\n const encodedMessage = getMessageBytes[Protocol.ROOM_DATA](type, message);\n\n let numClients = this.clients.length;\n while (numClients--) {\n const client = this.clients[numClients];\n\n if (options.except !== client) {\n client.enqueueRaw(encodedMessage);\n }\n }\n }\n\n private sendFullState(client: Client): void {\n client.enqueueRaw(getMessageBytes[Protocol.ROOM_STATE](this._serializer.getFullState(client)));\n }\n\n private _dequeueAfterPatchMessages() {\n const length = this._afterNextPatchQueue.length;\n\n if (length > 0) {\n for (let i = 0; i < length; i++) {\n const [target, args] = this._afterNextPatchQueue[i];\n\n if (target === \"broadcast\") {\n this.broadcast.apply(this, args);\n\n } else {\n (target as Client).raw.apply(target, args);\n }\n }\n\n // new messages may have been added in the meantime,\n // let's splice the ones that have been processed\n this._afterNextPatchQueue.splice(0, length);\n }\n }\n\n private async _reserveSeat(\n sessionId: string,\n joinOptions: any = true,\n seconds: number = this.seatReservationTime,\n allowReconnection: boolean = false,\n ) {\n if (!allowReconnection && this.hasReachedMaxClients()) {\n return false;\n }\n\n this.reservedSeats[sessionId] = joinOptions;\n\n if (!allowReconnection) {\n await this._incrementClientCount();\n\n this.reservedSeatTimeouts[sessionId] = setTimeout(async () => {\n delete this.reservedSeats[sessionId];\n delete this.reservedSeatTimeouts[sessionId];\n await this._decrementClientCount();\n }, seconds * 1000);\n\n this.resetAutoDisposeTimeout(seconds);\n }\n\n return true;\n }\n\n private _disposeIfEmpty() {\n const willDispose = (\n this.autoDispose &&\n this._autoDisposeTimeout === undefined &&\n this.clients.length === 0 &&\n Object.keys(this.reservedSeats).length === 0\n );\n\n if (willDispose) {\n this._events.emit('dispose');\n }\n\n return willDispose;\n }\n\n private async _dispose(): Promise<any> {\n let userReturnData;\n\n if (this.onDispose) {\n userReturnData = this.onDispose();\n }\n\n if (this._patchInterval) {\n clearInterval(this._patchInterval);\n this._patchInterval = undefined;\n }\n\n if (this._simulationInterval) {\n clearInterval(this._simulationInterval);\n this._simulationInterval = undefined;\n }\n\n if (this._autoDisposeTimeout) {\n clearInterval(this._autoDisposeTimeout);\n this._autoDisposeTimeout = undefined;\n }\n\n // clear all timeouts/intervals + force to stop ticking\n this.clock.clear();\n this.clock.stop();\n\n return await (userReturnData || Promise.resolve());\n }\n\n private _onMessage(client: Client, bytes: number[]) {\n // skip if client is on LEAVING state.\n if (client.state === ClientState.LEAVING) { return; }\n\n const it: Iterator = { offset: 0 };\n const code = decode.uint8(bytes, it);\n\n if (!bytes) {\n debugAndPrintError(`${this.roomName} (${this.roomId}), couldn't decode message: ${bytes}`);\n return;\n }\n\n if (code === Protocol.ROOM_DATA) {\n const messageType = (decode.stringCheck(bytes, it))\n ? decode.string(bytes, it)\n : decode.number(bytes, it);\n\n let message;\n try {\n message = (bytes.length > it.offset)\n ? msgpack.decode(bytes.slice(it.offset, bytes.length))\n : undefined;\n } catch (e) {\n debugAndPrintError(e);\n return;\n }\n\n if (this.onMessageHandlers[messageType]) {\n this.onMessageHandlers[messageType](client, message);\n\n } else if (this.onMessageHandlers['*']) {\n (this.onMessageHandlers['*'] as any)(client, messageType, message);\n\n } else {\n debugAndPrintError(`onMessage for \"${messageType}\" not registered.`);\n }\n\n } else if (code === Protocol.JOIN_ROOM && client.state === ClientState.JOINING) {\n // join room has been acknowledged by the client\n client.state = ClientState.JOINED;\n\n // send current state when new client joins the room\n if (this.state) {\n this.sendFullState(client);\n }\n\n // dequeue messages sent before client has joined effectively (on user-defined `onJoin`)\n if (client._enqueuedMessages.length > 0) {\n client._enqueuedMessages.forEach((enqueued) => client.raw(enqueued));\n }\n delete client._enqueuedMessages;\n\n } else if (code === Protocol.LEAVE_ROOM) {\n this._forciblyCloseClient(client, Protocol.WS_CLOSE_CONSENTED);\n }\n\n }\n\n private _forciblyCloseClient(client: Client, closeCode: number) {\n // stop receiving messages from this client\n client.ref.removeAllListeners('message');\n\n // prevent \"onLeave\" from being called twice if player asks to leave\n client.ref.removeListener('close', client.ref['onleave']);\n\n // only effectively close connection when \"onLeave\" is fulfilled\n this._onLeave(client, closeCode).then(() => client.leave(Protocol.WS_CLOSE_NORMAL));\n }\n\n private async _onLeave(client: Client, code?: number): Promise<any> {\n const success = spliceOne(this.clients, this.clients.indexOf(client));\n\n // call 'onLeave' method only if the client has been successfully accepted.\n if (success && this.onLeave) {\n try {\n client.state = ClientState.LEAVING;\n await this.onLeave(client, (code === Protocol.WS_CLOSE_CONSENTED));\n\n } catch (e) {\n debugAndPrintError(`onLeave error: ${(e && e.message || e || 'promise rejected')}`);\n }\n }\n\n if (client.state !== ClientState.RECONNECTED) {\n // try to dispose immediatelly if client reconnection isn't set up.\n const willDispose = await this._decrementClientCount();\n\n this._events.emit('leave', client, willDispose);\n }\n }\n\n private async _incrementClientCount() {\n // lock automatically when maxClients is reached\n if (!this._locked && this.hasReachedMaxClients()) {\n this._maxClientsReached = true;\n this.lock.call(this, true);\n }\n\n await this.listing.updateOne({\n $inc: { clients: 1 },\n $set: { locked: this._locked },\n });\n }\n\n private async _decrementClientCount() {\n const willDispose = this._disposeIfEmpty();\n\n if (this.internalState === RoomInternalState.DISCONNECTING) {\n return;\n }\n\n // unlock if room is available for new connections\n if (!willDispose) {\n if (this._maxClientsReached && !this._lockedExplicitly) {\n this._maxClientsReached = false;\n this.unlock.call(this, true);\n }\n\n // update room listing cache\n await this.listing.updateOne({\n $inc: { clients: -1 },\n $set: { locked: this._locked },\n });\n }\n\n return willDispose;\n }\n\n}\n"],"names":[],"mappings":"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"}
|
package/build/Server.d.ts
CHANGED
|
@@ -11,6 +11,11 @@ export declare type ServerOptions = {
|
|
|
11
11
|
driver?: matchMaker.MatchMakerDriver;
|
|
12
12
|
transport?: Transport;
|
|
13
13
|
gracefullyShutdown?: boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Display greeting message on server start.
|
|
16
|
+
* Default: true
|
|
17
|
+
*/
|
|
18
|
+
greet?: boolean;
|
|
14
19
|
/**
|
|
15
20
|
* Options below are now part of WebSocketTransport (@colyseus/ws-transport)
|
|
16
21
|
* TODO: remove me on 0.15.0
|
|
@@ -30,6 +35,7 @@ export declare class Server {
|
|
|
30
35
|
protected port: number;
|
|
31
36
|
protected driver: matchMaker.MatchMakerDriver;
|
|
32
37
|
protected processId: string;
|
|
38
|
+
protected greet: boolean;
|
|
33
39
|
private matchmakeRoute;
|
|
34
40
|
private allowedRoomNameChars;
|
|
35
41
|
constructor(options?: ServerOptions);
|
package/build/Server.js
CHANGED
|
@@ -23,12 +23,14 @@ class Server {
|
|
|
23
23
|
port;
|
|
24
24
|
driver;
|
|
25
25
|
processId = Utils.generateId();
|
|
26
|
+
greet;
|
|
26
27
|
matchmakeRoute = 'matchmake';
|
|
27
28
|
allowedRoomNameChars = /([a-zA-Z_\-0-9]+)/gi;
|
|
28
29
|
constructor(options = {}) {
|
|
29
|
-
const { gracefullyShutdown = true } = options;
|
|
30
|
+
const { gracefullyShutdown = true, greet = true } = options;
|
|
30
31
|
this.presence = options.presence || new LocalPresence.LocalPresence();
|
|
31
32
|
this.driver = options.driver || new index.LocalDriver();
|
|
33
|
+
this.greet = greet;
|
|
32
34
|
// setup matchmaker
|
|
33
35
|
MatchMaker.setup(this.presence, this.driver, this.processId);
|
|
34
36
|
// "presence" option is not used from now on
|
|
@@ -76,6 +78,12 @@ class Server {
|
|
|
76
78
|
*/
|
|
77
79
|
async listen(port, hostname, backlog, listeningListener) {
|
|
78
80
|
this.port = port;
|
|
81
|
+
/**
|
|
82
|
+
* Display greeting log
|
|
83
|
+
*/
|
|
84
|
+
if (this.greet) {
|
|
85
|
+
console.log();
|
|
86
|
+
}
|
|
79
87
|
return new Promise((resolve, reject) => {
|
|
80
88
|
this.transport.server?.on('error', (err) => reject(err));
|
|
81
89
|
this.transport.listen(port, hostname, backlog, (err) => {
|
package/build/Server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Server.js","sources":["../src/Server.ts"],"sourcesContent":["import http, { IncomingMessage, ServerResponse } from 'http';\n\nimport { debugAndPrintError, debugMatchMaking } from './Debug';\nimport * as matchMaker from './MatchMaker';\nimport { RegisteredHandler } from './matchmaker/RegisteredHandler';\nimport { Presence } from './presence/Presence';\n\nimport { Room } from './Room';\nimport { Type } from './types';\nimport { registerGracefulShutdown } from './Utils';\n\nimport { generateId } from '.';\nimport { registerNode, unregisterNode } from './discovery';\n\nimport { LocalPresence } from './presence/LocalPresence';\nimport { LocalDriver } from './matchmaker/driver';\n\nimport { Transport } from './Transport';\n\n// IServerOptions &\nexport type ServerOptions = {\n presence?: Presence,\n driver?: matchMaker.MatchMakerDriver,\n transport?: Transport,\n gracefullyShutdown?: boolean,\n\n /**\n * Options below are now part of WebSocketTransport (@colyseus/ws-transport)\n * TODO: remove me on 0.15.0\n */\n /** @deprecated */\n pingInterval?: number,\n\n /** @deprecated */\n pingMaxRetries?: number,\n\n /** @deprecated */\n verifyClient?: any,\n\n /** @deprecated */\n server?: http.Server,\n};\n\nexport class Server {\n public transport: Transport;\n\n protected presence: Presence;\n protected port: number;\n protected driver: matchMaker.MatchMakerDriver;\n protected processId: string = generateId();\n\n private matchmakeRoute = 'matchmake';\n private allowedRoomNameChars = /([a-zA-Z_\\-0-9]+)/gi;\n\n constructor(options: ServerOptions = {}) {\n const { gracefullyShutdown = true } = options;\n\n this.presence = options.presence || new LocalPresence();\n this.driver = options.driver || new LocalDriver();\n\n // setup matchmaker\n matchMaker.setup(this.presence, this.driver, this.processId);\n\n // \"presence\" option is not used from now on\n delete options.presence;\n\n this.attach(options);\n\n if (gracefullyShutdown) {\n registerGracefulShutdown((err) => this.gracefullyShutdown(true, err));\n }\n }\n\n public attach(options: ServerOptions) {\n /**\n * Display deprecation warnings for moved Transport options.\n * TODO: Remove me on 0.15\n */\n if (\n options.pingInterval !== undefined ||\n options.pingMaxRetries !== undefined ||\n options.server !== undefined ||\n options.verifyClient !== undefined\n ) {\n console.warn(\"DEPRECATION WARNING: 'pingInterval', 'pingMaxRetries', 'server', and 'verifyClient' Server options will be permanently moved to WebSocketTransport on v0.15\");\n console.warn(`new Server({\n transport: new WebSocketTransport({\n pingInterval: ...,\n pingMaxRetries: ...,\n server: ...,\n verifyClient: ...\n })\n})`);\n console.warn(\"👉 Documentation: https://docs.colyseus.io/server/transport/\")\n }\n\n const transport = options.transport || this.getDefaultTransport(options);\n delete options.transport;\n\n this.transport = transport;\n\n if (this.transport.server) {\n this.transport.server.once('listening', () => this.registerProcessForDiscovery());\n this.attachMatchMakingRoutes(this.transport.server as http.Server);\n }\n }\n\n /**\n * Bind the server into the port specified.\n *\n * @param port\n * @param hostname\n * @param backlog\n * @param listeningListener\n */\n public async listen(port: number, hostname?: string, backlog?: number, listeningListener?: Function) {\n this.port = port;\n\n return new Promise<void>((resolve, reject) => {\n this.transport.server?.on('error', (err) => reject(err));\n this.transport.listen(port, hostname, backlog, (err) => {\n if (listeningListener) {\n listeningListener(err);\n }\n\n if (err) {\n reject(err);\n\n } else {\n resolve();\n }\n });\n });\n }\n\n public registerProcessForDiscovery() {\n // register node for proxy/service discovery\n registerNode(this.presence, {\n port: this.port,\n processId: this.processId,\n });\n }\n\n /**\n * Define a new type of room for matchmaking.\n *\n * @param name public room identifier for match-making.\n * @param handler Room class definition\n * @param defaultOptions default options for `onCreate`\n */\n public define<T extends Type<Room>>(\n name: string,\n handler: T,\n defaultOptions?: Parameters<NonNullable<InstanceType<T>['onCreate']>>[0],\n ): RegisteredHandler {\n return matchMaker.defineRoomType(name, handler, defaultOptions);\n }\n\n public async gracefullyShutdown(exit: boolean = true, err?: Error) {\n try {\n await this.onShutdownCallback();\n\n await unregisterNode(this.presence, {\n port: this.port,\n processId: this.processId,\n });\n\n await matchMaker.gracefullyShutdown();\n\n this.transport.shutdown();\n this.presence.shutdown();\n this.driver.shutdown();\n\n } catch (e) {\n debugAndPrintError(`error during shutdown: ${e}`);\n\n } finally {\n if (exit) {\n process.exit(err ? 1 : 0);\n }\n }\n }\n\n /**\n * Add simulated latency between client and server.\n * @param milliseconds round trip latency in milliseconds.\n */\n public simulateLatency(milliseconds: number) {\n console.warn(`📶️❗ Colyseus latency simulation enabled → ${milliseconds}ms latency for round trip.`);\n\n const halfwayMS = (milliseconds / 2);\n this.transport.simulateLatency(halfwayMS);\n\n /* tslint:disable:no-string-literal */\n const _onMessage = Room.prototype['_onMessage'];\n /* tslint:disable:no-string-literal */\n Room.prototype['_onMessage'] = function (client, buffer) {\n // uWebSockets.js: duplicate buffer because it is cleared at native layer before the timeout.\n const cachedBuffer = Buffer.from(buffer);\n setTimeout(() => _onMessage.call(this, client, cachedBuffer), halfwayMS);\n };\n }\n\n /**\n * Register a callback that is going to be executed before the server shuts down.\n * @param callback\n */\n public onShutdown(callback: () => void | Promise<any>) {\n this.onShutdownCallback = callback;\n }\n\n protected getDefaultTransport(_: any): Transport {\n throw new Error(\"Please provide a 'transport' layer. Default transport not set.\");\n }\n\n protected onShutdownCallback: () => void | Promise<any> =\n () => Promise.resolve()\n\n protected attachMatchMakingRoutes(server: http.Server) {\n const listeners = server.listeners('request').slice(0);\n server.removeAllListeners('request');\n\n server.on('request', (req, res) => {\n if (req.url.indexOf(`/${this.matchmakeRoute}`) !== -1) {\n debugMatchMaking('received matchmake request: %s', req.url);\n this.handleMatchMakeRequest(req, res);\n\n } else {\n for (let i = 0, l = listeners.length; i < l; i++) {\n listeners[i].call(server, req, res);\n }\n }\n });\n }\n\n protected async handleMatchMakeRequest(req: IncomingMessage, res: ServerResponse) {\n const headers = {\n 'Access-Control-Allow-Headers': 'Origin, X-Requested-With, Content-Type, Accept',\n 'Access-Control-Allow-Methods': 'OPTIONS, POST, GET',\n 'Access-Control-Allow-Origin': '*',\n 'Access-Control-Max-Age': 2592000,\n // ...\n };\n\n if (req.method === 'OPTIONS') {\n res.writeHead(204, headers);\n res.end();\n\n } else if (req.method === 'POST') {\n const matchedParams = req.url.match(this.allowedRoomNameChars);\n const matchmakeIndex = matchedParams.indexOf(this.matchmakeRoute);\n const method = matchedParams[matchmakeIndex + 1];\n const name = matchedParams[matchmakeIndex + 2] || '';\n\n const data = [];\n req.on('data', (chunk) => data.push(chunk));\n req.on('end', async () => {\n headers['Content-Type'] = 'application/json';\n res.writeHead(200, headers);\n\n try {\n const clientOptions = JSON.parse(Buffer.concat(data).toString());\n const response = await matchMaker.controller.invokeMethod(method, name, clientOptions);\n res.write(JSON.stringify(response));\n\n } catch (e) {\n res.write(JSON.stringify({ code: e.code, error: e.message, }));\n }\n\n res.end();\n });\n\n } else if (req.method === 'GET') {\n const matchedParams = req.url.match(this.allowedRoomNameChars);\n const roomName = matchedParams.length > 1 ? matchedParams[matchedParams.length - 1] : \"\";\n\n headers['Content-Type'] = 'application/json';\n res.writeHead(200, headers);\n res.write(JSON.stringify(await matchMaker.controller.getAvailableRooms(roomName)));\n res.end();\n }\n\n }\n\n}\n"],"names":["generateId","LocalPresence","LocalDriver","matchMaker.setup","registerGracefulShutdown","registerNode","matchMaker.defineRoomType","unregisterNode","matchMaker.gracefullyShutdown","debugAndPrintError","Room","debugMatchMaking","matchMaker.controller.invokeMethod","matchMaker.controller.getAvailableRooms"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Server.js","sources":["../src/Server.ts"],"sourcesContent":["import http, { IncomingMessage, ServerResponse } from 'http';\n\nimport { debugAndPrintError, debugMatchMaking } from './Debug';\nimport * as matchMaker from './MatchMaker';\nimport { RegisteredHandler } from './matchmaker/RegisteredHandler';\nimport { Presence } from './presence/Presence';\n\nimport { Room } from './Room';\nimport { Type } from './types';\nimport { registerGracefulShutdown } from './Utils';\n\nimport { generateId } from '.';\nimport { registerNode, unregisterNode } from './discovery';\n\nimport { LocalPresence } from './presence/LocalPresence';\nimport { LocalDriver } from './matchmaker/driver';\n\nimport { Transport } from './Transport';\n\n// IServerOptions &\nexport type ServerOptions = {\n presence?: Presence,\n driver?: matchMaker.MatchMakerDriver,\n transport?: Transport,\n gracefullyShutdown?: boolean,\n\n /**\n * Display greeting message on server start.\n * Default: true\n */\n greet?: boolean,\n\n /**\n * Options below are now part of WebSocketTransport (@colyseus/ws-transport)\n * TODO: remove me on 0.15.0\n */\n /** @deprecated */\n pingInterval?: number,\n\n /** @deprecated */\n pingMaxRetries?: number,\n\n /** @deprecated */\n verifyClient?: any,\n\n /** @deprecated */\n server?: http.Server,\n};\n\nexport class Server {\n public transport: Transport;\n\n protected presence: Presence;\n protected port: number;\n protected driver: matchMaker.MatchMakerDriver;\n protected processId: string = generateId();\n\n protected greet: boolean;\n\n private matchmakeRoute = 'matchmake';\n private allowedRoomNameChars = /([a-zA-Z_\\-0-9]+)/gi;\n\n constructor(options: ServerOptions = {}) {\n const { gracefullyShutdown = true, greet = true } = options;\n\n this.presence = options.presence || new LocalPresence();\n this.driver = options.driver || new LocalDriver();\n this.greet = greet;\n\n // setup matchmaker\n matchMaker.setup(this.presence, this.driver, this.processId);\n\n // \"presence\" option is not used from now on\n delete options.presence;\n\n this.attach(options);\n\n if (gracefullyShutdown) {\n registerGracefulShutdown((err) => this.gracefullyShutdown(true, err));\n }\n }\n\n public attach(options: ServerOptions) {\n /**\n * Display deprecation warnings for moved Transport options.\n * TODO: Remove me on 0.15\n */\n if (\n options.pingInterval !== undefined ||\n options.pingMaxRetries !== undefined ||\n options.server !== undefined ||\n options.verifyClient !== undefined\n ) {\n console.warn(\"DEPRECATION WARNING: 'pingInterval', 'pingMaxRetries', 'server', and 'verifyClient' Server options will be permanently moved to WebSocketTransport on v0.15\");\n console.warn(`new Server({\n transport: new WebSocketTransport({\n pingInterval: ...,\n pingMaxRetries: ...,\n server: ...,\n verifyClient: ...\n })\n})`);\n console.warn(\"👉 Documentation: https://docs.colyseus.io/server/transport/\")\n }\n\n const transport = options.transport || this.getDefaultTransport(options);\n delete options.transport;\n\n this.transport = transport;\n\n if (this.transport.server) {\n this.transport.server.once('listening', () => this.registerProcessForDiscovery());\n this.attachMatchMakingRoutes(this.transport.server as http.Server);\n }\n }\n\n /**\n * Bind the server into the port specified.\n *\n * @param port\n * @param hostname\n * @param backlog\n * @param listeningListener\n */\n public async listen(port: number, hostname?: string, backlog?: number, listeningListener?: Function) {\n this.port = port;\n\n /**\n * Display greeting log\n */\n if (this.greet) {\n console.log();\n }\n\n return new Promise<void>((resolve, reject) => {\n this.transport.server?.on('error', (err) => reject(err));\n this.transport.listen(port, hostname, backlog, (err) => {\n if (listeningListener) {\n listeningListener(err);\n }\n\n if (err) {\n reject(err);\n\n } else {\n resolve();\n }\n });\n });\n }\n\n public registerProcessForDiscovery() {\n // register node for proxy/service discovery\n registerNode(this.presence, {\n port: this.port,\n processId: this.processId,\n });\n }\n\n /**\n * Define a new type of room for matchmaking.\n *\n * @param name public room identifier for match-making.\n * @param handler Room class definition\n * @param defaultOptions default options for `onCreate`\n */\n public define<T extends Type<Room>>(\n name: string,\n handler: T,\n defaultOptions?: Parameters<NonNullable<InstanceType<T>['onCreate']>>[0],\n ): RegisteredHandler {\n return matchMaker.defineRoomType(name, handler, defaultOptions);\n }\n\n public async gracefullyShutdown(exit: boolean = true, err?: Error) {\n try {\n await this.onShutdownCallback();\n\n await unregisterNode(this.presence, {\n port: this.port,\n processId: this.processId,\n });\n\n await matchMaker.gracefullyShutdown();\n\n this.transport.shutdown();\n this.presence.shutdown();\n this.driver.shutdown();\n\n } catch (e) {\n debugAndPrintError(`error during shutdown: ${e}`);\n\n } finally {\n if (exit) {\n process.exit(err ? 1 : 0);\n }\n }\n }\n\n /**\n * Add simulated latency between client and server.\n * @param milliseconds round trip latency in milliseconds.\n */\n public simulateLatency(milliseconds: number) {\n console.warn(`📶️❗ Colyseus latency simulation enabled → ${milliseconds}ms latency for round trip.`);\n\n const halfwayMS = (milliseconds / 2);\n this.transport.simulateLatency(halfwayMS);\n\n /* tslint:disable:no-string-literal */\n const _onMessage = Room.prototype['_onMessage'];\n /* tslint:disable:no-string-literal */\n Room.prototype['_onMessage'] = function (client, buffer) {\n // uWebSockets.js: duplicate buffer because it is cleared at native layer before the timeout.\n const cachedBuffer = Buffer.from(buffer);\n setTimeout(() => _onMessage.call(this, client, cachedBuffer), halfwayMS);\n };\n }\n\n /**\n * Register a callback that is going to be executed before the server shuts down.\n * @param callback\n */\n public onShutdown(callback: () => void | Promise<any>) {\n this.onShutdownCallback = callback;\n }\n\n protected getDefaultTransport(_: any): Transport {\n throw new Error(\"Please provide a 'transport' layer. Default transport not set.\");\n }\n\n protected onShutdownCallback: () => void | Promise<any> =\n () => Promise.resolve()\n\n protected attachMatchMakingRoutes(server: http.Server) {\n const listeners = server.listeners('request').slice(0);\n server.removeAllListeners('request');\n\n server.on('request', (req, res) => {\n if (req.url.indexOf(`/${this.matchmakeRoute}`) !== -1) {\n debugMatchMaking('received matchmake request: %s', req.url);\n this.handleMatchMakeRequest(req, res);\n\n } else {\n for (let i = 0, l = listeners.length; i < l; i++) {\n listeners[i].call(server, req, res);\n }\n }\n });\n }\n\n protected async handleMatchMakeRequest(req: IncomingMessage, res: ServerResponse) {\n const headers = {\n 'Access-Control-Allow-Headers': 'Origin, X-Requested-With, Content-Type, Accept',\n 'Access-Control-Allow-Methods': 'OPTIONS, POST, GET',\n 'Access-Control-Allow-Origin': '*',\n 'Access-Control-Max-Age': 2592000,\n // ...\n };\n\n if (req.method === 'OPTIONS') {\n res.writeHead(204, headers);\n res.end();\n\n } else if (req.method === 'POST') {\n const matchedParams = req.url.match(this.allowedRoomNameChars);\n const matchmakeIndex = matchedParams.indexOf(this.matchmakeRoute);\n const method = matchedParams[matchmakeIndex + 1];\n const name = matchedParams[matchmakeIndex + 2] || '';\n\n const data = [];\n req.on('data', (chunk) => data.push(chunk));\n req.on('end', async () => {\n headers['Content-Type'] = 'application/json';\n res.writeHead(200, headers);\n\n try {\n const clientOptions = JSON.parse(Buffer.concat(data).toString());\n const response = await matchMaker.controller.invokeMethod(method, name, clientOptions);\n res.write(JSON.stringify(response));\n\n } catch (e) {\n res.write(JSON.stringify({ code: e.code, error: e.message, }));\n }\n\n res.end();\n });\n\n } else if (req.method === 'GET') {\n const matchedParams = req.url.match(this.allowedRoomNameChars);\n const roomName = matchedParams.length > 1 ? matchedParams[matchedParams.length - 1] : \"\";\n\n headers['Content-Type'] = 'application/json';\n res.writeHead(200, headers);\n res.write(JSON.stringify(await matchMaker.controller.getAvailableRooms(roomName)));\n res.end();\n }\n\n }\n\n}\n"],"names":["generateId","LocalPresence","LocalDriver","matchMaker.setup","registerGracefulShutdown","registerNode","matchMaker.defineRoomType","unregisterNode","matchMaker.gracefullyShutdown","debugAndPrintError","Room","debugMatchMaking","matchMaker.controller.invokeMethod","matchMaker.controller.getAvailableRooms"],"mappings":"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"}
|
package/build/Server.mjs
CHANGED
|
@@ -19,12 +19,14 @@ class Server {
|
|
|
19
19
|
port;
|
|
20
20
|
driver;
|
|
21
21
|
processId = generateId();
|
|
22
|
+
greet;
|
|
22
23
|
matchmakeRoute = 'matchmake';
|
|
23
24
|
allowedRoomNameChars = /([a-zA-Z_\-0-9]+)/gi;
|
|
24
25
|
constructor(options = {}) {
|
|
25
|
-
const { gracefullyShutdown = true } = options;
|
|
26
|
+
const { gracefullyShutdown = true, greet = true } = options;
|
|
26
27
|
this.presence = options.presence || new LocalPresence();
|
|
27
28
|
this.driver = options.driver || new LocalDriver();
|
|
29
|
+
this.greet = greet;
|
|
28
30
|
// setup matchmaker
|
|
29
31
|
setup(this.presence, this.driver, this.processId);
|
|
30
32
|
// "presence" option is not used from now on
|
|
@@ -72,6 +74,12 @@ class Server {
|
|
|
72
74
|
*/
|
|
73
75
|
async listen(port, hostname, backlog, listeningListener) {
|
|
74
76
|
this.port = port;
|
|
77
|
+
/**
|
|
78
|
+
* Display greeting log
|
|
79
|
+
*/
|
|
80
|
+
if (this.greet) {
|
|
81
|
+
console.log();
|
|
82
|
+
}
|
|
75
83
|
return new Promise((resolve, reject) => {
|
|
76
84
|
this.transport.server?.on('error', (err) => reject(err));
|
|
77
85
|
this.transport.listen(port, hostname, backlog, (err) => {
|
package/build/Server.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Server.mjs","sources":["../src/Server.ts"],"sourcesContent":["import http, { IncomingMessage, ServerResponse } from 'http';\n\nimport { debugAndPrintError, debugMatchMaking } from './Debug';\nimport * as matchMaker from './MatchMaker';\nimport { RegisteredHandler } from './matchmaker/RegisteredHandler';\nimport { Presence } from './presence/Presence';\n\nimport { Room } from './Room';\nimport { Type } from './types';\nimport { registerGracefulShutdown } from './Utils';\n\nimport { generateId } from '.';\nimport { registerNode, unregisterNode } from './discovery';\n\nimport { LocalPresence } from './presence/LocalPresence';\nimport { LocalDriver } from './matchmaker/driver';\n\nimport { Transport } from './Transport';\n\n// IServerOptions &\nexport type ServerOptions = {\n presence?: Presence,\n driver?: matchMaker.MatchMakerDriver,\n transport?: Transport,\n gracefullyShutdown?: boolean,\n\n /**\n * Options below are now part of WebSocketTransport (@colyseus/ws-transport)\n * TODO: remove me on 0.15.0\n */\n /** @deprecated */\n pingInterval?: number,\n\n /** @deprecated */\n pingMaxRetries?: number,\n\n /** @deprecated */\n verifyClient?: any,\n\n /** @deprecated */\n server?: http.Server,\n};\n\nexport class Server {\n public transport: Transport;\n\n protected presence: Presence;\n protected port: number;\n protected driver: matchMaker.MatchMakerDriver;\n protected processId: string = generateId();\n\n private matchmakeRoute = 'matchmake';\n private allowedRoomNameChars = /([a-zA-Z_\\-0-9]+)/gi;\n\n constructor(options: ServerOptions = {}) {\n const { gracefullyShutdown = true } = options;\n\n this.presence = options.presence || new LocalPresence();\n this.driver = options.driver || new LocalDriver();\n\n // setup matchmaker\n matchMaker.setup(this.presence, this.driver, this.processId);\n\n // \"presence\" option is not used from now on\n delete options.presence;\n\n this.attach(options);\n\n if (gracefullyShutdown) {\n registerGracefulShutdown((err) => this.gracefullyShutdown(true, err));\n }\n }\n\n public attach(options: ServerOptions) {\n /**\n * Display deprecation warnings for moved Transport options.\n * TODO: Remove me on 0.15\n */\n if (\n options.pingInterval !== undefined ||\n options.pingMaxRetries !== undefined ||\n options.server !== undefined ||\n options.verifyClient !== undefined\n ) {\n console.warn(\"DEPRECATION WARNING: 'pingInterval', 'pingMaxRetries', 'server', and 'verifyClient' Server options will be permanently moved to WebSocketTransport on v0.15\");\n console.warn(`new Server({\n transport: new WebSocketTransport({\n pingInterval: ...,\n pingMaxRetries: ...,\n server: ...,\n verifyClient: ...\n })\n})`);\n console.warn(\"👉 Documentation: https://docs.colyseus.io/server/transport/\")\n }\n\n const transport = options.transport || this.getDefaultTransport(options);\n delete options.transport;\n\n this.transport = transport;\n\n if (this.transport.server) {\n this.transport.server.once('listening', () => this.registerProcessForDiscovery());\n this.attachMatchMakingRoutes(this.transport.server as http.Server);\n }\n }\n\n /**\n * Bind the server into the port specified.\n *\n * @param port\n * @param hostname\n * @param backlog\n * @param listeningListener\n */\n public async listen(port: number, hostname?: string, backlog?: number, listeningListener?: Function) {\n this.port = port;\n\n return new Promise<void>((resolve, reject) => {\n this.transport.server?.on('error', (err) => reject(err));\n this.transport.listen(port, hostname, backlog, (err) => {\n if (listeningListener) {\n listeningListener(err);\n }\n\n if (err) {\n reject(err);\n\n } else {\n resolve();\n }\n });\n });\n }\n\n public registerProcessForDiscovery() {\n // register node for proxy/service discovery\n registerNode(this.presence, {\n port: this.port,\n processId: this.processId,\n });\n }\n\n /**\n * Define a new type of room for matchmaking.\n *\n * @param name public room identifier for match-making.\n * @param handler Room class definition\n * @param defaultOptions default options for `onCreate`\n */\n public define<T extends Type<Room>>(\n name: string,\n handler: T,\n defaultOptions?: Parameters<NonNullable<InstanceType<T>['onCreate']>>[0],\n ): RegisteredHandler {\n return matchMaker.defineRoomType(name, handler, defaultOptions);\n }\n\n public async gracefullyShutdown(exit: boolean = true, err?: Error) {\n try {\n await this.onShutdownCallback();\n\n await unregisterNode(this.presence, {\n port: this.port,\n processId: this.processId,\n });\n\n await matchMaker.gracefullyShutdown();\n\n this.transport.shutdown();\n this.presence.shutdown();\n this.driver.shutdown();\n\n } catch (e) {\n debugAndPrintError(`error during shutdown: ${e}`);\n\n } finally {\n if (exit) {\n process.exit(err ? 1 : 0);\n }\n }\n }\n\n /**\n * Add simulated latency between client and server.\n * @param milliseconds round trip latency in milliseconds.\n */\n public simulateLatency(milliseconds: number) {\n console.warn(`📶️❗ Colyseus latency simulation enabled → ${milliseconds}ms latency for round trip.`);\n\n const halfwayMS = (milliseconds / 2);\n this.transport.simulateLatency(halfwayMS);\n\n /* tslint:disable:no-string-literal */\n const _onMessage = Room.prototype['_onMessage'];\n /* tslint:disable:no-string-literal */\n Room.prototype['_onMessage'] = function (client, buffer) {\n // uWebSockets.js: duplicate buffer because it is cleared at native layer before the timeout.\n const cachedBuffer = Buffer.from(buffer);\n setTimeout(() => _onMessage.call(this, client, cachedBuffer), halfwayMS);\n };\n }\n\n /**\n * Register a callback that is going to be executed before the server shuts down.\n * @param callback\n */\n public onShutdown(callback: () => void | Promise<any>) {\n this.onShutdownCallback = callback;\n }\n\n protected getDefaultTransport(_: any): Transport {\n throw new Error(\"Please provide a 'transport' layer. Default transport not set.\");\n }\n\n protected onShutdownCallback: () => void | Promise<any> =\n () => Promise.resolve()\n\n protected attachMatchMakingRoutes(server: http.Server) {\n const listeners = server.listeners('request').slice(0);\n server.removeAllListeners('request');\n\n server.on('request', (req, res) => {\n if (req.url.indexOf(`/${this.matchmakeRoute}`) !== -1) {\n debugMatchMaking('received matchmake request: %s', req.url);\n this.handleMatchMakeRequest(req, res);\n\n } else {\n for (let i = 0, l = listeners.length; i < l; i++) {\n listeners[i].call(server, req, res);\n }\n }\n });\n }\n\n protected async handleMatchMakeRequest(req: IncomingMessage, res: ServerResponse) {\n const headers = {\n 'Access-Control-Allow-Headers': 'Origin, X-Requested-With, Content-Type, Accept',\n 'Access-Control-Allow-Methods': 'OPTIONS, POST, GET',\n 'Access-Control-Allow-Origin': '*',\n 'Access-Control-Max-Age': 2592000,\n // ...\n };\n\n if (req.method === 'OPTIONS') {\n res.writeHead(204, headers);\n res.end();\n\n } else if (req.method === 'POST') {\n const matchedParams = req.url.match(this.allowedRoomNameChars);\n const matchmakeIndex = matchedParams.indexOf(this.matchmakeRoute);\n const method = matchedParams[matchmakeIndex + 1];\n const name = matchedParams[matchmakeIndex + 2] || '';\n\n const data = [];\n req.on('data', (chunk) => data.push(chunk));\n req.on('end', async () => {\n headers['Content-Type'] = 'application/json';\n res.writeHead(200, headers);\n\n try {\n const clientOptions = JSON.parse(Buffer.concat(data).toString());\n const response = await matchMaker.controller.invokeMethod(method, name, clientOptions);\n res.write(JSON.stringify(response));\n\n } catch (e) {\n res.write(JSON.stringify({ code: e.code, error: e.message, }));\n }\n\n res.end();\n });\n\n } else if (req.method === 'GET') {\n const matchedParams = req.url.match(this.allowedRoomNameChars);\n const roomName = matchedParams.length > 1 ? matchedParams[matchedParams.length - 1] : \"\";\n\n headers['Content-Type'] = 'application/json';\n res.writeHead(200, headers);\n res.write(JSON.stringify(await matchMaker.controller.getAvailableRooms(roomName)));\n res.end();\n }\n\n }\n\n}\n"],"names":["matchMaker.setup","matchMaker.defineRoomType","matchMaker.gracefullyShutdown","matchMaker.controller.invokeMethod","matchMaker.controller.getAvailableRooms"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Server.mjs","sources":["../src/Server.ts"],"sourcesContent":["import http, { IncomingMessage, ServerResponse } from 'http';\n\nimport { debugAndPrintError, debugMatchMaking } from './Debug';\nimport * as matchMaker from './MatchMaker';\nimport { RegisteredHandler } from './matchmaker/RegisteredHandler';\nimport { Presence } from './presence/Presence';\n\nimport { Room } from './Room';\nimport { Type } from './types';\nimport { registerGracefulShutdown } from './Utils';\n\nimport { generateId } from '.';\nimport { registerNode, unregisterNode } from './discovery';\n\nimport { LocalPresence } from './presence/LocalPresence';\nimport { LocalDriver } from './matchmaker/driver';\n\nimport { Transport } from './Transport';\n\n// IServerOptions &\nexport type ServerOptions = {\n presence?: Presence,\n driver?: matchMaker.MatchMakerDriver,\n transport?: Transport,\n gracefullyShutdown?: boolean,\n\n /**\n * Display greeting message on server start.\n * Default: true\n */\n greet?: boolean,\n\n /**\n * Options below are now part of WebSocketTransport (@colyseus/ws-transport)\n * TODO: remove me on 0.15.0\n */\n /** @deprecated */\n pingInterval?: number,\n\n /** @deprecated */\n pingMaxRetries?: number,\n\n /** @deprecated */\n verifyClient?: any,\n\n /** @deprecated */\n server?: http.Server,\n};\n\nexport class Server {\n public transport: Transport;\n\n protected presence: Presence;\n protected port: number;\n protected driver: matchMaker.MatchMakerDriver;\n protected processId: string = generateId();\n\n protected greet: boolean;\n\n private matchmakeRoute = 'matchmake';\n private allowedRoomNameChars = /([a-zA-Z_\\-0-9]+)/gi;\n\n constructor(options: ServerOptions = {}) {\n const { gracefullyShutdown = true, greet = true } = options;\n\n this.presence = options.presence || new LocalPresence();\n this.driver = options.driver || new LocalDriver();\n this.greet = greet;\n\n // setup matchmaker\n matchMaker.setup(this.presence, this.driver, this.processId);\n\n // \"presence\" option is not used from now on\n delete options.presence;\n\n this.attach(options);\n\n if (gracefullyShutdown) {\n registerGracefulShutdown((err) => this.gracefullyShutdown(true, err));\n }\n }\n\n public attach(options: ServerOptions) {\n /**\n * Display deprecation warnings for moved Transport options.\n * TODO: Remove me on 0.15\n */\n if (\n options.pingInterval !== undefined ||\n options.pingMaxRetries !== undefined ||\n options.server !== undefined ||\n options.verifyClient !== undefined\n ) {\n console.warn(\"DEPRECATION WARNING: 'pingInterval', 'pingMaxRetries', 'server', and 'verifyClient' Server options will be permanently moved to WebSocketTransport on v0.15\");\n console.warn(`new Server({\n transport: new WebSocketTransport({\n pingInterval: ...,\n pingMaxRetries: ...,\n server: ...,\n verifyClient: ...\n })\n})`);\n console.warn(\"👉 Documentation: https://docs.colyseus.io/server/transport/\")\n }\n\n const transport = options.transport || this.getDefaultTransport(options);\n delete options.transport;\n\n this.transport = transport;\n\n if (this.transport.server) {\n this.transport.server.once('listening', () => this.registerProcessForDiscovery());\n this.attachMatchMakingRoutes(this.transport.server as http.Server);\n }\n }\n\n /**\n * Bind the server into the port specified.\n *\n * @param port\n * @param hostname\n * @param backlog\n * @param listeningListener\n */\n public async listen(port: number, hostname?: string, backlog?: number, listeningListener?: Function) {\n this.port = port;\n\n /**\n * Display greeting log\n */\n if (this.greet) {\n console.log();\n }\n\n return new Promise<void>((resolve, reject) => {\n this.transport.server?.on('error', (err) => reject(err));\n this.transport.listen(port, hostname, backlog, (err) => {\n if (listeningListener) {\n listeningListener(err);\n }\n\n if (err) {\n reject(err);\n\n } else {\n resolve();\n }\n });\n });\n }\n\n public registerProcessForDiscovery() {\n // register node for proxy/service discovery\n registerNode(this.presence, {\n port: this.port,\n processId: this.processId,\n });\n }\n\n /**\n * Define a new type of room for matchmaking.\n *\n * @param name public room identifier for match-making.\n * @param handler Room class definition\n * @param defaultOptions default options for `onCreate`\n */\n public define<T extends Type<Room>>(\n name: string,\n handler: T,\n defaultOptions?: Parameters<NonNullable<InstanceType<T>['onCreate']>>[0],\n ): RegisteredHandler {\n return matchMaker.defineRoomType(name, handler, defaultOptions);\n }\n\n public async gracefullyShutdown(exit: boolean = true, err?: Error) {\n try {\n await this.onShutdownCallback();\n\n await unregisterNode(this.presence, {\n port: this.port,\n processId: this.processId,\n });\n\n await matchMaker.gracefullyShutdown();\n\n this.transport.shutdown();\n this.presence.shutdown();\n this.driver.shutdown();\n\n } catch (e) {\n debugAndPrintError(`error during shutdown: ${e}`);\n\n } finally {\n if (exit) {\n process.exit(err ? 1 : 0);\n }\n }\n }\n\n /**\n * Add simulated latency between client and server.\n * @param milliseconds round trip latency in milliseconds.\n */\n public simulateLatency(milliseconds: number) {\n console.warn(`📶️❗ Colyseus latency simulation enabled → ${milliseconds}ms latency for round trip.`);\n\n const halfwayMS = (milliseconds / 2);\n this.transport.simulateLatency(halfwayMS);\n\n /* tslint:disable:no-string-literal */\n const _onMessage = Room.prototype['_onMessage'];\n /* tslint:disable:no-string-literal */\n Room.prototype['_onMessage'] = function (client, buffer) {\n // uWebSockets.js: duplicate buffer because it is cleared at native layer before the timeout.\n const cachedBuffer = Buffer.from(buffer);\n setTimeout(() => _onMessage.call(this, client, cachedBuffer), halfwayMS);\n };\n }\n\n /**\n * Register a callback that is going to be executed before the server shuts down.\n * @param callback\n */\n public onShutdown(callback: () => void | Promise<any>) {\n this.onShutdownCallback = callback;\n }\n\n protected getDefaultTransport(_: any): Transport {\n throw new Error(\"Please provide a 'transport' layer. Default transport not set.\");\n }\n\n protected onShutdownCallback: () => void | Promise<any> =\n () => Promise.resolve()\n\n protected attachMatchMakingRoutes(server: http.Server) {\n const listeners = server.listeners('request').slice(0);\n server.removeAllListeners('request');\n\n server.on('request', (req, res) => {\n if (req.url.indexOf(`/${this.matchmakeRoute}`) !== -1) {\n debugMatchMaking('received matchmake request: %s', req.url);\n this.handleMatchMakeRequest(req, res);\n\n } else {\n for (let i = 0, l = listeners.length; i < l; i++) {\n listeners[i].call(server, req, res);\n }\n }\n });\n }\n\n protected async handleMatchMakeRequest(req: IncomingMessage, res: ServerResponse) {\n const headers = {\n 'Access-Control-Allow-Headers': 'Origin, X-Requested-With, Content-Type, Accept',\n 'Access-Control-Allow-Methods': 'OPTIONS, POST, GET',\n 'Access-Control-Allow-Origin': '*',\n 'Access-Control-Max-Age': 2592000,\n // ...\n };\n\n if (req.method === 'OPTIONS') {\n res.writeHead(204, headers);\n res.end();\n\n } else if (req.method === 'POST') {\n const matchedParams = req.url.match(this.allowedRoomNameChars);\n const matchmakeIndex = matchedParams.indexOf(this.matchmakeRoute);\n const method = matchedParams[matchmakeIndex + 1];\n const name = matchedParams[matchmakeIndex + 2] || '';\n\n const data = [];\n req.on('data', (chunk) => data.push(chunk));\n req.on('end', async () => {\n headers['Content-Type'] = 'application/json';\n res.writeHead(200, headers);\n\n try {\n const clientOptions = JSON.parse(Buffer.concat(data).toString());\n const response = await matchMaker.controller.invokeMethod(method, name, clientOptions);\n res.write(JSON.stringify(response));\n\n } catch (e) {\n res.write(JSON.stringify({ code: e.code, error: e.message, }));\n }\n\n res.end();\n });\n\n } else if (req.method === 'GET') {\n const matchedParams = req.url.match(this.allowedRoomNameChars);\n const roomName = matchedParams.length > 1 ? matchedParams[matchedParams.length - 1] : \"\";\n\n headers['Content-Type'] = 'application/json';\n res.writeHead(200, headers);\n res.write(JSON.stringify(await matchMaker.controller.getAvailableRooms(roomName)));\n res.end();\n }\n\n }\n\n}\n"],"names":["matchMaker.setup","matchMaker.defineRoomType","matchMaker.gracefullyShutdown","matchMaker.controller.invokeMethod","matchMaker.controller.getAvailableRooms"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/matchmaker/driver/interfaces.ts"],
|
|
4
|
-
"sourcesContent": ["export interface SortOptions { [fieldName: string]: 1 | -1 | 'asc' | 'desc' | 'ascending' | 'descending'; }\n\nexport interface IRoomListingData {\n clients: number;\n locked: boolean;\n private: boolean;\n maxClients: number;\n metadata: any;\n name: string;\n publicAddress?: string;\n processId: string;\n roomId: string;\n unlisted: boolean;\n [property: string]: any;\n}\n\nexport interface RoomListingData<Metadata= any> extends IRoomListingData {\n metadata: Metadata;\n\n updateOne(operations: any);\n save();\n remove();\n}\n\nexport interface QueryHelpers<T> {\n then: Promise<T>['then'];\n sort(options: SortOptions);\n}\n\nexport interface MatchMakerDriver {\n createInstance(initialValues: any): RoomListingData;\n\n find(\n conditions: Partial<IRoomListingData>,\n additionalProjectionFields?: any,\n ): Promise<RoomListingData[]> | RoomListingData[];\n\n findOne(conditions: Partial<IRoomListingData>): QueryHelpers<RoomListingData>;\n\n clear(): void;\n shutdown(): void;\n}\n"],
|
|
4
|
+
"sourcesContent": ["export interface SortOptions { [fieldName: string]: 1 | -1 | 'asc' | 'desc' | 'ascending' | 'descending'; }\n\nexport interface IRoomListingData {\n clients: number;\n locked: boolean;\n private: boolean;\n maxClients: number;\n metadata: any;\n name: string;\n publicAddress?: string;\n processId: string;\n roomId: string;\n unlisted: boolean;\n [property: string]: any;\n}\n\nexport interface RoomListingData<Metadata= any> extends IRoomListingData {\n metadata: Metadata;\n\n updateOne(operations: any);\n save();\n remove();\n}\n\nexport interface QueryHelpers<T> {\n then: Promise<T>['then'];\n sort(options: SortOptions);\n}\n\nexport interface MatchMakerDriver {\n\n /**\n * Initialize a room cache which contains CRUD operations for room listings.\n * \n * @param initialValues - Predefined room properties.\n * \n * @returns RoomData - New room cache.\n */\n createInstance(initialValues: any): RoomListingData;\n\n /**\n * Query rooms in room cache for given conditions.\n * \n * @param conditions - Filtering conditions.\n * \n * @returns Promise<RoomListingData[]> | RoomListingData[] - A promise or an object contaning room metadata list.\n */\n find(\n conditions: Partial<IRoomListingData>,\n additionalProjectionFields?: any,\n ): Promise<RoomListingData[]> | RoomListingData[];\n\n /**\n * Query for a room in room cache for given conditions.\n * \n * @param conditions - Filtering conditions.\n * \n * @returns `RoomListingData` - An object contaning filtered room metadata.\n */\n findOne(conditions: Partial<IRoomListingData>): QueryHelpers<RoomListingData>;\n\n /**\n * Empty the room cache.\n */\n clear(): void;\n\n /**\n * Dispose the connection of the room cache medium.\n */\n shutdown(): void;\n}\n"],
|
|
5
5
|
"mappings": ";;;;;;;;;;;;;AAAA;AAAA;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/presence/Presence.ts"],
|
|
4
|
-
"sourcesContent": ["
|
|
4
|
+
"sourcesContent": ["/**\n * When you need to scale your server on multiple processes and/or machines, you'd need to provide\n * the Presence option to the Server. The purpose of Presence is to allow communicating and\n * sharing data between different processes, specially during match-making.\n *\n * - Local presence - This is the default option. It's meant to be used when you're running Colyseus in\n * a single process.\n * - Redis presence - Use this option when you're running Colyseus on multiple processes and/or machines.\n *\n * @default Local presence\n */\nexport interface Presence {\n /**\n * Subscribes to the given topic. The callback will be triggered whenever a message is published on topic.\n *\n * @param topic - Topic name.\n * @param callback - Callback to trigger on subscribing.\n */\n subscribe(topic: string, callback: Function);\n /**\n * Unsubscribe from given topic.\n *\n * @param topic - Topic name.\n * @param callback - Callback to trigger on topic unsubscribing.\n */\n unsubscribe(topic: string, callback?: Function);\n\n /**\n * Posts a message to given topic.\n *\n * @param topic - Topic name.\n * @param data - Message body/object.\n */\n publish(topic: string, data: any);\n\n /**\n * Returns if key exists.\n *\n * @param roomId\n */\n exists(roomId: string): Promise<boolean>;\n\n /**\n * Set key to hold the string value and set key to timeout after a given number of seconds.\n *\n * @param key - Identifier.\n * @param value - Message body/object.\n * @param seconds - Timeout value.\n */\n setex(key: string, value: string, seconds: number);\n\n /**\n * Get the value of key.\n *\n * @param key - Identifier.\n */\n get(key: string);\n\n /**\n * Removes the specified key.\n *\n * @param key - Identifier of the object to removed.\n */\n del(key: string): void;\n\n /**\n * Add the specified members to the set stored at key. Specified members that are already\n * a member of this set are ignored. If key does not exist, a new set is created before\n * adding the specified members.\n *\n * @param key - Name/Identifier of the set.\n * @param value - Message body/object.\n */\n sadd(key: string, value: any);\n /**\n * Returns all the members of the set value stored at key.\n *\n * @param key - Name/Identifier of the set.\n */\n smembers(key: string): Promise<string[]>;\n /**\n * Returns if member is a member of the set stored at key.\n *\n * @param key - Name/Identifier of the set.\n * @param field - Key value within the set.\n * @returns `1` if the element is a member of the set else `0`.\n */\n sismember(key: string, field: string);\n /**\n * Remove the specified members from the set stored at key. Specified members that are not a\n * member of this set are ignored. If key does not exist, it is treated as an empty set\n * and this command returns 0.\n *\n * @param key - Name/Identifier of the set.\n * @param value - Key value within the set.\n */\n srem(key: string, value: any);\n /**\n * Returns the set cardinality (number of elements) of the set stored at key.\n *\n * @param key - Name/Identifier of the set.\n */\n scard(key: string);\n /**\n * Returns the members of the set resulting from the intersection of all the given sets.\n *\n * @param keys - Key values within the set.\n */\n sinter(...keys: string[]): Promise<string[]>;\n\n /**\n * Sets field in the hash stored at key to value. If key does not exist, a new key holding a hash is created.\n * If field already exists in the hash, it is overwritten.\n */\n hset(key: string, field: string, value: string);\n\n /**\n * Increments the number stored at field in the hash stored at key by increment. If key does not exist, a new key\n * holding a hash is created. If field does not exist the value is set to 0 before the operation is performed.\n */\n hincrby(key: string, field: string, value: number): number | Promise<number>;\n\n /**\n * Returns the value associated with field in the hash stored at key.\n */\n hget(key: string, field: string): Promise<string>;\n\n /**\n * Returns all fields and values of the hash stored at key.\n */\n hgetall(key: string): Promise<{ [key: string]: string }>;\n\n /**\n * Removes the specified fields from the hash stored at key. Specified fields that do not exist within\n * this hash are ignored. If key does not exist, it is treated as an empty hash and this command returns 0.\n */\n hdel(key: string, field: string);\n\n /**\n * Returns the number of fields contained in the hash stored at key\n */\n hlen(key: string): Promise<number>;\n\n /**\n * Increments the number stored at key by one. If the key does not exist, it is set to 0 before performing\n * the operation. An error is returned if the key contains a value of the wrong type or\n * contains a string that can not be represented as integer. This operation is limited to 64-bit signed integers.\n */\n incr(key: string): Promise<number>;\n\n /**\n * Decrements the number stored at key by one. If the key does not exist, it is set to 0 before performing\n * the operation. An error is returned if the key contains a value of the wrong type or contains a string\n * that can not be represented as integer. This operation is limited to 64-bit signed integers.\n */\n decr(key: string): Promise<number>;\n\n shutdown(): void;\n}\n"],
|
|
5
5
|
"mappings": ";;;;;;;;;;;;;AAAA;AAAA;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/build/utils/DevMode.js
CHANGED
|
@@ -16,7 +16,10 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
16
16
|
}
|
|
17
17
|
return to;
|
|
18
18
|
};
|
|
19
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
19
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
20
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
21
|
+
mod
|
|
22
|
+
));
|
|
20
23
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
21
24
|
var DevMode_exports = {};
|
|
22
25
|
__export(DevMode_exports, {
|
|
@@ -55,7 +58,11 @@ async function reloadFromCache() {
|
|
|
55
58
|
}
|
|
56
59
|
recreatedRoom.onRestoreRoom?.(roomHistory["cache"]);
|
|
57
60
|
for (const previousSessionId of roomHistory.clients) {
|
|
58
|
-
await (0, import_MatchMaker.remoteRoomCall)(
|
|
61
|
+
await (0, import_MatchMaker.remoteRoomCall)(
|
|
62
|
+
recreatedRoomListing.roomId,
|
|
63
|
+
"_reserveSeat",
|
|
64
|
+
[previousSessionId, {}, 20, false, true]
|
|
65
|
+
);
|
|
59
66
|
}
|
|
60
67
|
}
|
|
61
68
|
if (roomHistoryList.length > 0) {
|
|
@@ -2,6 +2,6 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/utils/DevMode.ts"],
|
|
4
4
|
"sourcesContent": ["import debug from \"debug\";\nimport { debugAndPrintError } from \"../Debug\";\n\nimport { getRoomById, handleCreateRoom, presence, remoteRoomCall } from \"../MatchMaker\";\nimport type { Room } from \"../Room\";\n\nexport const debugDevMode = debug('colyseus:devmode');\n\nexport let isDevMode: boolean = false;\n\nexport function setDevMode(bool: boolean) {\n isDevMode = bool;\n}\n\nexport async function reloadFromCache() {\n const roomHistoryList = Object.entries(await presence.hgetall(getRoomRestoreListKey()));\n debugDevMode(\"rooms to restore: %i\", roomHistoryList.length);\n\n for (const [roomId, value] of roomHistoryList) {\n let recreatedRoom: Room;\n\n const roomHistory = JSON.parse(value);\n debugDevMode(\"restoring room %s (%s)\", roomHistory.roomName, roomId);\n\n const recreatedRoomListing = await handleCreateRoom(roomHistory.roomName, roomHistory.clientOptions, roomId);\n console.debug(`\uD83D\uDD04 room '${roomId}' has been restored.`);\n\n // Set previous state\n if (roomHistory.hasOwnProperty(\"state\")) {\n recreatedRoom = getRoomById(recreatedRoomListing.roomId);\n recreatedRoom.state.decode(roomHistory.state);\n\n //\n // WORKAROUND: @colyseus/schema is not capable of encoding a decoded\n // state. thus, we need a fresh clone immediately after decoding\n //\n recreatedRoom.setState(recreatedRoom.state.clone());\n console.debug(`\uD83D\uDCCB room '${roomId}' state =>`, recreatedRoom.state.toJSON());\n }\n\n // call `onRestoreRoom` with custom 'cache'd property.\n recreatedRoom.onRestoreRoom?.(roomHistory[\"cache\"]);\n\n // Reserve seats for clients from cached history\n for (const previousSessionId of roomHistory.clients) {\n await remoteRoomCall(recreatedRoomListing.roomId, '_reserveSeat',\n [previousSessionId, {}, 20, false, true]); // reserve seat for 20 seconds\n }\n }\n\n if (roomHistoryList.length > 0) {\n console.debug(\"\u2705\", roomHistoryList.length, \"room(s) have been restored.\");\n }\n}\n\nexport async function cacheRoomHistory(rooms: { [roomId: string]: Room }) {\n for (const room of Object.values(rooms)) {\n const roomHistoryResult = await presence.hget(getRoomRestoreListKey(), room.roomId);\n if (roomHistoryResult) {\n try {\n const roomHistory = JSON.parse(roomHistoryResult);\n\n // custom cache method\n roomHistory[\"cache\"] = room.onCacheRoom?.();\n\n // encode state\n debugDevMode(\"caching room %s (%s)\", room.roomName, room.roomId);\n\n if (room.state) {\n roomHistory[\"state\"] = room.state.encodeAll();\n }\n\n // cache active clients and reserved seats\n roomHistory[\"clients\"] = room.clients.map((client) => client.sessionId);\n\n for (const sessionId in room['reservedSeats']) {\n roomHistory[\"clients\"].push(sessionId);\n }\n\n await presence.hset(getRoomRestoreListKey(), room.roomId, JSON.stringify(roomHistory));\n\n // Rewrite updated room history\n console.debug(`\uD83D\uDCBE caching room '${room.roomId}' (clients: ${room.clients.length}, state size: ${(roomHistory[\"state\"] || []).length} bytes)`);\n\n } catch (e) {\n debugAndPrintError(`\u274C couldn't cache room '${room.roomId}', due to:\\n${e.stack}`);\n }\n }\n }\n}\n\nexport async function getPreviousProcessId(hostname) {\n return await presence.hget(getProcessRestoreKey(), hostname);\n}\n\nexport function getRoomRestoreListKey() {\n return 'roomhistory';\n}\n\nexport function getProcessRestoreKey() {\n return 'processhistory';\n}"],
|
|
5
|
-
"mappings": "
|
|
6
|
-
"names": []
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAkB;AAClB,mBAAmC;AAEnC,wBAAwE;AAGjE,MAAM,mBAAe,aAAAA,SAAM,kBAAkB;AAE7C,IAAI,YAAqB;AAEzB,SAAS,WAAW,MAAe;AACxC,cAAY;AACd;AAEA,eAAsB,kBAAkB;AACtC,QAAM,kBAAkB,OAAO,QAAQ,MAAM,2BAAS,QAAQ,sBAAsB,CAAC,CAAC;AACtF,eAAa,wBAAwB,gBAAgB,MAAM;AAE3D,aAAW,CAAC,QAAQ,KAAK,KAAK,iBAAiB;AAC7C,QAAI;AAEJ,UAAM,cAAc,KAAK,MAAM,KAAK;AACpC,iBAAa,0BAA0B,YAAY,UAAU,MAAM;AAEnE,UAAM,uBAAuB,UAAM,oCAAiB,YAAY,UAAU,YAAY,eAAe,MAAM;AAC3G,YAAQ,MAAM,mBAAY,4BAA4B;AAGtD,QAAI,YAAY,eAAe,OAAO,GAAG;AACvC,0BAAgB,+BAAY,qBAAqB,MAAM;AACvD,oBAAc,MAAM,OAAO,YAAY,KAAK;AAM5C,oBAAc,SAAS,cAAc,MAAM,MAAM,CAAC;AAClD,cAAQ,MAAM,mBAAY,oBAAoB,cAAc,MAAM,OAAO,CAAC;AAAA,IAC5E;AAGA,kBAAc,gBAAgB,YAAY,QAAQ;AAGlD,eAAW,qBAAqB,YAAY,SAAS;AACnD,gBAAM;AAAA,QAAe,qBAAqB;AAAA,QAAQ;AAAA,QAChD,CAAC,mBAAmB,CAAC,GAAG,IAAI,OAAO,IAAI;AAAA,MAAC;AAAA,IAC5C;AAAA,EACF;AAEA,MAAI,gBAAgB,SAAS,GAAG;AAC9B,YAAQ,MAAM,UAAK,gBAAgB,QAAQ,6BAA6B;AAAA,EAC1E;AACF;AAEA,eAAsB,iBAAiB,OAAmC;AACxE,aAAW,QAAQ,OAAO,OAAO,KAAK,GAAG;AACvC,UAAM,oBAAoB,MAAM,2BAAS,KAAK,sBAAsB,GAAG,KAAK,MAAM;AAClF,QAAI,mBAAmB;AACrB,UAAI;AACF,cAAM,cAAc,KAAK,MAAM,iBAAiB;AAGhD,oBAAY,WAAW,KAAK,cAAc;AAG1C,qBAAa,wBAAwB,KAAK,UAAU,KAAK,MAAM;AAE/D,YAAI,KAAK,OAAO;AACd,sBAAY,WAAW,KAAK,MAAM,UAAU;AAAA,QAC9C;AAGA,oBAAY,aAAa,KAAK,QAAQ,IAAI,CAAC,WAAW,OAAO,SAAS;AAEtE,mBAAW,aAAa,KAAK,kBAAkB;AAC7C,sBAAY,WAAW,KAAK,SAAS;AAAA,QACvC;AAEA,cAAM,2BAAS,KAAK,sBAAsB,GAAG,KAAK,QAAQ,KAAK,UAAU,WAAW,CAAC;AAGrF,gBAAQ,MAAM,2BAAoB,KAAK,qBAAqB,KAAK,QAAQ,wBAAwB,YAAY,YAAY,CAAC,GAAG,eAAe;AAAA,MAE9I,SAAS,GAAP;AACA,6CAAmB,+BAA0B,KAAK;AAAA,EAAqB,EAAE,OAAO;AAAA,MAClF;AAAA,IACF;AAAA,EACF;AACF;AAEA,eAAsB,qBAAqB,UAAU;AACnD,SAAO,MAAM,2BAAS,KAAK,qBAAqB,GAAG,QAAQ;AAC7D;AAEO,SAAS,wBAAwB;AACtC,SAAO;AACT;AAEO,SAAS,uBAAuB;AACrC,SAAO;AACT;",
|
|
6
|
+
"names": ["debug"]
|
|
7
7
|
}
|
package/build/utils/DevMode.mjs
CHANGED
|
@@ -23,7 +23,11 @@ async function reloadFromCache() {
|
|
|
23
23
|
}
|
|
24
24
|
recreatedRoom.onRestoreRoom?.(roomHistory["cache"]);
|
|
25
25
|
for (const previousSessionId of roomHistory.clients) {
|
|
26
|
-
await remoteRoomCall(
|
|
26
|
+
await remoteRoomCall(
|
|
27
|
+
recreatedRoomListing.roomId,
|
|
28
|
+
"_reserveSeat",
|
|
29
|
+
[previousSessionId, {}, 20, false, true]
|
|
30
|
+
);
|
|
27
31
|
}
|
|
28
32
|
}
|
|
29
33
|
if (roomHistoryList.length > 0) {
|
|
@@ -2,6 +2,6 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/utils/DevMode.ts"],
|
|
4
4
|
"sourcesContent": ["import debug from \"debug\";\nimport { debugAndPrintError } from \"../Debug\";\n\nimport { getRoomById, handleCreateRoom, presence, remoteRoomCall } from \"../MatchMaker\";\nimport type { Room } from \"../Room\";\n\nexport const debugDevMode = debug('colyseus:devmode');\n\nexport let isDevMode: boolean = false;\n\nexport function setDevMode(bool: boolean) {\n isDevMode = bool;\n}\n\nexport async function reloadFromCache() {\n const roomHistoryList = Object.entries(await presence.hgetall(getRoomRestoreListKey()));\n debugDevMode(\"rooms to restore: %i\", roomHistoryList.length);\n\n for (const [roomId, value] of roomHistoryList) {\n let recreatedRoom: Room;\n\n const roomHistory = JSON.parse(value);\n debugDevMode(\"restoring room %s (%s)\", roomHistory.roomName, roomId);\n\n const recreatedRoomListing = await handleCreateRoom(roomHistory.roomName, roomHistory.clientOptions, roomId);\n console.debug(`\uD83D\uDD04 room '${roomId}' has been restored.`);\n\n // Set previous state\n if (roomHistory.hasOwnProperty(\"state\")) {\n recreatedRoom = getRoomById(recreatedRoomListing.roomId);\n recreatedRoom.state.decode(roomHistory.state);\n\n //\n // WORKAROUND: @colyseus/schema is not capable of encoding a decoded\n // state. thus, we need a fresh clone immediately after decoding\n //\n recreatedRoom.setState(recreatedRoom.state.clone());\n console.debug(`\uD83D\uDCCB room '${roomId}' state =>`, recreatedRoom.state.toJSON());\n }\n\n // call `onRestoreRoom` with custom 'cache'd property.\n recreatedRoom.onRestoreRoom?.(roomHistory[\"cache\"]);\n\n // Reserve seats for clients from cached history\n for (const previousSessionId of roomHistory.clients) {\n await remoteRoomCall(recreatedRoomListing.roomId, '_reserveSeat',\n [previousSessionId, {}, 20, false, true]); // reserve seat for 20 seconds\n }\n }\n\n if (roomHistoryList.length > 0) {\n console.debug(\"\u2705\", roomHistoryList.length, \"room(s) have been restored.\");\n }\n}\n\nexport async function cacheRoomHistory(rooms: { [roomId: string]: Room }) {\n for (const room of Object.values(rooms)) {\n const roomHistoryResult = await presence.hget(getRoomRestoreListKey(), room.roomId);\n if (roomHistoryResult) {\n try {\n const roomHistory = JSON.parse(roomHistoryResult);\n\n // custom cache method\n roomHistory[\"cache\"] = room.onCacheRoom?.();\n\n // encode state\n debugDevMode(\"caching room %s (%s)\", room.roomName, room.roomId);\n\n if (room.state) {\n roomHistory[\"state\"] = room.state.encodeAll();\n }\n\n // cache active clients and reserved seats\n roomHistory[\"clients\"] = room.clients.map((client) => client.sessionId);\n\n for (const sessionId in room['reservedSeats']) {\n roomHistory[\"clients\"].push(sessionId);\n }\n\n await presence.hset(getRoomRestoreListKey(), room.roomId, JSON.stringify(roomHistory));\n\n // Rewrite updated room history\n console.debug(`\uD83D\uDCBE caching room '${room.roomId}' (clients: ${room.clients.length}, state size: ${(roomHistory[\"state\"] || []).length} bytes)`);\n\n } catch (e) {\n debugAndPrintError(`\u274C couldn't cache room '${room.roomId}', due to:\\n${e.stack}`);\n }\n }\n }\n}\n\nexport async function getPreviousProcessId(hostname) {\n return await presence.hget(getProcessRestoreKey(), hostname);\n}\n\nexport function getRoomRestoreListKey() {\n return 'roomhistory';\n}\n\nexport function getProcessRestoreKey() {\n return 'processhistory';\n}"],
|
|
5
|
-
"mappings": "AAAA;
|
|
5
|
+
"mappings": "AAAA,OAAO,WAAW;AAClB,SAAS,0BAA0B;AAEnC,SAAS,aAAa,kBAAkB,UAAU,sBAAsB;AAGjE,MAAM,eAAe,MAAM,kBAAkB;AAE7C,IAAI,YAAqB;AAEzB,SAAS,WAAW,MAAe;AACxC,cAAY;AACd;AAEA,eAAsB,kBAAkB;AACtC,QAAM,kBAAkB,OAAO,QAAQ,MAAM,SAAS,QAAQ,sBAAsB,CAAC,CAAC;AACtF,eAAa,wBAAwB,gBAAgB,MAAM;AAE3D,aAAW,CAAC,QAAQ,KAAK,KAAK,iBAAiB;AAC7C,QAAI;AAEJ,UAAM,cAAc,KAAK,MAAM,KAAK;AACpC,iBAAa,0BAA0B,YAAY,UAAU,MAAM;AAEnE,UAAM,uBAAuB,MAAM,iBAAiB,YAAY,UAAU,YAAY,eAAe,MAAM;AAC3G,YAAQ,MAAM,mBAAY,4BAA4B;AAGtD,QAAI,YAAY,eAAe,OAAO,GAAG;AACvC,sBAAgB,YAAY,qBAAqB,MAAM;AACvD,oBAAc,MAAM,OAAO,YAAY,KAAK;AAM5C,oBAAc,SAAS,cAAc,MAAM,MAAM,CAAC;AAClD,cAAQ,MAAM,mBAAY,oBAAoB,cAAc,MAAM,OAAO,CAAC;AAAA,IAC5E;AAGA,kBAAc,gBAAgB,YAAY,QAAQ;AAGlD,eAAW,qBAAqB,YAAY,SAAS;AACnD,YAAM;AAAA,QAAe,qBAAqB;AAAA,QAAQ;AAAA,QAChD,CAAC,mBAAmB,CAAC,GAAG,IAAI,OAAO,IAAI;AAAA,MAAC;AAAA,IAC5C;AAAA,EACF;AAEA,MAAI,gBAAgB,SAAS,GAAG;AAC9B,YAAQ,MAAM,UAAK,gBAAgB,QAAQ,6BAA6B;AAAA,EAC1E;AACF;AAEA,eAAsB,iBAAiB,OAAmC;AACxE,aAAW,QAAQ,OAAO,OAAO,KAAK,GAAG;AACvC,UAAM,oBAAoB,MAAM,SAAS,KAAK,sBAAsB,GAAG,KAAK,MAAM;AAClF,QAAI,mBAAmB;AACrB,UAAI;AACF,cAAM,cAAc,KAAK,MAAM,iBAAiB;AAGhD,oBAAY,WAAW,KAAK,cAAc;AAG1C,qBAAa,wBAAwB,KAAK,UAAU,KAAK,MAAM;AAE/D,YAAI,KAAK,OAAO;AACd,sBAAY,WAAW,KAAK,MAAM,UAAU;AAAA,QAC9C;AAGA,oBAAY,aAAa,KAAK,QAAQ,IAAI,CAAC,WAAW,OAAO,SAAS;AAEtE,mBAAW,aAAa,KAAK,kBAAkB;AAC7C,sBAAY,WAAW,KAAK,SAAS;AAAA,QACvC;AAEA,cAAM,SAAS,KAAK,sBAAsB,GAAG,KAAK,QAAQ,KAAK,UAAU,WAAW,CAAC;AAGrF,gBAAQ,MAAM,2BAAoB,KAAK,qBAAqB,KAAK,QAAQ,wBAAwB,YAAY,YAAY,CAAC,GAAG,eAAe;AAAA,MAE9I,SAAS,GAAP;AACA,2BAAmB,+BAA0B,KAAK;AAAA,EAAqB,EAAE,OAAO;AAAA,MAClF;AAAA,IACF;AAAA,EACF;AACF;AAEA,eAAsB,qBAAqB,UAAU;AACnD,SAAO,MAAM,SAAS,KAAK,qBAAqB,GAAG,QAAQ;AAC7D;AAEO,SAAS,wBAAwB;AACtC,SAAO;AACT;AAEO,SAAS,uBAAuB;AACrC,SAAO;AACT;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/build/utils/Utils.js
CHANGED
|
@@ -16,7 +16,10 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
16
16
|
}
|
|
17
17
|
return to;
|
|
18
18
|
};
|
|
19
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
19
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
20
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
21
|
+
mod
|
|
22
|
+
));
|
|
20
23
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
21
24
|
var Utils_exports = {};
|
|
22
25
|
__export(Utils_exports, {
|
package/build/utils/Utils.js.map
CHANGED
|
@@ -2,6 +2,6 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/utils/Utils.ts"],
|
|
4
4
|
"sourcesContent": ["import nanoid from 'nanoid';\nimport { addExtension } from 'msgpackr';\n\nimport { debugAndPrintError } from '../Debug';\nimport { EventEmitter } from \"events\";\nimport { ServerOpts, Socket } from \"net\";\nimport { logger } from '../Logger';\nimport { Schema } from \"@colyseus/schema\";\n\n// remote room call timeouts\nexport const REMOTE_ROOM_SHORT_TIMEOUT = Number(process.env.COLYSEUS_PRESENCE_SHORT_TIMEOUT || 2000);\n\nexport function generateId(length: number = 9) {\n return nanoid(length);\n}\n\n//\n// nodemon sends SIGUSR2 before reloading\n// (https://github.com/remy/nodemon#controlling-shutdown-of-your-script)\n//\nconst signals: NodeJS.Signals[] = ['SIGINT', 'SIGTERM', 'SIGUSR2'];\n\nexport function registerGracefulShutdown(callback: (err?: Error) => void) {\n /**\n * Gracefully shutdown on uncaught errors\n */\n process.on('uncaughtException', (err) => {\n debugAndPrintError(err);\n callback(err);\n });\n\n signals.forEach((signal) =>\n process.once(signal, () => callback()));\n}\n\nexport function retry<T = any>(\n cb: Function,\n maxRetries: number = 3,\n errorWhiteList: any[] = [],\n retries: number = 0,\n) {\n return new Promise<T>((resolve, reject) => {\n cb()\n .then(resolve)\n .catch((e) => {\n if (\n errorWhiteList.indexOf(e.constructor) !== -1 &&\n retries++ < maxRetries\n ) {\n setTimeout(() => {\n retry<T>(cb, maxRetries, errorWhiteList, retries).\n then(resolve).\n catch((e2) => reject(e2));\n }, Math.floor(Math.random() * Math.pow(2, retries) * 400));\n\n } else {\n reject(e);\n }\n });\n });\n}\n\nexport function spliceOne(arr: any[], index: number): boolean {\n // manually splice availableRooms array\n // http://jsperf.com/manual-splice\n if (index === -1 || index >= arr.length) {\n return false;\n }\n\n const len = arr.length - 1;\n for (let i = index; i < len; i++) {\n arr[i] = arr[i + 1];\n }\n\n arr.length = len;\n return true;\n}\n\nexport class Deferred<T= any> {\n public promise: Promise<T>;\n\n public resolve: Function;\n public reject: Function;\n\n constructor() {\n this.promise = new Promise<T>((resolve, reject) => {\n this.resolve = resolve;\n this.reject = reject;\n });\n }\n\n public then(func: (value: T) => any) {\n return this.promise.then.apply(this.promise, arguments);\n }\n\n public catch(func: (value: any) => any) {\n return this.promise.catch(func);\n }\n\n}\n\nexport function merge(a: any, ...objs: any[]): any {\n for (let i = 0, len = objs.length; i < len; i++) {\n const b = objs[i];\n for (const key in b) {\n if (b.hasOwnProperty(key)) {\n a[key] = b[key];\n }\n }\n }\n return a;\n}\n\nexport class HybridArray<T> {\n public uniqueProperty: string;\n public hashedArray: { [key: string]: T } = {};\n public array: T[] = [];\n\n constructor(uniquePropertyName: string, items?: T[]) {\n this.uniqueProperty = uniquePropertyName;\n if (items) {\n this.array = this.array.concat(items);\n for (const element of items) {\n this.hashedArray[element[this.uniqueProperty]] = element;\n }\n }\n }\n\n public get length(): number {\n return this.array.length;\n }\n\n public add(item: T) {\n if (!this.hashedArray[item[this.uniqueProperty]]) {\n this.array.push(item);\n this.hashedArray[item[this.uniqueProperty]] = item;\n\n } else {\n logger.warn(`.add(): element already exists:`, item[this.uniqueProperty]);\n }\n }\n\n public at(index: number): T | undefined {\n if (index >= this.array.length) {\n this._badIndexWarning(index);\n\n } else {\n return this.array[index];\n }\n }\n\n public concat(items: T[]) {\n if (items) {\n for (const item of items) {\n this.hashedArray[item[this.uniqueProperty]] = item;\n }\n this.array.concat(items);\n }\n return this;\n }\n\n public find<S extends T>(predicate: (this: void, value: T, index: number, obj: T[]) => value is S, thisArg?: any): S;\n public find(predicate: (value: T, index: number, obj: T[]) => unknown, thisArg?: any): T;\n public find(predicate: any, thisArg?: any): T | undefined {\n return this.array.find(predicate, thisArg);\n }\n\n public filter(predicate: (value: T, index: number, array: T[]) => unknown, thisArg?: any): T[]\n public filter<S extends T>(predicate: (value: T, index: number, array: T[]) => value is S, thisArg?: any): S[] {\n return this.array.filter(predicate, thisArg);\n }\n\n public forEach(callbackfn: (value: T, index: number, array: T[]) => void, thisArg?: any): void {\n Array.prototype.forEach.call(this.array, callbackfn);\n }\n\n public get(key: string): T | undefined {\n return this.hashedArray[key];\n }\n\n public includes(element: T) {\n return this.hashedArray[element[this.uniqueProperty]] !== undefined;\n }\n\n public indexOf(element: T): number {\n return this.array.indexOf(element);\n }\n\n public map<U>(callback: (value: T, index: number, array: T[]) => U) {\n const result: U[] = [];\n for (let index = 0; index < this.array.length; index++) {\n result.push(callback(this.array[index], index, this.array));\n }\n return result;\n }\n\n public deleteAt(index: number) {\n if (index >= this.array.length) {\n this._badIndexWarning(index);\n return undefined;\n\n } else {\n const removable = this.spliceOne(index);\n delete this.hashedArray[removable[this.uniqueProperty]];\n return removable;\n }\n }\n\n public deleteByKey(key: string): T {\n if (!this.hashedArray[key]) {\n logger.error(`deleteByKey(): no such element for '${key}'.`);\n return undefined;\n } else {\n const removable = this.spliceOne(this.indexOf(this.hashedArray[key]));\n delete this.hashedArray[key];\n return removable;\n }\n }\n\n public delete(obj: T): T {\n if (this.hashedArray[obj[this.uniqueProperty]]) {\n return this.deleteByKey(obj[this.uniqueProperty]);\n\n } else if (this.indexOf(obj) != -1) {\n return this.deleteAt(this.indexOf(obj));\n\n } else {\n return undefined;\n }\n }\n\n private _badIndexWarning(index) {\n logger.warn(`Index out of range, index: ${index}`);\n }\n\n private spliceOne(index: number): T {\n // manually splice availableRooms array\n // http://jsperf.com/manual-splice\n if (index === -1 || index >= this.array.length) {\n this._badIndexWarning(index);\n return undefined;\n }\n\n const itemRemoved = this.array[index];\n\n const len = this.array.length - 1;\n for (let i = index; i < len; i++) {\n this.array[i] = this.array[i + 1];\n }\n this.array.length = len;\n\n return itemRemoved;\n }\n}\n\nexport declare interface DummyServer {\n constructor(options?: ServerOpts, connectionListener?: (socket: Socket) => void);\n\n listen(port?: number, hostname?: string, backlog?: number, listeningListener?: () => void): this;\n close(callback?: (err?: Error) => void): this;\n}\n\nexport class DummyServer extends EventEmitter {}\n\n// Add msgpackr extension to avoid circular references when encoding\n// https://github.com/kriszyp/msgpackr#custom-extensions\naddExtension({\n Class: Schema,\n type: 0,\n\n read(datum: any): any {\n return datum;\n },\n\n write(instance: any): any {\n return instance.toJSON();\n }\n});\n"],
|
|
5
|
-
"mappings": "
|
|
6
|
-
"names": []
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["nanoid"]
|
|
7
7
|
}
|
|
@@ -2,6 +2,6 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/utils/Utils.ts"],
|
|
4
4
|
"sourcesContent": ["import nanoid from 'nanoid';\nimport { addExtension } from 'msgpackr';\n\nimport { debugAndPrintError } from '../Debug';\nimport { EventEmitter } from \"events\";\nimport { ServerOpts, Socket } from \"net\";\nimport { logger } from '../Logger';\nimport { Schema } from \"@colyseus/schema\";\n\n// remote room call timeouts\nexport const REMOTE_ROOM_SHORT_TIMEOUT = Number(process.env.COLYSEUS_PRESENCE_SHORT_TIMEOUT || 2000);\n\nexport function generateId(length: number = 9) {\n return nanoid(length);\n}\n\n//\n// nodemon sends SIGUSR2 before reloading\n// (https://github.com/remy/nodemon#controlling-shutdown-of-your-script)\n//\nconst signals: NodeJS.Signals[] = ['SIGINT', 'SIGTERM', 'SIGUSR2'];\n\nexport function registerGracefulShutdown(callback: (err?: Error) => void) {\n /**\n * Gracefully shutdown on uncaught errors\n */\n process.on('uncaughtException', (err) => {\n debugAndPrintError(err);\n callback(err);\n });\n\n signals.forEach((signal) =>\n process.once(signal, () => callback()));\n}\n\nexport function retry<T = any>(\n cb: Function,\n maxRetries: number = 3,\n errorWhiteList: any[] = [],\n retries: number = 0,\n) {\n return new Promise<T>((resolve, reject) => {\n cb()\n .then(resolve)\n .catch((e) => {\n if (\n errorWhiteList.indexOf(e.constructor) !== -1 &&\n retries++ < maxRetries\n ) {\n setTimeout(() => {\n retry<T>(cb, maxRetries, errorWhiteList, retries).\n then(resolve).\n catch((e2) => reject(e2));\n }, Math.floor(Math.random() * Math.pow(2, retries) * 400));\n\n } else {\n reject(e);\n }\n });\n });\n}\n\nexport function spliceOne(arr: any[], index: number): boolean {\n // manually splice availableRooms array\n // http://jsperf.com/manual-splice\n if (index === -1 || index >= arr.length) {\n return false;\n }\n\n const len = arr.length - 1;\n for (let i = index; i < len; i++) {\n arr[i] = arr[i + 1];\n }\n\n arr.length = len;\n return true;\n}\n\nexport class Deferred<T= any> {\n public promise: Promise<T>;\n\n public resolve: Function;\n public reject: Function;\n\n constructor() {\n this.promise = new Promise<T>((resolve, reject) => {\n this.resolve = resolve;\n this.reject = reject;\n });\n }\n\n public then(func: (value: T) => any) {\n return this.promise.then.apply(this.promise, arguments);\n }\n\n public catch(func: (value: any) => any) {\n return this.promise.catch(func);\n }\n\n}\n\nexport function merge(a: any, ...objs: any[]): any {\n for (let i = 0, len = objs.length; i < len; i++) {\n const b = objs[i];\n for (const key in b) {\n if (b.hasOwnProperty(key)) {\n a[key] = b[key];\n }\n }\n }\n return a;\n}\n\nexport class HybridArray<T> {\n public uniqueProperty: string;\n public hashedArray: { [key: string]: T } = {};\n public array: T[] = [];\n\n constructor(uniquePropertyName: string, items?: T[]) {\n this.uniqueProperty = uniquePropertyName;\n if (items) {\n this.array = this.array.concat(items);\n for (const element of items) {\n this.hashedArray[element[this.uniqueProperty]] = element;\n }\n }\n }\n\n public get length(): number {\n return this.array.length;\n }\n\n public add(item: T) {\n if (!this.hashedArray[item[this.uniqueProperty]]) {\n this.array.push(item);\n this.hashedArray[item[this.uniqueProperty]] = item;\n\n } else {\n logger.warn(`.add(): element already exists:`, item[this.uniqueProperty]);\n }\n }\n\n public at(index: number): T | undefined {\n if (index >= this.array.length) {\n this._badIndexWarning(index);\n\n } else {\n return this.array[index];\n }\n }\n\n public concat(items: T[]) {\n if (items) {\n for (const item of items) {\n this.hashedArray[item[this.uniqueProperty]] = item;\n }\n this.array.concat(items);\n }\n return this;\n }\n\n public find<S extends T>(predicate: (this: void, value: T, index: number, obj: T[]) => value is S, thisArg?: any): S;\n public find(predicate: (value: T, index: number, obj: T[]) => unknown, thisArg?: any): T;\n public find(predicate: any, thisArg?: any): T | undefined {\n return this.array.find(predicate, thisArg);\n }\n\n public filter(predicate: (value: T, index: number, array: T[]) => unknown, thisArg?: any): T[]\n public filter<S extends T>(predicate: (value: T, index: number, array: T[]) => value is S, thisArg?: any): S[] {\n return this.array.filter(predicate, thisArg);\n }\n\n public forEach(callbackfn: (value: T, index: number, array: T[]) => void, thisArg?: any): void {\n Array.prototype.forEach.call(this.array, callbackfn);\n }\n\n public get(key: string): T | undefined {\n return this.hashedArray[key];\n }\n\n public includes(element: T) {\n return this.hashedArray[element[this.uniqueProperty]] !== undefined;\n }\n\n public indexOf(element: T): number {\n return this.array.indexOf(element);\n }\n\n public map<U>(callback: (value: T, index: number, array: T[]) => U) {\n const result: U[] = [];\n for (let index = 0; index < this.array.length; index++) {\n result.push(callback(this.array[index], index, this.array));\n }\n return result;\n }\n\n public deleteAt(index: number) {\n if (index >= this.array.length) {\n this._badIndexWarning(index);\n return undefined;\n\n } else {\n const removable = this.spliceOne(index);\n delete this.hashedArray[removable[this.uniqueProperty]];\n return removable;\n }\n }\n\n public deleteByKey(key: string): T {\n if (!this.hashedArray[key]) {\n logger.error(`deleteByKey(): no such element for '${key}'.`);\n return undefined;\n } else {\n const removable = this.spliceOne(this.indexOf(this.hashedArray[key]));\n delete this.hashedArray[key];\n return removable;\n }\n }\n\n public delete(obj: T): T {\n if (this.hashedArray[obj[this.uniqueProperty]]) {\n return this.deleteByKey(obj[this.uniqueProperty]);\n\n } else if (this.indexOf(obj) != -1) {\n return this.deleteAt(this.indexOf(obj));\n\n } else {\n return undefined;\n }\n }\n\n private _badIndexWarning(index) {\n logger.warn(`Index out of range, index: ${index}`);\n }\n\n private spliceOne(index: number): T {\n // manually splice availableRooms array\n // http://jsperf.com/manual-splice\n if (index === -1 || index >= this.array.length) {\n this._badIndexWarning(index);\n return undefined;\n }\n\n const itemRemoved = this.array[index];\n\n const len = this.array.length - 1;\n for (let i = index; i < len; i++) {\n this.array[i] = this.array[i + 1];\n }\n this.array.length = len;\n\n return itemRemoved;\n }\n}\n\nexport declare interface DummyServer {\n constructor(options?: ServerOpts, connectionListener?: (socket: Socket) => void);\n\n listen(port?: number, hostname?: string, backlog?: number, listeningListener?: () => void): this;\n close(callback?: (err?: Error) => void): this;\n}\n\nexport class DummyServer extends EventEmitter {}\n\n// Add msgpackr extension to avoid circular references when encoding\n// https://github.com/kriszyp/msgpackr#custom-extensions\naddExtension({\n Class: Schema,\n type: 0,\n\n read(datum: any): any {\n return datum;\n },\n\n write(instance: any): any {\n return instance.toJSON();\n }\n});\n"],
|
|
5
|
-
"mappings": "AAAA;
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@colyseus/core",
|
|
3
|
-
"version": "0.14.
|
|
3
|
+
"version": "0.14.34",
|
|
4
4
|
"description": "Multiplayer Framework for Node.js.",
|
|
5
5
|
"input": "./src/index.ts",
|
|
6
6
|
"main": "./build/index.js",
|
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
"node": ">= 14.x"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
+
"@colyseus/greeting-banner": "^1.0.0",
|
|
36
37
|
"@colyseus/schema": "^1.0.15",
|
|
37
38
|
"@gamestdio/timer": "^1.3.0",
|
|
38
39
|
"@types/redis": "^2.8.12",
|
|
@@ -44,5 +45,5 @@
|
|
|
44
45
|
"publishConfig": {
|
|
45
46
|
"access": "public"
|
|
46
47
|
},
|
|
47
|
-
"gitHead": "
|
|
48
|
+
"gitHead": "d7a378d80bdf9f4a8f7260c407ba2bb64c226832"
|
|
48
49
|
}
|