@colyseus/core 0.15.7 → 0.15.9
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/LICENSE +2 -1
- package/README.md +17 -66
- package/build/Protocol.d.ts +1 -0
- package/build/Protocol.js +1 -0
- package/build/Protocol.js.map +2 -2
- package/build/Protocol.mjs +1 -0
- package/build/Protocol.mjs.map +2 -2
- package/build/Room.js +32 -33
- package/build/Room.js.map +3 -3
- package/build/Room.mjs +32 -33
- package/build/Room.mjs.map +2 -2
- package/build/Server.js +1 -6
- package/build/Server.js.map +1 -1
- package/build/Server.mjs +1 -6
- package/build/Server.mjs.map +1 -1
- package/build/Transport.js +0 -1
- package/build/Transport.js.map +1 -1
- package/build/Transport.mjs +0 -1
- package/build/Transport.mjs.map +1 -1
- package/build/Utils.js +0 -3
- package/build/Utils.js.map +1 -1
- package/build/Utils.mjs +0 -3
- package/build/Utils.mjs.map +1 -1
- package/build/errors/ServerError.js +0 -1
- package/build/errors/ServerError.js.map +1 -1
- package/build/errors/ServerError.mjs +0 -1
- package/build/errors/ServerError.mjs.map +1 -1
- package/build/matchmaker/RegisteredHandler.js +1 -4
- package/build/matchmaker/RegisteredHandler.js.map +1 -1
- package/build/matchmaker/RegisteredHandler.mjs +1 -4
- package/build/matchmaker/RegisteredHandler.mjs.map +1 -1
- package/build/matchmaker/driver/Query.js +0 -2
- package/build/matchmaker/driver/Query.js.map +1 -1
- package/build/matchmaker/driver/Query.mjs +0 -2
- package/build/matchmaker/driver/Query.mjs.map +1 -1
- package/build/matchmaker/driver/RoomData.js +5 -12
- package/build/matchmaker/driver/RoomData.js.map +1 -1
- package/build/matchmaker/driver/RoomData.mjs +5 -12
- package/build/matchmaker/driver/RoomData.mjs.map +1 -1
- package/build/matchmaker/driver/index.js +3 -1
- package/build/matchmaker/driver/index.js.map +1 -1
- package/build/matchmaker/driver/index.mjs +3 -1
- package/build/matchmaker/driver/index.mjs.map +1 -1
- package/build/presence/LocalPresence.js +6 -6
- package/build/presence/LocalPresence.js.map +1 -1
- package/build/presence/LocalPresence.mjs +6 -6
- package/build/presence/LocalPresence.mjs.map +1 -1
- package/build/rooms/LobbyRoom.js +5 -3
- package/build/rooms/LobbyRoom.js.map +1 -1
- package/build/rooms/LobbyRoom.mjs +5 -3
- package/build/rooms/LobbyRoom.mjs.map +1 -1
- package/build/rooms/RelayRoom.js +8 -5
- package/build/rooms/RelayRoom.js.map +1 -1
- package/build/rooms/RelayRoom.mjs +8 -5
- package/build/rooms/RelayRoom.mjs.map +1 -1
- package/build/serializer/NoneSerializer.js +3 -1
- package/build/serializer/NoneSerializer.js.map +1 -1
- package/build/serializer/NoneSerializer.mjs +3 -1
- package/build/serializer/NoneSerializer.mjs.map +1 -1
- package/build/serializer/SchemaSerializer.js +4 -4
- package/build/serializer/SchemaSerializer.js.map +1 -1
- package/build/serializer/SchemaSerializer.mjs +4 -4
- package/build/serializer/SchemaSerializer.mjs.map +1 -1
- package/build/utils/Utils.js +0 -3
- package/build/utils/Utils.js.map +1 -1
- package/build/utils/Utils.mjs +0 -3
- package/build/utils/Utils.mjs.map +1 -1
- package/package.json +4 -3
package/build/Room.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import WebSocket from "ws";
|
|
1
2
|
import { unpack } from "msgpackr";
|
|
2
3
|
import { decode } from "@colyseus/schema";
|
|
3
4
|
import Clock from "@gamestdio/timer";
|
|
@@ -22,39 +23,25 @@ var RoomInternalState = /* @__PURE__ */ ((RoomInternalState2) => {
|
|
|
22
23
|
return RoomInternalState2;
|
|
23
24
|
})(RoomInternalState || {});
|
|
24
25
|
class Room {
|
|
25
|
-
get locked() {
|
|
26
|
-
return this._locked;
|
|
27
|
-
}
|
|
28
|
-
get metadata() {
|
|
29
|
-
return this.listing.metadata;
|
|
30
|
-
}
|
|
31
|
-
listing;
|
|
32
|
-
clock = new Clock();
|
|
33
|
-
#_roomId;
|
|
34
|
-
#_roomName;
|
|
35
|
-
maxClients = Infinity;
|
|
36
|
-
patchRate = DEFAULT_PATCH_RATE;
|
|
37
|
-
autoDispose = true;
|
|
38
|
-
state;
|
|
39
|
-
presence;
|
|
40
|
-
clients = new ClientArray();
|
|
41
|
-
_events = new EventEmitter();
|
|
42
|
-
seatReservationTime = DEFAULT_SEAT_RESERVATION_TIME;
|
|
43
|
-
reservedSeats = {};
|
|
44
|
-
reservedSeatTimeouts = {};
|
|
45
|
-
_reconnections = {};
|
|
46
|
-
_reconnectingSessionId = /* @__PURE__ */ new Map();
|
|
47
|
-
onMessageHandlers = {};
|
|
48
|
-
_serializer = noneSerializer;
|
|
49
|
-
_afterNextPatchQueue = [];
|
|
50
|
-
_simulationInterval;
|
|
51
|
-
_patchInterval;
|
|
52
|
-
_internalState = 0 /* CREATING */;
|
|
53
|
-
_locked = false;
|
|
54
|
-
_lockedExplicitly = false;
|
|
55
|
-
_maxClientsReached = false;
|
|
56
|
-
_autoDisposeTimeout;
|
|
57
26
|
constructor(presence) {
|
|
27
|
+
this.clock = new Clock();
|
|
28
|
+
this.maxClients = Infinity;
|
|
29
|
+
this.patchRate = DEFAULT_PATCH_RATE;
|
|
30
|
+
this.autoDispose = true;
|
|
31
|
+
this.clients = new ClientArray();
|
|
32
|
+
this._events = new EventEmitter();
|
|
33
|
+
this.seatReservationTime = DEFAULT_SEAT_RESERVATION_TIME;
|
|
34
|
+
this.reservedSeats = {};
|
|
35
|
+
this.reservedSeatTimeouts = {};
|
|
36
|
+
this._reconnections = {};
|
|
37
|
+
this._reconnectingSessionId = /* @__PURE__ */ new Map();
|
|
38
|
+
this.onMessageHandlers = {};
|
|
39
|
+
this._serializer = noneSerializer;
|
|
40
|
+
this._afterNextPatchQueue = [];
|
|
41
|
+
this._internalState = 0 /* CREATING */;
|
|
42
|
+
this._locked = false;
|
|
43
|
+
this._lockedExplicitly = false;
|
|
44
|
+
this._maxClientsReached = false;
|
|
58
45
|
this.presence = presence;
|
|
59
46
|
this._events.once("dispose", async () => {
|
|
60
47
|
try {
|
|
@@ -67,6 +54,14 @@ class Room {
|
|
|
67
54
|
this.setPatchRate(this.patchRate);
|
|
68
55
|
this.resetAutoDisposeTimeout(this.seatReservationTime);
|
|
69
56
|
}
|
|
57
|
+
get locked() {
|
|
58
|
+
return this._locked;
|
|
59
|
+
}
|
|
60
|
+
get metadata() {
|
|
61
|
+
return this.listing.metadata;
|
|
62
|
+
}
|
|
63
|
+
#_roomId;
|
|
64
|
+
#_roomName;
|
|
70
65
|
get roomName() {
|
|
71
66
|
return this.#_roomName;
|
|
72
67
|
}
|
|
@@ -266,16 +261,20 @@ class Room {
|
|
|
266
261
|
client._afterNextPatchQueue = this._afterNextPatchQueue;
|
|
267
262
|
client.ref["onleave"] = this._onLeave.bind(this, client);
|
|
268
263
|
client.ref.once("close", client.ref["onleave"]);
|
|
269
|
-
this.clients.push(client);
|
|
270
264
|
const previousReconnectionToken = this._reconnectingSessionId.get(sessionId);
|
|
271
265
|
if (previousReconnectionToken) {
|
|
266
|
+
this.clients.push(client);
|
|
272
267
|
this._reconnections[previousReconnectionToken]?.[1].resolve(client);
|
|
273
268
|
} else {
|
|
274
269
|
try {
|
|
275
270
|
client.auth = await this.onAuth(client, options, req);
|
|
271
|
+
if (client.readyState !== WebSocket.OPEN) {
|
|
272
|
+
throw new ServerError(Protocol.WS_CLOSE_GOING_AWAY, "already disconnected");
|
|
273
|
+
}
|
|
276
274
|
if (!client.auth) {
|
|
277
275
|
throw new ServerError(ErrorCode.AUTH_FAILED, "onAuth failed");
|
|
278
276
|
}
|
|
277
|
+
this.clients.push(client);
|
|
279
278
|
if (this.onJoin) {
|
|
280
279
|
await this.onJoin(client, options, client.auth);
|
|
281
280
|
}
|
package/build/Room.mjs.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/Room.ts"],
|
|
4
|
-
"sourcesContent": ["import http from 'http';\n\nimport { unpack } from 'msgpackr';\nimport { decode, Iterator, Schema } from '@colyseus/schema';\n\nimport Clock from '@gamestdio/timer';\nimport { EventEmitter } from 'events';\nimport { logger } from './Logger';\n\nimport { Presence } from './presence/Presence';\n\nimport { NoneSerializer } from './serializer/NoneSerializer';\nimport { SchemaSerializer } from './serializer/SchemaSerializer';\nimport { Serializer } from './serializer/Serializer';\n\nimport { ErrorCode, getMessageBytes, Protocol } from './Protocol';\nimport { Deferred, generateId } from './utils/Utils';\nimport { isDevMode } from './utils/DevMode';\n\nimport { debugAndPrintError, debugMessage } from './Debug';\nimport { ServerError } from './errors/ServerError';\nimport { RoomListingData } from './matchmaker/driver';\nimport { Client, ClientArray, ClientState, ISendOptions } from './Transport';\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 extends object= any> = new (presence?: Presence) => Room<T>;\n\nexport interface IBroadcastOptions extends ISendOptions {\n except?: Client | Client[];\n}\n\nexport enum RoomInternalState {\n CREATING = 0,\n CREATED = 1,\n DISPOSING = 2,\n}\n\ntype ExtractUserData<T> = T extends ClientArray<infer U> ? U : never;\ntype ExtractAuthData<T> = T extends ClientArray<infer _, infer U> ? U : never;\n\n/**\n * A Room class is meant to implement a game session, and/or serve as the communication channel\n * between a group of clients.\n *\n * - Rooms are created on demand during matchmaking by default\n * - Room classes must be exposed using `.define()`\n */\nexport abstract class Room<State extends object= any, Metadata= any> {\n\n /**\n * This property will change on these situations:\n * - The maximum number of allowed clients has been reached (`maxClients`)\n * - You manually locked, or unlocked the room using lock() or `unlock()`.\n *\n * @readonly\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\n /**\n * A ClockTimer instance, used for timing events.\n */\n public clock: Clock = new Clock();\n\n #_roomId: string;\n #_roomName: string;\n\n /**\n * Maximum number of clients allowed to connect into the room. When room reaches this limit,\n * it is locked automatically. Unless the room was explicitly locked by you via `lock()` method,\n * the room will be unlocked as soon as a client disconnects from it.\n */\n public maxClients: number = Infinity;\n /**\n * Frequency to send the room state to connected clients, in milliseconds.\n *\n * @default 50ms (20fps)\n */\n public patchRate: number = DEFAULT_PATCH_RATE;\n /**\n * Automatically dispose the room when last client disconnects.\n *\n * @default true\n */\n public autoDispose: boolean = true;\n\n /**\n * The state instance you provided to `setState()`.\n */\n public state: State;\n /**\n * The presence instance. Check Presence API for more details.\n *\n * @see {@link https://docs.colyseus.io/colyseus/server/presence/|Presence API}\n */\n public presence: Presence;\n\n /**\n * The array of connected clients.\n *\n * @see {@link https://docs.colyseus.io/colyseus/server/room/#client|Client instance}\n */\n public clients: ClientArray = new ClientArray();\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: { [reconnectionToken: string]: [string, Deferred] } = {};\n private _reconnectingSessionId = new Map<string, string>();\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 _internalState: RoomInternalState = RoomInternalState.CREATING;\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 /**\n * The name of the room you provided as first argument for `gameServer.define()`.\n *\n * @returns roomName string\n */\n public get roomName() { return this.#_roomName; }\n /**\n * Setting the name of the room. Overwriting this property is restricted.\n *\n * @param roomName\n */\n public set roomName(roomName: string) {\n if (this.#_roomName) {\n // prevent user from setting roomName after it has been defined.\n throw new ServerError(ErrorCode.APPLICATION_ERROR, \"'roomName' cannot be overwritten.\");\n }\n this.#_roomName = roomName;\n }\n\n /**\n * A unique, auto-generated, 9-character-long id of the room.\n * You may replace `this.roomId` during `onCreate()`.\n *\n * @returns roomId string\n */\n public get roomId() { return this.#_roomId; }\n /**\n * Setting the roomId, is restricted in room lifetime except upon room creation.\n *\n * @param roomId\n * @returns roomId string\n */\n public set roomId(roomId: string) {\n if (this._internalState !== RoomInternalState.CREATING && !isDevMode) {\n // prevent user from setting roomId after room has been created.\n throw new ServerError(ErrorCode.APPLICATION_ERROR, \"'roomId' can only be overridden upon room creation.\");\n }\n this.#_roomId = roomId;\n }\n\n // Optional abstract methods\n public onBeforePatch?(state: State): void | Promise<any>;\n public onCreate?(options: any): void | Promise<any>;\n public onJoin?(\n client: Client<ExtractUserData<typeof this['clients']>, ExtractAuthData<typeof this['clients']>>,\n options?: any,\n auth?: ExtractAuthData<typeof this['clients']>,\n ): void | Promise<any>;\n public onLeave?(\n client: Client<ExtractUserData<typeof this['clients']>, ExtractAuthData<typeof this['clients']>>,\n consented?: boolean,\n ): void | Promise<any>;\n public onDispose?(): void | Promise<any>;\n public onAuth(\n client: Client<ExtractUserData<typeof this['clients']>, ExtractAuthData<typeof this['clients']>>,\n options: any,\n request?: http.IncomingMessage\n ): any | Promise<any> {\n return true;\n }\n\n /**\n * devMode: When `devMode` is enabled, `onCacheRoom` method is called during\n * graceful shutdown.\n *\n * Implement this method to return custom data to be cached. `onRestoreRoom`\n * will be called with the data returned by `onCacheRoom`\n */\n public onCacheRoom?(): any;\n\n /**\n * devMode: When `devMode` is enabled, `onRestoreRoom` method is called during\n * process startup, with the data returned by the `onCacheRoom` method.\n */\n public onRestoreRoom?(cached?: any): void;\n\n /**\n * Returns whether the sum of connected clients and reserved seats exceeds maximum number of clients.\n *\n * @returns boolean\n */\n public hasReachedMaxClients(): boolean {\n return (\n (this.clients.length + Object.keys(this.reservedSeats).length) >= this.maxClients ||\n this._internalState === RoomInternalState.DISPOSING\n );\n }\n\n /**\n * Set the number of seconds a room can wait for a client to effectively join the room.\n * You should consider how long your `onAuth()` will have to wait for setting a different seat reservation time.\n * The default value is 15 seconds. You may set the `COLYSEUS_SEAT_RESERVATION_TIME`\n * environment variable if you'd like to change the seat reservation time globally.\n *\n * @default 15 seconds\n *\n * @param seconds - number of seconds.\n * @returns The modified Room object.\n */\n public setSeatReservationTime(seconds: number) {\n this.seatReservationTime = seconds;\n return this;\n }\n\n public hasReservedSeat(sessionId: string, reconnectionToken?: string): boolean {\n if (reconnectionToken) {\n const reconnection = this._reconnections[reconnectionToken];\n return (\n reconnection &&\n reconnection[0] === sessionId &&\n this.reservedSeats[sessionId] !== undefined &&\n this._reconnectingSessionId.has(sessionId)\n );\n\n } else {\n return (\n this.reservedSeats[sessionId] !== undefined &&\n (\n !this._reconnectingSessionId.has(sessionId) || // prevent possible \"reconnect\" requests without a reconnection token\n (this._reconnectingSessionId.get(sessionId) === sessionId) // devMode reconnection\n )\n );\n }\n }\n\n public checkReconnectionToken(reconnectionToken: string) {\n const reconnection = this._reconnections[reconnectionToken];\n const sessionId = (reconnection && reconnection[0]);\n\n if (this.hasReservedSeat(sessionId)) {\n this._reconnectingSessionId.set(sessionId, reconnectionToken);\n return sessionId;\n\n } else {\n return undefined;\n }\n }\n\n /**\n * (Optional) Set a simulation interval that can change the state of the game.\n * The simulation interval is your game loop.\n *\n * @default 16.6ms (60fps)\n *\n * @param onTickCallback - You can implement your physics or world updates here!\n * This is a good place to update the room state.\n * @param delay - Interval delay on executing `onTickCallback` in milliseconds.\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 /**\n * Locking the room will remove it from the pool of available rooms for new clients to connect to.\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 /**\n * Unlocking the room returns it to the pool of available rooms for new clients to connect to.\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 logger.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\n this.broadcastMessageType(typeOrSchema as string, messageOrOptions, opts);\n }\n }\n\n /**\n * Checks whether mutations have occurred in the state, and broadcast them to all connected clients.\n */\n public broadcastPatch() {\n if (this.onBeforePatch) {\n this.onBeforePatch(this.state);\n }\n\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>(\n messageType: '*',\n callback: (client: Client<ExtractUserData<typeof this['clients']>, ExtractAuthData<typeof this['clients']>>, type: string | number, message: T) => void\n );\n public onMessage<T = any>(\n messageType: string | number,\n callback: (client: Client<ExtractUserData<typeof this['clients']>, ExtractAuthData<typeof this['clients']>>, message: T) => void\n );\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 /**\n * Disconnect all connected clients, and then dispose the room.\n *\n * @param closeCode WebSocket close code (default = 4000, which is a \"consented leave\")\n * @returns Promise<void>\n */\n public async disconnect(closeCode: number = Protocol.WS_CLOSE_CONSENTED): Promise<any> {\n // skip if already disposing\n if (this._internalState === RoomInternalState.DISPOSING) {\n return;\n }\n\n this._internalState = RoomInternalState.DISPOSING;\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], closeCode);\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 // generate unique private reconnection token\n client._reconnectionToken = generateId();\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 previousReconnectionToken = this._reconnectingSessionId.get(sessionId);\n if (previousReconnectionToken) {\n this._reconnections[previousReconnectionToken]?.[1].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 this.clients.delete(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 client._reconnectionToken,\n this._serializer.id,\n this._serializer.handshake && this._serializer.handshake(),\n ));\n }\n\n /**\n * Allow the specified client to reconnect into the room. Must be used inside `onLeave()` method.\n * If seconds is provided, the reconnection is going to be cancelled after the provided amount of seconds.\n *\n * @param previousClient - The client which is to be waiting until re-connection happens.\n * @param seconds - Timeout period on re-connection in seconds.\n *\n * @returns Deferred<Client> - The differed is a promise like type.\n * This type can forcibly reject the promise by calling `.reject()`.\n */\n public allowReconnection(previousClient: Client, seconds: number | \"manual\"): Deferred<Client> {\n if (seconds === undefined) { // TODO: remove this check\n console.warn(\"DEPRECATED: allowReconnection() requires a second argument. Using \\\"manual\\\" mode.\");\n seconds = \"manual\";\n }\n\n if (seconds === \"manual\") {\n seconds = Infinity;\n }\n\n if (this._internalState === RoomInternalState.DISPOSING) {\n this._disposeIfEmpty(); // gracefully shutting down\n throw new Error('disconnecting');\n }\n\n const sessionId = previousClient.sessionId;\n const reconnectionToken = previousClient._reconnectionToken;\n\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[reconnectionToken] = [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._reconnections[reconnectionToken];\n delete this.reservedSeats[sessionId];\n delete this.reservedSeatTimeouts[sessionId];\n this._reconnectingSessionId.delete(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 debugMessage(\"broadcast: %O\", message);\n const encodedMessage = getMessageBytes[Protocol.ROOM_DATA_SCHEMA](message);\n const except = (typeof (options.except) !== \"undefined\")\n ? Array.isArray(options.except)\n ? options.except\n : [options.except]\n : undefined;\n\n let numClients = this.clients.length;\n while (numClients--) {\n const client = this.clients[numClients];\n\n if (!except || !except.includes(client)) {\n client.enqueueRaw(encodedMessage);\n }\n }\n }\n\n private broadcastMessageType(type: string, message?: any, options: IBroadcastOptions = {}) {\n debugMessage(\"broadcast: %O\", message);\n const encodedMessage = getMessageBytes.raw(Protocol.ROOM_DATA, type, message);\n const except = (typeof (options.except) !== \"undefined\")\n ? Array.isArray(options.except)\n ? options.except\n : [options.except]\n : undefined;\n\n let numClients = this.clients.length;\n while (numClients--) {\n const client = this.clients[numClients];\n\n if (!except || !except.includes(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 devModeReconnection?: boolean,\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 //\n // isDevMode workaround to allow players to reconnect on devMode\n //\n if (devModeReconnection) {\n this._reconnectingSessionId.set(sessionId, sessionId);\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 this._internalState = RoomInternalState.DISPOSING;\n\n await this.listing.remove();\n\n let userReturnData;\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 ? unpack(new Uint8Array(bytes.slice(it.offset, bytes.length)))\n : undefined;\n debugMessage(\"received: '%s' -> %j\", messageType, message);\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.ROOM_DATA_BYTES) {\n const messageType = (decode.stringCheck(bytes, it))\n ? decode.string(bytes, it)\n : decode.number(bytes, it);\n\n const message = bytes.slice(it.offset, bytes.length);\n debugMessage(\"received: '%s' -> %j\", messageType, message);\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(closeCode));\n }\n\n private async _onLeave(client: Client, code?: number): Promise<any> {\n const success = this.clients.delete(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 immediately 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.DISPOSING) {\n return true;\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"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import http from 'http';\nimport WebSocket from 'ws'; // TODO: move this to Transport\n\nimport { unpack } from 'msgpackr';\nimport { decode, Iterator, Schema } from '@colyseus/schema';\n\nimport Clock from '@gamestdio/timer';\nimport { EventEmitter } from 'events';\nimport { logger } from './Logger';\n\nimport { Presence } from './presence/Presence';\n\nimport { NoneSerializer } from './serializer/NoneSerializer';\nimport { SchemaSerializer } from './serializer/SchemaSerializer';\nimport { Serializer } from './serializer/Serializer';\n\nimport { ErrorCode, getMessageBytes, Protocol } from './Protocol';\nimport { Deferred, generateId } from './utils/Utils';\nimport { isDevMode } from './utils/DevMode';\n\nimport { debugAndPrintError, debugMessage } from './Debug';\nimport { ServerError } from './errors/ServerError';\nimport { RoomListingData } from './matchmaker/driver';\nimport { Client, ClientArray, ClientState, ISendOptions } from './Transport';\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 extends object= any> = new (presence?: Presence) => Room<T>;\n\nexport interface IBroadcastOptions extends ISendOptions {\n except?: Client | Client[];\n}\n\nexport enum RoomInternalState {\n CREATING = 0,\n CREATED = 1,\n DISPOSING = 2,\n}\n\ntype ExtractUserData<T> = T extends ClientArray<infer U> ? U : never;\ntype ExtractAuthData<T> = T extends ClientArray<infer _, infer U> ? U : never;\n\n/**\n * A Room class is meant to implement a game session, and/or serve as the communication channel\n * between a group of clients.\n *\n * - Rooms are created on demand during matchmaking by default\n * - Room classes must be exposed using `.define()`\n */\nexport abstract class Room<State extends object= any, Metadata= any> {\n\n /**\n * This property will change on these situations:\n * - The maximum number of allowed clients has been reached (`maxClients`)\n * - You manually locked, or unlocked the room using lock() or `unlock()`.\n *\n * @readonly\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\n /**\n * A ClockTimer instance, used for timing events.\n */\n public clock: Clock = new Clock();\n\n #_roomId: string;\n #_roomName: string;\n\n /**\n * Maximum number of clients allowed to connect into the room. When room reaches this limit,\n * it is locked automatically. Unless the room was explicitly locked by you via `lock()` method,\n * the room will be unlocked as soon as a client disconnects from it.\n */\n public maxClients: number = Infinity;\n /**\n * Frequency to send the room state to connected clients, in milliseconds.\n *\n * @default 50ms (20fps)\n */\n public patchRate: number = DEFAULT_PATCH_RATE;\n /**\n * Automatically dispose the room when last client disconnects.\n *\n * @default true\n */\n public autoDispose: boolean = true;\n\n /**\n * The state instance you provided to `setState()`.\n */\n public state: State;\n /**\n * The presence instance. Check Presence API for more details.\n *\n * @see {@link https://docs.colyseus.io/colyseus/server/presence/|Presence API}\n */\n public presence: Presence;\n\n /**\n * The array of connected clients.\n *\n * @see {@link https://docs.colyseus.io/colyseus/server/room/#client|Client instance}\n */\n public clients: ClientArray = new ClientArray();\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: { [reconnectionToken: string]: [string, Deferred] } = {};\n private _reconnectingSessionId = new Map<string, string>();\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 _internalState: RoomInternalState = RoomInternalState.CREATING;\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 /**\n * The name of the room you provided as first argument for `gameServer.define()`.\n *\n * @returns roomName string\n */\n public get roomName() { return this.#_roomName; }\n /**\n * Setting the name of the room. Overwriting this property is restricted.\n *\n * @param roomName\n */\n public set roomName(roomName: string) {\n if (this.#_roomName) {\n // prevent user from setting roomName after it has been defined.\n throw new ServerError(ErrorCode.APPLICATION_ERROR, \"'roomName' cannot be overwritten.\");\n }\n this.#_roomName = roomName;\n }\n\n /**\n * A unique, auto-generated, 9-character-long id of the room.\n * You may replace `this.roomId` during `onCreate()`.\n *\n * @returns roomId string\n */\n public get roomId() { return this.#_roomId; }\n /**\n * Setting the roomId, is restricted in room lifetime except upon room creation.\n *\n * @param roomId\n * @returns roomId string\n */\n public set roomId(roomId: string) {\n if (this._internalState !== RoomInternalState.CREATING && !isDevMode) {\n // prevent user from setting roomId after room has been created.\n throw new ServerError(ErrorCode.APPLICATION_ERROR, \"'roomId' can only be overridden upon room creation.\");\n }\n this.#_roomId = roomId;\n }\n\n // Optional abstract methods\n public onBeforePatch?(state: State): void | Promise<any>;\n public onCreate?(options: any): void | Promise<any>;\n public onJoin?(\n client: Client<ExtractUserData<typeof this['clients']>, ExtractAuthData<typeof this['clients']>>,\n options?: any,\n auth?: ExtractAuthData<typeof this['clients']>,\n ): void | Promise<any>;\n public onLeave?(\n client: Client<ExtractUserData<typeof this['clients']>, ExtractAuthData<typeof this['clients']>>,\n consented?: boolean,\n ): void | Promise<any>;\n public onDispose?(): void | Promise<any>;\n public onAuth(\n client: Client<ExtractUserData<typeof this['clients']>, ExtractAuthData<typeof this['clients']>>,\n options: any,\n request?: http.IncomingMessage\n ): any | Promise<any> {\n return true;\n }\n\n /**\n * devMode: When `devMode` is enabled, `onCacheRoom` method is called during\n * graceful shutdown.\n *\n * Implement this method to return custom data to be cached. `onRestoreRoom`\n * will be called with the data returned by `onCacheRoom`\n */\n public onCacheRoom?(): any;\n\n /**\n * devMode: When `devMode` is enabled, `onRestoreRoom` method is called during\n * process startup, with the data returned by the `onCacheRoom` method.\n */\n public onRestoreRoom?(cached?: any): void;\n\n /**\n * Returns whether the sum of connected clients and reserved seats exceeds maximum number of clients.\n *\n * @returns boolean\n */\n public hasReachedMaxClients(): boolean {\n return (\n (this.clients.length + Object.keys(this.reservedSeats).length) >= this.maxClients ||\n this._internalState === RoomInternalState.DISPOSING\n );\n }\n\n /**\n * Set the number of seconds a room can wait for a client to effectively join the room.\n * You should consider how long your `onAuth()` will have to wait for setting a different seat reservation time.\n * The default value is 15 seconds. You may set the `COLYSEUS_SEAT_RESERVATION_TIME`\n * environment variable if you'd like to change the seat reservation time globally.\n *\n * @default 15 seconds\n *\n * @param seconds - number of seconds.\n * @returns The modified Room object.\n */\n public setSeatReservationTime(seconds: number) {\n this.seatReservationTime = seconds;\n return this;\n }\n\n public hasReservedSeat(sessionId: string, reconnectionToken?: string): boolean {\n if (reconnectionToken) {\n const reconnection = this._reconnections[reconnectionToken];\n return (\n reconnection &&\n reconnection[0] === sessionId &&\n this.reservedSeats[sessionId] !== undefined &&\n this._reconnectingSessionId.has(sessionId)\n );\n\n } else {\n return (\n this.reservedSeats[sessionId] !== undefined &&\n (\n !this._reconnectingSessionId.has(sessionId) || // prevent possible \"reconnect\" requests without a reconnection token\n (this._reconnectingSessionId.get(sessionId) === sessionId) // devMode reconnection\n )\n );\n }\n }\n\n public checkReconnectionToken(reconnectionToken: string) {\n const reconnection = this._reconnections[reconnectionToken];\n const sessionId = (reconnection && reconnection[0]);\n\n if (this.hasReservedSeat(sessionId)) {\n this._reconnectingSessionId.set(sessionId, reconnectionToken);\n return sessionId;\n\n } else {\n return undefined;\n }\n }\n\n /**\n * (Optional) Set a simulation interval that can change the state of the game.\n * The simulation interval is your game loop.\n *\n * @default 16.6ms (60fps)\n *\n * @param onTickCallback - You can implement your physics or world updates here!\n * This is a good place to update the room state.\n * @param delay - Interval delay on executing `onTickCallback` in milliseconds.\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 /**\n * Locking the room will remove it from the pool of available rooms for new clients to connect to.\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 /**\n * Unlocking the room returns it to the pool of available rooms for new clients to connect to.\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 logger.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\n this.broadcastMessageType(typeOrSchema as string, messageOrOptions, opts);\n }\n }\n\n /**\n * Checks whether mutations have occurred in the state, and broadcast them to all connected clients.\n */\n public broadcastPatch() {\n if (this.onBeforePatch) {\n this.onBeforePatch(this.state);\n }\n\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>(\n messageType: '*',\n callback: (client: Client<ExtractUserData<typeof this['clients']>, ExtractAuthData<typeof this['clients']>>, type: string | number, message: T) => void\n );\n public onMessage<T = any>(\n messageType: string | number,\n callback: (client: Client<ExtractUserData<typeof this['clients']>, ExtractAuthData<typeof this['clients']>>, message: T) => void\n );\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 /**\n * Disconnect all connected clients, and then dispose the room.\n *\n * @param closeCode WebSocket close code (default = 4000, which is a \"consented leave\")\n * @returns Promise<void>\n */\n public async disconnect(closeCode: number = Protocol.WS_CLOSE_CONSENTED): Promise<any> {\n // skip if already disposing\n if (this._internalState === RoomInternalState.DISPOSING) {\n return;\n }\n\n this._internalState = RoomInternalState.DISPOSING;\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], closeCode);\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 // generate unique private reconnection token\n client._reconnectionToken = generateId();\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 const previousReconnectionToken = this._reconnectingSessionId.get(sessionId);\n if (previousReconnectionToken) {\n this.clients.push(client);\n this._reconnections[previousReconnectionToken]?.[1].resolve(client);\n\n } else {\n try {\n client.auth = await this.onAuth(client, options, req);\n\n //\n // On async onAuth, client may have been disconnected.\n //\n if (client.readyState !== WebSocket.OPEN) {\n throw new ServerError(Protocol.WS_CLOSE_GOING_AWAY, 'already disconnected');\n }\n\n if (!client.auth) {\n throw new ServerError(ErrorCode.AUTH_FAILED, 'onAuth failed');\n }\n\n this.clients.push(client);\n\n if (this.onJoin) {\n await this.onJoin(client, options, client.auth);\n }\n } catch (e) {\n this.clients.delete(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 client._reconnectionToken,\n this._serializer.id,\n this._serializer.handshake && this._serializer.handshake(),\n ));\n }\n\n /**\n * Allow the specified client to reconnect into the room. Must be used inside `onLeave()` method.\n * If seconds is provided, the reconnection is going to be cancelled after the provided amount of seconds.\n *\n * @param previousClient - The client which is to be waiting until re-connection happens.\n * @param seconds - Timeout period on re-connection in seconds.\n *\n * @returns Deferred<Client> - The differed is a promise like type.\n * This type can forcibly reject the promise by calling `.reject()`.\n */\n public allowReconnection(previousClient: Client, seconds: number | \"manual\"): Deferred<Client> {\n if (seconds === undefined) { // TODO: remove this check\n console.warn(\"DEPRECATED: allowReconnection() requires a second argument. Using \\\"manual\\\" mode.\");\n seconds = \"manual\";\n }\n\n if (seconds === \"manual\") {\n seconds = Infinity;\n }\n\n if (this._internalState === RoomInternalState.DISPOSING) {\n this._disposeIfEmpty(); // gracefully shutting down\n throw new Error('disconnecting');\n }\n\n const sessionId = previousClient.sessionId;\n const reconnectionToken = previousClient._reconnectionToken;\n\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[reconnectionToken] = [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._reconnections[reconnectionToken];\n delete this.reservedSeats[sessionId];\n delete this.reservedSeatTimeouts[sessionId];\n this._reconnectingSessionId.delete(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 debugMessage(\"broadcast: %O\", message);\n const encodedMessage = getMessageBytes[Protocol.ROOM_DATA_SCHEMA](message);\n const except = (typeof (options.except) !== \"undefined\")\n ? Array.isArray(options.except)\n ? options.except\n : [options.except]\n : undefined;\n\n let numClients = this.clients.length;\n while (numClients--) {\n const client = this.clients[numClients];\n\n if (!except || !except.includes(client)) {\n client.enqueueRaw(encodedMessage);\n }\n }\n }\n\n private broadcastMessageType(type: string, message?: any, options: IBroadcastOptions = {}) {\n debugMessage(\"broadcast: %O\", message);\n const encodedMessage = getMessageBytes.raw(Protocol.ROOM_DATA, type, message);\n const except = (typeof (options.except) !== \"undefined\")\n ? Array.isArray(options.except)\n ? options.except\n : [options.except]\n : undefined;\n\n let numClients = this.clients.length;\n while (numClients--) {\n const client = this.clients[numClients];\n\n if (!except || !except.includes(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 devModeReconnection?: boolean,\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 //\n // isDevMode workaround to allow players to reconnect on devMode\n //\n if (devModeReconnection) {\n this._reconnectingSessionId.set(sessionId, sessionId);\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 this._internalState = RoomInternalState.DISPOSING;\n\n await this.listing.remove();\n\n let userReturnData;\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 ? unpack(new Uint8Array(bytes.slice(it.offset, bytes.length)))\n : undefined;\n debugMessage(\"received: '%s' -> %j\", messageType, message);\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.ROOM_DATA_BYTES) {\n const messageType = (decode.stringCheck(bytes, it))\n ? decode.string(bytes, it)\n : decode.number(bytes, it);\n\n const message = bytes.slice(it.offset, bytes.length);\n debugMessage(\"received: '%s' -> %j\", messageType, message);\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(closeCode));\n }\n\n private async _onLeave(client: Client, code?: number): Promise<any> {\n const success = this.clients.delete(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 immediately 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.DISPOSING) {\n return true;\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"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["RoomInternalState"]
|
|
7
7
|
}
|
package/build/Server.js
CHANGED
|
@@ -37,12 +37,8 @@ var import_driver = require("./matchmaker/driver");
|
|
|
37
37
|
var import_Logger = require("./Logger");
|
|
38
38
|
var import_DevMode = require("./utils/DevMode");
|
|
39
39
|
class Server {
|
|
40
|
-
transport;
|
|
41
|
-
presence;
|
|
42
|
-
driver;
|
|
43
|
-
port;
|
|
44
|
-
greet;
|
|
45
40
|
constructor(options = {}) {
|
|
41
|
+
this.onShutdownCallback = () => Promise.resolve();
|
|
46
42
|
const { gracefullyShutdown = true, greet = true } = options;
|
|
47
43
|
(0, import_DevMode.setDevMode)(options.devMode === true);
|
|
48
44
|
this.presence = options.presence || new import_LocalPresence.LocalPresence();
|
|
@@ -152,7 +148,6 @@ class Server {
|
|
|
152
148
|
getDefaultTransport(_) {
|
|
153
149
|
throw new Error("Please provide a 'transport' layer. Default transport not set.");
|
|
154
150
|
}
|
|
155
|
-
onShutdownCallback = () => Promise.resolve();
|
|
156
151
|
attachMatchMakingRoutes(server) {
|
|
157
152
|
const listeners = server.listeners("request").slice(0);
|
|
158
153
|
server.removeAllListeners("request");
|
package/build/Server.js.map
CHANGED
|
@@ -2,6 +2,6 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/Server.ts"],
|
|
4
4
|
"sourcesContent": ["import http, { IncomingMessage, ServerResponse } from 'http';\nimport greeting from \"@colyseus/greeting-banner\";\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/Utils';\n\nimport { registerNode, unregisterNode} from './discovery';\n\nimport { LocalPresence } from './presence/LocalPresence';\nimport { LocalDriver } from './matchmaker/driver';\n\nimport { Transport } from './Transport';\nimport { logger, setLogger } from './Logger';\nimport { setDevMode, isDevMode } from './utils/DevMode';\n\n// IServerOptions &\nexport type ServerOptions = {\n publicAddress?: string,\n presence?: Presence,\n driver?: matchMaker.MatchMakerDriver,\n transport?: Transport,\n gracefullyShutdown?: boolean,\n logger?: any;\n\n /**\n * If enabled, rooms are going to be restored in the server-side upon restart,\n * clients are going to automatically re-connect when server reboots.\n *\n * Beware of \"schema mismatch\" issues. When updating Schema structures and\n * reloading existing data, you may see \"schema mismatch\" errors in the\n * client-side.\n *\n * (This operation is costly and should never be used in a production\n * environment)\n */\n devMode?: 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 driver: matchMaker.MatchMakerDriver;\n\n protected port: number;\n protected greet: boolean;\n\n constructor(options: ServerOptions = {}) {\n const { gracefullyShutdown = true, greet = true } = options;\n\n setDevMode(options.devMode === true);\n\n this.presence = options.presence || new LocalPresence();\n this.driver = options.driver || new LocalDriver();\n this.greet = greet;\n\n this.attach(options);\n\n matchMaker.setup(\n this.presence,\n this.driver,\n options.publicAddress,\n );\n\n if (gracefullyShutdown) {\n registerGracefulShutdown((err) => this.gracefullyShutdown(true, err));\n }\n\n if (options.logger) {\n setLogger(options.logger);\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 logger.warn(\"DEPRECATION WARNING: 'pingInterval', 'pingMaxRetries', 'server', and 'verifyClient' Server options will be permanently moved to WebSocketTransport on v0.15\");\n logger.warn(`new Server({\n transport: new WebSocketTransport({\n pingInterval: ...,\n pingMaxRetries: ...,\n server: ...,\n verifyClient: ...\n })\n})`);\n logger.warn(\"\uD83D\uDC49 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 // Make sure matchmaker is ready before accepting connections\n // (isDevMode: matchmaker may take extra milliseconds to restore the rooms)\n //\n await matchMaker.onReady;\n\n /**\n * Greetings!\n */\n if (this.greet) {\n console.log(greeting);\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 async registerProcessForDiscovery() {\n // register node for proxy/service discovery\n await registerNode(this.presence, {\n port: this.port,\n processId: matchMaker.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 /**\n * Remove a room definition from matchmaking.\n * This method does not destroy any room. It only dissallows matchmaking\n */\n public removeRoomType(name: string): void {\n matchMaker.removeRoomType(name);\n }\n\n public async gracefullyShutdown(exit: boolean = true, err?: Error) {\n if (matchMaker.isGracefullyShuttingDown) {\n return;\n }\n\n await unregisterNode(this.presence, {\n port: this.port,\n processId: matchMaker.processId,\n });\n\n try {\n await matchMaker.gracefullyShutdown();\n this.transport.shutdown();\n this.presence.shutdown();\n this.driver.shutdown();\n await this.onShutdownCallback();\n\n } catch (e) {\n debugAndPrintError(`error during shutdown: ${e}`);\n\n } finally {\n if (exit) {\n process.exit((err && !isDevMode) ? 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 logger.warn(`\uD83D\uDCF6\uFE0F\u2757 Colyseus latency simulation enabled \u2192 ${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(`/${matchMaker.controller.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 // do not accept matchmaking requests if already shutting down\n if (matchMaker.isGracefullyShuttingDown) {\n res.writeHead(503, {});\n res.end();\n return;\n }\n\n const headers = Object.assign(\n {},\n matchMaker.controller.DEFAULT_CORS_HEADERS,\n matchMaker.controller.getCorsHeaders.call(undefined, req)\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(matchMaker.controller.allowedRoomNameChars);\n const matchmakeIndex = matchedParams.indexOf(matchMaker.controller.matchmakeRoute);\n const method = matchedParams[matchmakeIndex + 1];\n const roomName = 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, roomName, 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(matchMaker.controller.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}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,6BAAqB;AAErB,mBAAqD;AACrD,iBAA4B;AAI5B,kBAAqB;AAErB,mBAAyC;AAEzC,uBAA4C;AAE5C,2BAA8B;AAC9B,oBAA4B;AAG5B,oBAAkC;AAClC,qBAAsC;AA+C/B,MAAM,OAAO;AAAA,
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["greeting"]
|
|
7
7
|
}
|
package/build/Server.mjs
CHANGED
|
@@ -9,12 +9,8 @@ import { LocalDriver } from "./matchmaker/driver";
|
|
|
9
9
|
import { logger, setLogger } from "./Logger";
|
|
10
10
|
import { setDevMode, isDevMode } from "./utils/DevMode";
|
|
11
11
|
class Server {
|
|
12
|
-
transport;
|
|
13
|
-
presence;
|
|
14
|
-
driver;
|
|
15
|
-
port;
|
|
16
|
-
greet;
|
|
17
12
|
constructor(options = {}) {
|
|
13
|
+
this.onShutdownCallback = () => Promise.resolve();
|
|
18
14
|
const { gracefullyShutdown = true, greet = true } = options;
|
|
19
15
|
setDevMode(options.devMode === true);
|
|
20
16
|
this.presence = options.presence || new LocalPresence();
|
|
@@ -124,7 +120,6 @@ class Server {
|
|
|
124
120
|
getDefaultTransport(_) {
|
|
125
121
|
throw new Error("Please provide a 'transport' layer. Default transport not set.");
|
|
126
122
|
}
|
|
127
|
-
onShutdownCallback = () => Promise.resolve();
|
|
128
123
|
attachMatchMakingRoutes(server) {
|
|
129
124
|
const listeners = server.listeners("request").slice(0);
|
|
130
125
|
server.removeAllListeners("request");
|
package/build/Server.mjs.map
CHANGED
|
@@ -2,6 +2,6 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/Server.ts"],
|
|
4
4
|
"sourcesContent": ["import http, { IncomingMessage, ServerResponse } from 'http';\nimport greeting from \"@colyseus/greeting-banner\";\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/Utils';\n\nimport { registerNode, unregisterNode} from './discovery';\n\nimport { LocalPresence } from './presence/LocalPresence';\nimport { LocalDriver } from './matchmaker/driver';\n\nimport { Transport } from './Transport';\nimport { logger, setLogger } from './Logger';\nimport { setDevMode, isDevMode } from './utils/DevMode';\n\n// IServerOptions &\nexport type ServerOptions = {\n publicAddress?: string,\n presence?: Presence,\n driver?: matchMaker.MatchMakerDriver,\n transport?: Transport,\n gracefullyShutdown?: boolean,\n logger?: any;\n\n /**\n * If enabled, rooms are going to be restored in the server-side upon restart,\n * clients are going to automatically re-connect when server reboots.\n *\n * Beware of \"schema mismatch\" issues. When updating Schema structures and\n * reloading existing data, you may see \"schema mismatch\" errors in the\n * client-side.\n *\n * (This operation is costly and should never be used in a production\n * environment)\n */\n devMode?: 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 driver: matchMaker.MatchMakerDriver;\n\n protected port: number;\n protected greet: boolean;\n\n constructor(options: ServerOptions = {}) {\n const { gracefullyShutdown = true, greet = true } = options;\n\n setDevMode(options.devMode === true);\n\n this.presence = options.presence || new LocalPresence();\n this.driver = options.driver || new LocalDriver();\n this.greet = greet;\n\n this.attach(options);\n\n matchMaker.setup(\n this.presence,\n this.driver,\n options.publicAddress,\n );\n\n if (gracefullyShutdown) {\n registerGracefulShutdown((err) => this.gracefullyShutdown(true, err));\n }\n\n if (options.logger) {\n setLogger(options.logger);\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 logger.warn(\"DEPRECATION WARNING: 'pingInterval', 'pingMaxRetries', 'server', and 'verifyClient' Server options will be permanently moved to WebSocketTransport on v0.15\");\n logger.warn(`new Server({\n transport: new WebSocketTransport({\n pingInterval: ...,\n pingMaxRetries: ...,\n server: ...,\n verifyClient: ...\n })\n})`);\n logger.warn(\"\uD83D\uDC49 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 // Make sure matchmaker is ready before accepting connections\n // (isDevMode: matchmaker may take extra milliseconds to restore the rooms)\n //\n await matchMaker.onReady;\n\n /**\n * Greetings!\n */\n if (this.greet) {\n console.log(greeting);\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 async registerProcessForDiscovery() {\n // register node for proxy/service discovery\n await registerNode(this.presence, {\n port: this.port,\n processId: matchMaker.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 /**\n * Remove a room definition from matchmaking.\n * This method does not destroy any room. It only dissallows matchmaking\n */\n public removeRoomType(name: string): void {\n matchMaker.removeRoomType(name);\n }\n\n public async gracefullyShutdown(exit: boolean = true, err?: Error) {\n if (matchMaker.isGracefullyShuttingDown) {\n return;\n }\n\n await unregisterNode(this.presence, {\n port: this.port,\n processId: matchMaker.processId,\n });\n\n try {\n await matchMaker.gracefullyShutdown();\n this.transport.shutdown();\n this.presence.shutdown();\n this.driver.shutdown();\n await this.onShutdownCallback();\n\n } catch (e) {\n debugAndPrintError(`error during shutdown: ${e}`);\n\n } finally {\n if (exit) {\n process.exit((err && !isDevMode) ? 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 logger.warn(`\uD83D\uDCF6\uFE0F\u2757 Colyseus latency simulation enabled \u2192 ${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(`/${matchMaker.controller.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 // do not accept matchmaking requests if already shutting down\n if (matchMaker.isGracefullyShuttingDown) {\n res.writeHead(503, {});\n res.end();\n return;\n }\n\n const headers = Object.assign(\n {},\n matchMaker.controller.DEFAULT_CORS_HEADERS,\n matchMaker.controller.getCorsHeaders.call(undefined, req)\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(matchMaker.controller.allowedRoomNameChars);\n const matchmakeIndex = matchedParams.indexOf(matchMaker.controller.matchmakeRoute);\n const method = matchedParams[matchmakeIndex + 1];\n const roomName = 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, roomName, 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(matchMaker.controller.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}\n"],
|
|
5
|
-
"mappings": "AACA,OAAO,cAAc;AAErB,SAAS,oBAAoB,wBAAwB;AACrD,YAAY,gBAAgB;AAI5B,SAAS,YAAY;AAErB,SAAS,gCAAgC;AAEzC,SAAS,cAAc,sBAAqB;AAE5C,SAAS,qBAAqB;AAC9B,SAAS,mBAAmB;AAG5B,SAAS,QAAQ,iBAAiB;AAClC,SAAS,YAAY,iBAAiB;AA+C/B,MAAM,OAAO;AAAA,
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/build/Transport.js
CHANGED
|
@@ -24,7 +24,6 @@ __export(Transport_exports, {
|
|
|
24
24
|
module.exports = __toCommonJS(Transport_exports);
|
|
25
25
|
var import_Utils2 = require("./Utils");
|
|
26
26
|
class Transport {
|
|
27
|
-
server;
|
|
28
27
|
}
|
|
29
28
|
var ClientState = /* @__PURE__ */ ((ClientState2) => {
|
|
30
29
|
ClientState2[ClientState2["JOINING"] = 0] = "JOINING";
|
package/build/Transport.js.map
CHANGED
|
@@ -2,6 +2,6 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/Transport.ts"],
|
|
4
4
|
"sourcesContent": ["import * as http from 'http';\nimport * as https from 'https';\nimport * as net from 'net';\n\nimport { Schema } from '@colyseus/schema';\nimport { EventEmitter } from 'events';\nimport { DummyServer } from './utils/Utils';\nimport { spliceOne } from './Utils';\n\nexport abstract class Transport {\n public server?: net.Server | http.Server | https.Server | DummyServer;\n\n public abstract listen(port?: number, hostname?: string, backlog?: number, listeningListener?: Function): this;\n public abstract shutdown(): void;\n\n public abstract simulateLatency(milliseconds: number): void;\n}\n\nexport interface ISendOptions {\n afterNextPatch?: boolean;\n}\n\nexport enum ClientState { JOINING, JOINED, RECONNECTED, LEAVING }\n\n/**\n * The client instance from the server-side is responsible for the transport layer between the server and the client.\n * It should not be confused with the Client from the client-side SDK, as they have completely different purposes!\n * You operate on client instances from `this.clients`, `Room#onJoin()`, `Room#onLeave()` and `Room#onMessage()`.\n *\n * - This is the raw WebSocket connection coming from the `ws` package. There are more methods available which aren't\n * encouraged to use along with Colyseus.\n */\nexport interface Client<UserData=any, AuthData=any> {\n readyState: number;\n\n id: string;\n /**\n * Unique id per session.\n */\n sessionId: string; // TODO: remove sessionId on version 1.0.0\n state: ClientState;\n\n ref: EventEmitter;\n\n upgradeReq?: http.IncomingMessage; // cross-compatibility for ws (v3.x+) and uws\n\n /**\n * User-defined data can be attached to the Client instance through this variable.\n * - Can be used to store custom data about the client's connection. userData is not synchronized with the client,\n * and should be used only to keep player-specific with its connection.\n */\n userData?: UserData;\n\n /**\n * auth data provided by your `onAuth`\n */\n auth?: AuthData;\n pingCount?: number; // ping / pong\n\n _reconnectionToken: string;\n _enqueuedMessages?: any[];\n _afterNextPatchQueue: Array<[string | Client, IArguments]>;\n\n raw(data: ArrayLike<number>, options?: ISendOptions, cb?: (err?: Error) => void): void;\n enqueueRaw(data: ArrayLike<number>, options?: ISendOptions): void;\n\n /**\n * Send a type of message to the client. Messages are encoded with MsgPack and can hold any\n * JSON-serializable data structure.\n *\n * @param type String or Number identifier the client SDK will use to receive this message\n * @param message Message payload. (automatically encoded with msgpack.)\n * @param options\n */\n send(type: string | number, message?: any, options?: ISendOptions): void;\n send(message: Schema, options?: ISendOptions): void;\n\n /**\n * Send raw bytes to this specific client.\n *\n * @param type String or Number identifier the client SDK will use to receive this message\n * @param bytes Raw byte array payload\n * @param options\n */\n sendBytes(type: string | number, bytes: number[] | Uint8Array, options?: ISendOptions): void;\n\n /**\n * Disconnect this client from the room.\n *\n * @param code Custom close code. Default value is 1000.\n * @param data\n * @see {@link https://docs.colyseus.io/colyseus/server/room/#leavecode-number}\n */\n leave(code?: number, data?: string): void;\n\n /**\n * @deprecated Use .leave() instead.\n */\n close(code?: number, data?: string): void;\n\n /**\n * Triggers `onError` with specified code to the client-side.\n *\n * @param code\n * @param message\n */\n error(code: number, message?: string): void;\n}\n\nexport class ClientArray<UserData = any, AuthData = any> extends Array<Client<UserData, AuthData>> {\n public getById(sessionId: string): Client<UserData, AuthData> | undefined {\n return this.find((client) => client.sessionId === sessionId);\n }\n\n public delete(client: Client<UserData, AuthData>): boolean {\n return spliceOne(this, this.indexOf(client));\n }\n}"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAOA,IAAAA,gBAA0B;AAEnB,MAAe,UAAU;
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAOA,IAAAA,gBAA0B;AAEnB,MAAe,UAAU;AAOhC;AAMO,IAAK,cAAL,kBAAKC,iBAAL;AAAmB,EAAAA,0BAAA;AAAS,EAAAA,0BAAA;AAAQ,EAAAA,0BAAA;AAAa,EAAAA,0BAAA;AAA5C,SAAAA;AAAA,GAAA;AAuFL,MAAM,oBAAoD,MAAkC;AAAA,EAC1F,QAAQ,WAA2D;AACxE,WAAO,KAAK,KAAK,CAAC,WAAW,OAAO,cAAc,SAAS;AAAA,EAC7D;AAAA,EAEO,OAAO,QAA6C;AACzD,eAAO,yBAAU,MAAM,KAAK,QAAQ,MAAM,CAAC;AAAA,EAC7C;AACF;",
|
|
6
6
|
"names": ["import_Utils", "ClientState"]
|
|
7
7
|
}
|
package/build/Transport.mjs
CHANGED
package/build/Transport.mjs.map
CHANGED
|
@@ -2,6 +2,6 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/Transport.ts"],
|
|
4
4
|
"sourcesContent": ["import * as http from 'http';\nimport * as https from 'https';\nimport * as net from 'net';\n\nimport { Schema } from '@colyseus/schema';\nimport { EventEmitter } from 'events';\nimport { DummyServer } from './utils/Utils';\nimport { spliceOne } from './Utils';\n\nexport abstract class Transport {\n public server?: net.Server | http.Server | https.Server | DummyServer;\n\n public abstract listen(port?: number, hostname?: string, backlog?: number, listeningListener?: Function): this;\n public abstract shutdown(): void;\n\n public abstract simulateLatency(milliseconds: number): void;\n}\n\nexport interface ISendOptions {\n afterNextPatch?: boolean;\n}\n\nexport enum ClientState { JOINING, JOINED, RECONNECTED, LEAVING }\n\n/**\n * The client instance from the server-side is responsible for the transport layer between the server and the client.\n * It should not be confused with the Client from the client-side SDK, as they have completely different purposes!\n * You operate on client instances from `this.clients`, `Room#onJoin()`, `Room#onLeave()` and `Room#onMessage()`.\n *\n * - This is the raw WebSocket connection coming from the `ws` package. There are more methods available which aren't\n * encouraged to use along with Colyseus.\n */\nexport interface Client<UserData=any, AuthData=any> {\n readyState: number;\n\n id: string;\n /**\n * Unique id per session.\n */\n sessionId: string; // TODO: remove sessionId on version 1.0.0\n state: ClientState;\n\n ref: EventEmitter;\n\n upgradeReq?: http.IncomingMessage; // cross-compatibility for ws (v3.x+) and uws\n\n /**\n * User-defined data can be attached to the Client instance through this variable.\n * - Can be used to store custom data about the client's connection. userData is not synchronized with the client,\n * and should be used only to keep player-specific with its connection.\n */\n userData?: UserData;\n\n /**\n * auth data provided by your `onAuth`\n */\n auth?: AuthData;\n pingCount?: number; // ping / pong\n\n _reconnectionToken: string;\n _enqueuedMessages?: any[];\n _afterNextPatchQueue: Array<[string | Client, IArguments]>;\n\n raw(data: ArrayLike<number>, options?: ISendOptions, cb?: (err?: Error) => void): void;\n enqueueRaw(data: ArrayLike<number>, options?: ISendOptions): void;\n\n /**\n * Send a type of message to the client. Messages are encoded with MsgPack and can hold any\n * JSON-serializable data structure.\n *\n * @param type String or Number identifier the client SDK will use to receive this message\n * @param message Message payload. (automatically encoded with msgpack.)\n * @param options\n */\n send(type: string | number, message?: any, options?: ISendOptions): void;\n send(message: Schema, options?: ISendOptions): void;\n\n /**\n * Send raw bytes to this specific client.\n *\n * @param type String or Number identifier the client SDK will use to receive this message\n * @param bytes Raw byte array payload\n * @param options\n */\n sendBytes(type: string | number, bytes: number[] | Uint8Array, options?: ISendOptions): void;\n\n /**\n * Disconnect this client from the room.\n *\n * @param code Custom close code. Default value is 1000.\n * @param data\n * @see {@link https://docs.colyseus.io/colyseus/server/room/#leavecode-number}\n */\n leave(code?: number, data?: string): void;\n\n /**\n * @deprecated Use .leave() instead.\n */\n close(code?: number, data?: string): void;\n\n /**\n * Triggers `onError` with specified code to the client-side.\n *\n * @param code\n * @param message\n */\n error(code: number, message?: string): void;\n}\n\nexport class ClientArray<UserData = any, AuthData = any> extends Array<Client<UserData, AuthData>> {\n public getById(sessionId: string): Client<UserData, AuthData> | undefined {\n return this.find((client) => client.sessionId === sessionId);\n }\n\n public delete(client: Client<UserData, AuthData>): boolean {\n return spliceOne(this, this.indexOf(client));\n }\n}"],
|
|
5
|
-
"mappings": "AAOA,SAAS,iBAAiB;AAEnB,MAAe,UAAU;
|
|
5
|
+
"mappings": "AAOA,SAAS,iBAAiB;AAEnB,MAAe,UAAU;AAOhC;AAMO,IAAK,cAAL,kBAAKA,iBAAL;AAAmB,EAAAA,0BAAA;AAAS,EAAAA,0BAAA;AAAQ,EAAAA,0BAAA;AAAa,EAAAA,0BAAA;AAA5C,SAAAA;AAAA,GAAA;AAuFL,MAAM,oBAAoD,MAAkC;AAAA,EAC1F,QAAQ,WAA2D;AACxE,WAAO,KAAK,KAAK,CAAC,WAAW,OAAO,cAAc,SAAS;AAAA,EAC7D;AAAA,EAEO,OAAO,QAA6C;AACzD,WAAO,UAAU,MAAM,KAAK,QAAQ,MAAM,CAAC;AAAA,EAC7C;AACF;",
|
|
6
6
|
"names": ["ClientState"]
|
|
7
7
|
}
|
package/build/Utils.js
CHANGED
package/build/Utils.js.map
CHANGED
|
@@ -2,6 +2,6 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/Utils.ts"],
|
|
4
4
|
"sourcesContent": ["import nanoid from 'nanoid';\n\nimport { debugAndPrintError } from './Debug';\nimport { EventEmitter } from \"events\";\nimport { ServerOpts, Socket } from \"net\";\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 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 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\n for (let i = index; i < len; i++) {\n arr[i] = arr[i + 1];\n }\n\n arr.length = len;\n\n return true;\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 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"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAAmB;AAEnB,mBAAmC;AACnC,oBAA6B;AAItB,MAAM,4BAA4B,OAAO,QAAQ,IAAI,mCAAmC,GAAI;AAE5F,SAAS,WAAW,SAAiB,GAAG;AAC7C,aAAO,cAAAA,SAAO,MAAM;AACtB;AAMA,MAAM,UAA4B,CAAC,UAAU,WAAW,SAAS;AAE1D,SAAS,yBAAyB,UAAiC;AAIxE,UAAQ,GAAG,qBAAqB,CAAC,QAAQ;AACvC,yCAAmB,GAAG;AACtB,aAAS,GAAG;AAAA,EACd,CAAC;AAED,UAAQ,QAAQ,CAAC,WACf,QAAQ,KAAK,QAAQ,MAAM,SAAS,CAAC,CAAC;AAC1C;AAEO,SAAS,MACd,IACA,aAAqB,GACrB,iBAAwB,CAAC,GACzB,UAAkB,GAClB;AACA,SAAO,IAAI,QAAW,CAAC,SAAS,WAAW;AACzC,OAAG,EACA,KAAK,OAAO,EACZ,MAAM,CAAC,MAAM;AACZ,UACE,eAAe,QAAQ,EAAE,WAAW,MAAM,MAC1C,YAAY,YACZ;AACA,mBAAW,MAAM;AACf,gBAAS,IAAI,YAAY,gBAAgB,OAAO,EAC9C,KAAK,OAAO,EACZ,MAAM,CAAC,OAAO,OAAO,EAAE,CAAC;AAAA,QAC5B,GAAG,KAAK,MAAM,KAAK,OAAO,IAAI,KAAK,IAAI,GAAG,OAAO,IAAI,GAAG,CAAC;AAAA,MAE3D,OAAO;AACL,eAAO,CAAC;AAAA,MACV;AAAA,IACF,CAAC;AAAA,EACL,CAAC;AACH;AAEO,MAAM,SAAiB;AAAA,
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAAmB;AAEnB,mBAAmC;AACnC,oBAA6B;AAItB,MAAM,4BAA4B,OAAO,QAAQ,IAAI,mCAAmC,GAAI;AAE5F,SAAS,WAAW,SAAiB,GAAG;AAC7C,aAAO,cAAAA,SAAO,MAAM;AACtB;AAMA,MAAM,UAA4B,CAAC,UAAU,WAAW,SAAS;AAE1D,SAAS,yBAAyB,UAAiC;AAIxE,UAAQ,GAAG,qBAAqB,CAAC,QAAQ;AACvC,yCAAmB,GAAG;AACtB,aAAS,GAAG;AAAA,EACd,CAAC;AAED,UAAQ,QAAQ,CAAC,WACf,QAAQ,KAAK,QAAQ,MAAM,SAAS,CAAC,CAAC;AAC1C;AAEO,SAAS,MACd,IACA,aAAqB,GACrB,iBAAwB,CAAC,GACzB,UAAkB,GAClB;AACA,SAAO,IAAI,QAAW,CAAC,SAAS,WAAW;AACzC,OAAG,EACA,KAAK,OAAO,EACZ,MAAM,CAAC,MAAM;AACZ,UACE,eAAe,QAAQ,EAAE,WAAW,MAAM,MAC1C,YAAY,YACZ;AACA,mBAAW,MAAM;AACf,gBAAS,IAAI,YAAY,gBAAgB,OAAO,EAC9C,KAAK,OAAO,EACZ,MAAM,CAAC,OAAO,OAAO,EAAE,CAAC;AAAA,QAC5B,GAAG,KAAK,MAAM,KAAK,OAAO,IAAI,KAAK,IAAI,GAAG,OAAO,IAAI,GAAG,CAAC;AAAA,MAE3D,OAAO;AACL,eAAO,CAAC;AAAA,MACV;AAAA,IACF,CAAC;AAAA,EACL,CAAC;AACH;AAEO,MAAM,SAAiB;AAAA,EAM5B,cAAc;AACZ,SAAK,UAAU,IAAI,QAAW,CAAC,SAAS,WAAW;AACjD,WAAK,UAAU;AACf,WAAK,SAAS;AAAA,IAChB,CAAC;AAAA,EACH;AAAA,EAEO,KAAK,MAAyB;AACnC,WAAO,KAAK,QAAQ,KAAK,MAAM,KAAK,SAAS,SAAS;AAAA,EACxD;AAAA,EAEO,MAAM,MAA2B;AACtC,WAAO,KAAK,QAAQ,MAAM,IAAI;AAAA,EAChC;AAEF;AAEO,SAAS,UAAU,KAAY,OAAwB;AAG5D,MAAI,UAAU,MAAM,SAAS,IAAI,QAAQ;AACvC,WAAO;AAAA,EACT;AAEA,QAAM,MAAM,IAAI,SAAS;AAEzB,WAAS,IAAI,OAAO,IAAI,KAAK,KAAK;AAChC,QAAI,KAAK,IAAI,IAAI;AAAA,EACnB;AAEA,MAAI,SAAS;AAEb,SAAO;AACT;AAEO,SAAS,MAAM,MAAW,MAAkB;AACjD,WAAS,IAAI,GAAG,MAAM,KAAK,QAAQ,IAAI,KAAK,KAAK;AAC/C,UAAM,IAAI,KAAK;AACf,eAAW,OAAO,GAAG;AACnB,UAAI,EAAE,eAAe,GAAG,GAAG;AACzB,UAAE,OAAO,EAAE;AAAA,MACb;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AASO,MAAM,oBAAoB,2BAAa;AAAC;",
|
|
6
6
|
"names": ["nanoid"]
|
|
7
7
|
}
|
package/build/Utils.mjs
CHANGED
package/build/Utils.mjs.map
CHANGED
|
@@ -2,6 +2,6 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/Utils.ts"],
|
|
4
4
|
"sourcesContent": ["import nanoid from 'nanoid';\n\nimport { debugAndPrintError } from './Debug';\nimport { EventEmitter } from \"events\";\nimport { ServerOpts, Socket } from \"net\";\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 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 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\n for (let i = index; i < len; i++) {\n arr[i] = arr[i + 1];\n }\n\n arr.length = len;\n\n return true;\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 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"],
|
|
5
|
-
"mappings": "AAAA,OAAO,YAAY;AAEnB,SAAS,0BAA0B;AACnC,SAAS,oBAAoB;AAItB,MAAM,4BAA4B,OAAO,QAAQ,IAAI,mCAAmC,GAAI;AAE5F,SAAS,WAAW,SAAiB,GAAG;AAC7C,SAAO,OAAO,MAAM;AACtB;AAMA,MAAM,UAA4B,CAAC,UAAU,WAAW,SAAS;AAE1D,SAAS,yBAAyB,UAAiC;AAIxE,UAAQ,GAAG,qBAAqB,CAAC,QAAQ;AACvC,uBAAmB,GAAG;AACtB,aAAS,GAAG;AAAA,EACd,CAAC;AAED,UAAQ,QAAQ,CAAC,WACf,QAAQ,KAAK,QAAQ,MAAM,SAAS,CAAC,CAAC;AAC1C;AAEO,SAAS,MACd,IACA,aAAqB,GACrB,iBAAwB,CAAC,GACzB,UAAkB,GAClB;AACA,SAAO,IAAI,QAAW,CAAC,SAAS,WAAW;AACzC,OAAG,EACA,KAAK,OAAO,EACZ,MAAM,CAAC,MAAM;AACZ,UACE,eAAe,QAAQ,EAAE,WAAW,MAAM,MAC1C,YAAY,YACZ;AACA,mBAAW,MAAM;AACf,gBAAS,IAAI,YAAY,gBAAgB,OAAO,EAC9C,KAAK,OAAO,EACZ,MAAM,CAAC,OAAO,OAAO,EAAE,CAAC;AAAA,QAC5B,GAAG,KAAK,MAAM,KAAK,OAAO,IAAI,KAAK,IAAI,GAAG,OAAO,IAAI,GAAG,CAAC;AAAA,MAE3D,OAAO;AACL,eAAO,CAAC;AAAA,MACV;AAAA,IACF,CAAC;AAAA,EACL,CAAC;AACH;AAEO,MAAM,SAAiB;AAAA,
|
|
5
|
+
"mappings": "AAAA,OAAO,YAAY;AAEnB,SAAS,0BAA0B;AACnC,SAAS,oBAAoB;AAItB,MAAM,4BAA4B,OAAO,QAAQ,IAAI,mCAAmC,GAAI;AAE5F,SAAS,WAAW,SAAiB,GAAG;AAC7C,SAAO,OAAO,MAAM;AACtB;AAMA,MAAM,UAA4B,CAAC,UAAU,WAAW,SAAS;AAE1D,SAAS,yBAAyB,UAAiC;AAIxE,UAAQ,GAAG,qBAAqB,CAAC,QAAQ;AACvC,uBAAmB,GAAG;AACtB,aAAS,GAAG;AAAA,EACd,CAAC;AAED,UAAQ,QAAQ,CAAC,WACf,QAAQ,KAAK,QAAQ,MAAM,SAAS,CAAC,CAAC;AAC1C;AAEO,SAAS,MACd,IACA,aAAqB,GACrB,iBAAwB,CAAC,GACzB,UAAkB,GAClB;AACA,SAAO,IAAI,QAAW,CAAC,SAAS,WAAW;AACzC,OAAG,EACA,KAAK,OAAO,EACZ,MAAM,CAAC,MAAM;AACZ,UACE,eAAe,QAAQ,EAAE,WAAW,MAAM,MAC1C,YAAY,YACZ;AACA,mBAAW,MAAM;AACf,gBAAS,IAAI,YAAY,gBAAgB,OAAO,EAC9C,KAAK,OAAO,EACZ,MAAM,CAAC,OAAO,OAAO,EAAE,CAAC;AAAA,QAC5B,GAAG,KAAK,MAAM,KAAK,OAAO,IAAI,KAAK,IAAI,GAAG,OAAO,IAAI,GAAG,CAAC;AAAA,MAE3D,OAAO;AACL,eAAO,CAAC;AAAA,MACV;AAAA,IACF,CAAC;AAAA,EACL,CAAC;AACH;AAEO,MAAM,SAAiB;AAAA,EAM5B,cAAc;AACZ,SAAK,UAAU,IAAI,QAAW,CAAC,SAAS,WAAW;AACjD,WAAK,UAAU;AACf,WAAK,SAAS;AAAA,IAChB,CAAC;AAAA,EACH;AAAA,EAEO,KAAK,MAAyB;AACnC,WAAO,KAAK,QAAQ,KAAK,MAAM,KAAK,SAAS,SAAS;AAAA,EACxD;AAAA,EAEO,MAAM,MAA2B;AACtC,WAAO,KAAK,QAAQ,MAAM,IAAI;AAAA,EAChC;AAEF;AAEO,SAAS,UAAU,KAAY,OAAwB;AAG5D,MAAI,UAAU,MAAM,SAAS,IAAI,QAAQ;AACvC,WAAO;AAAA,EACT;AAEA,QAAM,MAAM,IAAI,SAAS;AAEzB,WAAS,IAAI,OAAO,IAAI,KAAK,KAAK;AAChC,QAAI,KAAK,IAAI,IAAI;AAAA,EACnB;AAEA,MAAI,SAAS;AAEb,SAAO;AACT;AAEO,SAAS,MAAM,MAAW,MAAkB;AACjD,WAAS,IAAI,GAAG,MAAM,KAAK,QAAQ,IAAI,KAAK,KAAK;AAC/C,UAAM,IAAI,KAAK;AACf,eAAW,OAAO,GAAG;AACnB,UAAI,EAAE,eAAe,GAAG,GAAG;AACzB,UAAE,OAAO,EAAE;AAAA,MACb;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AASO,MAAM,oBAAoB,aAAa;AAAC;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -22,7 +22,6 @@ __export(ServerError_exports, {
|
|
|
22
22
|
module.exports = __toCommonJS(ServerError_exports);
|
|
23
23
|
var import_Protocol = require("../Protocol");
|
|
24
24
|
class ServerError extends Error {
|
|
25
|
-
code;
|
|
26
25
|
constructor(code = import_Protocol.ErrorCode.MATCHMAKE_UNHANDLED, message) {
|
|
27
26
|
super(message);
|
|
28
27
|
if (Error.captureStackTrace) {
|