{
  "version": 3,
  "sources": ["../src/Room.ts"],
  "sourcesContent": ["import { unpack } from '@colyseus/msgpackr';\nimport { decode, type Iterator, $changes } from '@colyseus/schema';\n\nimport Clock from '@colyseus/timer';\nimport { EventEmitter } from 'events';\nimport { logger } from './Logger.js';\n\nimport { Presence } from './presence/Presence.js';\n\nimport { NoneSerializer } from './serializer/NoneSerializer.js';\nimport { SchemaSerializer } from './serializer/SchemaSerializer.js';\nimport { Serializer } from './serializer/Serializer.js';\n\nimport { ErrorCode, getMessageBytes, Protocol } from './Protocol.js';\nimport { Deferred, generateId, wrapTryCatch } from './utils/Utils.js';\nimport { isDevMode } from './utils/DevMode.js';\n\nimport { debugAndPrintError, debugMatchMaking, debugMessage } from './Debug.js';\nimport { RoomCache } from './matchmaker/driver/api.js';\nimport { ServerError } from './errors/ServerError.js';\nimport { AuthContext, Client, ClientPrivate, ClientArray, ClientState, ISendOptions } from './Transport.js';\nimport { OnAuthException, OnCreateException, OnDisposeException, OnJoinException, OnLeaveException, OnMessageException, RoomException, SimulationIntervalException, TimedEventException } from './errors/RoomExceptions.js';\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 interface IBroadcastOptions extends ISendOptions {\n  except?: Client | Client[];\n}\n\nexport enum RoomInternalState {\n  CREATING = 0,\n  CREATED = 1,\n  DISPOSING = 2,\n}\n\nexport type ExtractUserData<T> = T extends ClientArray<infer U> ? U : never;\nexport type 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, UserData = any, AuthData = 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: RoomCache<Metadata>;\n\n  /**\n   * Timing events tied to the room instance.\n   * Intervals and timeouts are cleared when the room is disposed.\n   */\n  public clock: Clock = new Clock();\n\n  #_roomId: string;\n  #_roomName: string;\n  #_onLeaveConcurrent: number = 0; // number of onLeave calls in progress\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  #_maxClientsReached: boolean = false;\n  #_maxClients: number;\n\n  /**\n   * Automatically dispose the room when last client disconnects.\n   *\n   * @default true\n   */\n  public autoDispose: boolean = true;\n  #_autoDispose: boolean;\n\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  #_patchRate: number;\n  #_patchInterval: NodeJS.Timeout;\n\n  /**\n   * The state instance you provided to `setState()`.\n   */\n  public state: State;\n  #_state: State;\n\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<UserData, AuthData> = 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, any, boolean?, boolean?] } = {};\n  protected reservedSeatTimeouts: { [sessionId: string]: NodeJS.Timeout } = {};\n\n  protected _reconnections: { [reconnectionToken: string]: [string, Deferred] } = {};\n  private _reconnectingSessionId = new Map<string, string>();\n\n  private onMessageHandlers: {\n    [id: string]: {\n      callback: (...args: any[]) => void,\n      validate?: (data: unknown) => any,\n    }\n  } = {\n      '__no_message_handler': {\n        callback: (client: Client, messageType: string, _: unknown) => {\n          const errorMessage = `room onMessage for \"${messageType}\" not registered.`;\n          debugAndPrintError(`${errorMessage} (roomId: ${this.roomId})`);\n\n          if (isDevMode) {\n            // send error code to client in development mode\n            client.error(ErrorCode.INVALID_PAYLOAD, errorMessage);\n\n          } else {\n            // immediately close the connection in production\n            client.leave(Protocol.WS_CLOSE_WITH_ERROR, errorMessage);\n          }\n        }\n      }\n    };\n\n  private _serializer: Serializer<State> = noneSerializer;\n  private _afterNextPatchQueue: Array<[string | Client, IArguments]> = [];\n\n  private _simulationInterval: NodeJS.Timeout;\n\n  private _internalState: RoomInternalState = RoomInternalState.CREATING;\n\n  private _lockedExplicitly: boolean = false;\n  #_locked: 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.Timeout;\n\n  constructor() {\n    this._events.once('dispose', () => {\n      this._dispose()\n        .catch((e) => debugAndPrintError(`onDispose error: ${(e && e.stack || e.message || e || 'promise rejected')} (roomId: ${this.roomId})`))\n        .finally(() => this._events.emit('disconnect'));\n    });\n\n    /**\n     * If `onUncaughtException` is defined, it will automatically catch exceptions\n     */\n    if (this.onUncaughtException !== undefined) {\n      this.#registerUncaughtExceptionHandlers();\n    }\n  }\n\n  /**\n   * This method is called by the MatchMaker before onCreate()\n   * @internal\n   */\n  protected __init() {\n    this.#_state = this.state;\n    this.#_autoDispose = this.autoDispose;\n    this.#_patchRate = this.patchRate;\n    this.#_maxClients = this.maxClients;\n\n    Object.defineProperties(this, {\n      state: {\n        enumerable: true,\n        get: () => this.#_state,\n        set: (newState: State) => {\n          if (newState?.constructor[Symbol.metadata] !== undefined || newState[$changes] !== undefined) {\n            this.setSerializer(new SchemaSerializer());\n          } else if ('_definition' in newState) {\n            throw new Error(\"@colyseus/schema v2 compatibility currently missing (reach out if you need it)\");\n          } else if ($changes === undefined) {\n            throw new Error(\"Multiple @colyseus/schema versions detected. Please make sure you don't have multiple versions of @colyseus/schema installed.\");\n          }\n          this._serializer.reset(newState);\n          this.#_state = newState;\n        },\n      },\n\n      maxClients: {\n        enumerable: true,\n        get: () => this.#_maxClients,\n        set: (value: number) => {\n          this.#_maxClients = value;\n\n          if (this._internalState === RoomInternalState.CREATED) {\n            const hasReachedMaxClients = this.hasReachedMaxClients();\n\n            // unlock room if maxClients has been increased\n            if (!this._lockedExplicitly && this.#_maxClientsReached && !hasReachedMaxClients) {\n              this.#_maxClientsReached = false;\n              this.#_locked = false;\n              this.listing.locked = false;\n            }\n\n            // lock room if maxClients has been decreased\n            if (hasReachedMaxClients) {\n              this.#_maxClientsReached = true;\n              this.#_locked = true;\n              this.listing.locked = true;\n            }\n\n            this.listing.maxClients = value;\n            this.listing.save();\n          }\n        },\n      },\n\n      autoDispose: {\n        enumerable: true,\n        get: () => this.#_autoDispose,\n        set: (value: boolean) => {\n          if (\n            value !== this.#_autoDispose &&\n            this._internalState !== RoomInternalState.DISPOSING\n          ) {\n            this.#_autoDispose = value;\n            this.resetAutoDisposeTimeout();\n          }\n        },\n      },\n\n      patchRate: {\n        enumerable: true,\n        get: () => this.#_patchRate,\n        set: (milliseconds: number) => {\n          this.#_patchRate = milliseconds;\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          if (milliseconds !== null && milliseconds !== 0) {\n            this.#_patchInterval = setInterval(() => this.broadcastPatch(), milliseconds);\n          }\n        },\n      },\n    });\n\n    // set patch interval, now with the setter\n    this.patchRate = this.#_patchRate;\n\n    // set state, now with the setter\n    if (this.#_state) {\n      this.state = this.#_state;\n    }\n\n    // set default _autoDisposeTimeout\n    this.resetAutoDisposeTimeout(this.seatReservationTime);\n\n    this.clock.start();\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  /**\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?(client: Client<UserData, AuthData>, options?: any, auth?: AuthData): void | Promise<any>;\n  public onLeave?(client: Client<UserData, AuthData>, consented?: boolean): void | Promise<any>;\n  public onDispose?(): void | Promise<any>;\n\n  /**\n   * Define a custom exception handler.\n   * If defined, all lifecycle hooks will be wrapped by try/catch, and the exception will be forwarded to this method.\n   *\n   * These methods will be wrapped by try/catch:\n   * - `onMessage`\n   * - `onAuth` / `onJoin` / `onLeave` / `onCreate` / `onDispose`\n   * - `clock.setTimeout` / `clock.setInterval`\n   * - `setSimulationInterval`\n   *\n   * (Experimental: this feature is subject to change in the future - we're currently getting feedback to improve it)\n   */\n  public onUncaughtException?(error: RoomException<this>, methodName: 'onCreate' | 'onAuth' | 'onJoin' | 'onLeave' | 'onDispose' | 'onMessage' | 'setSimulationInterval' | 'setInterval' | 'setTimeout'): void;\n\n  public onAuth(\n    client: Client<UserData, AuthData>,\n    options: any,\n    context: AuthContext\n  ): any | Promise<any> {\n    return true;\n  }\n\n  static async onAuth(\n    token: string,\n    options: any,\n    context: AuthContext\n  ): Promise<unknown> {\n    return true;\n  }\n\n  /**\n   * This method is called during graceful shutdown of the server process\n   * You may override this method to dispose the room in your own way.\n   *\n   * Once process reaches room count of 0, the room process will be terminated.\n   */\n  public onBeforeShutdown() {\n    this.disconnect(\n      (isDevMode)\n        ? Protocol.WS_CLOSE_DEVMODE_RESTART\n        : Protocol.WS_CLOSE_CONSENTED\n    );\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    const reservedSeat = this.reservedSeats[sessionId];\n\n    // seat reservation not found / expired\n    if (reservedSeat === undefined) {\n      return false;\n    }\n\n    if (reservedSeat[3]) {\n      // reconnection\n      return (\n        reconnectionToken &&\n        this._reconnections[reconnectionToken]?.[0] === sessionId &&\n        this._reconnectingSessionId.has(sessionId)\n      );\n\n    } else {\n      // seat reservation not consumed\n      return reservedSeat[2] === false;\n    }\n  }\n\n  public checkReconnectionToken(reconnectionToken: string) {\n    const sessionId = this._reconnections[reconnectionToken]?.[0];\n    const reservedSeat = this.reservedSeats[sessionId];\n\n    if (reservedSeat && reservedSeat[3]) {\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      if (this.onUncaughtException !== undefined) {\n        onTickCallback = wrapTryCatch(onTickCallback, this.onUncaughtException.bind(this), SimulationIntervalException, 'setSimulationInterval');\n      }\n\n      this._simulationInterval = setInterval(() => {\n        this.clock.tick();\n        onTickCallback(this.clock.deltaTime);\n      }, delay);\n    }\n  }\n\n  /**\n   * @deprecated Use `.patchRate=` instead.\n   */\n  public setPatchRate(milliseconds: number | null): void {\n    this.patchRate = milliseconds;\n  }\n\n  /**\n   * @deprecated Use `.state =` instead.\n   */\n  public setState(newState: State) {\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    if (this.listing.private === bool) return;\n\n    this.listing.private = bool;\n\n    if (this._internalState === RoomInternalState.CREATED) {\n      await this.listing.save();\n    }\n\n    this._events.emit('visibility-change', bool);\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, 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    if (options && options.afterNextPatch) {\n      delete options.afterNextPatch;\n      this._afterNextPatchQueue.push(['broadcast', arguments]);\n      return;\n    }\n\n    this.broadcastMessageType(type, message, options);\n  }\n\n  /**\n   * Broadcast bytes (UInt8Arrays) to a particular room\n   */\n  public broadcastBytes(type: string | number, message: Uint8Array, options: IBroadcastOptions) {\n    if (options && options.afterNextPatch) {\n      delete options.afterNextPatch;\n      this._afterNextPatchQueue.push(['broadcastBytes', arguments]);\n      return;\n    }\n\n    this.broadcastMessageType(type as string, message, options);\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<UserData, AuthData>, type: string | number, message: T) => void\n  );\n  public onMessage<T = any>(\n    messageType: string | number,\n    callback: (client: Client<UserData, AuthData>, message: T) => void,\n    validate?: (message: unknown) => T,\n  );\n  public onMessage<T = any>(\n    messageType: '*' | string | number,\n    callback: (...args: any[]) => void,\n    validate?: (message: unknown) => T,\n  ) {\n    this.onMessageHandlers[messageType] = (this.onUncaughtException !== undefined)\n      ? { validate, callback: wrapTryCatch(callback, this.onUncaughtException.bind(this), OnMessageException, 'onMessage', false, messageType) }\n      : { validate, callback };\n\n\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 disconnect(closeCode: number = Protocol.WS_CLOSE_CONSENTED): Promise<any> {\n    // skip if already disposing\n    if (this._internalState === RoomInternalState.DISPOSING) {\n      return Promise.resolve(`disconnect() ignored: room (${this.roomId}) is already disposing.`);\n\n    } else if (this._internalState === RoomInternalState.CREATING) {\n      throw new Error(\"cannot disconnect during onCreate()\");\n    }\n\n    this._internalState = RoomInternalState.DISPOSING;\n    this.listing.remove();\n\n    this.#_autoDispose = true;\n\n    const delayedDisconnection = new Promise<void>((resolve) =>\n      this._events.once('disconnect', () => resolve()));\n\n    // reject pending reconnections\n    for (const [_, reconnection] of Object.values(this._reconnections)) {\n      reconnection.reject(new Error(\"disconnecting\"));\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] as Client & ClientPrivate, closeCode);\n      }\n\n    } else {\n      // no clients connected, dispose immediately.\n      this._events.emit('dispose');\n    }\n\n    return delayedDisconnection;\n  }\n\n  public async ['_onJoin'](client: Client & ClientPrivate, authContext: AuthContext) {\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 [joinOptions, authData, isConsumed, isWaitingReconnection] = this.reservedSeats[sessionId];\n\n    //\n    // TODO: remove this check on 1.0.0\n    // - the seat reservation is used to keep track of number of clients and their pending seats (see `hasReachedMaxClients`)\n    // - when we fully migrate to static onAuth(), the seat reservation can be removed immediately here\n    // - if async onAuth() is in use, the seat reservation is removed after onAuth() is fulfilled.\n    // - mark reservation as \"consumed\"\n    //\n    if (isConsumed) {\n      throw new ServerError(ErrorCode.MATCHMAKE_EXPIRED, \"already consumed\");\n    }\n    this.reservedSeats[sessionId][2] = true; // flag seat reservation as \"consumed\"\n    debugMatchMaking('consuming seat reservation, sessionId: \\'%s\\' (roomId: %s)', client.sessionId, this.roomId);\n\n    // share \"after next patch queue\" reference with every client.\n    client._afterNextPatchQueue = this._afterNextPatchQueue;\n\n    // add temporary callback to keep track of disconnections during `onJoin`.\n    client.ref['onleave'] = (_) => client.state = ClientState.LEAVING;\n    client.ref.once('close', client.ref['onleave']);\n\n    if (isWaitingReconnection) {\n      const previousReconnectionToken = this._reconnectingSessionId.get(sessionId);\n      if (previousReconnectionToken) {\n        this.clients.push(client);\n        //\n        // await for reconnection:\n        // (end user may customize the reconnection token at this step)\n        //\n        await this._reconnections[previousReconnectionToken]?.[1].resolve(client);\n\n      } else {\n        const errorMessage = (process.env.NODE_ENV === 'production')\n          ? \"already consumed\" // trick possible fraudsters...\n          : \"bad reconnection token\" // ...or developers\n        throw new ServerError(ErrorCode.MATCHMAKE_EXPIRED, errorMessage);\n      }\n\n    } else {\n      try {\n        if (authData) {\n          client.auth = authData;\n\n        } else if (this.onAuth !== Room.prototype.onAuth) {\n          try {\n            client.auth = await this.onAuth(client, joinOptions, authContext);\n\n            if (!client.auth) {\n              throw new ServerError(ErrorCode.AUTH_FAILED, 'onAuth failed');\n            }\n\n          } catch (e) {\n            // remove seat reservation\n            delete this.reservedSeats[sessionId];\n            await this._decrementClientCount();\n            throw e;\n          }\n        }\n\n        //\n        // On async onAuth, client may have been disconnected.\n        //\n        if (client.state === ClientState.LEAVING) {\n          throw new ServerError(Protocol.WS_CLOSE_GOING_AWAY, 'already disconnected');\n        }\n\n        this.clients.push(client);\n\n        //\n        // Flag sessionId as non-enumarable so hasReachedMaxClients() doesn't count it\n        // (https://github.com/colyseus/colyseus/issues/726)\n        //\n        Object.defineProperty(this.reservedSeats, sessionId, {\n          value: this.reservedSeats[sessionId],\n          enumerable: false,\n        });\n\n        if (this.onJoin) {\n          await this.onJoin(client, joinOptions, client.auth);\n        }\n\n        // @ts-ignore: client left during `onJoin`, call _onLeave immediately.\n        if (client.state === ClientState.LEAVING) {\n          throw new Error(\"early_leave\");\n\n        } else {\n          // remove seat reservation\n          delete this.reservedSeats[sessionId];\n\n          // emit 'join' to room handler\n          this._events.emit('join', client);\n        }\n\n      } catch (e) {\n        await this._onLeave(client, Protocol.WS_CLOSE_GOING_AWAY);\n\n        // remove seat reservation\n        delete this.reservedSeats[sessionId];\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    }\n\n    // state might already be ClientState.LEAVING here\n    if (client.state === ClientState.JOINING) {\n      client.ref.removeListener('close', client.ref['onleave']);\n\n      // only bind _onLeave after onJoin has been successful\n      client.ref['onleave'] = this._onLeave.bind(this, client);\n      client.ref.once('close', client.ref['onleave']);\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  /**\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    //\n    // Return rejected promise if client has never fully JOINED.\n    //\n    // (having `_enqueuedMessages !== undefined` means that the client has never been at \"ClientState.JOINED\" state)\n    //\n    if ((previousClient as unknown as ClientPrivate)._enqueuedMessages !== undefined) {\n      // @ts-ignore\n      return Promise.reject(new Error(\"not joined\"));\n    }\n\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      // @ts-ignore\n      return Promise.reject(new Error(\"disposing\"));\n    }\n\n    const sessionId = previousClient.sessionId;\n    const reconnectionToken = previousClient.reconnectionToken;\n\n    this._reserveSeat(sessionId, true, previousClient.auth, seconds, true);\n\n    // keep reconnection reference in case the user reconnects into this room.\n    const reconnection = new Deferred<Client & ClientPrivate>();\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        newClient.view = previousClient.view;\n\n        // for convenience: populate previous client reference with new client\n        previousClient.state = ClientState.RECONNECTED;\n        previousClient.ref = newClient.ref;\n        previousClient.reconnectionToken = newClient.reconnectionToken;\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 broadcastMessageType(type: number | string, message?: any | Uint8Array, options: IBroadcastOptions = {}) {\n    debugMessage(\"broadcast: %O (roomId: %s)\", message, this.roomId);\n\n    const encodedMessage = (message instanceof Uint8Array)\n      ? getMessageBytes.raw(Protocol.ROOM_DATA_BYTES, type, undefined, message)\n      : getMessageBytes.raw(Protocol.ROOM_DATA, type, message)\n\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  protected sendFullState(client: Client): void {\n    client.raw(this._serializer.getFullState(client));\n  }\n\n  protected _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  protected async _reserveSeat(\n    sessionId: string,\n    joinOptions: any = true,\n    authData: any = undefined,\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, authData, false, allowReconnection];\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  protected _disposeIfEmpty() {\n    const willDispose = (\n      this.#_onLeaveConcurrent === 0 && // no \"onLeave\" calls in progress\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  protected async _dispose(): Promise<any> {\n    this._internalState = RoomInternalState.DISPOSING;\n\n    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  protected _onMessage(client: Client & ClientPrivate, buffer: Buffer) {\n    // skip if client is on LEAVING state.\n    if (client.state === ClientState.LEAVING) { return; }\n\n    const it: Iterator = { offset: 1 };\n    const code = buffer[0];\n\n    if (!buffer) {\n      debugAndPrintError(`${this.roomName} (roomId: ${this.roomId}), couldn't decode message: ${buffer}`);\n      return;\n    }\n\n    if (code === Protocol.ROOM_DATA) {\n      const messageType = (decode.stringCheck(buffer, it))\n        ? decode.string(buffer, it)\n        : decode.number(buffer, it);\n      const messageTypeHandler = this.onMessageHandlers[messageType];\n\n      let message;\n      try {\n        message = (buffer.byteLength > it.offset)\n          ? unpack(buffer.subarray(it.offset, buffer.byteLength))\n          : undefined;\n        debugMessage(\"received: '%s' -> %j (roomId: %s)\", messageType, message, this.roomId);\n\n        // custom message validation\n        if (messageTypeHandler?.validate !== undefined) {\n          message = messageTypeHandler.validate(message);\n        }\n\n      } catch (e) {\n        debugAndPrintError(e);\n        client.leave(Protocol.WS_CLOSE_WITH_ERROR);\n        return;\n      }\n\n      if (messageTypeHandler) {\n        messageTypeHandler.callback(client, message);\n\n      } else {\n        (this.onMessageHandlers['*'] || this.onMessageHandlers['__no_message_handler']).callback(client, messageType, message);\n      }\n\n    } else if (code === Protocol.ROOM_DATA_BYTES) {\n      const messageType = (decode.stringCheck(buffer, it))\n        ? decode.string(buffer, it)\n        : decode.number(buffer, it);\n      const messageTypeHandler = this.onMessageHandlers[messageType];\n\n      let message = buffer.subarray(it.offset, buffer.byteLength);\n      debugMessage(\"received: '%s' -> %j (roomId: %s)\", messageType, message, this.roomId);\n\n      // custom message validation\n      if (messageTypeHandler?.validate !== undefined) {\n        message = messageTypeHandler.validate(message);\n      }\n\n      if (messageTypeHandler) {\n        messageTypeHandler.callback(client, message);\n\n      } else {\n        (this.onMessageHandlers['*'] || this.onMessageHandlers['__no_message_handler']).callback(client, messageType, message);\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      client._joinedAt = this.clock.elapsedTime;\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  protected _forciblyCloseClient(client: Client & ClientPrivate, 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  protected async _onLeave(client: Client, code?: number): Promise<any> {\n    debugMatchMaking('onLeave, sessionId: \\'%s\\' (close code: %d, roomId: %s)', client.sessionId, code, this.roomId);\n\n    // call 'onLeave' method only if the client has been successfully accepted.\n    client.state = ClientState.LEAVING;\n\n    if (!this.clients.delete(client)) {\n      // skip if client already left the room\n      return;\n    }\n\n    if (this.onLeave) {\n      try {\n        this.#_onLeaveConcurrent++;\n        await this.onLeave(client, (code === Protocol.WS_CLOSE_CONSENTED));\n\n      } catch (e) {\n        debugAndPrintError(`onLeave error: ${(e && e.message || e || 'promise rejected')} (roomId: ${this.roomId})`);\n\n      } finally {\n        this.#_onLeaveConcurrent--;\n      }\n    }\n\n    // check for manual \"reconnection\" flow\n    if (this._reconnections[client.reconnectionToken]) {\n      this._reconnections[client.reconnectionToken][1].catch(async () => {\n        await this._onAfterLeave(client);\n      });\n\n      // @ts-ignore (client.state may be modified at onLeave())\n    } else if (client.state !== ClientState.RECONNECTED) {\n      await this._onAfterLeave(client);\n    }\n  }\n\n  protected async _onAfterLeave(client: Client) {\n    // try to dispose immediately if client reconnection isn't set up.\n    const willDispose = await this._decrementClientCount();\n\n    // trigger 'leave' only if seat reservation has been fully consumed\n    if (this.reservedSeats[client.sessionId] === undefined) {\n      this._events.emit('leave', client, willDispose);\n    }\n\n  }\n\n  protected 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  protected 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  #registerUncaughtExceptionHandlers() {\n    const onUncaughtException = this.onUncaughtException.bind(this);\n    const originalSetTimeout = this.clock.setTimeout;\n    this.clock.setTimeout = (cb, timeout, ...args) => {\n      return originalSetTimeout.call(this.clock, wrapTryCatch(cb, onUncaughtException, TimedEventException, 'setTimeout'), timeout, ...args);\n    };\n\n    const originalSetInterval = this.clock.setInterval;\n    this.clock.setInterval = (cb, timeout, ...args) => {\n      return originalSetInterval.call(this.clock, wrapTryCatch(cb, onUncaughtException, TimedEventException, 'setInterval'), timeout, ...args);\n    };\n\n    if (this.onCreate !== undefined) {\n      this.onCreate = wrapTryCatch(this.onCreate.bind(this), onUncaughtException, OnCreateException, 'onCreate', true);\n    }\n\n    if (this.onAuth !== undefined) {\n      this.onAuth = wrapTryCatch(this.onAuth.bind(this), onUncaughtException, OnAuthException, 'onAuth', true);\n    }\n\n    if (this.onJoin !== undefined) {\n      this.onJoin = wrapTryCatch(this.onJoin.bind(this), onUncaughtException, OnJoinException, 'onJoin', true);\n    }\n\n    if (this.onLeave !== undefined) {\n      this.onLeave = wrapTryCatch(this.onLeave.bind(this), onUncaughtException, OnLeaveException, 'onLeave', true);\n    }\n\n    if (this.onDispose !== undefined) {\n      this.onDispose = wrapTryCatch(this.onDispose.bind(this), onUncaughtException, OnDisposeException, 'onDispose');\n    }\n  }\n\n}\n"],
  "mappings": "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",
  "names": ["RoomInternalState"]
}
