tiaoom 0.0.34 → 0.0.35

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tiaoom",
3
- "version": "0.0.34",
3
+ "version": "0.0.35",
4
4
  "description": "",
5
5
  "main": "./src/index.cjs",
6
6
  "module": "./src/index.mjs",
package/src/index.cjs CHANGED
@@ -699,26 +699,26 @@ var Tiaoom = class extends events.EventEmitter {
699
699
  }
700
700
  run() {
701
701
  var _this$messageInstance;
702
- (_this$messageInstance = this.messageInstance) === null || _this$messageInstance === void 0 || _this$messageInstance.on("message", (message, cb) => {
702
+ (_this$messageInstance = this.messageInstance) === null || _this$messageInstance === void 0 || _this$messageInstance.on("message", async (message, cb) => {
703
703
  message.sender = message.sender ? this.searchPlayer(message.sender) || message.sender : null;
704
704
  try {
705
705
  switch (message.type) {
706
706
  case RecvMessageTypes.RoomList: return cb === null || cb === void 0 ? void 0 : cb(null, this.rooms);
707
707
  case RecvMessageTypes.PlayerList: return cb === null || cb === void 0 ? void 0 : cb(null, this.players);
708
- case RecvMessageTypes.RoomCreate: return this.createRoom(message.sender, message.data);
709
- case RecvMessageTypes.PlayerJoin: return this.joinPlayer(message.sender, message.data);
710
- case RecvMessageTypes.PlayerLeave: return this.leavePlayer(message.sender, message.data);
711
- case RecvMessageTypes.PlayerStandUp: return this.leaveSeat(message.sender, message.data);
708
+ case RecvMessageTypes.RoomCreate: return await this.createRoom(message.sender, message.data);
709
+ case RecvMessageTypes.PlayerJoin: return await this.joinPlayer(message.sender, message.data);
710
+ case RecvMessageTypes.PlayerLeave: return await this.leavePlayer(message.sender, message.data);
711
+ case RecvMessageTypes.PlayerStandUp: return await this.leaveSeat(message.sender, message.data);
712
712
  case RecvMessageTypes.RoomGet: return cb === null || cb === void 0 ? void 0 : cb(null, this.searchRoom(message.data));
713
- case RecvMessageTypes.RoomStart: return this.startRoom(message.sender, message.data);
714
- case RecvMessageTypes.RoomKick: return this.kickPlayer(message.sender, message.data);
715
- case RecvMessageTypes.RoomTransfer: return this.transferOwner(message.sender, message.data);
716
- case RecvMessageTypes.RoomClose: return this.closeRoom(message.sender, message.data);
717
- case RecvMessageTypes.PlayerLogin: return this.loginPlayer(message.data);
718
- case RecvMessageTypes.PlayerLogout: return this.removePlayer(message.data);
719
- case MessageTypes.PlayerOffline: return this.offlinePlayer(message.data);
720
- case RecvMessageTypes.PlayerReady: return this.readyPlayer(message.sender, message.data);
721
- case RecvMessageTypes.PlayerUnready: return this.unReadyPlayer(message.sender, message.data);
713
+ case RecvMessageTypes.RoomStart: return await this.startRoom(message.sender, message.data);
714
+ case RecvMessageTypes.RoomKick: return await this.kickPlayer(message.sender, message.data);
715
+ case RecvMessageTypes.RoomTransfer: return await this.transferOwner(message.sender, message.data);
716
+ case RecvMessageTypes.RoomClose: return await this.closeRoom(message.sender, message.data);
717
+ case RecvMessageTypes.PlayerLogin: return await this.loginPlayer(message.data);
718
+ case RecvMessageTypes.PlayerLogout: return await this.removePlayer(message.data);
719
+ case MessageTypes.PlayerOffline: return await this.offlinePlayer(message.data);
720
+ case RecvMessageTypes.PlayerReady: return await this.readyPlayer(message.sender, message.data);
721
+ case RecvMessageTypes.PlayerUnready: return await this.unReadyPlayer(message.sender, message.data);
722
722
  case RecvMessageTypes.RoomPlayerCommand:
723
723
  var _this$searchRoom;
724
724
  return (_this$searchRoom = this.searchRoom(message.data)) === null || _this$searchRoom === void 0 ? void 0 : _this$searchRoom.emit("player-command", {
@@ -791,7 +791,7 @@ var Tiaoom = class extends events.EventEmitter {
791
791
  const roomId = typeof room === "string" ? room : room === null || room === void 0 ? void 0 : room.id;
792
792
  return this.rooms.find((target) => target.id === roomId);
793
793
  }
794
- createRoom(sender, options) {
794
+ async createRoom(sender, options) {
795
795
  if (!sender) throw new Error("missing player information.");
796
796
  if (!options.name) throw new Error("missing room id or name.");
797
797
  if (this.searchRoom(options)) throw new Error("room already exists.");
@@ -812,13 +812,13 @@ var Tiaoom = class extends events.EventEmitter {
812
812
  }, true);
813
813
  return room;
814
814
  }
815
- startRoom(sender, room) {
815
+ async startRoom(sender, room) {
816
816
  const roomInstance = this.searchRoom(room);
817
817
  if (!roomInstance) throw new Error("room not found.");
818
818
  roomInstance.start(sender);
819
819
  return this.emit("room-player", roomInstance);
820
820
  }
821
- closeRoom(sender, room) {
821
+ async closeRoom(sender, room) {
822
822
  const roomIndex = this.rooms.findIndex((r) => r.id === room.id);
823
823
  const roomInstance = this.rooms[roomIndex];
824
824
  if (!roomInstance) throw new Error("room not found.");
@@ -831,7 +831,7 @@ var Tiaoom = class extends events.EventEmitter {
831
831
  roomInstance.emit("close");
832
832
  return room;
833
833
  }
834
- kickPlayer(sender, data) {
834
+ async kickPlayer(sender, data) {
835
835
  const room = this.searchRoom(data.roomId);
836
836
  if (!room) throw new Error("room not found.");
837
837
  if (!sender.isAdmin) {
@@ -844,7 +844,7 @@ var Tiaoom = class extends events.EventEmitter {
844
844
  if (roomPlayer) this.emit("room-player", room);
845
845
  return roomPlayer;
846
846
  }
847
- transferOwner(sender, data) {
847
+ async transferOwner(sender, data) {
848
848
  const room = this.searchRoom(data.roomId);
849
849
  if (!room) throw new Error("room not found.");
850
850
  const creator = room.players.find((p) => p.isCreator);
@@ -902,7 +902,7 @@ var Tiaoom = class extends events.EventEmitter {
902
902
  if (roomPlayer) this.emit("room-player", room);
903
903
  return roomPlayer;
904
904
  }
905
- leavePlayer(sender, player) {
905
+ async leavePlayer(sender, player) {
906
906
  if (!player.roomId) throw new Error("missing room id.");
907
907
  const room = this.rooms.find((room$1) => room$1.id === player.roomId);
908
908
  if (!room) throw new Error("room not found.");
@@ -912,7 +912,7 @@ var Tiaoom = class extends events.EventEmitter {
912
912
  if (roomPlayer) this.emit("room-player", room);
913
913
  return roomPlayer;
914
914
  }
915
- leaveSeat(sender, player) {
915
+ async leaveSeat(sender, player) {
916
916
  if (!player.roomId) throw new Error("missing room id.");
917
917
  const room = this.rooms.find((room$1) => room$1.id === player.roomId);
918
918
  if (!room) throw new Error("room not found.");
@@ -922,7 +922,7 @@ var Tiaoom = class extends events.EventEmitter {
922
922
  if (roomPlayer) this.emit("room-player", room);
923
923
  return roomPlayer;
924
924
  }
925
- readyPlayer(sender, player) {
925
+ async readyPlayer(sender, player) {
926
926
  const playerInstance = this.searchPlayer(sender);
927
927
  if (!playerInstance) throw new Error("player not found.");
928
928
  if (!player.roomId) throw new Error("missing room id.");
@@ -940,7 +940,7 @@ var Tiaoom = class extends events.EventEmitter {
940
940
  room.emit("update", room);
941
941
  return this;
942
942
  }
943
- unReadyPlayer(sender, player) {
943
+ async unReadyPlayer(sender, player) {
944
944
  const playerInstance = this.searchPlayer(sender);
945
945
  if (!playerInstance) throw new Error("player not found.");
946
946
  if (!player.roomId) throw new Error("missing room id.");
@@ -957,7 +957,7 @@ var Tiaoom = class extends events.EventEmitter {
957
957
  room.emit("update", room);
958
958
  return this;
959
959
  }
960
- removePlayer(sender) {
960
+ async removePlayer(sender) {
961
961
  const playerIndex = this.players.findIndex((p) => p.id === (sender === null || sender === void 0 ? void 0 : sender.id));
962
962
  const player = this.players[playerIndex];
963
963
  if (playerIndex > -1) {
@@ -966,7 +966,7 @@ var Tiaoom = class extends events.EventEmitter {
966
966
  }
967
967
  return player;
968
968
  }
969
- offlinePlayer(sender) {
969
+ async offlinePlayer(sender) {
970
970
  const room = this.rooms.find((room$1) => room$1.players.some((p) => p.id === (sender === null || sender === void 0 ? void 0 : sender.id)));
971
971
  if (room) setTimeout(() => {
972
972
  const playerInstance = room.players.find((p) => p.id === sender.id && p.role === PlayerRole.player);
@@ -979,7 +979,7 @@ var Tiaoom = class extends events.EventEmitter {
979
979
  this.removePlayer(sender);
980
980
  return sender;
981
981
  }
982
- send(message) {
982
+ async send(message) {
983
983
  if (message.type.startsWith("player.") && message.sender) {
984
984
  var _this$messageInstance2;
985
985
  const player = message.sender;
package/src/index.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["EventEmitter","status","EventEmitter","player","EventEmitter","room"],"sources":["../lib/models/message.ts","../lib/models/player.ts","../lib/models/room.ts","../lib/index.ts"],"sourcesContent":["import EventEmitter from \"events\";\nimport { IPlayer, IPlayerOptions } from \"./player\";\nimport { IRoom, IRoomPlayer, IRoomOptions } from \"./room\";\nimport { IMessageEmitterEvents, IMessageEvents } from \"@lib/events/message\";\n\n/**\n * 消息包类型枚举\n * player: 'command', 'message', 'join', 'leave', 'status'\n */\nexport enum MessageTypes {\n /**\n * 连接准备就绪事件\n */\n SysReady = \"sys.ready\",\n /**\n * 连接关闭事件\n */\n SysClose = \"sys.close\",\n /**\n * 错误事件\n */\n SysError = \"sys.error\",\n /**\n * 全局错误\n */\n GlobalError = \"global.error\",\n /**\n * 房间列表\n */\n RoomList = \"room.list\",\n /**\n * 房间创建\n */\n RoomCreate = \"room.create\",\n /**\n * 房间更新\n */\n RoomUpdate = \"room.update\",\n /**\n * 房间开始\n */\n RoomStart = \"room.start\",\n /**\n * 房间结束\n */\n RoomEnd = \"room.end\",\n /**\n * 房间关闭\n */\n RoomClose = \"room.close\",\n /**\n * 房间全部玩家已准备\n */\n RoomAllReady = \"room.all-ready\",\n /**\n * 房间命令\n */\n RoomCommand = \"room.command\",\n /**\n * 房间内玩家发送的指令\n */\n RoomPlayerCommand = \"room.player-command\",\n /**\n * 房间消息\n */\n RoomMessage = \"room.message\",\n /**\n * 玩家加入房间\n */\n RoomJoin = \"room.join\",\n /**\n * 玩家离开房间\n */\n RoomLeave = \"room.leave\",\n /**\n * 房间玩家准备\n */\n RoomPlayerReady = \"room.player-ready\",\n /**\n * 房间玩家取消准备\n */\n RoomPlayerUnready = \"room.player-unready\",\n /**\n * 玩家列表\n */\n PlayerList = \"player.list\",\n /**\n * 玩家登录\n */\n PlayerLogin = \"player.login\",\n /**\n * 玩家登出\n */\n PlayerLogout = \"player.logout\",\n /**\n * 玩家离线\n */\n PlayerOffline = \"player.offline\",\n /**\n * *玩家消息\n */\n PlayerMessage = \"player.message\",\n /**\n * *玩家命令\n */\n PlayerCommand = \"player.command\",\n /**\n * 玩家错误信息\n */\n PlayerError = \"player.error\",\n /**\n * 全局消息\n */\n GlobalMessage = \"global.message\",\n /**\n * 全局命令\n */\n GlobalCommand = \"global.command\",\n}\n\n/**\n * 客户端发送消息包类型枚举\n * player: 'command', 'message', 'join', 'leave', 'status'\n */\nexport enum RecvMessageTypes {\n /**\n * 房间列表\n */\n RoomList = \"room.list\",\n /**\n * 玩家列表\n */\n PlayerList = \"player.list\",\n /**\n * 房间创建\n */\n RoomCreate = \"room.create\",\n /**\n * 玩家加入房间\n */\n PlayerJoin = \"player.join\",\n /**\n * 玩家离开房间\n */\n PlayerLeave = \"player.leave\",\n /**\n * 玩家离开座位\n */\n PlayerStandUp = \"player.standup\",\n /**\n * 房间获取\n */\n RoomGet = \"room.get\",\n /**\n * 房间开始\n */\n RoomStart = \"room.start\",\n /**\n * 房间踢出玩家\n */\n RoomKick = \"room.kick\",\n /**\n * 房间转移\n */\n RoomTransfer = \"room.transfer\",\n /**\n * 房间关闭\n */\n RoomClose = \"room.close\", \n /**\n * 玩家登录\n */\n PlayerLogin = \"player.login\",\n /**\n * 玩家登出\n */\n PlayerLogout = \"player.logout\",\n /**\n * 玩家准备\n */\n PlayerReady = \"player.ready\",\n /**\n * 玩家取消准备\n */\n PlayerUnready = \"player.unready\",\n /**\n * 房间内玩家发送的指令\n */\n RoomPlayerCommand = \"room.player-command\",\n /**\n * 全局命令\n */\n GlobalCommand = \"global.command\",\n}\n\n/**\n * 消息包接口\n */\nexport interface IMessagePackage {\n /**\n * 消息类型\n */\n type: MessageTypes;\n /**\n * 消息数据\n */\n data?: IPlayerOptions | IRoomOptions | IPlayer | IRoom | IRoomPlayer | any\n /**\n * 发送者信息\n */\n sender?: IPlayer | IRoomPlayer | IRoom;\n}\n\n/**\n * 批量消息包\n */\nexport interface IMessagePackages {\n /**\n * 消息类型\n */\n type: MessageTypes;\n /**\n * 消息数据\n */\n data?: IPlayerOptions | IRoomOptions | IPlayer | IRoom | IRoomPlayer | any\n /**\n * 发送者 Id 数组\n */\n senderIds: string[];\n}\n\n/**\n * 消息数据接口,包含发送者信息\n */\nexport interface IMessageData extends IMessagePackage {\n sender: IPlayer | IRoomPlayer | IRoom;\n}\n\n/**\n * 消息通信接口\n */\nexport interface IMessage extends EventEmitter<IMessageEmitterEvents> {\n /**\n * 监听消息事件\n * @param event 事件名,具体见 MessageEvents\n * @param listener 监听器\n */\n on<K extends keyof IMessageEvents>(event: K, listener: IMessageEvents[K]): this;\n /**\n * 触发消息事件\n * @param event 事件名,具体见 MessageEvents\n * @param args 参数\n */\n emit<K extends keyof IMessageEvents>(event: K, ...args: Parameters<IMessageEvents[K]>): boolean;\n /**\n * 关闭连接\n */\n close(): void;\n /**\n * 发送消息包\n * @param message 消息包\n */\n send(message: IMessagePackages): void;\n}\n","import { PlayerEvents } from \"@lib/events/player\";\nimport EventEmitter from \"events\";\nimport { P } from \"tsdown/index-BQZ2CZuJ\";\n\n/**\n * 玩家选项接口\n */\nexport interface IPlayerOptions {\n /**\n * 玩家ID\n */\n id: string;\n /**\n * 玩家名称\n */\n name: string;\n /**\n * 玩家属性\n */\n attributes?: any;\n /**\n * 发送者函数\n */\n sender?: (type: string, ...message: any) => void;\n /**\n * 是否超级管理员\n */\n isAdmin?: boolean;\n}\n\n/**\n * 玩家状态枚举\n */\nexport enum PlayerStatus {\n /**\n * 已准备\n */\n ready = 'ready',\n /**\n * 未准备\n */\n unready = 'unready',\n /**\n * 在线\n */\n online = 'online',\n /**\n * 游戏中\n */\n playing = 'playing',\n /**\n * 离线\n */\n offline = 'offline',\n}\n\n/**\n * 玩家接口\n */\nexport interface IPlayer extends IPlayerOptions {\n /**\n * 玩家状态\n */\n status: PlayerStatus;\n}\n\n/**\n * 玩家\n */\nexport class Player extends EventEmitter implements IPlayer {\n /**\n * 监听玩家事件\n * @param event 事件名,具体见 PlayEvents\n * @param listener 监听器\n * @returns this\n */\n on<K extends keyof PlayerEvents>(event: K, listener: PlayerEvents[K]): this {\n return super.on(event, listener);\n }\n\n /**\n * 触发玩家事件\n * @param event 事件名,具体见 PlayEvents\n * @param args 参数\n * @returns 是否有监听器被触发\n */\n emit<K extends keyof PlayerEvents>(event: K, ...args: Parameters<PlayerEvents[K]>): boolean {\n return super.emit(event, ...args);\n }\n \n id: string = \"\";\n name: string = \"\";\n attributes?: any;\n sender?: (type: string, ...message: any) => void;\n isAdmin: boolean = false;\n\n private _status: PlayerStatus = PlayerStatus.online;\n status: PlayerStatus = PlayerStatus.online;\n\n constructor(player: Partial<IPlayerOptions> | Player, status: PlayerStatus = PlayerStatus.online) {\n super();\n Object.defineProperty(this, 'status', {\n enumerable: true,\n configurable: true,\n get: () => this._status,\n set: (value: PlayerStatus) => {\n this._status = value;\n this.emit('status', value);\n }\n });\n this.id = player.id || new Date().getTime().toString();\n this.name = player.name || \"\";\n this.attributes = player.attributes || {};\n this.sender = player.sender;\n\n this._status = status;\n if (player instanceof Player) this._status = player.status;\n this.on('status', (status: PlayerStatus) => {\n this._status = status;\n });\n \n const events: Array<keyof PlayerEvents> = ['command', 'message', 'status'];\n events.forEach((event) => {\n this.on(event, (...data: any) => {\n this.sender?.(event, ...data);\n });\n }); \n }\n\n toJSON() {\n return {\n id: this.id,\n name: this.name,\n attributes: this.attributes,\n status: this.status,\n isAdmin: this.isAdmin,\n };\n }\n\n toString() {\n return JSON.stringify(this.toJSON());\n }\n\n /**\n * 设置发送者函数\n * @param {(type: string, ...message: any) => void} sender 发送者函数\n * @returns this\n */\n setSender(sender: (type: string, ...message: any) => void) {\n this.sender = sender;\n return this;\n }\n}","import { IPlayer, Player, IPlayerOptions, PlayerStatus } from \"./player\";\nimport EventEmitter from \"events\";\nimport { RoomEvents } from \"@lib/events\";\n\n/**\n * 房间选项接口\n */\nexport interface IRoomOptions {\n /**\n * 房间号\n */\n id: string, \n /**\n * 房间名称\n */\n name: string,\n /**\n * 房间容量\n */\n size: number, \n /**\n * 最小容量\n */\n minSize: number,\n /**\n * 其他属性\n */\n attrs?: Record<string, any>,\n}\n\n/**\n * 房间玩家角色\n */\nexport enum PlayerRole {\n /**\n * 玩家\n */\n player = 'player',\n /**\n * 观众\n */\n watcher = 'watcher',\n /**\n * 管理员\n */\n admin = 'admin',\n}\n\n/**\n * 房间状态\n */\nexport enum RoomStatus {\n /**\n * 等待中\n */\n waiting = 'waiting',\n /**\n * 已准备\n */\n ready = 'ready',\n /**\n * 游戏中\n */\n playing = 'playing',\n}\n\n/**\n * 房间接口\n */\nexport interface IRoom extends IRoomOptions {\n /**\n * 房间玩家列表\n */\n players: RoomPlayer[];\n}\n\n/**\n * 房间玩家选项接口\n */\nexport interface IRoomPlayerOptions extends IPlayerOptions {\n /**\n * 房间Id\n */\n roomId?: string;\n}\n\n/**\n * 房间玩家接口\n */\nexport interface IRoomPlayer extends IRoomPlayerOptions, IPlayer {\n /**\n * 是否已准备\n */\n isReady: boolean;\n /**\n * 玩家角色\n */\n role: PlayerRole;\n /**\n * 是否为房主\n */\n isCreator: boolean;\n /**\n * 房间 Id\n */\n roomId: string;\n}\n\n/**\n * 房间玩家\n */\nexport class RoomPlayer extends Player implements IRoomPlayer {\n isReady: boolean = false;\n role: PlayerRole = PlayerRole.player;\n isCreator: boolean = false;\n roomId: string;\n\n constructor(player: Partial<IRoomPlayer>, role: PlayerRole = PlayerRole.player) {\n super(player);\n this.isReady = player.isReady || false;\n this.isCreator = player.isCreator || false;\n this.roomId = player.roomId || '';\n this.role = player.role || role;\n this.status = player.status || PlayerStatus.online;\n if (player instanceof Player && player.sender) super.setSender(player.sender);\n }\n\n toJSON() {\n return {\n ...super.toJSON(),\n status: this.status,\n role: this.role,\n isReady: this.isReady,\n isCreator: this.isCreator,\n };\n }\n}\n\n/**\n * 房间\n */\nexport class Room extends EventEmitter implements IRoom {\n /**\n * 监听房间事件\n * @param event 事件名,具体见 RoomEvents\n * @param listener 监听器\n * @returns this\n */\n on<K extends keyof RoomEvents>(event: K, listener: RoomEvents[K]): this {\n return super.on(event, listener);\n }\n\n /**\n * 触发房间事件\n * @param event 事件名,具体见 RoomEvents\n * @param args 参数\n * @returns 是否有监听器被触发\n */\n emit<K extends keyof RoomEvents>(event: K, ...args: Parameters<RoomEvents[K]>): boolean {\n return super.emit(event, ...args);\n }\n\n id: string;\n size: number = 10;\n name: string = '';\n minSize: number = 2;\n attrs?: Record<string, any>;\n players: RoomPlayer[] = [];\n\n /**\n * 有效玩家列表(非观众)\n */\n get validPlayers() {\n return this.players.filter((player) => player.role === PlayerRole.player);\n }\n\n /**\n * 观众列表\n */\n get watchers() {\n return this.players.filter((player) => player.role === PlayerRole.watcher);\n }\n\n /**\n * 消息发送器\n */\n private sender?: (type: string, ...message: any) => void;\n\n /**\n * 房间玩家是否已准备好\n */\n get isReady(): boolean {\n return this.players.length >= this.minSize\n && this.players.every((target) => target.isReady || target.role === PlayerRole.watcher); // is all player ready\n }\n\n /**\n * 房间状态\n */\n get status(): RoomStatus {\n if (!this.isReady) return RoomStatus.waiting;\n if (this.players.findIndex((target) => target.status === PlayerStatus.playing) != -1) return RoomStatus.playing;\n return RoomStatus.ready;\n }\n\n /**\n * 房间是否在游戏中\n */\n get isPlaying(): boolean {\n return this.status === RoomStatus.playing;\n }\n\n /**\n * 房间是否已满\n */\n get isFull(): boolean {\n return this.validPlayers.length == this.size;\n }\n\n /**\n * 房主\n */\n get owner(): RoomPlayer | undefined {\n const creator = this.players.find((player) => player.isCreator);\n return creator;\n }\n\n toJSON() {\n return {\n id: this.id,\n name: this.name,\n size: this.size || 10,\n minSize: this.minSize,\n status: this.status,\n players: this.players.map((player) => player.toJSON()),\n attrs: this.attrs,\n }\n }\n\n toString() {\n return JSON.stringify(this.toJSON());\n }\n\n constructor(room: Partial<IRoomOptions> | Room, players: RoomPlayer[] = []) {\n super();\n if (room instanceof Room) {\n this.players = room.players;\n this.players.forEach((p) => {\n p.roomId = room.id;\n });\n }\n\n this.id = room.id || new Date().getTime().toString();\n this.name = room.name || '';\n this.size = room.size || 10;\n this.minSize = room.minSize || 2;\n this.attrs = room.attrs;\n this.players = players;\n \n const events: Array<keyof RoomEvents> = ['message', 'command', 'start', 'end', 'all-ready', 'player-unready', 'player-ready', 'join', 'leave'];\n events.forEach((event) => {\n this.on(event, (...data: any) => {\n this.sender?.(event, ...data);\n });\n });\n }\n\n /**\n * 设置房主\n * @param {Player} player 玩家\n * @returns this\n */\n setCreator(player: Player) {\n const roomPlayer = this.searchPlayer(player);\n if (roomPlayer) {\n this.players.forEach((p) => {\n p.isCreator = false;\n });\n roomPlayer.isCreator = true;\n this.emit(\"update\", this);\n }\n return this;\n }\n\n /**\n * 添加玩家\n * @param {Player} player 玩家\n * @param {boolean} isCreator 是否房主\n * @returns 玩家实例 \n */\n addPlayer(player: Player, isCreator: boolean = false) {\n let roomPlayer = this.searchPlayer(player);\n if (roomPlayer) {\n if (roomPlayer.role === PlayerRole.watcher && !this.isFull && !this.isPlaying) {\n roomPlayer.role = PlayerRole.player;\n roomPlayer.isCreator = isCreator;\n this.emit(\"update\", this);\n }\n return roomPlayer;\n }\n\n if (isCreator) {\n this.players.forEach((p) => {\n p.isCreator = false;\n });\n }\n roomPlayer = new RoomPlayer(player, this.isFull || this.isPlaying ? PlayerRole.watcher : PlayerRole.player);\n roomPlayer.isCreator = isCreator;\n roomPlayer.roomId = this.id;\n this.players.push(roomPlayer);\n this.emit(\"join\", { ...roomPlayer.toJSON(), roomId: this.id });\n \n return roomPlayer;\n }\n\n /**\n * 离开座位\n * @param {string | IPlayer} player 玩家 / 玩家 id\n */\n leaveSeat(playerId: string): RoomPlayer;\n leaveSeat(player: IPlayer): RoomPlayer;\n leaveSeat(player: IPlayer | string) {\n const playerId = typeof player === \"string\" ? player : player.id;\n const roomPlayer = this.searchPlayer(playerId);\n if (roomPlayer && roomPlayer.role === PlayerRole.player) {\n roomPlayer.role = PlayerRole.watcher;\n roomPlayer.isReady = false;\n this.emit(\"leave\", { ...roomPlayer, roomId: this.id });\n if (roomPlayer.isCreator && this.validPlayers.length > 0) {\n this.validPlayers[0].isCreator = true;\n this.emit(\"update\", this);\n }\n }\n return roomPlayer!;\n }\n\n /**\n * 踢出玩家\n * @param {string | IPlayer} player 玩家 / 玩家 id\n */\n kickPlayer(playerId: string): RoomPlayer;\n kickPlayer(player: IPlayer): RoomPlayer;\n kickPlayer(player: IPlayer | string) {\n const playerId = typeof player === \"string\" ? player : player.id;\n const index = this.players.findIndex((p) => p.id == playerId);\n const roomPlayer = this.players[index];\n if (index > -1) {\n roomPlayer.status = PlayerStatus.online;\n this.emit(\"leave\", { ...roomPlayer, roomId: this.id });\n this.players.splice(index, 1);\n if (roomPlayer.isCreator && this.players.length > 0) {\n this.players[0].isCreator = true;\n this.emit(\"update\", this);\n }\n }\n return roomPlayer;\n }\n\n /**\n * 搜索玩家\n * @param {string | IPlayer} player 玩家 / 玩家 id\n */\n searchPlayer(playerId: string): RoomPlayer | undefined;\n searchPlayer(player: IPlayer): RoomPlayer | undefined;\n searchPlayer(player: string | IPlayer) {\n const playerId = typeof player === \"string\" ? player : player?.id;\n return this.players.find((player) => player.id == playerId);\n }\n\n /**\n * 开始游戏\n */\n start(sender: IPlayer) {\n if (!this.isReady) {\n throw new Error('room is not ready.');\n }\n if (this.status === RoomStatus.playing) {\n throw new Error('room is already started.');\n }\n this.players.forEach((player) => {\n if (player.role != PlayerRole.player) return;\n player.status = PlayerStatus.playing;\n player.emit('status', PlayerStatus.playing);\n });\n this.emit(\"update\", this);\n return this.emit(\"start\", this);\n }\n\n /**\n * 结束游戏\n */\n end() {\n this.players.forEach((player) => {\n if (player.role != PlayerRole.player) return;\n player.status = PlayerStatus.unready;\n player.emit('status', PlayerStatus.unready);\n });\n this.emit(\"update\", this);\n return this.emit(\"end\", this);\n }\n\n /**\n * 设置消息发送器\n * @param sender 消息发送器\n */\n setSender(sender: (type: string, ...message: any) => void) {\n this.sender = sender;\n return this;\n }\n}\n","import { EventEmitter } from \"events\";\nimport { TiaoomEvents } from \"@lib/events\";\nimport { IMessage, RecvMessageTypes, MessageTypes, IMessagePackage } from \"@lib/models/message\";\nimport { IRoom, IRoomPlayer, Room, IRoomOptions, IRoomPlayerOptions, RoomStatus, PlayerRole } from \"@lib/models/room\";\nimport { IPlayer, Player, IPlayerOptions, PlayerStatus } from \"@lib/models/player\";\n\nexport interface ITiaoomOptions {\n socket: IMessage;\n}\n\nexport class Tiaoom extends EventEmitter {\n rooms: Room[] = []; // room list\n players: Player[] = []; // player list\n messageInstance?: IMessage;\n\n constructor({ socket }: ITiaoomOptions) {\n super();\n this.messageInstance = socket;\n }\n\n /**\n * 导出 JSON 数据\n * @returns 房间与玩家数据\n */\n toJSON() {\n return {\n rooms: this.rooms,\n players: this.players,\n };\n }\n\n /**\n * 从数据加载\n * @param data 房间与玩家数据\n * @returns this\n */\n loadFrom(data: { rooms?: Room[]; players?: Player[] }) {\n this.rooms = data.rooms?.map((r) => new Room(r, r.players)) ?? [];\n this.players = data.players?.map((p) => new Player(p, p.status)) ?? [];\n this.rooms.forEach((room) => {\n room.setSender((type, message, sender) => {\n this.send({ type: `room.${type}` as MessageTypes, data: message, sender: room });\n })\n })\n setTimeout(() => {\n this.rooms.forEach((room) => {\n room.players.forEach((player) => {\n if (!this.players.some((p) => p.id === player.id)) {\n this.offlinePlayer(player);\n }\n })\n })\n }, 60 * 1000);\n return this;\n }\n\n on<K extends keyof TiaoomEvents>(event: K, listener: TiaoomEvents[K]): this {\n super.on(event, listener);\n return this\n }\n\n emit<K extends keyof TiaoomEvents>(event: K, ...args: Parameters<TiaoomEvents[K]>): boolean {\n return super.emit(event, ...args);\n }\n\n /**\n * 判断玩家是否为管理员\n * @param player 玩家信息\n * @returns 是否为管理员\n */\n async isAdmin(_player: IPlayer) {\n return false;\n }\n\n /**\n * 判断玩家是否被封禁\n * @param _player 玩家信息\n * @returns 是否被封禁\n */\n async isBanned(_player: IPlayer) {\n return false;\n }\n\n run() {\n this.messageInstance?.on(\"message\", (message: any, cb?: (err: Error | null, data?: any) => any) => {\n message.sender = message.sender ? this.searchPlayer(message.sender) || message.sender : null;\n try {\n switch (message.type) {\n case RecvMessageTypes.RoomList:\n return cb?.(null, this.rooms);\n case RecvMessageTypes.PlayerList:\n return cb?.(null, this.players);\n case RecvMessageTypes.RoomCreate:\n return this.createRoom(message.sender, message.data);\n case RecvMessageTypes.PlayerJoin:\n return this.joinPlayer(message.sender, message.data);\n case RecvMessageTypes.PlayerLeave:\n return this.leavePlayer(message.sender, message.data);\n case RecvMessageTypes.PlayerStandUp:\n return this.leaveSeat(message.sender, message.data);\n case RecvMessageTypes.RoomGet:\n return cb?.(null, this.searchRoom(message.data));\n case RecvMessageTypes.RoomStart:\n return this.startRoom(message.sender, message.data);\n case RecvMessageTypes.RoomKick:\n return this.kickPlayer(message.sender, message.data);\n case RecvMessageTypes.RoomTransfer:\n return this.transferOwner(message.sender, message.data);\n case RecvMessageTypes.RoomClose:\n return this.closeRoom(message.sender, message.data);\n case RecvMessageTypes.PlayerLogin:\n return this.loginPlayer(message.data);\n case RecvMessageTypes.PlayerLogout:\n return this.removePlayer(message.data);\n case MessageTypes.PlayerOffline:\n return this.offlinePlayer(message.data);\n case RecvMessageTypes.PlayerReady:\n return this.readyPlayer(message.sender, message.data);\n case RecvMessageTypes.PlayerUnready:\n return this.unReadyPlayer(message.sender, message.data);\n case RecvMessageTypes.RoomPlayerCommand:\n return this.searchRoom(message.data)?.emit(\"player-command\", { ...message.data , sender: message.sender });\n case RecvMessageTypes.GlobalCommand:\n return this.emit(\"command\", { ...message.data , sender: message.sender });\n default:\n throw new Error('unknown message type.');\n }\n } catch (error) {\n cb?.(error as Error);\n if (message.sender) this.send({\n type: MessageTypes.PlayerError,\n data: {\n name: (error as Error).name, \n message: (error as Error).message,\n stack: (error as Error).stack,\n },\n sender: message.sender,\n });\n }\n });\n\n this.on('player', (player, online) => {\n this.send({ type: online ? MessageTypes.PlayerLogin : MessageTypes.PlayerLogout, data: player });\n });\n\n this.on('players', (players) => {\n this.send({ type: MessageTypes.PlayerList, data: players });\n });\n\n this.on('room', (room) => {\n this.send({ type: MessageTypes.RoomCreate, data: room });\n });\n\n this.on('room-player', (room) => {\n this.send({ type: MessageTypes.RoomUpdate, data: room });\n });\n\n this.on('rooms', (rooms) => {\n this.send({ type: MessageTypes.RoomList, data: rooms });\n });\n\n this.on('message', (data, sender) => {\n this.send({ type: MessageTypes.GlobalMessage, data, sender });\n });\n\n return this;\n }\n\n searchPlayer(player: string): Player | undefined;\n searchPlayer(player: IPlayerOptions | IRoomPlayerOptions): Player | undefined;\n\n searchPlayer(player: IPlayerOptions | IRoomPlayerOptions | string) {\n const playerId = typeof player === \"string\" ? player : player?.id;\n return this.players.find((target) => target.id === playerId);\n }\n\n searchRoom(room: string): Room | undefined;\n searchRoom(room: Partial<IRoomOptions>): Room | undefined;\n\n searchRoom(room: Partial<IRoomOptions> | string) {\n const roomId = typeof room === \"string\" ? room : room?.id;\n return this.rooms.find((target) => target.id === roomId);\n }\n\n createRoom(sender: IPlayer, options: IRoomOptions) {\n if (!sender) {\n throw new Error('missing player information.');\n }\n\n if (!options.name) {\n throw new Error('missing room id or name.');\n }\n const roomInstance = this.searchRoom(options);\n if (roomInstance) {\n throw new Error('room already exists.');\n }\n\n if (this.rooms.some(r => r.players.some(p => p.id === sender?.id))) {\n throw new Error('you are already in a room.');\n }\n\n const room = new Room(options);\n room.setSender((type, message, sender) => {\n this.send({ type: `room.${type}` as MessageTypes, data: message, sender: room });\n });\n \n this.rooms.push(room);\n this.emit(\"room\", room);\n this.joinPlayer(sender, { roomId: room.id, ...sender }, true);\n return room;\n }\n\n startRoom(sender: IPlayer, room: IRoom) {\n const roomInstance = this.searchRoom(room);\n if (!roomInstance) {\n throw new Error('room not found.');\n }\n roomInstance.start(sender);\n\n return this.emit(\"room-player\", roomInstance);\n }\n\n closeRoom(sender: IPlayer | null, room: IRoom) {\n const roomIndex = this.rooms.findIndex((r) => r.id === room.id);\n const roomInstance = this.rooms[roomIndex];\n if (!roomInstance) {\n throw new Error('room not found.');\n }\n\n if (sender?.id && !sender.isAdmin) {\n const senderInRoom = roomInstance.searchPlayer(sender);\n if (!senderInRoom || !senderInRoom.isCreator) {\n throw new Error('permission denied.');\n }\n }\n\n room = this.rooms.splice(roomIndex, 1)[0];\n\n this.emit(\"rooms\", this.rooms);\n roomInstance.emit('close');\n return room;\n }\n\n kickPlayer(sender: IPlayer, data: { roomId: string, playerId: string }) {\n const room = this.searchRoom(data.roomId);\n if (!room) {\n throw new Error('room not found.');\n }\n\n if (!sender.isAdmin) {\n const senderInRoom = room.searchPlayer(sender);\n if (!senderInRoom || !senderInRoom.isCreator) {\n throw new Error('permission denied.');\n }\n }\n\n const targetPlayer = room.players.find(p => p.id === data.playerId);\n if (!targetPlayer) {\n throw new Error('player not found in room.');\n }\n\n const roomPlayer = room.kickPlayer(targetPlayer);\n if (roomPlayer) this.emit(\"room-player\", room);\n return roomPlayer;\n }\n\n transferOwner(sender: IPlayer, data: { roomId: string, playerId: string }) {\n const room = this.searchRoom(data.roomId);\n if (!room) {\n throw new Error('room not found.');\n }\n\n const creator = room.players.find(p => p.isCreator);\n if (!sender.isAdmin) {\n const senderInRoom = room.searchPlayer(sender);\n if (!senderInRoom || !senderInRoom.isCreator) {\n throw new Error('permission denied.');\n }\n } else {\n\n }\n\n const targetPlayer = room.players.find(p => p.id === data.playerId);\n if (!targetPlayer) {\n throw new Error('player not found in room.');\n }\n\n if (targetPlayer.id === sender.id) {\n return;\n }\n\n if (creator) creator.isCreator = false;\n targetPlayer.isCreator = true;\n\n this.emit(\"room-player\", room);\n return room;\n }\n\n async loginPlayer (player: IPlayerOptions, cb?: (data: { player: Player }) => void) {\n let playerInstance = this.searchPlayer(player);\n if (!playerInstance?.sender) {\n if (!playerInstance) {\n playerInstance = new Player(player);\n this.players.push(playerInstance);\n }\n playerInstance.isAdmin = await this.isAdmin(playerInstance);\n playerInstance.setSender((type, message) => {\n this.send({ type: `player.${type}` as MessageTypes, data: message, sender: playerInstance });\n });\n this.emit(\"player\", playerInstance, true);\n\n const room = this.rooms.find(r => r.players.some(p => p.id === playerInstance!.id));\n if (room) {\n const playerIndex = room.players.findIndex(p => p.id === playerInstance!.id);\n if (playerIndex >= 0) {\n const status = room?.status == RoomStatus.playing ? PlayerStatus.playing : PlayerStatus.online;\n playerInstance.status = status;\n playerInstance.attributes = Object.assign({}, room.players[playerIndex].attributes, playerInstance.attributes);\n Object.assign(room.players[playerIndex], playerInstance);\n room.emit('update', room);\n }\n }\n }\n\n playerInstance.emit(\"status\", playerInstance.status);\n\n cb?.({ player: playerInstance });\n return playerInstance;\n }\n\n async joinPlayer(sender: IPlayer, player: IRoomPlayerOptions, isCreator: boolean = false) {\n let playerInstance = this.searchPlayer(sender);\n if (!playerInstance) {\n playerInstance = await this.loginPlayer(sender);\n }\n\n if (!player.roomId) {\n throw new Error('missing room id.');\n }\n\n const room = this.rooms.find((room) => room.id === player.roomId);\n if (!room) {\n throw new Error('room not found.');\n }\n\n if (!isCreator && !room.players.some(p => p.isCreator)) {\n isCreator = true;\n }\n\n const roomPlayer = room.addPlayer(playerInstance, isCreator);\n if (roomPlayer) {\n this.emit(\"room-player\", room);\n }\n\n return roomPlayer;\n }\n\n leavePlayer(sender: IPlayer, player: IRoomPlayerOptions) {\n if (!player.roomId) {\n throw new Error('missing room id.');\n }\n\n const room = this.rooms.find((room) => room.id === player.roomId);\n if (!room) {\n throw new Error('room not found.');\n }\n\n const playerInstance = room.searchPlayer(sender);\n if (!playerInstance) {\n throw new Error('player not in room.');\n }\n\n const roomPlayer = room.kickPlayer(playerInstance);\n\n if (roomPlayer) this.emit(\"room-player\", room);\n\n return roomPlayer;\n }\n \n leaveSeat(sender: IPlayer, player: IRoomPlayerOptions) {\n if (!player.roomId) {\n throw new Error('missing room id.');\n }\n\n const room = this.rooms.find((room) => room.id === player.roomId);\n if (!room) {\n throw new Error('room not found.');\n }\n\n const playerInstance = room.searchPlayer(sender);\n if (!playerInstance) {\n throw new Error('player not in room.');\n }\n\n const roomPlayer = room.leaveSeat(playerInstance);\n if (roomPlayer) this.emit(\"room-player\", room);\n\n return roomPlayer;\n }\n\n readyPlayer(sender: IPlayer, player: IRoomPlayer) {\n const playerInstance = this.searchPlayer(sender);\n if (!playerInstance) {\n throw new Error('player not found.');\n }\n\n if (!player.roomId) {\n throw new Error('missing room id.');\n }\n\n const room = this.rooms.find((room) => room.id === player.roomId);\n if (!room) {\n throw new Error('room not found.');\n }\n\n const roomPlayer = room.searchPlayer(playerInstance);\n \n if (!roomPlayer) {\n throw new Error('player not in room.');\n }\n\n roomPlayer.isReady = true;\n\n if (room.isReady) {\n room.emit(\"all-ready\", room.players);\n }\n\n playerInstance.status = PlayerStatus.ready;\n\n room.emit(\"player-ready\", { ...player, ...roomPlayer });\n room.emit('update', room);\n\n return this;\n }\n \n unReadyPlayer(sender: IPlayer, player: IRoomPlayer) {\n const playerInstance = this.searchPlayer(sender);\n if (!playerInstance) {\n throw new Error('player not found.');\n }\n\n if (!player.roomId) {\n throw new Error('missing room id.');\n }\n\n const room = this.rooms.find((room) => room.id === player.roomId);\n if (!room) {\n throw new Error('room not found.');\n }\n\n const roomPlayer = room.searchPlayer(playerInstance);\n \n if (!roomPlayer) {\n throw new Error('player not in room.');\n }\n\n roomPlayer.isReady = false;\n playerInstance.status = PlayerStatus.unready;\n room.emit(\"player-unready\", { ...player, ...roomPlayer });\n room.emit('update', room);\n\n return this;\n }\n\n removePlayer(sender: IPlayer) {\n const playerIndex = this.players.findIndex((p) => p.id === sender?.id);\n const player = this.players[playerIndex];\n if (playerIndex > -1) {\n this.players.splice(playerIndex, 1)[0];\n this.emit(\"player\", player, false);\n }\n return player;\n }\n\n offlinePlayer(sender: IPlayer) {\n const room = this.rooms.find((room) => room.players.some(p => p.id === sender?.id));\n if (room) {\n setTimeout(() => {\n const playerInstance = room.players.find(p => p.id === sender.id && p.role === PlayerRole.player);\n if (this.players.some(p => p.id === sender.id) || !playerInstance) \n return; // player is online\n playerInstance.status = PlayerStatus.offline;\n room.emit(\"player-offline\", playerInstance);\n playerInstance.status = PlayerStatus.offline;\n room.emit('update', room);\n }, 60 * 1000); // 1 minute later\n }\n this.removePlayer(sender);\n return sender;\n }\n\n send(message: IMessagePackage) {\n // send a message to the client\n if (message.type.startsWith('player.') && message.sender) {\n const player = message.sender as Player;\n // Send to all sockets of the player\n this.messageInstance?.send({ \n type: message.type, \n data: message.data, \n senderIds: [player.id]\n });\n }\n else if (message.type.startsWith('room.') && message.sender) {\n const room = message.sender as Room;\n this.messageInstance?.send({ \n type: message.type, \n data: message.data, \n senderIds: room.players.map(p => p.id)\n });\n } else {\n this.messageInstance?.send({ \n type: message.type, \n data: message.data, \n senderIds: this.players.map(p => p.id)\n });\n }\n }\n}\n\nexport * from \"@lib/models/message\";\nexport * from \"@lib/models/room\";\nexport * from \"@lib/models/player\";\nexport * from \"@lib/events\";"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","names":["EventEmitter","status","EventEmitter","player","EventEmitter","room"],"sources":["../lib/models/message.ts","../lib/models/player.ts","../lib/models/room.ts","../lib/index.ts"],"sourcesContent":["import EventEmitter from \"events\";\nimport { IPlayer, IPlayerOptions } from \"./player\";\nimport { IRoom, IRoomPlayer, IRoomOptions } from \"./room\";\nimport { IMessageEmitterEvents, IMessageEvents } from \"@lib/events/message\";\n\n/**\n * 消息包类型枚举\n * player: 'command', 'message', 'join', 'leave', 'status'\n */\nexport enum MessageTypes {\n /**\n * 连接准备就绪事件\n */\n SysReady = \"sys.ready\",\n /**\n * 连接关闭事件\n */\n SysClose = \"sys.close\",\n /**\n * 错误事件\n */\n SysError = \"sys.error\",\n /**\n * 全局错误\n */\n GlobalError = \"global.error\",\n /**\n * 房间列表\n */\n RoomList = \"room.list\",\n /**\n * 房间创建\n */\n RoomCreate = \"room.create\",\n /**\n * 房间更新\n */\n RoomUpdate = \"room.update\",\n /**\n * 房间开始\n */\n RoomStart = \"room.start\",\n /**\n * 房间结束\n */\n RoomEnd = \"room.end\",\n /**\n * 房间关闭\n */\n RoomClose = \"room.close\",\n /**\n * 房间全部玩家已准备\n */\n RoomAllReady = \"room.all-ready\",\n /**\n * 房间命令\n */\n RoomCommand = \"room.command\",\n /**\n * 房间内玩家发送的指令\n */\n RoomPlayerCommand = \"room.player-command\",\n /**\n * 房间消息\n */\n RoomMessage = \"room.message\",\n /**\n * 玩家加入房间\n */\n RoomJoin = \"room.join\",\n /**\n * 玩家离开房间\n */\n RoomLeave = \"room.leave\",\n /**\n * 房间玩家准备\n */\n RoomPlayerReady = \"room.player-ready\",\n /**\n * 房间玩家取消准备\n */\n RoomPlayerUnready = \"room.player-unready\",\n /**\n * 玩家列表\n */\n PlayerList = \"player.list\",\n /**\n * 玩家登录\n */\n PlayerLogin = \"player.login\",\n /**\n * 玩家登出\n */\n PlayerLogout = \"player.logout\",\n /**\n * 玩家离线\n */\n PlayerOffline = \"player.offline\",\n /**\n * *玩家消息\n */\n PlayerMessage = \"player.message\",\n /**\n * *玩家命令\n */\n PlayerCommand = \"player.command\",\n /**\n * 玩家错误信息\n */\n PlayerError = \"player.error\",\n /**\n * 全局消息\n */\n GlobalMessage = \"global.message\",\n /**\n * 全局命令\n */\n GlobalCommand = \"global.command\",\n}\n\n/**\n * 客户端发送消息包类型枚举\n * player: 'command', 'message', 'join', 'leave', 'status'\n */\nexport enum RecvMessageTypes {\n /**\n * 房间列表\n */\n RoomList = \"room.list\",\n /**\n * 玩家列表\n */\n PlayerList = \"player.list\",\n /**\n * 房间创建\n */\n RoomCreate = \"room.create\",\n /**\n * 玩家加入房间\n */\n PlayerJoin = \"player.join\",\n /**\n * 玩家离开房间\n */\n PlayerLeave = \"player.leave\",\n /**\n * 玩家离开座位\n */\n PlayerStandUp = \"player.standup\",\n /**\n * 房间获取\n */\n RoomGet = \"room.get\",\n /**\n * 房间开始\n */\n RoomStart = \"room.start\",\n /**\n * 房间踢出玩家\n */\n RoomKick = \"room.kick\",\n /**\n * 房间转移\n */\n RoomTransfer = \"room.transfer\",\n /**\n * 房间关闭\n */\n RoomClose = \"room.close\", \n /**\n * 玩家登录\n */\n PlayerLogin = \"player.login\",\n /**\n * 玩家登出\n */\n PlayerLogout = \"player.logout\",\n /**\n * 玩家准备\n */\n PlayerReady = \"player.ready\",\n /**\n * 玩家取消准备\n */\n PlayerUnready = \"player.unready\",\n /**\n * 房间内玩家发送的指令\n */\n RoomPlayerCommand = \"room.player-command\",\n /**\n * 全局命令\n */\n GlobalCommand = \"global.command\",\n}\n\n/**\n * 消息包接口\n */\nexport interface IMessagePackage {\n /**\n * 消息类型\n */\n type: MessageTypes;\n /**\n * 消息数据\n */\n data?: IPlayerOptions | IRoomOptions | IPlayer | IRoom | IRoomPlayer | any\n /**\n * 发送者信息\n */\n sender?: IPlayer | IRoomPlayer | IRoom;\n}\n\n/**\n * 批量消息包\n */\nexport interface IMessagePackages {\n /**\n * 消息类型\n */\n type: MessageTypes;\n /**\n * 消息数据\n */\n data?: IPlayerOptions | IRoomOptions | IPlayer | IRoom | IRoomPlayer | any\n /**\n * 发送者 Id 数组\n */\n senderIds: string[];\n}\n\n/**\n * 消息数据接口,包含发送者信息\n */\nexport interface IMessageData extends IMessagePackage {\n sender: IPlayer | IRoomPlayer | IRoom;\n}\n\n/**\n * 消息通信接口\n */\nexport interface IMessage extends EventEmitter<IMessageEmitterEvents> {\n /**\n * 监听消息事件\n * @param event 事件名,具体见 MessageEvents\n * @param listener 监听器\n */\n on<K extends keyof IMessageEvents>(event: K, listener: IMessageEvents[K]): this;\n /**\n * 触发消息事件\n * @param event 事件名,具体见 MessageEvents\n * @param args 参数\n */\n emit<K extends keyof IMessageEvents>(event: K, ...args: Parameters<IMessageEvents[K]>): boolean;\n /**\n * 关闭连接\n */\n close(): void;\n /**\n * 发送消息包\n * @param message 消息包\n */\n send(message: IMessagePackages): void;\n}\n","import { PlayerEvents } from \"@lib/events/player\";\nimport EventEmitter from \"events\";\nimport { P } from \"tsdown/index-BQZ2CZuJ\";\n\n/**\n * 玩家选项接口\n */\nexport interface IPlayerOptions {\n /**\n * 玩家ID\n */\n id: string;\n /**\n * 玩家名称\n */\n name: string;\n /**\n * 玩家属性\n */\n attributes?: any;\n /**\n * 发送者函数\n */\n sender?: (type: string, ...message: any) => void;\n /**\n * 是否超级管理员\n */\n isAdmin?: boolean;\n}\n\n/**\n * 玩家状态枚举\n */\nexport enum PlayerStatus {\n /**\n * 已准备\n */\n ready = 'ready',\n /**\n * 未准备\n */\n unready = 'unready',\n /**\n * 在线\n */\n online = 'online',\n /**\n * 游戏中\n */\n playing = 'playing',\n /**\n * 离线\n */\n offline = 'offline',\n}\n\n/**\n * 玩家接口\n */\nexport interface IPlayer extends IPlayerOptions {\n /**\n * 玩家状态\n */\n status: PlayerStatus;\n}\n\n/**\n * 玩家\n */\nexport class Player extends EventEmitter implements IPlayer {\n /**\n * 监听玩家事件\n * @param event 事件名,具体见 PlayEvents\n * @param listener 监听器\n * @returns this\n */\n on<K extends keyof PlayerEvents>(event: K, listener: PlayerEvents[K]): this {\n return super.on(event, listener);\n }\n\n /**\n * 触发玩家事件\n * @param event 事件名,具体见 PlayEvents\n * @param args 参数\n * @returns 是否有监听器被触发\n */\n emit<K extends keyof PlayerEvents>(event: K, ...args: Parameters<PlayerEvents[K]>): boolean {\n return super.emit(event, ...args);\n }\n \n id: string = \"\";\n name: string = \"\";\n attributes?: any;\n sender?: (type: string, ...message: any) => void;\n isAdmin: boolean = false;\n\n private _status: PlayerStatus = PlayerStatus.online;\n status: PlayerStatus = PlayerStatus.online;\n\n constructor(player: Partial<IPlayerOptions> | Player, status: PlayerStatus = PlayerStatus.online) {\n super();\n Object.defineProperty(this, 'status', {\n enumerable: true,\n configurable: true,\n get: () => this._status,\n set: (value: PlayerStatus) => {\n this._status = value;\n this.emit('status', value);\n }\n });\n this.id = player.id || new Date().getTime().toString();\n this.name = player.name || \"\";\n this.attributes = player.attributes || {};\n this.sender = player.sender;\n\n this._status = status;\n if (player instanceof Player) this._status = player.status;\n this.on('status', (status: PlayerStatus) => {\n this._status = status;\n });\n \n const events: Array<keyof PlayerEvents> = ['command', 'message', 'status'];\n events.forEach((event) => {\n this.on(event, (...data: any) => {\n this.sender?.(event, ...data);\n });\n }); \n }\n\n toJSON() {\n return {\n id: this.id,\n name: this.name,\n attributes: this.attributes,\n status: this.status,\n isAdmin: this.isAdmin,\n };\n }\n\n toString() {\n return JSON.stringify(this.toJSON());\n }\n\n /**\n * 设置发送者函数\n * @param {(type: string, ...message: any) => void} sender 发送者函数\n * @returns this\n */\n setSender(sender: (type: string, ...message: any) => void) {\n this.sender = sender;\n return this;\n }\n}","import { IPlayer, Player, IPlayerOptions, PlayerStatus } from \"./player\";\nimport EventEmitter from \"events\";\nimport { RoomEvents } from \"@lib/events\";\n\n/**\n * 房间选项接口\n */\nexport interface IRoomOptions {\n /**\n * 房间号\n */\n id: string, \n /**\n * 房间名称\n */\n name: string,\n /**\n * 房间容量\n */\n size: number, \n /**\n * 最小容量\n */\n minSize: number,\n /**\n * 其他属性\n */\n attrs?: Record<string, any>,\n}\n\n/**\n * 房间玩家角色\n */\nexport enum PlayerRole {\n /**\n * 玩家\n */\n player = 'player',\n /**\n * 观众\n */\n watcher = 'watcher',\n /**\n * 管理员\n */\n admin = 'admin',\n}\n\n/**\n * 房间状态\n */\nexport enum RoomStatus {\n /**\n * 等待中\n */\n waiting = 'waiting',\n /**\n * 已准备\n */\n ready = 'ready',\n /**\n * 游戏中\n */\n playing = 'playing',\n}\n\n/**\n * 房间接口\n */\nexport interface IRoom extends IRoomOptions {\n /**\n * 房间玩家列表\n */\n players: RoomPlayer[];\n}\n\n/**\n * 房间玩家选项接口\n */\nexport interface IRoomPlayerOptions extends IPlayerOptions {\n /**\n * 房间Id\n */\n roomId?: string;\n}\n\n/**\n * 房间玩家接口\n */\nexport interface IRoomPlayer extends IRoomPlayerOptions, IPlayer {\n /**\n * 是否已准备\n */\n isReady: boolean;\n /**\n * 玩家角色\n */\n role: PlayerRole;\n /**\n * 是否为房主\n */\n isCreator: boolean;\n /**\n * 房间 Id\n */\n roomId: string;\n}\n\n/**\n * 房间玩家\n */\nexport class RoomPlayer extends Player implements IRoomPlayer {\n isReady: boolean = false;\n role: PlayerRole = PlayerRole.player;\n isCreator: boolean = false;\n roomId: string;\n\n constructor(player: Partial<IRoomPlayer>, role: PlayerRole = PlayerRole.player) {\n super(player);\n this.isReady = player.isReady || false;\n this.isCreator = player.isCreator || false;\n this.roomId = player.roomId || '';\n this.role = player.role || role;\n this.status = player.status || PlayerStatus.online;\n if (player instanceof Player && player.sender) super.setSender(player.sender);\n }\n\n toJSON() {\n return {\n ...super.toJSON(),\n status: this.status,\n role: this.role,\n isReady: this.isReady,\n isCreator: this.isCreator,\n };\n }\n}\n\n/**\n * 房间\n */\nexport class Room extends EventEmitter implements IRoom {\n /**\n * 监听房间事件\n * @param event 事件名,具体见 RoomEvents\n * @param listener 监听器\n * @returns this\n */\n on<K extends keyof RoomEvents>(event: K, listener: RoomEvents[K]): this {\n return super.on(event, listener);\n }\n\n /**\n * 触发房间事件\n * @param event 事件名,具体见 RoomEvents\n * @param args 参数\n * @returns 是否有监听器被触发\n */\n emit<K extends keyof RoomEvents>(event: K, ...args: Parameters<RoomEvents[K]>): boolean {\n return super.emit(event, ...args);\n }\n\n id: string;\n size: number = 10;\n name: string = '';\n minSize: number = 2;\n attrs?: Record<string, any>;\n players: RoomPlayer[] = [];\n\n /**\n * 有效玩家列表(非观众)\n */\n get validPlayers() {\n return this.players.filter((player) => player.role === PlayerRole.player);\n }\n\n /**\n * 观众列表\n */\n get watchers() {\n return this.players.filter((player) => player.role === PlayerRole.watcher);\n }\n\n /**\n * 消息发送器\n */\n private sender?: (type: string, ...message: any) => void;\n\n /**\n * 房间玩家是否已准备好\n */\n get isReady(): boolean {\n return this.players.length >= this.minSize\n && this.players.every((target) => target.isReady || target.role === PlayerRole.watcher); // is all player ready\n }\n\n /**\n * 房间状态\n */\n get status(): RoomStatus {\n if (!this.isReady) return RoomStatus.waiting;\n if (this.players.findIndex((target) => target.status === PlayerStatus.playing) != -1) return RoomStatus.playing;\n return RoomStatus.ready;\n }\n\n /**\n * 房间是否在游戏中\n */\n get isPlaying(): boolean {\n return this.status === RoomStatus.playing;\n }\n\n /**\n * 房间是否已满\n */\n get isFull(): boolean {\n return this.validPlayers.length == this.size;\n }\n\n /**\n * 房主\n */\n get owner(): RoomPlayer | undefined {\n const creator = this.players.find((player) => player.isCreator);\n return creator;\n }\n\n toJSON() {\n return {\n id: this.id,\n name: this.name,\n size: this.size || 10,\n minSize: this.minSize,\n status: this.status,\n players: this.players.map((player) => player.toJSON()),\n attrs: this.attrs,\n }\n }\n\n toString() {\n return JSON.stringify(this.toJSON());\n }\n\n constructor(room: Partial<IRoomOptions> | Room, players: RoomPlayer[] = []) {\n super();\n if (room instanceof Room) {\n this.players = room.players;\n this.players.forEach((p) => {\n p.roomId = room.id;\n });\n }\n\n this.id = room.id || new Date().getTime().toString();\n this.name = room.name || '';\n this.size = room.size || 10;\n this.minSize = room.minSize || 2;\n this.attrs = room.attrs;\n this.players = players;\n \n const events: Array<keyof RoomEvents> = ['message', 'command', 'start', 'end', 'all-ready', 'player-unready', 'player-ready', 'join', 'leave'];\n events.forEach((event) => {\n this.on(event, (...data: any) => {\n this.sender?.(event, ...data);\n });\n });\n }\n\n /**\n * 设置房主\n * @param {Player} player 玩家\n * @returns this\n */\n setCreator(player: Player) {\n const roomPlayer = this.searchPlayer(player);\n if (roomPlayer) {\n this.players.forEach((p) => {\n p.isCreator = false;\n });\n roomPlayer.isCreator = true;\n this.emit(\"update\", this);\n }\n return this;\n }\n\n /**\n * 添加玩家\n * @param {Player} player 玩家\n * @param {boolean} isCreator 是否房主\n * @returns 玩家实例 \n */\n addPlayer(player: Player, isCreator: boolean = false) {\n let roomPlayer = this.searchPlayer(player);\n if (roomPlayer) {\n if (roomPlayer.role === PlayerRole.watcher && !this.isFull && !this.isPlaying) {\n roomPlayer.role = PlayerRole.player;\n roomPlayer.isCreator = isCreator;\n this.emit(\"update\", this);\n }\n return roomPlayer;\n }\n\n if (isCreator) {\n this.players.forEach((p) => {\n p.isCreator = false;\n });\n }\n roomPlayer = new RoomPlayer(player, this.isFull || this.isPlaying ? PlayerRole.watcher : PlayerRole.player);\n roomPlayer.isCreator = isCreator;\n roomPlayer.roomId = this.id;\n this.players.push(roomPlayer);\n this.emit(\"join\", { ...roomPlayer.toJSON(), roomId: this.id });\n \n return roomPlayer;\n }\n\n /**\n * 离开座位\n * @param {string | IPlayer} player 玩家 / 玩家 id\n */\n leaveSeat(playerId: string): RoomPlayer;\n leaveSeat(player: IPlayer): RoomPlayer;\n leaveSeat(player: IPlayer | string) {\n const playerId = typeof player === \"string\" ? player : player.id;\n const roomPlayer = this.searchPlayer(playerId);\n if (roomPlayer && roomPlayer.role === PlayerRole.player) {\n roomPlayer.role = PlayerRole.watcher;\n roomPlayer.isReady = false;\n this.emit(\"leave\", { ...roomPlayer, roomId: this.id });\n if (roomPlayer.isCreator && this.validPlayers.length > 0) {\n this.validPlayers[0].isCreator = true;\n this.emit(\"update\", this);\n }\n }\n return roomPlayer!;\n }\n\n /**\n * 踢出玩家\n * @param {string | IPlayer} player 玩家 / 玩家 id\n */\n kickPlayer(playerId: string): RoomPlayer;\n kickPlayer(player: IPlayer): RoomPlayer;\n kickPlayer(player: IPlayer | string) {\n const playerId = typeof player === \"string\" ? player : player.id;\n const index = this.players.findIndex((p) => p.id == playerId);\n const roomPlayer = this.players[index];\n if (index > -1) {\n roomPlayer.status = PlayerStatus.online;\n this.emit(\"leave\", { ...roomPlayer, roomId: this.id });\n this.players.splice(index, 1);\n if (roomPlayer.isCreator && this.players.length > 0) {\n this.players[0].isCreator = true;\n this.emit(\"update\", this);\n }\n }\n return roomPlayer;\n }\n\n /**\n * 搜索玩家\n * @param {string | IPlayer} player 玩家 / 玩家 id\n */\n searchPlayer(playerId: string): RoomPlayer | undefined;\n searchPlayer(player: IPlayer): RoomPlayer | undefined;\n searchPlayer(player: string | IPlayer) {\n const playerId = typeof player === \"string\" ? player : player?.id;\n return this.players.find((player) => player.id == playerId);\n }\n\n /**\n * 开始游戏\n */\n start(sender: IPlayer) {\n if (!this.isReady) {\n throw new Error('room is not ready.');\n }\n if (this.status === RoomStatus.playing) {\n throw new Error('room is already started.');\n }\n this.players.forEach((player) => {\n if (player.role != PlayerRole.player) return;\n player.status = PlayerStatus.playing;\n player.emit('status', PlayerStatus.playing);\n });\n this.emit(\"update\", this);\n return this.emit(\"start\", this);\n }\n\n /**\n * 结束游戏\n */\n end() {\n this.players.forEach((player) => {\n if (player.role != PlayerRole.player) return;\n player.status = PlayerStatus.unready;\n player.emit('status', PlayerStatus.unready);\n });\n this.emit(\"update\", this);\n return this.emit(\"end\", this);\n }\n\n /**\n * 设置消息发送器\n * @param sender 消息发送器\n */\n setSender(sender: (type: string, ...message: any) => void) {\n this.sender = sender;\n return this;\n }\n}\n","import { EventEmitter } from \"events\";\nimport { TiaoomEvents } from \"@lib/events\";\nimport { IMessage, RecvMessageTypes, MessageTypes, IMessagePackage } from \"@lib/models/message\";\nimport { IRoom, IRoomPlayer, Room, IRoomOptions, IRoomPlayerOptions, RoomStatus, PlayerRole } from \"@lib/models/room\";\nimport { IPlayer, Player, IPlayerOptions, PlayerStatus } from \"@lib/models/player\";\n\nexport interface ITiaoomOptions {\n socket: IMessage;\n}\n\nexport class Tiaoom extends EventEmitter {\n rooms: Room[] = []; // room list\n players: Player[] = []; // player list\n messageInstance?: IMessage;\n\n constructor({ socket }: ITiaoomOptions) {\n super();\n this.messageInstance = socket;\n }\n\n /**\n * 导出 JSON 数据\n * @returns 房间与玩家数据\n */\n toJSON() {\n return {\n rooms: this.rooms,\n players: this.players,\n };\n }\n\n /**\n * 从数据加载\n * @param data 房间与玩家数据\n * @returns this\n */\n loadFrom(data: { rooms?: Room[]; players?: Player[] }) {\n this.rooms = data.rooms?.map((r) => new Room(r, r.players)) ?? [];\n this.players = data.players?.map((p) => new Player(p, p.status)) ?? [];\n this.rooms.forEach((room) => {\n room.setSender((type, message, sender) => {\n this.send({ type: `room.${type}` as MessageTypes, data: message, sender: room });\n })\n })\n setTimeout(() => {\n this.rooms.forEach((room) => {\n room.players.forEach((player) => {\n if (!this.players.some((p) => p.id === player.id)) {\n this.offlinePlayer(player);\n }\n })\n })\n }, 60 * 1000);\n return this;\n }\n\n on<K extends keyof TiaoomEvents>(event: K, listener: TiaoomEvents[K]): this {\n super.on(event, listener);\n return this\n }\n\n emit<K extends keyof TiaoomEvents>(event: K, ...args: Parameters<TiaoomEvents[K]>): boolean {\n return super.emit(event, ...args);\n }\n\n /**\n * 判断玩家是否为管理员\n * @param player 玩家信息\n * @returns 是否为管理员\n */\n async isAdmin(_player: IPlayer) {\n return false;\n }\n\n /**\n * 判断玩家是否被封禁\n * @param _player 玩家信息\n * @returns 是否被封禁\n */\n async isBanned(_player: IPlayer) {\n return false;\n }\n\n run() {\n this.messageInstance?.on(\"message\", async (message: any, cb?: (err: Error | null, data?: any) => any) => {\n message.sender = message.sender ? this.searchPlayer(message.sender) || message.sender : null;\n try {\n switch (message.type) {\n case RecvMessageTypes.RoomList:\n return cb?.(null, this.rooms);\n case RecvMessageTypes.PlayerList:\n return cb?.(null, this.players);\n case RecvMessageTypes.RoomCreate:\n return await this.createRoom(message.sender, message.data);\n case RecvMessageTypes.PlayerJoin:\n return await this.joinPlayer(message.sender, message.data);\n case RecvMessageTypes.PlayerLeave:\n return await this.leavePlayer(message.sender, message.data);\n case RecvMessageTypes.PlayerStandUp:\n return await this.leaveSeat(message.sender, message.data);\n case RecvMessageTypes.RoomGet:\n return cb?.(null, this.searchRoom(message.data));\n case RecvMessageTypes.RoomStart:\n return await this.startRoom(message.sender, message.data);\n case RecvMessageTypes.RoomKick:\n return await this.kickPlayer(message.sender, message.data);\n case RecvMessageTypes.RoomTransfer:\n return await this.transferOwner(message.sender, message.data);\n case RecvMessageTypes.RoomClose:\n return await this.closeRoom(message.sender, message.data);\n case RecvMessageTypes.PlayerLogin:\n return await this.loginPlayer(message.data);\n case RecvMessageTypes.PlayerLogout:\n return await this.removePlayer(message.data);\n case MessageTypes.PlayerOffline:\n return await this.offlinePlayer(message.data);\n case RecvMessageTypes.PlayerReady:\n return await this.readyPlayer(message.sender, message.data);\n case RecvMessageTypes.PlayerUnready:\n return await this.unReadyPlayer(message.sender, message.data);\n case RecvMessageTypes.RoomPlayerCommand:\n return this.searchRoom(message.data)?.emit(\"player-command\", { ...message.data , sender: message.sender });\n case RecvMessageTypes.GlobalCommand:\n return this.emit(\"command\", { ...message.data , sender: message.sender });\n default:\n throw new Error('unknown message type.');\n }\n } catch (error) {\n cb?.(error as Error);\n if (message.sender) this.send({\n type: MessageTypes.PlayerError,\n data: {\n name: (error as Error).name, \n message: (error as Error).message,\n stack: (error as Error).stack,\n },\n sender: message.sender,\n });\n }\n });\n\n this.on('player', (player, online) => {\n this.send({ type: online ? MessageTypes.PlayerLogin : MessageTypes.PlayerLogout, data: player });\n });\n\n this.on('players', (players) => {\n this.send({ type: MessageTypes.PlayerList, data: players });\n });\n\n this.on('room', (room) => {\n this.send({ type: MessageTypes.RoomCreate, data: room });\n });\n\n this.on('room-player', (room) => {\n this.send({ type: MessageTypes.RoomUpdate, data: room });\n });\n\n this.on('rooms', (rooms) => {\n this.send({ type: MessageTypes.RoomList, data: rooms });\n });\n\n this.on('message', (data, sender) => {\n this.send({ type: MessageTypes.GlobalMessage, data, sender });\n });\n\n return this;\n }\n\n searchPlayer(player: string): Player | undefined;\n searchPlayer(player: IPlayerOptions | IRoomPlayerOptions): Player | undefined;\n\n searchPlayer(player: IPlayerOptions | IRoomPlayerOptions | string) {\n const playerId = typeof player === \"string\" ? player : player?.id;\n return this.players.find((target) => target.id === playerId);\n }\n\n searchRoom(room: string): Room | undefined;\n searchRoom(room: Partial<IRoomOptions>): Room | undefined;\n\n searchRoom(room: Partial<IRoomOptions> | string) {\n const roomId = typeof room === \"string\" ? room : room?.id;\n return this.rooms.find((target) => target.id === roomId);\n }\n\n async createRoom(sender: IPlayer, options: IRoomOptions) {\n if (!sender) {\n throw new Error('missing player information.');\n }\n\n if (!options.name) {\n throw new Error('missing room id or name.');\n }\n const roomInstance = this.searchRoom(options);\n if (roomInstance) {\n throw new Error('room already exists.');\n }\n\n if (this.rooms.some(r => r.players.some(p => p.id === sender?.id))) {\n throw new Error('you are already in a room.');\n }\n\n const room = new Room(options);\n room.setSender((type, message, sender) => {\n this.send({ type: `room.${type}` as MessageTypes, data: message, sender: room });\n });\n \n this.rooms.push(room);\n this.emit(\"room\", room);\n this.joinPlayer(sender, { roomId: room.id, ...sender }, true);\n return room;\n }\n\n async startRoom(sender: IPlayer, room: IRoom) {\n const roomInstance = this.searchRoom(room);\n if (!roomInstance) {\n throw new Error('room not found.');\n }\n roomInstance.start(sender);\n\n return this.emit(\"room-player\", roomInstance);\n }\n\n async closeRoom(sender: IPlayer | null, room: IRoom) {\n const roomIndex = this.rooms.findIndex((r) => r.id === room.id);\n const roomInstance = this.rooms[roomIndex];\n if (!roomInstance) {\n throw new Error('room not found.');\n }\n\n if (sender?.id && !sender.isAdmin) {\n const senderInRoom = roomInstance.searchPlayer(sender);\n if (!senderInRoom || !senderInRoom.isCreator) {\n throw new Error('permission denied.');\n }\n }\n\n room = this.rooms.splice(roomIndex, 1)[0];\n\n this.emit(\"rooms\", this.rooms);\n roomInstance.emit('close');\n return room;\n }\n\n async kickPlayer(sender: IPlayer, data: { roomId: string, playerId: string }) {\n const room = this.searchRoom(data.roomId);\n if (!room) {\n throw new Error('room not found.');\n }\n\n if (!sender.isAdmin) {\n const senderInRoom = room.searchPlayer(sender);\n if (!senderInRoom || !senderInRoom.isCreator) {\n throw new Error('permission denied.');\n }\n }\n\n const targetPlayer = room.players.find(p => p.id === data.playerId);\n if (!targetPlayer) {\n throw new Error('player not found in room.');\n }\n\n const roomPlayer = room.kickPlayer(targetPlayer);\n if (roomPlayer) this.emit(\"room-player\", room);\n return roomPlayer;\n }\n\n async transferOwner(sender: IPlayer, data: { roomId: string, playerId: string }) {\n const room = this.searchRoom(data.roomId);\n if (!room) {\n throw new Error('room not found.');\n }\n\n const creator = room.players.find(p => p.isCreator);\n if (!sender.isAdmin) {\n const senderInRoom = room.searchPlayer(sender);\n if (!senderInRoom || !senderInRoom.isCreator) {\n throw new Error('permission denied.');\n }\n } else {\n\n }\n\n const targetPlayer = room.players.find(p => p.id === data.playerId);\n if (!targetPlayer) {\n throw new Error('player not found in room.');\n }\n\n if (targetPlayer.id === sender.id) {\n return;\n }\n\n if (creator) creator.isCreator = false;\n targetPlayer.isCreator = true;\n\n this.emit(\"room-player\", room);\n return room;\n }\n\n async loginPlayer (player: IPlayerOptions, cb?: (data: { player: Player }) => void) {\n let playerInstance = this.searchPlayer(player);\n if (!playerInstance?.sender) {\n if (!playerInstance) {\n playerInstance = new Player(player);\n this.players.push(playerInstance);\n }\n playerInstance.isAdmin = await this.isAdmin(playerInstance);\n playerInstance.setSender((type, message) => {\n this.send({ type: `player.${type}` as MessageTypes, data: message, sender: playerInstance });\n });\n this.emit(\"player\", playerInstance, true);\n\n const room = this.rooms.find(r => r.players.some(p => p.id === playerInstance!.id));\n if (room) {\n const playerIndex = room.players.findIndex(p => p.id === playerInstance!.id);\n if (playerIndex >= 0) {\n const status = room?.status == RoomStatus.playing ? PlayerStatus.playing : PlayerStatus.online;\n playerInstance.status = status;\n playerInstance.attributes = Object.assign({}, room.players[playerIndex].attributes, playerInstance.attributes);\n Object.assign(room.players[playerIndex], playerInstance);\n room.emit('update', room);\n }\n }\n }\n\n playerInstance.emit(\"status\", playerInstance.status);\n\n cb?.({ player: playerInstance });\n return playerInstance;\n }\n\n async joinPlayer(sender: IPlayer, player: IRoomPlayerOptions, isCreator: boolean = false) {\n let playerInstance = this.searchPlayer(sender);\n if (!playerInstance) {\n playerInstance = await this.loginPlayer(sender);\n }\n\n if (!player.roomId) {\n throw new Error('missing room id.');\n }\n\n const room = this.rooms.find((room) => room.id === player.roomId);\n if (!room) {\n throw new Error('room not found.');\n }\n\n if (!isCreator && !room.players.some(p => p.isCreator)) {\n isCreator = true;\n }\n\n const roomPlayer = room.addPlayer(playerInstance, isCreator);\n if (roomPlayer) {\n this.emit(\"room-player\", room);\n }\n\n return roomPlayer;\n }\n\n async leavePlayer(sender: IPlayer, player: IRoomPlayerOptions) {\n if (!player.roomId) {\n throw new Error('missing room id.');\n }\n\n const room = this.rooms.find((room) => room.id === player.roomId);\n if (!room) {\n throw new Error('room not found.');\n }\n\n const playerInstance = room.searchPlayer(sender);\n if (!playerInstance) {\n throw new Error('player not in room.');\n }\n\n const roomPlayer = room.kickPlayer(playerInstance);\n\n if (roomPlayer) this.emit(\"room-player\", room);\n\n return roomPlayer;\n }\n \n async leaveSeat(sender: IPlayer, player: IRoomPlayerOptions) {\n if (!player.roomId) {\n throw new Error('missing room id.');\n }\n\n const room = this.rooms.find((room) => room.id === player.roomId);\n if (!room) {\n throw new Error('room not found.');\n }\n\n const playerInstance = room.searchPlayer(sender);\n if (!playerInstance) {\n throw new Error('player not in room.');\n }\n\n const roomPlayer = room.leaveSeat(playerInstance);\n if (roomPlayer) this.emit(\"room-player\", room);\n\n return roomPlayer;\n }\n\n async readyPlayer(sender: IPlayer, player: IRoomPlayer) {\n const playerInstance = this.searchPlayer(sender);\n if (!playerInstance) {\n throw new Error('player not found.');\n }\n\n if (!player.roomId) {\n throw new Error('missing room id.');\n }\n\n const room = this.rooms.find((room) => room.id === player.roomId);\n if (!room) {\n throw new Error('room not found.');\n }\n\n const roomPlayer = room.searchPlayer(playerInstance);\n \n if (!roomPlayer) {\n throw new Error('player not in room.');\n }\n\n roomPlayer.isReady = true;\n\n if (room.isReady) {\n room.emit(\"all-ready\", room.players);\n }\n\n playerInstance.status = PlayerStatus.ready;\n\n room.emit(\"player-ready\", { ...player, ...roomPlayer });\n room.emit('update', room);\n\n return this;\n }\n \n async unReadyPlayer(sender: IPlayer, player: IRoomPlayer) {\n const playerInstance = this.searchPlayer(sender);\n if (!playerInstance) {\n throw new Error('player not found.');\n }\n\n if (!player.roomId) {\n throw new Error('missing room id.');\n }\n\n const room = this.rooms.find((room) => room.id === player.roomId);\n if (!room) {\n throw new Error('room not found.');\n }\n\n const roomPlayer = room.searchPlayer(playerInstance);\n \n if (!roomPlayer) {\n throw new Error('player not in room.');\n }\n\n roomPlayer.isReady = false;\n playerInstance.status = PlayerStatus.unready;\n room.emit(\"player-unready\", { ...player, ...roomPlayer });\n room.emit('update', room);\n\n return this;\n }\n\n async removePlayer(sender: IPlayer) {\n const playerIndex = this.players.findIndex((p) => p.id === sender?.id);\n const player = this.players[playerIndex];\n if (playerIndex > -1) {\n this.players.splice(playerIndex, 1)[0];\n this.emit(\"player\", player, false);\n }\n return player;\n }\n\n async offlinePlayer(sender: IPlayer) {\n const room = this.rooms.find((room) => room.players.some(p => p.id === sender?.id));\n if (room) {\n setTimeout(() => {\n const playerInstance = room.players.find(p => p.id === sender.id && p.role === PlayerRole.player);\n if (this.players.some(p => p.id === sender.id) || !playerInstance) \n return; // player is online\n playerInstance.status = PlayerStatus.offline;\n room.emit(\"player-offline\", playerInstance);\n playerInstance.status = PlayerStatus.offline;\n room.emit('update', room);\n }, 60 * 1000); // 1 minute later\n }\n this.removePlayer(sender);\n return sender;\n }\n\n async send(message: IMessagePackage) {\n // send a message to the client\n if (message.type.startsWith('player.') && message.sender) {\n const player = message.sender as Player;\n // Send to all sockets of the player\n this.messageInstance?.send({ \n type: message.type, \n data: message.data, \n senderIds: [player.id]\n });\n }\n else if (message.type.startsWith('room.') && message.sender) {\n const room = message.sender as Room;\n this.messageInstance?.send({ \n type: message.type, \n data: message.data, \n senderIds: room.players.map(p => p.id)\n });\n } else {\n this.messageInstance?.send({ \n type: message.type, \n data: message.data, \n senderIds: this.players.map(p => p.id)\n });\n }\n }\n}\n\nexport * from \"@lib/models/message\";\nexport * from \"@lib/models/room\";\nexport * from \"@lib/models/player\";\nexport * from \"@lib/events\";"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AASA,IAAY,wDAAL;;;;AAIL;;;;AAIA;;;;AAIA;;;;AAIA;;;;AAIA;;;;AAIA;;;;AAIA;;;;AAIA;;;;AAIA;;;;AAIA;;;;AAIA;;;;AAIA;;;;AAIA;;;;AAIA;;;;AAIA;;;;AAIA;;;;AAIA;;;;AAIA;;;;AAIA;;;;AAIA;;;;AAIA;;;;AAIA;;;;AAIA;;;;AAIA;;;;AAIA;;;;AAIA;;;;AAIA;;;;;;;AAOF,IAAY,gEAAL;;;;AAIL;;;;AAIA;;;;AAIA;;;;AAIA;;;;AAIA;;;;AAIA;;;;AAIA;;;;AAIA;;;;AAIA;;;;AAIA;;;;AAIA;;;;AAIA;;;;AAIA;;;;AAIA;;;;AAIA;;;;AAIA;;;;AAIA;;;;;;;;;AC/JF,IAAY,wDAAL;;;;AAIL;;;;AAIA;;;;AAIA;;;;AAIA;;;;AAIA;;;;;;AAgBF,IAAa,SAAb,MAAa,eAAeA,eAAgC;;;;;;;CAO1D,GAAiC,OAAU,UAAiC;AAC1E,SAAO,MAAM,GAAG,OAAO,SAAS;;;;;;;;CASlC,KAAmC,OAAU,GAAG,MAA4C;AAC1F,SAAO,MAAM,KAAK,OAAO,GAAG,KAAK;;CAYnC,YAAY,QAA0C,SAAuB,aAAa,QAAQ;AAChG,SAAO;YAVI;cACE;iBAGI;iBAEa,aAAa;gBACtB,aAAa;AAIlC,SAAO,eAAe,MAAM,UAAU;GACpC,YAAY;GACZ,cAAc;GACd,WAAW,KAAK;GAChB,MAAM,UAAwB;AAC5B,SAAK,UAAU;AACf,SAAK,KAAK,UAAU,MAAM;;GAE7B,CAAC;AACF,OAAK,KAAK,OAAO,uBAAM,IAAI,MAAM,EAAC,SAAS,CAAC,UAAU;AACtD,OAAK,OAAO,OAAO,QAAQ;AAC3B,OAAK,aAAa,OAAO,cAAc,EAAE;AACzC,OAAK,SAAS,OAAO;AAErB,OAAK,UAAU;AACf,MAAI,kBAAkB,OAAQ,MAAK,UAAU,OAAO;AACpD,OAAK,GAAG,WAAW,aAAyB;AAC1C,QAAK,UAAUC;IACf;AAGF,EAD0C;GAAC;GAAW;GAAW;GAAS,CACnE,SAAS,UAAU;AACxB,QAAK,GAAG,QAAQ,GAAG,SAAc;;AAC/B,yBAAK,uEAAS,OAAO,GAAG,KAAK;KAC7B;IACF;;CAGJ,SAAS;AACP,SAAO;GACL,IAAI,KAAK;GACT,MAAM,KAAK;GACX,YAAY,KAAK;GACjB,QAAQ,KAAK;GACb,SAAS,KAAK;GACf;;CAGH,WAAW;AACT,SAAO,KAAK,UAAU,KAAK,QAAQ,CAAC;;;;;;;CAQtC,UAAU,QAAiD;AACzD,OAAK,SAAS;AACd,SAAO;;;;;;;;;ACrHX,IAAY,oDAAL;;;;AAIL;;;;AAIA;;;;AAIA;;;;;;AAMF,IAAY,oDAAL;;;;AAIL;;;;AAIA;;;;AAIA;;;;;;AAgDF,IAAa,aAAb,cAAgC,OAA8B;CAM5D,YAAY,QAA8B,OAAmB,WAAW,QAAQ;AAC9E,QAAM,OAAO;iBANI;cACA,WAAW;mBACT;AAKnB,OAAK,UAAU,OAAO,WAAW;AACjC,OAAK,YAAY,OAAO,aAAa;AACrC,OAAK,SAAS,OAAO,UAAU;AAC/B,OAAK,OAAO,OAAO,QAAQ;AAC3B,OAAK,SAAS,OAAO,UAAU,aAAa;AAC5C,MAAI,kBAAkB,UAAU,OAAO,OAAQ,OAAM,UAAU,OAAO,OAAO;;CAG/E,SAAS;AACP,SAAO;GACL,GAAG,MAAM,QAAQ;GACjB,QAAQ,KAAK;GACb,MAAM,KAAK;GACX,SAAS,KAAK;GACd,WAAW,KAAK;GACjB;;;;;;AAOL,IAAa,OAAb,MAAa,aAAaC,eAA8B;;;;;;;CAOtD,GAA+B,OAAU,UAA+B;AACtE,SAAO,MAAM,GAAG,OAAO,SAAS;;;;;;;;CASlC,KAAiC,OAAU,GAAG,MAA0C;AACtF,SAAO,MAAM,KAAK,OAAO,GAAG,KAAK;;;;;CAanC,IAAI,eAAe;AACjB,SAAO,KAAK,QAAQ,QAAQ,WAAW,OAAO,SAAS,WAAW,OAAO;;;;;CAM3E,IAAI,WAAW;AACb,SAAO,KAAK,QAAQ,QAAQ,WAAW,OAAO,SAAS,WAAW,QAAQ;;;;;CAW5E,IAAI,UAAmB;AACrB,SAAO,KAAK,QAAQ,UAAU,KAAK,WAC9B,KAAK,QAAQ,OAAO,WAAW,OAAO,WAAW,OAAO,SAAS,WAAW,QAAQ;;;;;CAM3F,IAAI,SAAqB;AACvB,MAAI,CAAC,KAAK,QAAS,QAAO,WAAW;AACrC,MAAI,KAAK,QAAQ,WAAW,WAAW,OAAO,WAAW,aAAa,QAAQ,IAAI,GAAI,QAAO,WAAW;AACxG,SAAO,WAAW;;;;;CAMpB,IAAI,YAAqB;AACvB,SAAO,KAAK,WAAW,WAAW;;;;;CAMpC,IAAI,SAAkB;AACpB,SAAO,KAAK,aAAa,UAAU,KAAK;;;;;CAM1C,IAAI,QAAgC;AAElC,SADgB,KAAK,QAAQ,MAAM,WAAW,OAAO,UAAU;;CAIjE,SAAS;AACP,SAAO;GACL,IAAI,KAAK;GACT,MAAM,KAAK;GACX,MAAM,KAAK,QAAQ;GACnB,SAAS,KAAK;GACd,QAAQ,KAAK;GACb,SAAS,KAAK,QAAQ,KAAK,WAAW,OAAO,QAAQ,CAAC;GACtD,OAAO,KAAK;GACb;;CAGH,WAAW;AACT,SAAO,KAAK,UAAU,KAAK,QAAQ,CAAC;;CAGtC,YAAY,MAAoC,UAAwB,EAAE,EAAE;AAC1E,SAAO;cAjFM;cACA;iBACG;iBAEM,EAAE;AA8ExB,MAAI,gBAAgB,MAAM;AACxB,QAAK,UAAU,KAAK;AACpB,QAAK,QAAQ,SAAS,MAAM;AAC1B,MAAE,SAAS,KAAK;KAChB;;AAGJ,OAAK,KAAK,KAAK,uBAAM,IAAI,MAAM,EAAC,SAAS,CAAC,UAAU;AACpD,OAAK,OAAO,KAAK,QAAQ;AACzB,OAAK,OAAO,KAAK,QAAQ;AACzB,OAAK,UAAU,KAAK,WAAW;AAC/B,OAAK,QAAQ,KAAK;AAClB,OAAK,UAAU;AAGf,EADwC;GAAC;GAAW;GAAW;GAAS;GAAO;GAAa;GAAkB;GAAgB;GAAQ;GAAQ,CACvI,SAAS,UAAU;AACxB,QAAK,GAAG,QAAQ,GAAG,SAAc;;AAC/B,yBAAK,uEAAS,OAAO,GAAG,KAAK;KAC7B;IACF;;;;;;;CAQJ,WAAW,QAAgB;EACzB,MAAM,aAAa,KAAK,aAAa,OAAO;AAC5C,MAAI,YAAY;AACd,QAAK,QAAQ,SAAS,MAAM;AAC1B,MAAE,YAAY;KACd;AACF,cAAW,YAAY;AACvB,QAAK,KAAK,UAAU,KAAK;;AAE3B,SAAO;;;;;;;;CAST,UAAU,QAAgB,YAAqB,OAAO;EACpD,IAAI,aAAa,KAAK,aAAa,OAAO;AAC1C,MAAI,YAAY;AACd,OAAI,WAAW,SAAS,WAAW,WAAW,CAAC,KAAK,UAAU,CAAC,KAAK,WAAW;AAC7E,eAAW,OAAO,WAAW;AAC7B,eAAW,YAAY;AACvB,SAAK,KAAK,UAAU,KAAK;;AAE3B,UAAO;;AAGT,MAAI,UACF,MAAK,QAAQ,SAAS,MAAM;AAC1B,KAAE,YAAY;IACd;AAEJ,eAAa,IAAI,WAAW,QAAQ,KAAK,UAAU,KAAK,YAAY,WAAW,UAAU,WAAW,OAAO;AAC3G,aAAW,YAAY;AACvB,aAAW,SAAS,KAAK;AACzB,OAAK,QAAQ,KAAK,WAAW;AAC7B,OAAK,KAAK,QAAQ;GAAE,GAAG,WAAW,QAAQ;GAAE,QAAQ,KAAK;GAAI,CAAC;AAE9D,SAAO;;CAST,UAAU,QAA0B;EAClC,MAAM,WAAW,OAAO,WAAW,WAAW,SAAS,OAAO;EAC9D,MAAM,aAAa,KAAK,aAAa,SAAS;AAC9C,MAAI,cAAc,WAAW,SAAS,WAAW,QAAQ;AACvD,cAAW,OAAO,WAAW;AAC7B,cAAW,UAAU;AACrB,QAAK,KAAK,SAAU;IAAE,GAAG;IAAY,QAAQ,KAAK;IAAI,CAAC;AACvD,OAAI,WAAW,aAAa,KAAK,aAAa,SAAS,GAAG;AACxD,SAAK,aAAa,GAAG,YAAY;AACjC,SAAK,KAAK,UAAU,KAAK;;;AAG7B,SAAO;;CAST,WAAW,QAA0B;EACnC,MAAM,WAAW,OAAO,WAAW,WAAW,SAAS,OAAO;EAC9D,MAAM,QAAQ,KAAK,QAAQ,WAAW,MAAM,EAAE,MAAM,SAAS;EAC7D,MAAM,aAAa,KAAK,QAAQ;AAChC,MAAI,QAAQ,IAAI;AACd,cAAW,SAAS,aAAa;AACjC,QAAK,KAAK,SAAU;IAAE,GAAG;IAAY,QAAQ,KAAK;IAAI,CAAC;AACvD,QAAK,QAAQ,OAAO,OAAO,EAAE;AAC7B,OAAI,WAAW,aAAa,KAAK,QAAQ,SAAS,GAAG;AACnD,SAAK,QAAQ,GAAG,YAAY;AAC5B,SAAK,KAAK,UAAU,KAAK;;;AAG7B,SAAO;;CAST,aAAa,QAA0B;EACrC,MAAM,WAAW,OAAO,WAAW,WAAW,yDAAS,OAAQ;AAC/D,SAAO,KAAK,QAAQ,MAAM,aAAWC,SAAO,MAAM,SAAS;;;;;CAM7D,MAAM,QAAiB;AACrB,MAAI,CAAC,KAAK,QACR,OAAM,IAAI,MAAM,qBAAqB;AAEvC,MAAI,KAAK,WAAW,WAAW,QAC7B,OAAM,IAAI,MAAM,2BAA2B;AAE7C,OAAK,QAAQ,SAAS,WAAW;AAC/B,OAAI,OAAO,QAAQ,WAAW,OAAQ;AACtC,UAAO,SAAS,aAAa;AAC7B,UAAO,KAAK,UAAU,aAAa,QAAQ;IAC3C;AACF,OAAK,KAAK,UAAU,KAAK;AACzB,SAAO,KAAK,KAAK,SAAS,KAAK;;;;;CAMjC,MAAM;AACJ,OAAK,QAAQ,SAAS,WAAW;AAC/B,OAAI,OAAO,QAAQ,WAAW,OAAQ;AACtC,UAAO,SAAS,aAAa;AAC7B,UAAO,KAAK,UAAU,aAAa,QAAQ;IAC3C;AACF,OAAK,KAAK,UAAU,KAAK;AACzB,SAAO,KAAK,KAAK,OAAO,KAAK;;;;;;CAO/B,UAAU,QAAiD;AACzD,OAAK,SAAS;AACd,SAAO;;;;;;AC7YX,IAAa,SAAb,cAA4BC,oBAAa;CAKvC,YAAY,EAAE,UAA0B;AACtC,SAAO;eALO,EAAE;iBACE,EAAE;AAKpB,OAAK,kBAAkB;;;;;;CAOzB,SAAS;AACP,SAAO;GACL,OAAO,KAAK;GACZ,SAAS,KAAK;GACf;;;;;;;CAQH,SAAS,MAA8C;;AACrD,OAAK,wBAAQ,KAAK,iEAAO,KAAK,MAAM,IAAI,KAAK,GAAG,EAAE,QAAQ,CAAC,KAAI,EAAE;AACjE,OAAK,4BAAU,KAAK,uEAAS,KAAK,MAAM,IAAI,OAAO,GAAG,EAAE,OAAO,CAAC,KAAI,EAAE;AACtE,OAAK,MAAM,SAAS,SAAS;AAC3B,QAAK,WAAW,MAAM,SAAS,WAAW;AACxC,SAAK,KAAK;KAAE,MAAM,QAAQ;KAAwB,MAAM;KAAS,QAAQ;KAAM,CAAC;KAChF;IACF;AACF,mBAAiB;AACf,QAAK,MAAM,SAAS,SAAS;AAC3B,SAAK,QAAQ,SAAS,WAAW;AAC/B,SAAI,CAAC,KAAK,QAAQ,MAAM,MAAM,EAAE,OAAO,OAAO,GAAG,CAC/C,MAAK,cAAc,OAAO;MAE5B;KACF;KACD,KAAK,IAAK;AACb,SAAO;;CAGT,GAAiC,OAAU,UAAiC;AAC1E,QAAM,GAAG,OAAO,SAAS;AACzB,SAAO;;CAGT,KAAmC,OAAU,GAAG,MAA4C;AAC1F,SAAO,MAAM,KAAK,OAAO,GAAG,KAAK;;;;;;;CAQnC,MAAM,QAAQ,SAAkB;AAC9B,SAAO;;;;;;;CAQT,MAAM,SAAS,SAAkB;AAC/B,SAAO;;CAGT,MAAM;;AACJ,gCAAK,uFAAiB,GAAG,WAAW,OAAO,SAAc,OAAgD;AACvG,WAAQ,SAAS,QAAQ,SAAS,KAAK,aAAa,QAAQ,OAAO,IAAI,QAAQ,SAAS;AACxF,OAAI;AACF,YAAQ,QAAQ,MAAhB;KACE,KAAK,iBAAiB,SACpB,gDAAO,GAAK,MAAM,KAAK,MAAM;KAC/B,KAAK,iBAAiB,WACpB,gDAAO,GAAK,MAAM,KAAK,QAAQ;KACjC,KAAK,iBAAiB,WACpB,QAAO,MAAM,KAAK,WAAW,QAAQ,QAAQ,QAAQ,KAAK;KAC5D,KAAK,iBAAiB,WACpB,QAAO,MAAM,KAAK,WAAW,QAAQ,QAAQ,QAAQ,KAAK;KAC5D,KAAK,iBAAiB,YACpB,QAAO,MAAM,KAAK,YAAY,QAAQ,QAAQ,QAAQ,KAAK;KAC7D,KAAK,iBAAiB,cACpB,QAAO,MAAM,KAAK,UAAU,QAAQ,QAAQ,QAAQ,KAAK;KAC3D,KAAK,iBAAiB,QACpB,gDAAO,GAAK,MAAM,KAAK,WAAW,QAAQ,KAAK,CAAC;KAClD,KAAK,iBAAiB,UACpB,QAAO,MAAM,KAAK,UAAU,QAAQ,QAAQ,QAAQ,KAAK;KAC3D,KAAK,iBAAiB,SACpB,QAAO,MAAM,KAAK,WAAW,QAAQ,QAAQ,QAAQ,KAAK;KAC5D,KAAK,iBAAiB,aACpB,QAAO,MAAM,KAAK,cAAc,QAAQ,QAAQ,QAAQ,KAAK;KAC/D,KAAK,iBAAiB,UACpB,QAAO,MAAM,KAAK,UAAU,QAAQ,QAAQ,QAAQ,KAAK;KAC3D,KAAK,iBAAiB,YACpB,QAAO,MAAM,KAAK,YAAY,QAAQ,KAAK;KAC7C,KAAK,iBAAiB,aACpB,QAAO,MAAM,KAAK,aAAa,QAAQ,KAAK;KAC9C,KAAK,aAAa,cAChB,QAAO,MAAM,KAAK,cAAc,QAAQ,KAAK;KAC/C,KAAK,iBAAiB,YACpB,QAAO,MAAM,KAAK,YAAY,QAAQ,QAAQ,QAAQ,KAAK;KAC7D,KAAK,iBAAiB,cACpB,QAAO,MAAM,KAAK,cAAc,QAAQ,QAAQ,QAAQ,KAAK;KAC/D,KAAK,iBAAiB;;AACpB,iCAAO,KAAK,WAAW,QAAQ,KAAK,sEAAE,KAAK,kBAAkB;OAAE,GAAG,QAAQ;OAAO,QAAQ,QAAQ;OAAQ,CAAC;KAC5G,KAAK,iBAAiB,cACpB,QAAO,KAAK,KAAK,WAAW;MAAE,GAAG,QAAQ;MAAO,QAAQ,QAAQ;MAAQ,CAAC;KAC3E,QACE,OAAM,IAAI,MAAM,wBAAwB;;YAErC,OAAO;AACd,uCAAK,MAAe;AACpB,QAAI,QAAQ,OAAQ,MAAK,KAAK;KAC5B,MAAM,aAAa;KACnB,MAAM;MACJ,MAAO,MAAgB;MACvB,SAAU,MAAgB;MAC1B,OAAQ,MAAgB;MACzB;KACD,QAAQ,QAAQ;KACjB,CAAC;;IAEJ;AAEF,OAAK,GAAG,WAAW,QAAQ,WAAW;AACpC,QAAK,KAAK;IAAE,MAAM,SAAS,aAAa,cAAc,aAAa;IAAc,MAAM;IAAQ,CAAC;IAChG;AAEF,OAAK,GAAG,YAAY,YAAY;AAC9B,QAAK,KAAK;IAAE,MAAM,aAAa;IAAY,MAAM;IAAS,CAAC;IAC3D;AAEF,OAAK,GAAG,SAAS,SAAS;AACxB,QAAK,KAAK;IAAE,MAAM,aAAa;IAAY,MAAM;IAAM,CAAC;IACxD;AAEF,OAAK,GAAG,gBAAgB,SAAS;AAC/B,QAAK,KAAK;IAAE,MAAM,aAAa;IAAY,MAAM;IAAM,CAAC;IACxD;AAEF,OAAK,GAAG,UAAU,UAAU;AAC1B,QAAK,KAAK;IAAE,MAAM,aAAa;IAAU,MAAM;IAAO,CAAC;IACvD;AAEF,OAAK,GAAG,YAAY,MAAM,WAAW;AACnC,QAAK,KAAK;IAAE,MAAM,aAAa;IAAe;IAAM;IAAQ,CAAC;IAC7D;AAEF,SAAO;;CAMT,aAAa,QAAsD;EACjE,MAAM,WAAW,OAAO,WAAW,WAAW,yDAAS,OAAQ;AAC/D,SAAO,KAAK,QAAQ,MAAM,WAAW,OAAO,OAAO,SAAS;;CAM9D,WAAW,MAAsC;EAC/C,MAAM,SAAS,OAAO,SAAS,WAAW,mDAAO,KAAM;AACvD,SAAO,KAAK,MAAM,MAAM,WAAW,OAAO,OAAO,OAAO;;CAG1D,MAAM,WAAW,QAAiB,SAAuB;AACvD,MAAI,CAAC,OACH,OAAM,IAAI,MAAM,8BAA8B;AAGhD,MAAI,CAAC,QAAQ,KACX,OAAM,IAAI,MAAM,2BAA2B;AAG7C,MADqB,KAAK,WAAW,QAAQ,CAE3C,OAAM,IAAI,MAAM,uBAAuB;AAGzC,MAAI,KAAK,MAAM,MAAK,MAAK,EAAE,QAAQ,MAAK,MAAK,EAAE,wDAAO,OAAQ,IAAG,CAAC,CAChE,OAAM,IAAI,MAAM,6BAA6B;EAG/C,MAAM,OAAO,IAAI,KAAK,QAAQ;AAC9B,OAAK,WAAW,MAAM,SAAS,aAAW;AACxC,QAAK,KAAK;IAAE,MAAM,QAAQ;IAAwB,MAAM;IAAS,QAAQ;IAAM,CAAC;IAChF;AAEF,OAAK,MAAM,KAAK,KAAK;AACrB,OAAK,KAAK,QAAQ,KAAK;AACvB,OAAK,WAAW,QAAQ;GAAE,QAAQ,KAAK;GAAI,GAAG;GAAQ,EAAE,KAAK;AAC7D,SAAO;;CAGT,MAAM,UAAU,QAAiB,MAAa;EAC5C,MAAM,eAAe,KAAK,WAAW,KAAK;AAC1C,MAAI,CAAC,aACH,OAAM,IAAI,MAAM,kBAAkB;AAEpC,eAAa,MAAM,OAAO;AAE1B,SAAO,KAAK,KAAK,eAAe,aAAa;;CAG/C,MAAM,UAAU,QAAwB,MAAa;EACnD,MAAM,YAAY,KAAK,MAAM,WAAW,MAAM,EAAE,OAAO,KAAK,GAAG;EAC/D,MAAM,eAAe,KAAK,MAAM;AAChC,MAAI,CAAC,aACH,OAAM,IAAI,MAAM,kBAAkB;AAGpC,uDAAI,OAAQ,OAAM,CAAC,OAAO,SAAS;GACjC,MAAM,eAAe,aAAa,aAAa,OAAO;AACtD,OAAI,CAAC,gBAAgB,CAAC,aAAa,UACjC,OAAM,IAAI,MAAM,qBAAqB;;AAIzC,SAAO,KAAK,MAAM,OAAO,WAAW,EAAE,CAAC;AAEvC,OAAK,KAAK,SAAS,KAAK,MAAM;AAC9B,eAAa,KAAK,QAAQ;AAC1B,SAAO;;CAGT,MAAM,WAAW,QAAiB,MAA4C;EAC5E,MAAM,OAAO,KAAK,WAAW,KAAK,OAAO;AACzC,MAAI,CAAC,KACH,OAAM,IAAI,MAAM,kBAAkB;AAGpC,MAAI,CAAC,OAAO,SAAS;GACnB,MAAM,eAAe,KAAK,aAAa,OAAO;AAC9C,OAAI,CAAC,gBAAgB,CAAC,aAAa,UACjC,OAAM,IAAI,MAAM,qBAAqB;;EAIzC,MAAM,eAAe,KAAK,QAAQ,MAAK,MAAK,EAAE,OAAO,KAAK,SAAS;AACnE,MAAI,CAAC,aACH,OAAM,IAAI,MAAM,4BAA4B;EAG9C,MAAM,aAAa,KAAK,WAAW,aAAa;AAChD,MAAI,WAAY,MAAK,KAAK,eAAe,KAAK;AAC9C,SAAO;;CAGT,MAAM,cAAc,QAAiB,MAA4C;EAC/E,MAAM,OAAO,KAAK,WAAW,KAAK,OAAO;AACzC,MAAI,CAAC,KACH,OAAM,IAAI,MAAM,kBAAkB;EAGpC,MAAM,UAAU,KAAK,QAAQ,MAAK,MAAK,EAAE,UAAU;AACnD,MAAI,CAAC,OAAO,SAAS;GACnB,MAAM,eAAe,KAAK,aAAa,OAAO;AAC9C,OAAI,CAAC,gBAAgB,CAAC,aAAa,UACjC,OAAM,IAAI,MAAM,qBAAqB;;EAMzC,MAAM,eAAe,KAAK,QAAQ,MAAK,MAAK,EAAE,OAAO,KAAK,SAAS;AACnE,MAAI,CAAC,aACH,OAAM,IAAI,MAAM,4BAA4B;AAG9C,MAAI,aAAa,OAAO,OAAO,GAC7B;AAGF,MAAI,QAAS,SAAQ,YAAY;AACjC,eAAa,YAAY;AAEzB,OAAK,KAAK,eAAe,KAAK;AAC9B,SAAO;;CAGT,MAAM,YAAa,QAAwB,IAAyC;EAClF,IAAI,iBAAiB,KAAK,aAAa,OAAO;AAC9C,MAAI,kEAAC,eAAgB,SAAQ;AAC3B,OAAI,CAAC,gBAAgB;AACnB,qBAAiB,IAAI,OAAO,OAAO;AACnC,SAAK,QAAQ,KAAK,eAAe;;AAEnC,kBAAe,UAAU,MAAM,KAAK,QAAQ,eAAe;AAC3D,kBAAe,WAAW,MAAM,YAAY;AAC1C,SAAK,KAAK;KAAE,MAAM,UAAU;KAAwB,MAAM;KAAS,QAAQ;KAAgB,CAAC;KAC5F;AACF,QAAK,KAAK,UAAU,gBAAgB,KAAK;GAEzC,MAAM,OAAO,KAAK,MAAM,MAAK,MAAK,EAAE,QAAQ,MAAK,MAAK,EAAE,OAAO,eAAgB,GAAG,CAAC;AACnF,OAAI,MAAM;IACR,MAAM,cAAc,KAAK,QAAQ,WAAU,MAAK,EAAE,OAAO,eAAgB,GAAG;AAC5E,QAAI,eAAe,GAAG;AAEpB,oBAAe,sDADA,KAAM,WAAU,WAAW,UAAU,aAAa,UAAU,aAAa;AAExF,oBAAe,aAAa,OAAO,OAAO,EAAE,EAAE,KAAK,QAAQ,aAAa,YAAY,eAAe,WAAW;AAC9G,YAAO,OAAO,KAAK,QAAQ,cAAc,eAAe;AACxD,UAAK,KAAK,UAAU,KAAK;;;;AAK/B,iBAAe,KAAK,UAAU,eAAe,OAAO;AAEpD,qCAAK,EAAE,QAAQ,gBAAgB,CAAC;AAChC,SAAO;;CAGT,MAAM,WAAW,QAAiB,QAA4B,YAAqB,OAAO;EACxF,IAAI,iBAAiB,KAAK,aAAa,OAAO;AAC9C,MAAI,CAAC,eACH,kBAAiB,MAAM,KAAK,YAAY,OAAO;AAGjD,MAAI,CAAC,OAAO,OACV,OAAM,IAAI,MAAM,mBAAmB;EAGrC,MAAM,OAAO,KAAK,MAAM,MAAM,WAASC,OAAK,OAAO,OAAO,OAAO;AACjE,MAAI,CAAC,KACH,OAAM,IAAI,MAAM,kBAAkB;AAGpC,MAAI,CAAC,aAAa,CAAC,KAAK,QAAQ,MAAK,MAAK,EAAE,UAAU,CACpD,aAAY;EAGd,MAAM,aAAa,KAAK,UAAU,gBAAgB,UAAU;AAC5D,MAAI,WACF,MAAK,KAAK,eAAe,KAAK;AAGhC,SAAO;;CAGT,MAAM,YAAY,QAAiB,QAA4B;AAC7D,MAAI,CAAC,OAAO,OACV,OAAM,IAAI,MAAM,mBAAmB;EAGrC,MAAM,OAAO,KAAK,MAAM,MAAM,WAASA,OAAK,OAAO,OAAO,OAAO;AACjE,MAAI,CAAC,KACH,OAAM,IAAI,MAAM,kBAAkB;EAGpC,MAAM,iBAAiB,KAAK,aAAa,OAAO;AAChD,MAAI,CAAC,eACH,OAAM,IAAI,MAAM,sBAAsB;EAGxC,MAAM,aAAa,KAAK,WAAW,eAAe;AAElD,MAAI,WAAY,MAAK,KAAK,eAAe,KAAK;AAE9C,SAAO;;CAGT,MAAM,UAAU,QAAiB,QAA4B;AAC3D,MAAI,CAAC,OAAO,OACV,OAAM,IAAI,MAAM,mBAAmB;EAGrC,MAAM,OAAO,KAAK,MAAM,MAAM,WAASA,OAAK,OAAO,OAAO,OAAO;AACjE,MAAI,CAAC,KACH,OAAM,IAAI,MAAM,kBAAkB;EAGpC,MAAM,iBAAiB,KAAK,aAAa,OAAO;AAChD,MAAI,CAAC,eACH,OAAM,IAAI,MAAM,sBAAsB;EAGxC,MAAM,aAAa,KAAK,UAAU,eAAe;AACjD,MAAI,WAAY,MAAK,KAAK,eAAe,KAAK;AAE9C,SAAO;;CAGT,MAAM,YAAY,QAAiB,QAAqB;EACtD,MAAM,iBAAiB,KAAK,aAAa,OAAO;AAChD,MAAI,CAAC,eACH,OAAM,IAAI,MAAM,oBAAoB;AAGtC,MAAI,CAAC,OAAO,OACV,OAAM,IAAI,MAAM,mBAAmB;EAGrC,MAAM,OAAO,KAAK,MAAM,MAAM,WAASA,OAAK,OAAO,OAAO,OAAO;AACjE,MAAI,CAAC,KACH,OAAM,IAAI,MAAM,kBAAkB;EAGpC,MAAM,aAAa,KAAK,aAAa,eAAe;AAEpD,MAAI,CAAC,WACH,OAAM,IAAI,MAAM,sBAAsB;AAGxC,aAAW,UAAU;AAErB,MAAI,KAAK,QACP,MAAK,KAAK,aAAa,KAAK,QAAQ;AAGtC,iBAAe,SAAS,aAAa;AAErC,OAAK,KAAK,gBAAgB;GAAE,GAAG;GAAQ,GAAG;GAAY,CAAC;AACvD,OAAK,KAAK,UAAU,KAAK;AAEzB,SAAO;;CAGT,MAAM,cAAc,QAAiB,QAAqB;EACxD,MAAM,iBAAiB,KAAK,aAAa,OAAO;AAChD,MAAI,CAAC,eACH,OAAM,IAAI,MAAM,oBAAoB;AAGtC,MAAI,CAAC,OAAO,OACV,OAAM,IAAI,MAAM,mBAAmB;EAGrC,MAAM,OAAO,KAAK,MAAM,MAAM,WAASA,OAAK,OAAO,OAAO,OAAO;AACjE,MAAI,CAAC,KACH,OAAM,IAAI,MAAM,kBAAkB;EAGpC,MAAM,aAAa,KAAK,aAAa,eAAe;AAEpD,MAAI,CAAC,WACH,OAAM,IAAI,MAAM,sBAAsB;AAGxC,aAAW,UAAU;AACrB,iBAAe,SAAS,aAAa;AACrC,OAAK,KAAK,kBAAkB;GAAE,GAAG;GAAQ,GAAG;GAAY,CAAC;AACzD,OAAK,KAAK,UAAU,KAAK;AAEzB,SAAO;;CAGT,MAAM,aAAa,QAAiB;EAClC,MAAM,cAAc,KAAK,QAAQ,WAAW,MAAM,EAAE,wDAAO,OAAQ,IAAG;EACtE,MAAM,SAAS,KAAK,QAAQ;AAC5B,MAAI,cAAc,IAAI;AACpB,QAAK,QAAQ,OAAO,aAAa,EAAE,CAAC;AACpC,QAAK,KAAK,UAAU,QAAQ,MAAM;;AAEpC,SAAO;;CAGT,MAAM,cAAc,QAAiB;EACnC,MAAM,OAAO,KAAK,MAAM,MAAM,WAASA,OAAK,QAAQ,MAAK,MAAK,EAAE,wDAAO,OAAQ,IAAG,CAAC;AACnF,MAAI,KACF,kBAAiB;GACf,MAAM,iBAAiB,KAAK,QAAQ,MAAK,MAAK,EAAE,OAAO,OAAO,MAAM,EAAE,SAAS,WAAW,OAAO;AACjG,OAAI,KAAK,QAAQ,MAAK,MAAK,EAAE,OAAO,OAAO,GAAG,IAAI,CAAC,eACjD;AACF,kBAAe,SAAS,aAAa;AACrC,QAAK,KAAK,kBAAkB,eAAe;AAC3C,kBAAe,SAAS,aAAa;AACrC,QAAK,KAAK,UAAU,KAAK;KACxB,KAAK,IAAK;AAEf,OAAK,aAAa,OAAO;AACzB,SAAO;;CAGT,MAAM,KAAK,SAA0B;AAEnC,MAAI,QAAQ,KAAK,WAAW,UAAU,IAAI,QAAQ,QAAQ;;GACxD,MAAM,SAAS,QAAQ;AAEvB,kCAAK,yFAAiB,KAAK;IACzB,MAAM,QAAQ;IACd,MAAM,QAAQ;IACd,WAAW,CAAC,OAAO,GAAG;IACvB,CAAC;aAEK,QAAQ,KAAK,WAAW,QAAQ,IAAI,QAAQ,QAAQ;;GAC3D,MAAM,OAAO,QAAQ;AACrB,kCAAK,yFAAiB,KAAK;IACzB,MAAM,QAAQ;IACd,MAAM,QAAQ;IACd,WAAW,KAAK,QAAQ,KAAI,MAAK,EAAE,GAAG;IACvC,CAAC;SACG;;AACL,kCAAK,yFAAiB,KAAK;IACzB,MAAM,QAAQ;IACd,MAAM,QAAQ;IACd,WAAW,KAAK,QAAQ,KAAI,MAAK,EAAE,GAAG;IACvC,CAAC"}
package/src/index.d.cts CHANGED
@@ -855,28 +855,28 @@ declare class Tiaoom extends EventEmitter {
855
855
  searchPlayer(player: IPlayerOptions | IRoomPlayerOptions): Player | undefined;
856
856
  searchRoom(room: string): Room | undefined;
857
857
  searchRoom(room: Partial<IRoomOptions>): Room | undefined;
858
- createRoom(sender: IPlayer, options: IRoomOptions): Room;
859
- startRoom(sender: IPlayer, room: IRoom): boolean;
860
- closeRoom(sender: IPlayer | null, room: IRoom): IRoom;
858
+ createRoom(sender: IPlayer, options: IRoomOptions): Promise<Room>;
859
+ startRoom(sender: IPlayer, room: IRoom): Promise<boolean>;
860
+ closeRoom(sender: IPlayer | null, room: IRoom): Promise<IRoom>;
861
861
  kickPlayer(sender: IPlayer, data: {
862
862
  roomId: string;
863
863
  playerId: string;
864
- }): RoomPlayer;
864
+ }): Promise<RoomPlayer>;
865
865
  transferOwner(sender: IPlayer, data: {
866
866
  roomId: string;
867
867
  playerId: string;
868
- }): Room | undefined;
868
+ }): Promise<Room | undefined>;
869
869
  loginPlayer(player: IPlayerOptions, cb?: (data: {
870
870
  player: Player;
871
871
  }) => void): Promise<Player>;
872
872
  joinPlayer(sender: IPlayer, player: IRoomPlayerOptions, isCreator?: boolean): Promise<RoomPlayer>;
873
- leavePlayer(sender: IPlayer, player: IRoomPlayerOptions): RoomPlayer;
874
- leaveSeat(sender: IPlayer, player: IRoomPlayerOptions): RoomPlayer;
875
- readyPlayer(sender: IPlayer, player: IRoomPlayer): this;
876
- unReadyPlayer(sender: IPlayer, player: IRoomPlayer): this;
877
- removePlayer(sender: IPlayer): Player;
878
- offlinePlayer(sender: IPlayer): IPlayer;
879
- send(message: IMessagePackage): void;
873
+ leavePlayer(sender: IPlayer, player: IRoomPlayerOptions): Promise<RoomPlayer>;
874
+ leaveSeat(sender: IPlayer, player: IRoomPlayerOptions): Promise<RoomPlayer>;
875
+ readyPlayer(sender: IPlayer, player: IRoomPlayer): Promise<this>;
876
+ unReadyPlayer(sender: IPlayer, player: IRoomPlayer): Promise<this>;
877
+ removePlayer(sender: IPlayer): Promise<Player>;
878
+ offlinePlayer(sender: IPlayer): Promise<IPlayer>;
879
+ send(message: IMessagePackage): Promise<void>;
880
880
  }
881
881
  //#endregion
882
882
  export { IMessage, IMessageData, IMessageEmitterEvents, IMessageEvents, IMessagePackage, IMessagePackages, IPlayer, IPlayerOptions, IRoom, IRoomOptions, IRoomPlayer, IRoomPlayerOptions, ITiaoomOptions, MessageTypes, Player, PlayerEvents, PlayerRole, PlayerStatus, RecvMessageTypes, Room, RoomEvents, RoomPlayer, RoomStatus, Tiaoom, TiaoomEvents };
package/src/index.d.mts CHANGED
@@ -855,28 +855,28 @@ declare class Tiaoom extends EventEmitter {
855
855
  searchPlayer(player: IPlayerOptions | IRoomPlayerOptions): Player | undefined;
856
856
  searchRoom(room: string): Room | undefined;
857
857
  searchRoom(room: Partial<IRoomOptions>): Room | undefined;
858
- createRoom(sender: IPlayer, options: IRoomOptions): Room;
859
- startRoom(sender: IPlayer, room: IRoom): boolean;
860
- closeRoom(sender: IPlayer | null, room: IRoom): IRoom;
858
+ createRoom(sender: IPlayer, options: IRoomOptions): Promise<Room>;
859
+ startRoom(sender: IPlayer, room: IRoom): Promise<boolean>;
860
+ closeRoom(sender: IPlayer | null, room: IRoom): Promise<IRoom>;
861
861
  kickPlayer(sender: IPlayer, data: {
862
862
  roomId: string;
863
863
  playerId: string;
864
- }): RoomPlayer;
864
+ }): Promise<RoomPlayer>;
865
865
  transferOwner(sender: IPlayer, data: {
866
866
  roomId: string;
867
867
  playerId: string;
868
- }): Room | undefined;
868
+ }): Promise<Room | undefined>;
869
869
  loginPlayer(player: IPlayerOptions, cb?: (data: {
870
870
  player: Player;
871
871
  }) => void): Promise<Player>;
872
872
  joinPlayer(sender: IPlayer, player: IRoomPlayerOptions, isCreator?: boolean): Promise<RoomPlayer>;
873
- leavePlayer(sender: IPlayer, player: IRoomPlayerOptions): RoomPlayer;
874
- leaveSeat(sender: IPlayer, player: IRoomPlayerOptions): RoomPlayer;
875
- readyPlayer(sender: IPlayer, player: IRoomPlayer): this;
876
- unReadyPlayer(sender: IPlayer, player: IRoomPlayer): this;
877
- removePlayer(sender: IPlayer): Player;
878
- offlinePlayer(sender: IPlayer): IPlayer;
879
- send(message: IMessagePackage): void;
873
+ leavePlayer(sender: IPlayer, player: IRoomPlayerOptions): Promise<RoomPlayer>;
874
+ leaveSeat(sender: IPlayer, player: IRoomPlayerOptions): Promise<RoomPlayer>;
875
+ readyPlayer(sender: IPlayer, player: IRoomPlayer): Promise<this>;
876
+ unReadyPlayer(sender: IPlayer, player: IRoomPlayer): Promise<this>;
877
+ removePlayer(sender: IPlayer): Promise<Player>;
878
+ offlinePlayer(sender: IPlayer): Promise<IPlayer>;
879
+ send(message: IMessagePackage): Promise<void>;
880
880
  }
881
881
  //#endregion
882
882
  export { IMessage, IMessageData, IMessageEmitterEvents, IMessageEvents, IMessagePackage, IMessagePackages, IPlayer, IPlayerOptions, IRoom, IRoomOptions, IRoomPlayer, IRoomPlayerOptions, ITiaoomOptions, MessageTypes, Player, PlayerEvents, PlayerRole, PlayerStatus, RecvMessageTypes, Room, RoomEvents, RoomPlayer, RoomStatus, Tiaoom, TiaoomEvents };
package/src/index.mjs CHANGED
@@ -671,26 +671,26 @@ var Tiaoom = class extends EventEmitter {
671
671
  }
672
672
  run() {
673
673
  var _this$messageInstance;
674
- (_this$messageInstance = this.messageInstance) === null || _this$messageInstance === void 0 || _this$messageInstance.on("message", (message, cb) => {
674
+ (_this$messageInstance = this.messageInstance) === null || _this$messageInstance === void 0 || _this$messageInstance.on("message", async (message, cb) => {
675
675
  message.sender = message.sender ? this.searchPlayer(message.sender) || message.sender : null;
676
676
  try {
677
677
  switch (message.type) {
678
678
  case RecvMessageTypes.RoomList: return cb === null || cb === void 0 ? void 0 : cb(null, this.rooms);
679
679
  case RecvMessageTypes.PlayerList: return cb === null || cb === void 0 ? void 0 : cb(null, this.players);
680
- case RecvMessageTypes.RoomCreate: return this.createRoom(message.sender, message.data);
681
- case RecvMessageTypes.PlayerJoin: return this.joinPlayer(message.sender, message.data);
682
- case RecvMessageTypes.PlayerLeave: return this.leavePlayer(message.sender, message.data);
683
- case RecvMessageTypes.PlayerStandUp: return this.leaveSeat(message.sender, message.data);
680
+ case RecvMessageTypes.RoomCreate: return await this.createRoom(message.sender, message.data);
681
+ case RecvMessageTypes.PlayerJoin: return await this.joinPlayer(message.sender, message.data);
682
+ case RecvMessageTypes.PlayerLeave: return await this.leavePlayer(message.sender, message.data);
683
+ case RecvMessageTypes.PlayerStandUp: return await this.leaveSeat(message.sender, message.data);
684
684
  case RecvMessageTypes.RoomGet: return cb === null || cb === void 0 ? void 0 : cb(null, this.searchRoom(message.data));
685
- case RecvMessageTypes.RoomStart: return this.startRoom(message.sender, message.data);
686
- case RecvMessageTypes.RoomKick: return this.kickPlayer(message.sender, message.data);
687
- case RecvMessageTypes.RoomTransfer: return this.transferOwner(message.sender, message.data);
688
- case RecvMessageTypes.RoomClose: return this.closeRoom(message.sender, message.data);
689
- case RecvMessageTypes.PlayerLogin: return this.loginPlayer(message.data);
690
- case RecvMessageTypes.PlayerLogout: return this.removePlayer(message.data);
691
- case MessageTypes.PlayerOffline: return this.offlinePlayer(message.data);
692
- case RecvMessageTypes.PlayerReady: return this.readyPlayer(message.sender, message.data);
693
- case RecvMessageTypes.PlayerUnready: return this.unReadyPlayer(message.sender, message.data);
685
+ case RecvMessageTypes.RoomStart: return await this.startRoom(message.sender, message.data);
686
+ case RecvMessageTypes.RoomKick: return await this.kickPlayer(message.sender, message.data);
687
+ case RecvMessageTypes.RoomTransfer: return await this.transferOwner(message.sender, message.data);
688
+ case RecvMessageTypes.RoomClose: return await this.closeRoom(message.sender, message.data);
689
+ case RecvMessageTypes.PlayerLogin: return await this.loginPlayer(message.data);
690
+ case RecvMessageTypes.PlayerLogout: return await this.removePlayer(message.data);
691
+ case MessageTypes.PlayerOffline: return await this.offlinePlayer(message.data);
692
+ case RecvMessageTypes.PlayerReady: return await this.readyPlayer(message.sender, message.data);
693
+ case RecvMessageTypes.PlayerUnready: return await this.unReadyPlayer(message.sender, message.data);
694
694
  case RecvMessageTypes.RoomPlayerCommand:
695
695
  var _this$searchRoom;
696
696
  return (_this$searchRoom = this.searchRoom(message.data)) === null || _this$searchRoom === void 0 ? void 0 : _this$searchRoom.emit("player-command", {
@@ -763,7 +763,7 @@ var Tiaoom = class extends EventEmitter {
763
763
  const roomId = typeof room === "string" ? room : room === null || room === void 0 ? void 0 : room.id;
764
764
  return this.rooms.find((target) => target.id === roomId);
765
765
  }
766
- createRoom(sender, options) {
766
+ async createRoom(sender, options) {
767
767
  if (!sender) throw new Error("missing player information.");
768
768
  if (!options.name) throw new Error("missing room id or name.");
769
769
  if (this.searchRoom(options)) throw new Error("room already exists.");
@@ -784,13 +784,13 @@ var Tiaoom = class extends EventEmitter {
784
784
  }, true);
785
785
  return room;
786
786
  }
787
- startRoom(sender, room) {
787
+ async startRoom(sender, room) {
788
788
  const roomInstance = this.searchRoom(room);
789
789
  if (!roomInstance) throw new Error("room not found.");
790
790
  roomInstance.start(sender);
791
791
  return this.emit("room-player", roomInstance);
792
792
  }
793
- closeRoom(sender, room) {
793
+ async closeRoom(sender, room) {
794
794
  const roomIndex = this.rooms.findIndex((r) => r.id === room.id);
795
795
  const roomInstance = this.rooms[roomIndex];
796
796
  if (!roomInstance) throw new Error("room not found.");
@@ -803,7 +803,7 @@ var Tiaoom = class extends EventEmitter {
803
803
  roomInstance.emit("close");
804
804
  return room;
805
805
  }
806
- kickPlayer(sender, data) {
806
+ async kickPlayer(sender, data) {
807
807
  const room = this.searchRoom(data.roomId);
808
808
  if (!room) throw new Error("room not found.");
809
809
  if (!sender.isAdmin) {
@@ -816,7 +816,7 @@ var Tiaoom = class extends EventEmitter {
816
816
  if (roomPlayer) this.emit("room-player", room);
817
817
  return roomPlayer;
818
818
  }
819
- transferOwner(sender, data) {
819
+ async transferOwner(sender, data) {
820
820
  const room = this.searchRoom(data.roomId);
821
821
  if (!room) throw new Error("room not found.");
822
822
  const creator = room.players.find((p) => p.isCreator);
@@ -874,7 +874,7 @@ var Tiaoom = class extends EventEmitter {
874
874
  if (roomPlayer) this.emit("room-player", room);
875
875
  return roomPlayer;
876
876
  }
877
- leavePlayer(sender, player) {
877
+ async leavePlayer(sender, player) {
878
878
  if (!player.roomId) throw new Error("missing room id.");
879
879
  const room = this.rooms.find((room$1) => room$1.id === player.roomId);
880
880
  if (!room) throw new Error("room not found.");
@@ -884,7 +884,7 @@ var Tiaoom = class extends EventEmitter {
884
884
  if (roomPlayer) this.emit("room-player", room);
885
885
  return roomPlayer;
886
886
  }
887
- leaveSeat(sender, player) {
887
+ async leaveSeat(sender, player) {
888
888
  if (!player.roomId) throw new Error("missing room id.");
889
889
  const room = this.rooms.find((room$1) => room$1.id === player.roomId);
890
890
  if (!room) throw new Error("room not found.");
@@ -894,7 +894,7 @@ var Tiaoom = class extends EventEmitter {
894
894
  if (roomPlayer) this.emit("room-player", room);
895
895
  return roomPlayer;
896
896
  }
897
- readyPlayer(sender, player) {
897
+ async readyPlayer(sender, player) {
898
898
  const playerInstance = this.searchPlayer(sender);
899
899
  if (!playerInstance) throw new Error("player not found.");
900
900
  if (!player.roomId) throw new Error("missing room id.");
@@ -912,7 +912,7 @@ var Tiaoom = class extends EventEmitter {
912
912
  room.emit("update", room);
913
913
  return this;
914
914
  }
915
- unReadyPlayer(sender, player) {
915
+ async unReadyPlayer(sender, player) {
916
916
  const playerInstance = this.searchPlayer(sender);
917
917
  if (!playerInstance) throw new Error("player not found.");
918
918
  if (!player.roomId) throw new Error("missing room id.");
@@ -929,7 +929,7 @@ var Tiaoom = class extends EventEmitter {
929
929
  room.emit("update", room);
930
930
  return this;
931
931
  }
932
- removePlayer(sender) {
932
+ async removePlayer(sender) {
933
933
  const playerIndex = this.players.findIndex((p) => p.id === (sender === null || sender === void 0 ? void 0 : sender.id));
934
934
  const player = this.players[playerIndex];
935
935
  if (playerIndex > -1) {
@@ -938,7 +938,7 @@ var Tiaoom = class extends EventEmitter {
938
938
  }
939
939
  return player;
940
940
  }
941
- offlinePlayer(sender) {
941
+ async offlinePlayer(sender) {
942
942
  const room = this.rooms.find((room$1) => room$1.players.some((p) => p.id === (sender === null || sender === void 0 ? void 0 : sender.id)));
943
943
  if (room) setTimeout(() => {
944
944
  const playerInstance = room.players.find((p) => p.id === sender.id && p.role === PlayerRole.player);
@@ -951,7 +951,7 @@ var Tiaoom = class extends EventEmitter {
951
951
  this.removePlayer(sender);
952
952
  return sender;
953
953
  }
954
- send(message) {
954
+ async send(message) {
955
955
  if (message.type.startsWith("player.") && message.sender) {
956
956
  var _this$messageInstance2;
957
957
  const player = message.sender;
package/src/index.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["EventEmitter","status","EventEmitter","player","room"],"sources":["../lib/models/message.ts","../lib/models/player.ts","../lib/models/room.ts","../lib/index.ts"],"sourcesContent":["import EventEmitter from \"events\";\nimport { IPlayer, IPlayerOptions } from \"./player\";\nimport { IRoom, IRoomPlayer, IRoomOptions } from \"./room\";\nimport { IMessageEmitterEvents, IMessageEvents } from \"@lib/events/message\";\n\n/**\n * 消息包类型枚举\n * player: 'command', 'message', 'join', 'leave', 'status'\n */\nexport enum MessageTypes {\n /**\n * 连接准备就绪事件\n */\n SysReady = \"sys.ready\",\n /**\n * 连接关闭事件\n */\n SysClose = \"sys.close\",\n /**\n * 错误事件\n */\n SysError = \"sys.error\",\n /**\n * 全局错误\n */\n GlobalError = \"global.error\",\n /**\n * 房间列表\n */\n RoomList = \"room.list\",\n /**\n * 房间创建\n */\n RoomCreate = \"room.create\",\n /**\n * 房间更新\n */\n RoomUpdate = \"room.update\",\n /**\n * 房间开始\n */\n RoomStart = \"room.start\",\n /**\n * 房间结束\n */\n RoomEnd = \"room.end\",\n /**\n * 房间关闭\n */\n RoomClose = \"room.close\",\n /**\n * 房间全部玩家已准备\n */\n RoomAllReady = \"room.all-ready\",\n /**\n * 房间命令\n */\n RoomCommand = \"room.command\",\n /**\n * 房间内玩家发送的指令\n */\n RoomPlayerCommand = \"room.player-command\",\n /**\n * 房间消息\n */\n RoomMessage = \"room.message\",\n /**\n * 玩家加入房间\n */\n RoomJoin = \"room.join\",\n /**\n * 玩家离开房间\n */\n RoomLeave = \"room.leave\",\n /**\n * 房间玩家准备\n */\n RoomPlayerReady = \"room.player-ready\",\n /**\n * 房间玩家取消准备\n */\n RoomPlayerUnready = \"room.player-unready\",\n /**\n * 玩家列表\n */\n PlayerList = \"player.list\",\n /**\n * 玩家登录\n */\n PlayerLogin = \"player.login\",\n /**\n * 玩家登出\n */\n PlayerLogout = \"player.logout\",\n /**\n * 玩家离线\n */\n PlayerOffline = \"player.offline\",\n /**\n * *玩家消息\n */\n PlayerMessage = \"player.message\",\n /**\n * *玩家命令\n */\n PlayerCommand = \"player.command\",\n /**\n * 玩家错误信息\n */\n PlayerError = \"player.error\",\n /**\n * 全局消息\n */\n GlobalMessage = \"global.message\",\n /**\n * 全局命令\n */\n GlobalCommand = \"global.command\",\n}\n\n/**\n * 客户端发送消息包类型枚举\n * player: 'command', 'message', 'join', 'leave', 'status'\n */\nexport enum RecvMessageTypes {\n /**\n * 房间列表\n */\n RoomList = \"room.list\",\n /**\n * 玩家列表\n */\n PlayerList = \"player.list\",\n /**\n * 房间创建\n */\n RoomCreate = \"room.create\",\n /**\n * 玩家加入房间\n */\n PlayerJoin = \"player.join\",\n /**\n * 玩家离开房间\n */\n PlayerLeave = \"player.leave\",\n /**\n * 玩家离开座位\n */\n PlayerStandUp = \"player.standup\",\n /**\n * 房间获取\n */\n RoomGet = \"room.get\",\n /**\n * 房间开始\n */\n RoomStart = \"room.start\",\n /**\n * 房间踢出玩家\n */\n RoomKick = \"room.kick\",\n /**\n * 房间转移\n */\n RoomTransfer = \"room.transfer\",\n /**\n * 房间关闭\n */\n RoomClose = \"room.close\", \n /**\n * 玩家登录\n */\n PlayerLogin = \"player.login\",\n /**\n * 玩家登出\n */\n PlayerLogout = \"player.logout\",\n /**\n * 玩家准备\n */\n PlayerReady = \"player.ready\",\n /**\n * 玩家取消准备\n */\n PlayerUnready = \"player.unready\",\n /**\n * 房间内玩家发送的指令\n */\n RoomPlayerCommand = \"room.player-command\",\n /**\n * 全局命令\n */\n GlobalCommand = \"global.command\",\n}\n\n/**\n * 消息包接口\n */\nexport interface IMessagePackage {\n /**\n * 消息类型\n */\n type: MessageTypes;\n /**\n * 消息数据\n */\n data?: IPlayerOptions | IRoomOptions | IPlayer | IRoom | IRoomPlayer | any\n /**\n * 发送者信息\n */\n sender?: IPlayer | IRoomPlayer | IRoom;\n}\n\n/**\n * 批量消息包\n */\nexport interface IMessagePackages {\n /**\n * 消息类型\n */\n type: MessageTypes;\n /**\n * 消息数据\n */\n data?: IPlayerOptions | IRoomOptions | IPlayer | IRoom | IRoomPlayer | any\n /**\n * 发送者 Id 数组\n */\n senderIds: string[];\n}\n\n/**\n * 消息数据接口,包含发送者信息\n */\nexport interface IMessageData extends IMessagePackage {\n sender: IPlayer | IRoomPlayer | IRoom;\n}\n\n/**\n * 消息通信接口\n */\nexport interface IMessage extends EventEmitter<IMessageEmitterEvents> {\n /**\n * 监听消息事件\n * @param event 事件名,具体见 MessageEvents\n * @param listener 监听器\n */\n on<K extends keyof IMessageEvents>(event: K, listener: IMessageEvents[K]): this;\n /**\n * 触发消息事件\n * @param event 事件名,具体见 MessageEvents\n * @param args 参数\n */\n emit<K extends keyof IMessageEvents>(event: K, ...args: Parameters<IMessageEvents[K]>): boolean;\n /**\n * 关闭连接\n */\n close(): void;\n /**\n * 发送消息包\n * @param message 消息包\n */\n send(message: IMessagePackages): void;\n}\n","import { PlayerEvents } from \"@lib/events/player\";\nimport EventEmitter from \"events\";\nimport { P } from \"tsdown/index-BQZ2CZuJ\";\n\n/**\n * 玩家选项接口\n */\nexport interface IPlayerOptions {\n /**\n * 玩家ID\n */\n id: string;\n /**\n * 玩家名称\n */\n name: string;\n /**\n * 玩家属性\n */\n attributes?: any;\n /**\n * 发送者函数\n */\n sender?: (type: string, ...message: any) => void;\n /**\n * 是否超级管理员\n */\n isAdmin?: boolean;\n}\n\n/**\n * 玩家状态枚举\n */\nexport enum PlayerStatus {\n /**\n * 已准备\n */\n ready = 'ready',\n /**\n * 未准备\n */\n unready = 'unready',\n /**\n * 在线\n */\n online = 'online',\n /**\n * 游戏中\n */\n playing = 'playing',\n /**\n * 离线\n */\n offline = 'offline',\n}\n\n/**\n * 玩家接口\n */\nexport interface IPlayer extends IPlayerOptions {\n /**\n * 玩家状态\n */\n status: PlayerStatus;\n}\n\n/**\n * 玩家\n */\nexport class Player extends EventEmitter implements IPlayer {\n /**\n * 监听玩家事件\n * @param event 事件名,具体见 PlayEvents\n * @param listener 监听器\n * @returns this\n */\n on<K extends keyof PlayerEvents>(event: K, listener: PlayerEvents[K]): this {\n return super.on(event, listener);\n }\n\n /**\n * 触发玩家事件\n * @param event 事件名,具体见 PlayEvents\n * @param args 参数\n * @returns 是否有监听器被触发\n */\n emit<K extends keyof PlayerEvents>(event: K, ...args: Parameters<PlayerEvents[K]>): boolean {\n return super.emit(event, ...args);\n }\n \n id: string = \"\";\n name: string = \"\";\n attributes?: any;\n sender?: (type: string, ...message: any) => void;\n isAdmin: boolean = false;\n\n private _status: PlayerStatus = PlayerStatus.online;\n status: PlayerStatus = PlayerStatus.online;\n\n constructor(player: Partial<IPlayerOptions> | Player, status: PlayerStatus = PlayerStatus.online) {\n super();\n Object.defineProperty(this, 'status', {\n enumerable: true,\n configurable: true,\n get: () => this._status,\n set: (value: PlayerStatus) => {\n this._status = value;\n this.emit('status', value);\n }\n });\n this.id = player.id || new Date().getTime().toString();\n this.name = player.name || \"\";\n this.attributes = player.attributes || {};\n this.sender = player.sender;\n\n this._status = status;\n if (player instanceof Player) this._status = player.status;\n this.on('status', (status: PlayerStatus) => {\n this._status = status;\n });\n \n const events: Array<keyof PlayerEvents> = ['command', 'message', 'status'];\n events.forEach((event) => {\n this.on(event, (...data: any) => {\n this.sender?.(event, ...data);\n });\n }); \n }\n\n toJSON() {\n return {\n id: this.id,\n name: this.name,\n attributes: this.attributes,\n status: this.status,\n isAdmin: this.isAdmin,\n };\n }\n\n toString() {\n return JSON.stringify(this.toJSON());\n }\n\n /**\n * 设置发送者函数\n * @param {(type: string, ...message: any) => void} sender 发送者函数\n * @returns this\n */\n setSender(sender: (type: string, ...message: any) => void) {\n this.sender = sender;\n return this;\n }\n}","import { IPlayer, Player, IPlayerOptions, PlayerStatus } from \"./player\";\nimport EventEmitter from \"events\";\nimport { RoomEvents } from \"@lib/events\";\n\n/**\n * 房间选项接口\n */\nexport interface IRoomOptions {\n /**\n * 房间号\n */\n id: string, \n /**\n * 房间名称\n */\n name: string,\n /**\n * 房间容量\n */\n size: number, \n /**\n * 最小容量\n */\n minSize: number,\n /**\n * 其他属性\n */\n attrs?: Record<string, any>,\n}\n\n/**\n * 房间玩家角色\n */\nexport enum PlayerRole {\n /**\n * 玩家\n */\n player = 'player',\n /**\n * 观众\n */\n watcher = 'watcher',\n /**\n * 管理员\n */\n admin = 'admin',\n}\n\n/**\n * 房间状态\n */\nexport enum RoomStatus {\n /**\n * 等待中\n */\n waiting = 'waiting',\n /**\n * 已准备\n */\n ready = 'ready',\n /**\n * 游戏中\n */\n playing = 'playing',\n}\n\n/**\n * 房间接口\n */\nexport interface IRoom extends IRoomOptions {\n /**\n * 房间玩家列表\n */\n players: RoomPlayer[];\n}\n\n/**\n * 房间玩家选项接口\n */\nexport interface IRoomPlayerOptions extends IPlayerOptions {\n /**\n * 房间Id\n */\n roomId?: string;\n}\n\n/**\n * 房间玩家接口\n */\nexport interface IRoomPlayer extends IRoomPlayerOptions, IPlayer {\n /**\n * 是否已准备\n */\n isReady: boolean;\n /**\n * 玩家角色\n */\n role: PlayerRole;\n /**\n * 是否为房主\n */\n isCreator: boolean;\n /**\n * 房间 Id\n */\n roomId: string;\n}\n\n/**\n * 房间玩家\n */\nexport class RoomPlayer extends Player implements IRoomPlayer {\n isReady: boolean = false;\n role: PlayerRole = PlayerRole.player;\n isCreator: boolean = false;\n roomId: string;\n\n constructor(player: Partial<IRoomPlayer>, role: PlayerRole = PlayerRole.player) {\n super(player);\n this.isReady = player.isReady || false;\n this.isCreator = player.isCreator || false;\n this.roomId = player.roomId || '';\n this.role = player.role || role;\n this.status = player.status || PlayerStatus.online;\n if (player instanceof Player && player.sender) super.setSender(player.sender);\n }\n\n toJSON() {\n return {\n ...super.toJSON(),\n status: this.status,\n role: this.role,\n isReady: this.isReady,\n isCreator: this.isCreator,\n };\n }\n}\n\n/**\n * 房间\n */\nexport class Room extends EventEmitter implements IRoom {\n /**\n * 监听房间事件\n * @param event 事件名,具体见 RoomEvents\n * @param listener 监听器\n * @returns this\n */\n on<K extends keyof RoomEvents>(event: K, listener: RoomEvents[K]): this {\n return super.on(event, listener);\n }\n\n /**\n * 触发房间事件\n * @param event 事件名,具体见 RoomEvents\n * @param args 参数\n * @returns 是否有监听器被触发\n */\n emit<K extends keyof RoomEvents>(event: K, ...args: Parameters<RoomEvents[K]>): boolean {\n return super.emit(event, ...args);\n }\n\n id: string;\n size: number = 10;\n name: string = '';\n minSize: number = 2;\n attrs?: Record<string, any>;\n players: RoomPlayer[] = [];\n\n /**\n * 有效玩家列表(非观众)\n */\n get validPlayers() {\n return this.players.filter((player) => player.role === PlayerRole.player);\n }\n\n /**\n * 观众列表\n */\n get watchers() {\n return this.players.filter((player) => player.role === PlayerRole.watcher);\n }\n\n /**\n * 消息发送器\n */\n private sender?: (type: string, ...message: any) => void;\n\n /**\n * 房间玩家是否已准备好\n */\n get isReady(): boolean {\n return this.players.length >= this.minSize\n && this.players.every((target) => target.isReady || target.role === PlayerRole.watcher); // is all player ready\n }\n\n /**\n * 房间状态\n */\n get status(): RoomStatus {\n if (!this.isReady) return RoomStatus.waiting;\n if (this.players.findIndex((target) => target.status === PlayerStatus.playing) != -1) return RoomStatus.playing;\n return RoomStatus.ready;\n }\n\n /**\n * 房间是否在游戏中\n */\n get isPlaying(): boolean {\n return this.status === RoomStatus.playing;\n }\n\n /**\n * 房间是否已满\n */\n get isFull(): boolean {\n return this.validPlayers.length == this.size;\n }\n\n /**\n * 房主\n */\n get owner(): RoomPlayer | undefined {\n const creator = this.players.find((player) => player.isCreator);\n return creator;\n }\n\n toJSON() {\n return {\n id: this.id,\n name: this.name,\n size: this.size || 10,\n minSize: this.minSize,\n status: this.status,\n players: this.players.map((player) => player.toJSON()),\n attrs: this.attrs,\n }\n }\n\n toString() {\n return JSON.stringify(this.toJSON());\n }\n\n constructor(room: Partial<IRoomOptions> | Room, players: RoomPlayer[] = []) {\n super();\n if (room instanceof Room) {\n this.players = room.players;\n this.players.forEach((p) => {\n p.roomId = room.id;\n });\n }\n\n this.id = room.id || new Date().getTime().toString();\n this.name = room.name || '';\n this.size = room.size || 10;\n this.minSize = room.minSize || 2;\n this.attrs = room.attrs;\n this.players = players;\n \n const events: Array<keyof RoomEvents> = ['message', 'command', 'start', 'end', 'all-ready', 'player-unready', 'player-ready', 'join', 'leave'];\n events.forEach((event) => {\n this.on(event, (...data: any) => {\n this.sender?.(event, ...data);\n });\n });\n }\n\n /**\n * 设置房主\n * @param {Player} player 玩家\n * @returns this\n */\n setCreator(player: Player) {\n const roomPlayer = this.searchPlayer(player);\n if (roomPlayer) {\n this.players.forEach((p) => {\n p.isCreator = false;\n });\n roomPlayer.isCreator = true;\n this.emit(\"update\", this);\n }\n return this;\n }\n\n /**\n * 添加玩家\n * @param {Player} player 玩家\n * @param {boolean} isCreator 是否房主\n * @returns 玩家实例 \n */\n addPlayer(player: Player, isCreator: boolean = false) {\n let roomPlayer = this.searchPlayer(player);\n if (roomPlayer) {\n if (roomPlayer.role === PlayerRole.watcher && !this.isFull && !this.isPlaying) {\n roomPlayer.role = PlayerRole.player;\n roomPlayer.isCreator = isCreator;\n this.emit(\"update\", this);\n }\n return roomPlayer;\n }\n\n if (isCreator) {\n this.players.forEach((p) => {\n p.isCreator = false;\n });\n }\n roomPlayer = new RoomPlayer(player, this.isFull || this.isPlaying ? PlayerRole.watcher : PlayerRole.player);\n roomPlayer.isCreator = isCreator;\n roomPlayer.roomId = this.id;\n this.players.push(roomPlayer);\n this.emit(\"join\", { ...roomPlayer.toJSON(), roomId: this.id });\n \n return roomPlayer;\n }\n\n /**\n * 离开座位\n * @param {string | IPlayer} player 玩家 / 玩家 id\n */\n leaveSeat(playerId: string): RoomPlayer;\n leaveSeat(player: IPlayer): RoomPlayer;\n leaveSeat(player: IPlayer | string) {\n const playerId = typeof player === \"string\" ? player : player.id;\n const roomPlayer = this.searchPlayer(playerId);\n if (roomPlayer && roomPlayer.role === PlayerRole.player) {\n roomPlayer.role = PlayerRole.watcher;\n roomPlayer.isReady = false;\n this.emit(\"leave\", { ...roomPlayer, roomId: this.id });\n if (roomPlayer.isCreator && this.validPlayers.length > 0) {\n this.validPlayers[0].isCreator = true;\n this.emit(\"update\", this);\n }\n }\n return roomPlayer!;\n }\n\n /**\n * 踢出玩家\n * @param {string | IPlayer} player 玩家 / 玩家 id\n */\n kickPlayer(playerId: string): RoomPlayer;\n kickPlayer(player: IPlayer): RoomPlayer;\n kickPlayer(player: IPlayer | string) {\n const playerId = typeof player === \"string\" ? player : player.id;\n const index = this.players.findIndex((p) => p.id == playerId);\n const roomPlayer = this.players[index];\n if (index > -1) {\n roomPlayer.status = PlayerStatus.online;\n this.emit(\"leave\", { ...roomPlayer, roomId: this.id });\n this.players.splice(index, 1);\n if (roomPlayer.isCreator && this.players.length > 0) {\n this.players[0].isCreator = true;\n this.emit(\"update\", this);\n }\n }\n return roomPlayer;\n }\n\n /**\n * 搜索玩家\n * @param {string | IPlayer} player 玩家 / 玩家 id\n */\n searchPlayer(playerId: string): RoomPlayer | undefined;\n searchPlayer(player: IPlayer): RoomPlayer | undefined;\n searchPlayer(player: string | IPlayer) {\n const playerId = typeof player === \"string\" ? player : player?.id;\n return this.players.find((player) => player.id == playerId);\n }\n\n /**\n * 开始游戏\n */\n start(sender: IPlayer) {\n if (!this.isReady) {\n throw new Error('room is not ready.');\n }\n if (this.status === RoomStatus.playing) {\n throw new Error('room is already started.');\n }\n this.players.forEach((player) => {\n if (player.role != PlayerRole.player) return;\n player.status = PlayerStatus.playing;\n player.emit('status', PlayerStatus.playing);\n });\n this.emit(\"update\", this);\n return this.emit(\"start\", this);\n }\n\n /**\n * 结束游戏\n */\n end() {\n this.players.forEach((player) => {\n if (player.role != PlayerRole.player) return;\n player.status = PlayerStatus.unready;\n player.emit('status', PlayerStatus.unready);\n });\n this.emit(\"update\", this);\n return this.emit(\"end\", this);\n }\n\n /**\n * 设置消息发送器\n * @param sender 消息发送器\n */\n setSender(sender: (type: string, ...message: any) => void) {\n this.sender = sender;\n return this;\n }\n}\n","import { EventEmitter } from \"events\";\nimport { TiaoomEvents } from \"@lib/events\";\nimport { IMessage, RecvMessageTypes, MessageTypes, IMessagePackage } from \"@lib/models/message\";\nimport { IRoom, IRoomPlayer, Room, IRoomOptions, IRoomPlayerOptions, RoomStatus, PlayerRole } from \"@lib/models/room\";\nimport { IPlayer, Player, IPlayerOptions, PlayerStatus } from \"@lib/models/player\";\n\nexport interface ITiaoomOptions {\n socket: IMessage;\n}\n\nexport class Tiaoom extends EventEmitter {\n rooms: Room[] = []; // room list\n players: Player[] = []; // player list\n messageInstance?: IMessage;\n\n constructor({ socket }: ITiaoomOptions) {\n super();\n this.messageInstance = socket;\n }\n\n /**\n * 导出 JSON 数据\n * @returns 房间与玩家数据\n */\n toJSON() {\n return {\n rooms: this.rooms,\n players: this.players,\n };\n }\n\n /**\n * 从数据加载\n * @param data 房间与玩家数据\n * @returns this\n */\n loadFrom(data: { rooms?: Room[]; players?: Player[] }) {\n this.rooms = data.rooms?.map((r) => new Room(r, r.players)) ?? [];\n this.players = data.players?.map((p) => new Player(p, p.status)) ?? [];\n this.rooms.forEach((room) => {\n room.setSender((type, message, sender) => {\n this.send({ type: `room.${type}` as MessageTypes, data: message, sender: room });\n })\n })\n setTimeout(() => {\n this.rooms.forEach((room) => {\n room.players.forEach((player) => {\n if (!this.players.some((p) => p.id === player.id)) {\n this.offlinePlayer(player);\n }\n })\n })\n }, 60 * 1000);\n return this;\n }\n\n on<K extends keyof TiaoomEvents>(event: K, listener: TiaoomEvents[K]): this {\n super.on(event, listener);\n return this\n }\n\n emit<K extends keyof TiaoomEvents>(event: K, ...args: Parameters<TiaoomEvents[K]>): boolean {\n return super.emit(event, ...args);\n }\n\n /**\n * 判断玩家是否为管理员\n * @param player 玩家信息\n * @returns 是否为管理员\n */\n async isAdmin(_player: IPlayer) {\n return false;\n }\n\n /**\n * 判断玩家是否被封禁\n * @param _player 玩家信息\n * @returns 是否被封禁\n */\n async isBanned(_player: IPlayer) {\n return false;\n }\n\n run() {\n this.messageInstance?.on(\"message\", (message: any, cb?: (err: Error | null, data?: any) => any) => {\n message.sender = message.sender ? this.searchPlayer(message.sender) || message.sender : null;\n try {\n switch (message.type) {\n case RecvMessageTypes.RoomList:\n return cb?.(null, this.rooms);\n case RecvMessageTypes.PlayerList:\n return cb?.(null, this.players);\n case RecvMessageTypes.RoomCreate:\n return this.createRoom(message.sender, message.data);\n case RecvMessageTypes.PlayerJoin:\n return this.joinPlayer(message.sender, message.data);\n case RecvMessageTypes.PlayerLeave:\n return this.leavePlayer(message.sender, message.data);\n case RecvMessageTypes.PlayerStandUp:\n return this.leaveSeat(message.sender, message.data);\n case RecvMessageTypes.RoomGet:\n return cb?.(null, this.searchRoom(message.data));\n case RecvMessageTypes.RoomStart:\n return this.startRoom(message.sender, message.data);\n case RecvMessageTypes.RoomKick:\n return this.kickPlayer(message.sender, message.data);\n case RecvMessageTypes.RoomTransfer:\n return this.transferOwner(message.sender, message.data);\n case RecvMessageTypes.RoomClose:\n return this.closeRoom(message.sender, message.data);\n case RecvMessageTypes.PlayerLogin:\n return this.loginPlayer(message.data);\n case RecvMessageTypes.PlayerLogout:\n return this.removePlayer(message.data);\n case MessageTypes.PlayerOffline:\n return this.offlinePlayer(message.data);\n case RecvMessageTypes.PlayerReady:\n return this.readyPlayer(message.sender, message.data);\n case RecvMessageTypes.PlayerUnready:\n return this.unReadyPlayer(message.sender, message.data);\n case RecvMessageTypes.RoomPlayerCommand:\n return this.searchRoom(message.data)?.emit(\"player-command\", { ...message.data , sender: message.sender });\n case RecvMessageTypes.GlobalCommand:\n return this.emit(\"command\", { ...message.data , sender: message.sender });\n default:\n throw new Error('unknown message type.');\n }\n } catch (error) {\n cb?.(error as Error);\n if (message.sender) this.send({\n type: MessageTypes.PlayerError,\n data: {\n name: (error as Error).name, \n message: (error as Error).message,\n stack: (error as Error).stack,\n },\n sender: message.sender,\n });\n }\n });\n\n this.on('player', (player, online) => {\n this.send({ type: online ? MessageTypes.PlayerLogin : MessageTypes.PlayerLogout, data: player });\n });\n\n this.on('players', (players) => {\n this.send({ type: MessageTypes.PlayerList, data: players });\n });\n\n this.on('room', (room) => {\n this.send({ type: MessageTypes.RoomCreate, data: room });\n });\n\n this.on('room-player', (room) => {\n this.send({ type: MessageTypes.RoomUpdate, data: room });\n });\n\n this.on('rooms', (rooms) => {\n this.send({ type: MessageTypes.RoomList, data: rooms });\n });\n\n this.on('message', (data, sender) => {\n this.send({ type: MessageTypes.GlobalMessage, data, sender });\n });\n\n return this;\n }\n\n searchPlayer(player: string): Player | undefined;\n searchPlayer(player: IPlayerOptions | IRoomPlayerOptions): Player | undefined;\n\n searchPlayer(player: IPlayerOptions | IRoomPlayerOptions | string) {\n const playerId = typeof player === \"string\" ? player : player?.id;\n return this.players.find((target) => target.id === playerId);\n }\n\n searchRoom(room: string): Room | undefined;\n searchRoom(room: Partial<IRoomOptions>): Room | undefined;\n\n searchRoom(room: Partial<IRoomOptions> | string) {\n const roomId = typeof room === \"string\" ? room : room?.id;\n return this.rooms.find((target) => target.id === roomId);\n }\n\n createRoom(sender: IPlayer, options: IRoomOptions) {\n if (!sender) {\n throw new Error('missing player information.');\n }\n\n if (!options.name) {\n throw new Error('missing room id or name.');\n }\n const roomInstance = this.searchRoom(options);\n if (roomInstance) {\n throw new Error('room already exists.');\n }\n\n if (this.rooms.some(r => r.players.some(p => p.id === sender?.id))) {\n throw new Error('you are already in a room.');\n }\n\n const room = new Room(options);\n room.setSender((type, message, sender) => {\n this.send({ type: `room.${type}` as MessageTypes, data: message, sender: room });\n });\n \n this.rooms.push(room);\n this.emit(\"room\", room);\n this.joinPlayer(sender, { roomId: room.id, ...sender }, true);\n return room;\n }\n\n startRoom(sender: IPlayer, room: IRoom) {\n const roomInstance = this.searchRoom(room);\n if (!roomInstance) {\n throw new Error('room not found.');\n }\n roomInstance.start(sender);\n\n return this.emit(\"room-player\", roomInstance);\n }\n\n closeRoom(sender: IPlayer | null, room: IRoom) {\n const roomIndex = this.rooms.findIndex((r) => r.id === room.id);\n const roomInstance = this.rooms[roomIndex];\n if (!roomInstance) {\n throw new Error('room not found.');\n }\n\n if (sender?.id && !sender.isAdmin) {\n const senderInRoom = roomInstance.searchPlayer(sender);\n if (!senderInRoom || !senderInRoom.isCreator) {\n throw new Error('permission denied.');\n }\n }\n\n room = this.rooms.splice(roomIndex, 1)[0];\n\n this.emit(\"rooms\", this.rooms);\n roomInstance.emit('close');\n return room;\n }\n\n kickPlayer(sender: IPlayer, data: { roomId: string, playerId: string }) {\n const room = this.searchRoom(data.roomId);\n if (!room) {\n throw new Error('room not found.');\n }\n\n if (!sender.isAdmin) {\n const senderInRoom = room.searchPlayer(sender);\n if (!senderInRoom || !senderInRoom.isCreator) {\n throw new Error('permission denied.');\n }\n }\n\n const targetPlayer = room.players.find(p => p.id === data.playerId);\n if (!targetPlayer) {\n throw new Error('player not found in room.');\n }\n\n const roomPlayer = room.kickPlayer(targetPlayer);\n if (roomPlayer) this.emit(\"room-player\", room);\n return roomPlayer;\n }\n\n transferOwner(sender: IPlayer, data: { roomId: string, playerId: string }) {\n const room = this.searchRoom(data.roomId);\n if (!room) {\n throw new Error('room not found.');\n }\n\n const creator = room.players.find(p => p.isCreator);\n if (!sender.isAdmin) {\n const senderInRoom = room.searchPlayer(sender);\n if (!senderInRoom || !senderInRoom.isCreator) {\n throw new Error('permission denied.');\n }\n } else {\n\n }\n\n const targetPlayer = room.players.find(p => p.id === data.playerId);\n if (!targetPlayer) {\n throw new Error('player not found in room.');\n }\n\n if (targetPlayer.id === sender.id) {\n return;\n }\n\n if (creator) creator.isCreator = false;\n targetPlayer.isCreator = true;\n\n this.emit(\"room-player\", room);\n return room;\n }\n\n async loginPlayer (player: IPlayerOptions, cb?: (data: { player: Player }) => void) {\n let playerInstance = this.searchPlayer(player);\n if (!playerInstance?.sender) {\n if (!playerInstance) {\n playerInstance = new Player(player);\n this.players.push(playerInstance);\n }\n playerInstance.isAdmin = await this.isAdmin(playerInstance);\n playerInstance.setSender((type, message) => {\n this.send({ type: `player.${type}` as MessageTypes, data: message, sender: playerInstance });\n });\n this.emit(\"player\", playerInstance, true);\n\n const room = this.rooms.find(r => r.players.some(p => p.id === playerInstance!.id));\n if (room) {\n const playerIndex = room.players.findIndex(p => p.id === playerInstance!.id);\n if (playerIndex >= 0) {\n const status = room?.status == RoomStatus.playing ? PlayerStatus.playing : PlayerStatus.online;\n playerInstance.status = status;\n playerInstance.attributes = Object.assign({}, room.players[playerIndex].attributes, playerInstance.attributes);\n Object.assign(room.players[playerIndex], playerInstance);\n room.emit('update', room);\n }\n }\n }\n\n playerInstance.emit(\"status\", playerInstance.status);\n\n cb?.({ player: playerInstance });\n return playerInstance;\n }\n\n async joinPlayer(sender: IPlayer, player: IRoomPlayerOptions, isCreator: boolean = false) {\n let playerInstance = this.searchPlayer(sender);\n if (!playerInstance) {\n playerInstance = await this.loginPlayer(sender);\n }\n\n if (!player.roomId) {\n throw new Error('missing room id.');\n }\n\n const room = this.rooms.find((room) => room.id === player.roomId);\n if (!room) {\n throw new Error('room not found.');\n }\n\n if (!isCreator && !room.players.some(p => p.isCreator)) {\n isCreator = true;\n }\n\n const roomPlayer = room.addPlayer(playerInstance, isCreator);\n if (roomPlayer) {\n this.emit(\"room-player\", room);\n }\n\n return roomPlayer;\n }\n\n leavePlayer(sender: IPlayer, player: IRoomPlayerOptions) {\n if (!player.roomId) {\n throw new Error('missing room id.');\n }\n\n const room = this.rooms.find((room) => room.id === player.roomId);\n if (!room) {\n throw new Error('room not found.');\n }\n\n const playerInstance = room.searchPlayer(sender);\n if (!playerInstance) {\n throw new Error('player not in room.');\n }\n\n const roomPlayer = room.kickPlayer(playerInstance);\n\n if (roomPlayer) this.emit(\"room-player\", room);\n\n return roomPlayer;\n }\n \n leaveSeat(sender: IPlayer, player: IRoomPlayerOptions) {\n if (!player.roomId) {\n throw new Error('missing room id.');\n }\n\n const room = this.rooms.find((room) => room.id === player.roomId);\n if (!room) {\n throw new Error('room not found.');\n }\n\n const playerInstance = room.searchPlayer(sender);\n if (!playerInstance) {\n throw new Error('player not in room.');\n }\n\n const roomPlayer = room.leaveSeat(playerInstance);\n if (roomPlayer) this.emit(\"room-player\", room);\n\n return roomPlayer;\n }\n\n readyPlayer(sender: IPlayer, player: IRoomPlayer) {\n const playerInstance = this.searchPlayer(sender);\n if (!playerInstance) {\n throw new Error('player not found.');\n }\n\n if (!player.roomId) {\n throw new Error('missing room id.');\n }\n\n const room = this.rooms.find((room) => room.id === player.roomId);\n if (!room) {\n throw new Error('room not found.');\n }\n\n const roomPlayer = room.searchPlayer(playerInstance);\n \n if (!roomPlayer) {\n throw new Error('player not in room.');\n }\n\n roomPlayer.isReady = true;\n\n if (room.isReady) {\n room.emit(\"all-ready\", room.players);\n }\n\n playerInstance.status = PlayerStatus.ready;\n\n room.emit(\"player-ready\", { ...player, ...roomPlayer });\n room.emit('update', room);\n\n return this;\n }\n \n unReadyPlayer(sender: IPlayer, player: IRoomPlayer) {\n const playerInstance = this.searchPlayer(sender);\n if (!playerInstance) {\n throw new Error('player not found.');\n }\n\n if (!player.roomId) {\n throw new Error('missing room id.');\n }\n\n const room = this.rooms.find((room) => room.id === player.roomId);\n if (!room) {\n throw new Error('room not found.');\n }\n\n const roomPlayer = room.searchPlayer(playerInstance);\n \n if (!roomPlayer) {\n throw new Error('player not in room.');\n }\n\n roomPlayer.isReady = false;\n playerInstance.status = PlayerStatus.unready;\n room.emit(\"player-unready\", { ...player, ...roomPlayer });\n room.emit('update', room);\n\n return this;\n }\n\n removePlayer(sender: IPlayer) {\n const playerIndex = this.players.findIndex((p) => p.id === sender?.id);\n const player = this.players[playerIndex];\n if (playerIndex > -1) {\n this.players.splice(playerIndex, 1)[0];\n this.emit(\"player\", player, false);\n }\n return player;\n }\n\n offlinePlayer(sender: IPlayer) {\n const room = this.rooms.find((room) => room.players.some(p => p.id === sender?.id));\n if (room) {\n setTimeout(() => {\n const playerInstance = room.players.find(p => p.id === sender.id && p.role === PlayerRole.player);\n if (this.players.some(p => p.id === sender.id) || !playerInstance) \n return; // player is online\n playerInstance.status = PlayerStatus.offline;\n room.emit(\"player-offline\", playerInstance);\n playerInstance.status = PlayerStatus.offline;\n room.emit('update', room);\n }, 60 * 1000); // 1 minute later\n }\n this.removePlayer(sender);\n return sender;\n }\n\n send(message: IMessagePackage) {\n // send a message to the client\n if (message.type.startsWith('player.') && message.sender) {\n const player = message.sender as Player;\n // Send to all sockets of the player\n this.messageInstance?.send({ \n type: message.type, \n data: message.data, \n senderIds: [player.id]\n });\n }\n else if (message.type.startsWith('room.') && message.sender) {\n const room = message.sender as Room;\n this.messageInstance?.send({ \n type: message.type, \n data: message.data, \n senderIds: room.players.map(p => p.id)\n });\n } else {\n this.messageInstance?.send({ \n type: message.type, \n data: message.data, \n senderIds: this.players.map(p => p.id)\n });\n }\n }\n}\n\nexport * from \"@lib/models/message\";\nexport * from \"@lib/models/room\";\nexport * from \"@lib/models/player\";\nexport * from \"@lib/events\";"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["EventEmitter","status","EventEmitter","player","room"],"sources":["../lib/models/message.ts","../lib/models/player.ts","../lib/models/room.ts","../lib/index.ts"],"sourcesContent":["import EventEmitter from \"events\";\nimport { IPlayer, IPlayerOptions } from \"./player\";\nimport { IRoom, IRoomPlayer, IRoomOptions } from \"./room\";\nimport { IMessageEmitterEvents, IMessageEvents } from \"@lib/events/message\";\n\n/**\n * 消息包类型枚举\n * player: 'command', 'message', 'join', 'leave', 'status'\n */\nexport enum MessageTypes {\n /**\n * 连接准备就绪事件\n */\n SysReady = \"sys.ready\",\n /**\n * 连接关闭事件\n */\n SysClose = \"sys.close\",\n /**\n * 错误事件\n */\n SysError = \"sys.error\",\n /**\n * 全局错误\n */\n GlobalError = \"global.error\",\n /**\n * 房间列表\n */\n RoomList = \"room.list\",\n /**\n * 房间创建\n */\n RoomCreate = \"room.create\",\n /**\n * 房间更新\n */\n RoomUpdate = \"room.update\",\n /**\n * 房间开始\n */\n RoomStart = \"room.start\",\n /**\n * 房间结束\n */\n RoomEnd = \"room.end\",\n /**\n * 房间关闭\n */\n RoomClose = \"room.close\",\n /**\n * 房间全部玩家已准备\n */\n RoomAllReady = \"room.all-ready\",\n /**\n * 房间命令\n */\n RoomCommand = \"room.command\",\n /**\n * 房间内玩家发送的指令\n */\n RoomPlayerCommand = \"room.player-command\",\n /**\n * 房间消息\n */\n RoomMessage = \"room.message\",\n /**\n * 玩家加入房间\n */\n RoomJoin = \"room.join\",\n /**\n * 玩家离开房间\n */\n RoomLeave = \"room.leave\",\n /**\n * 房间玩家准备\n */\n RoomPlayerReady = \"room.player-ready\",\n /**\n * 房间玩家取消准备\n */\n RoomPlayerUnready = \"room.player-unready\",\n /**\n * 玩家列表\n */\n PlayerList = \"player.list\",\n /**\n * 玩家登录\n */\n PlayerLogin = \"player.login\",\n /**\n * 玩家登出\n */\n PlayerLogout = \"player.logout\",\n /**\n * 玩家离线\n */\n PlayerOffline = \"player.offline\",\n /**\n * *玩家消息\n */\n PlayerMessage = \"player.message\",\n /**\n * *玩家命令\n */\n PlayerCommand = \"player.command\",\n /**\n * 玩家错误信息\n */\n PlayerError = \"player.error\",\n /**\n * 全局消息\n */\n GlobalMessage = \"global.message\",\n /**\n * 全局命令\n */\n GlobalCommand = \"global.command\",\n}\n\n/**\n * 客户端发送消息包类型枚举\n * player: 'command', 'message', 'join', 'leave', 'status'\n */\nexport enum RecvMessageTypes {\n /**\n * 房间列表\n */\n RoomList = \"room.list\",\n /**\n * 玩家列表\n */\n PlayerList = \"player.list\",\n /**\n * 房间创建\n */\n RoomCreate = \"room.create\",\n /**\n * 玩家加入房间\n */\n PlayerJoin = \"player.join\",\n /**\n * 玩家离开房间\n */\n PlayerLeave = \"player.leave\",\n /**\n * 玩家离开座位\n */\n PlayerStandUp = \"player.standup\",\n /**\n * 房间获取\n */\n RoomGet = \"room.get\",\n /**\n * 房间开始\n */\n RoomStart = \"room.start\",\n /**\n * 房间踢出玩家\n */\n RoomKick = \"room.kick\",\n /**\n * 房间转移\n */\n RoomTransfer = \"room.transfer\",\n /**\n * 房间关闭\n */\n RoomClose = \"room.close\", \n /**\n * 玩家登录\n */\n PlayerLogin = \"player.login\",\n /**\n * 玩家登出\n */\n PlayerLogout = \"player.logout\",\n /**\n * 玩家准备\n */\n PlayerReady = \"player.ready\",\n /**\n * 玩家取消准备\n */\n PlayerUnready = \"player.unready\",\n /**\n * 房间内玩家发送的指令\n */\n RoomPlayerCommand = \"room.player-command\",\n /**\n * 全局命令\n */\n GlobalCommand = \"global.command\",\n}\n\n/**\n * 消息包接口\n */\nexport interface IMessagePackage {\n /**\n * 消息类型\n */\n type: MessageTypes;\n /**\n * 消息数据\n */\n data?: IPlayerOptions | IRoomOptions | IPlayer | IRoom | IRoomPlayer | any\n /**\n * 发送者信息\n */\n sender?: IPlayer | IRoomPlayer | IRoom;\n}\n\n/**\n * 批量消息包\n */\nexport interface IMessagePackages {\n /**\n * 消息类型\n */\n type: MessageTypes;\n /**\n * 消息数据\n */\n data?: IPlayerOptions | IRoomOptions | IPlayer | IRoom | IRoomPlayer | any\n /**\n * 发送者 Id 数组\n */\n senderIds: string[];\n}\n\n/**\n * 消息数据接口,包含发送者信息\n */\nexport interface IMessageData extends IMessagePackage {\n sender: IPlayer | IRoomPlayer | IRoom;\n}\n\n/**\n * 消息通信接口\n */\nexport interface IMessage extends EventEmitter<IMessageEmitterEvents> {\n /**\n * 监听消息事件\n * @param event 事件名,具体见 MessageEvents\n * @param listener 监听器\n */\n on<K extends keyof IMessageEvents>(event: K, listener: IMessageEvents[K]): this;\n /**\n * 触发消息事件\n * @param event 事件名,具体见 MessageEvents\n * @param args 参数\n */\n emit<K extends keyof IMessageEvents>(event: K, ...args: Parameters<IMessageEvents[K]>): boolean;\n /**\n * 关闭连接\n */\n close(): void;\n /**\n * 发送消息包\n * @param message 消息包\n */\n send(message: IMessagePackages): void;\n}\n","import { PlayerEvents } from \"@lib/events/player\";\nimport EventEmitter from \"events\";\nimport { P } from \"tsdown/index-BQZ2CZuJ\";\n\n/**\n * 玩家选项接口\n */\nexport interface IPlayerOptions {\n /**\n * 玩家ID\n */\n id: string;\n /**\n * 玩家名称\n */\n name: string;\n /**\n * 玩家属性\n */\n attributes?: any;\n /**\n * 发送者函数\n */\n sender?: (type: string, ...message: any) => void;\n /**\n * 是否超级管理员\n */\n isAdmin?: boolean;\n}\n\n/**\n * 玩家状态枚举\n */\nexport enum PlayerStatus {\n /**\n * 已准备\n */\n ready = 'ready',\n /**\n * 未准备\n */\n unready = 'unready',\n /**\n * 在线\n */\n online = 'online',\n /**\n * 游戏中\n */\n playing = 'playing',\n /**\n * 离线\n */\n offline = 'offline',\n}\n\n/**\n * 玩家接口\n */\nexport interface IPlayer extends IPlayerOptions {\n /**\n * 玩家状态\n */\n status: PlayerStatus;\n}\n\n/**\n * 玩家\n */\nexport class Player extends EventEmitter implements IPlayer {\n /**\n * 监听玩家事件\n * @param event 事件名,具体见 PlayEvents\n * @param listener 监听器\n * @returns this\n */\n on<K extends keyof PlayerEvents>(event: K, listener: PlayerEvents[K]): this {\n return super.on(event, listener);\n }\n\n /**\n * 触发玩家事件\n * @param event 事件名,具体见 PlayEvents\n * @param args 参数\n * @returns 是否有监听器被触发\n */\n emit<K extends keyof PlayerEvents>(event: K, ...args: Parameters<PlayerEvents[K]>): boolean {\n return super.emit(event, ...args);\n }\n \n id: string = \"\";\n name: string = \"\";\n attributes?: any;\n sender?: (type: string, ...message: any) => void;\n isAdmin: boolean = false;\n\n private _status: PlayerStatus = PlayerStatus.online;\n status: PlayerStatus = PlayerStatus.online;\n\n constructor(player: Partial<IPlayerOptions> | Player, status: PlayerStatus = PlayerStatus.online) {\n super();\n Object.defineProperty(this, 'status', {\n enumerable: true,\n configurable: true,\n get: () => this._status,\n set: (value: PlayerStatus) => {\n this._status = value;\n this.emit('status', value);\n }\n });\n this.id = player.id || new Date().getTime().toString();\n this.name = player.name || \"\";\n this.attributes = player.attributes || {};\n this.sender = player.sender;\n\n this._status = status;\n if (player instanceof Player) this._status = player.status;\n this.on('status', (status: PlayerStatus) => {\n this._status = status;\n });\n \n const events: Array<keyof PlayerEvents> = ['command', 'message', 'status'];\n events.forEach((event) => {\n this.on(event, (...data: any) => {\n this.sender?.(event, ...data);\n });\n }); \n }\n\n toJSON() {\n return {\n id: this.id,\n name: this.name,\n attributes: this.attributes,\n status: this.status,\n isAdmin: this.isAdmin,\n };\n }\n\n toString() {\n return JSON.stringify(this.toJSON());\n }\n\n /**\n * 设置发送者函数\n * @param {(type: string, ...message: any) => void} sender 发送者函数\n * @returns this\n */\n setSender(sender: (type: string, ...message: any) => void) {\n this.sender = sender;\n return this;\n }\n}","import { IPlayer, Player, IPlayerOptions, PlayerStatus } from \"./player\";\nimport EventEmitter from \"events\";\nimport { RoomEvents } from \"@lib/events\";\n\n/**\n * 房间选项接口\n */\nexport interface IRoomOptions {\n /**\n * 房间号\n */\n id: string, \n /**\n * 房间名称\n */\n name: string,\n /**\n * 房间容量\n */\n size: number, \n /**\n * 最小容量\n */\n minSize: number,\n /**\n * 其他属性\n */\n attrs?: Record<string, any>,\n}\n\n/**\n * 房间玩家角色\n */\nexport enum PlayerRole {\n /**\n * 玩家\n */\n player = 'player',\n /**\n * 观众\n */\n watcher = 'watcher',\n /**\n * 管理员\n */\n admin = 'admin',\n}\n\n/**\n * 房间状态\n */\nexport enum RoomStatus {\n /**\n * 等待中\n */\n waiting = 'waiting',\n /**\n * 已准备\n */\n ready = 'ready',\n /**\n * 游戏中\n */\n playing = 'playing',\n}\n\n/**\n * 房间接口\n */\nexport interface IRoom extends IRoomOptions {\n /**\n * 房间玩家列表\n */\n players: RoomPlayer[];\n}\n\n/**\n * 房间玩家选项接口\n */\nexport interface IRoomPlayerOptions extends IPlayerOptions {\n /**\n * 房间Id\n */\n roomId?: string;\n}\n\n/**\n * 房间玩家接口\n */\nexport interface IRoomPlayer extends IRoomPlayerOptions, IPlayer {\n /**\n * 是否已准备\n */\n isReady: boolean;\n /**\n * 玩家角色\n */\n role: PlayerRole;\n /**\n * 是否为房主\n */\n isCreator: boolean;\n /**\n * 房间 Id\n */\n roomId: string;\n}\n\n/**\n * 房间玩家\n */\nexport class RoomPlayer extends Player implements IRoomPlayer {\n isReady: boolean = false;\n role: PlayerRole = PlayerRole.player;\n isCreator: boolean = false;\n roomId: string;\n\n constructor(player: Partial<IRoomPlayer>, role: PlayerRole = PlayerRole.player) {\n super(player);\n this.isReady = player.isReady || false;\n this.isCreator = player.isCreator || false;\n this.roomId = player.roomId || '';\n this.role = player.role || role;\n this.status = player.status || PlayerStatus.online;\n if (player instanceof Player && player.sender) super.setSender(player.sender);\n }\n\n toJSON() {\n return {\n ...super.toJSON(),\n status: this.status,\n role: this.role,\n isReady: this.isReady,\n isCreator: this.isCreator,\n };\n }\n}\n\n/**\n * 房间\n */\nexport class Room extends EventEmitter implements IRoom {\n /**\n * 监听房间事件\n * @param event 事件名,具体见 RoomEvents\n * @param listener 监听器\n * @returns this\n */\n on<K extends keyof RoomEvents>(event: K, listener: RoomEvents[K]): this {\n return super.on(event, listener);\n }\n\n /**\n * 触发房间事件\n * @param event 事件名,具体见 RoomEvents\n * @param args 参数\n * @returns 是否有监听器被触发\n */\n emit<K extends keyof RoomEvents>(event: K, ...args: Parameters<RoomEvents[K]>): boolean {\n return super.emit(event, ...args);\n }\n\n id: string;\n size: number = 10;\n name: string = '';\n minSize: number = 2;\n attrs?: Record<string, any>;\n players: RoomPlayer[] = [];\n\n /**\n * 有效玩家列表(非观众)\n */\n get validPlayers() {\n return this.players.filter((player) => player.role === PlayerRole.player);\n }\n\n /**\n * 观众列表\n */\n get watchers() {\n return this.players.filter((player) => player.role === PlayerRole.watcher);\n }\n\n /**\n * 消息发送器\n */\n private sender?: (type: string, ...message: any) => void;\n\n /**\n * 房间玩家是否已准备好\n */\n get isReady(): boolean {\n return this.players.length >= this.minSize\n && this.players.every((target) => target.isReady || target.role === PlayerRole.watcher); // is all player ready\n }\n\n /**\n * 房间状态\n */\n get status(): RoomStatus {\n if (!this.isReady) return RoomStatus.waiting;\n if (this.players.findIndex((target) => target.status === PlayerStatus.playing) != -1) return RoomStatus.playing;\n return RoomStatus.ready;\n }\n\n /**\n * 房间是否在游戏中\n */\n get isPlaying(): boolean {\n return this.status === RoomStatus.playing;\n }\n\n /**\n * 房间是否已满\n */\n get isFull(): boolean {\n return this.validPlayers.length == this.size;\n }\n\n /**\n * 房主\n */\n get owner(): RoomPlayer | undefined {\n const creator = this.players.find((player) => player.isCreator);\n return creator;\n }\n\n toJSON() {\n return {\n id: this.id,\n name: this.name,\n size: this.size || 10,\n minSize: this.minSize,\n status: this.status,\n players: this.players.map((player) => player.toJSON()),\n attrs: this.attrs,\n }\n }\n\n toString() {\n return JSON.stringify(this.toJSON());\n }\n\n constructor(room: Partial<IRoomOptions> | Room, players: RoomPlayer[] = []) {\n super();\n if (room instanceof Room) {\n this.players = room.players;\n this.players.forEach((p) => {\n p.roomId = room.id;\n });\n }\n\n this.id = room.id || new Date().getTime().toString();\n this.name = room.name || '';\n this.size = room.size || 10;\n this.minSize = room.minSize || 2;\n this.attrs = room.attrs;\n this.players = players;\n \n const events: Array<keyof RoomEvents> = ['message', 'command', 'start', 'end', 'all-ready', 'player-unready', 'player-ready', 'join', 'leave'];\n events.forEach((event) => {\n this.on(event, (...data: any) => {\n this.sender?.(event, ...data);\n });\n });\n }\n\n /**\n * 设置房主\n * @param {Player} player 玩家\n * @returns this\n */\n setCreator(player: Player) {\n const roomPlayer = this.searchPlayer(player);\n if (roomPlayer) {\n this.players.forEach((p) => {\n p.isCreator = false;\n });\n roomPlayer.isCreator = true;\n this.emit(\"update\", this);\n }\n return this;\n }\n\n /**\n * 添加玩家\n * @param {Player} player 玩家\n * @param {boolean} isCreator 是否房主\n * @returns 玩家实例 \n */\n addPlayer(player: Player, isCreator: boolean = false) {\n let roomPlayer = this.searchPlayer(player);\n if (roomPlayer) {\n if (roomPlayer.role === PlayerRole.watcher && !this.isFull && !this.isPlaying) {\n roomPlayer.role = PlayerRole.player;\n roomPlayer.isCreator = isCreator;\n this.emit(\"update\", this);\n }\n return roomPlayer;\n }\n\n if (isCreator) {\n this.players.forEach((p) => {\n p.isCreator = false;\n });\n }\n roomPlayer = new RoomPlayer(player, this.isFull || this.isPlaying ? PlayerRole.watcher : PlayerRole.player);\n roomPlayer.isCreator = isCreator;\n roomPlayer.roomId = this.id;\n this.players.push(roomPlayer);\n this.emit(\"join\", { ...roomPlayer.toJSON(), roomId: this.id });\n \n return roomPlayer;\n }\n\n /**\n * 离开座位\n * @param {string | IPlayer} player 玩家 / 玩家 id\n */\n leaveSeat(playerId: string): RoomPlayer;\n leaveSeat(player: IPlayer): RoomPlayer;\n leaveSeat(player: IPlayer | string) {\n const playerId = typeof player === \"string\" ? player : player.id;\n const roomPlayer = this.searchPlayer(playerId);\n if (roomPlayer && roomPlayer.role === PlayerRole.player) {\n roomPlayer.role = PlayerRole.watcher;\n roomPlayer.isReady = false;\n this.emit(\"leave\", { ...roomPlayer, roomId: this.id });\n if (roomPlayer.isCreator && this.validPlayers.length > 0) {\n this.validPlayers[0].isCreator = true;\n this.emit(\"update\", this);\n }\n }\n return roomPlayer!;\n }\n\n /**\n * 踢出玩家\n * @param {string | IPlayer} player 玩家 / 玩家 id\n */\n kickPlayer(playerId: string): RoomPlayer;\n kickPlayer(player: IPlayer): RoomPlayer;\n kickPlayer(player: IPlayer | string) {\n const playerId = typeof player === \"string\" ? player : player.id;\n const index = this.players.findIndex((p) => p.id == playerId);\n const roomPlayer = this.players[index];\n if (index > -1) {\n roomPlayer.status = PlayerStatus.online;\n this.emit(\"leave\", { ...roomPlayer, roomId: this.id });\n this.players.splice(index, 1);\n if (roomPlayer.isCreator && this.players.length > 0) {\n this.players[0].isCreator = true;\n this.emit(\"update\", this);\n }\n }\n return roomPlayer;\n }\n\n /**\n * 搜索玩家\n * @param {string | IPlayer} player 玩家 / 玩家 id\n */\n searchPlayer(playerId: string): RoomPlayer | undefined;\n searchPlayer(player: IPlayer): RoomPlayer | undefined;\n searchPlayer(player: string | IPlayer) {\n const playerId = typeof player === \"string\" ? player : player?.id;\n return this.players.find((player) => player.id == playerId);\n }\n\n /**\n * 开始游戏\n */\n start(sender: IPlayer) {\n if (!this.isReady) {\n throw new Error('room is not ready.');\n }\n if (this.status === RoomStatus.playing) {\n throw new Error('room is already started.');\n }\n this.players.forEach((player) => {\n if (player.role != PlayerRole.player) return;\n player.status = PlayerStatus.playing;\n player.emit('status', PlayerStatus.playing);\n });\n this.emit(\"update\", this);\n return this.emit(\"start\", this);\n }\n\n /**\n * 结束游戏\n */\n end() {\n this.players.forEach((player) => {\n if (player.role != PlayerRole.player) return;\n player.status = PlayerStatus.unready;\n player.emit('status', PlayerStatus.unready);\n });\n this.emit(\"update\", this);\n return this.emit(\"end\", this);\n }\n\n /**\n * 设置消息发送器\n * @param sender 消息发送器\n */\n setSender(sender: (type: string, ...message: any) => void) {\n this.sender = sender;\n return this;\n }\n}\n","import { EventEmitter } from \"events\";\nimport { TiaoomEvents } from \"@lib/events\";\nimport { IMessage, RecvMessageTypes, MessageTypes, IMessagePackage } from \"@lib/models/message\";\nimport { IRoom, IRoomPlayer, Room, IRoomOptions, IRoomPlayerOptions, RoomStatus, PlayerRole } from \"@lib/models/room\";\nimport { IPlayer, Player, IPlayerOptions, PlayerStatus } from \"@lib/models/player\";\n\nexport interface ITiaoomOptions {\n socket: IMessage;\n}\n\nexport class Tiaoom extends EventEmitter {\n rooms: Room[] = []; // room list\n players: Player[] = []; // player list\n messageInstance?: IMessage;\n\n constructor({ socket }: ITiaoomOptions) {\n super();\n this.messageInstance = socket;\n }\n\n /**\n * 导出 JSON 数据\n * @returns 房间与玩家数据\n */\n toJSON() {\n return {\n rooms: this.rooms,\n players: this.players,\n };\n }\n\n /**\n * 从数据加载\n * @param data 房间与玩家数据\n * @returns this\n */\n loadFrom(data: { rooms?: Room[]; players?: Player[] }) {\n this.rooms = data.rooms?.map((r) => new Room(r, r.players)) ?? [];\n this.players = data.players?.map((p) => new Player(p, p.status)) ?? [];\n this.rooms.forEach((room) => {\n room.setSender((type, message, sender) => {\n this.send({ type: `room.${type}` as MessageTypes, data: message, sender: room });\n })\n })\n setTimeout(() => {\n this.rooms.forEach((room) => {\n room.players.forEach((player) => {\n if (!this.players.some((p) => p.id === player.id)) {\n this.offlinePlayer(player);\n }\n })\n })\n }, 60 * 1000);\n return this;\n }\n\n on<K extends keyof TiaoomEvents>(event: K, listener: TiaoomEvents[K]): this {\n super.on(event, listener);\n return this\n }\n\n emit<K extends keyof TiaoomEvents>(event: K, ...args: Parameters<TiaoomEvents[K]>): boolean {\n return super.emit(event, ...args);\n }\n\n /**\n * 判断玩家是否为管理员\n * @param player 玩家信息\n * @returns 是否为管理员\n */\n async isAdmin(_player: IPlayer) {\n return false;\n }\n\n /**\n * 判断玩家是否被封禁\n * @param _player 玩家信息\n * @returns 是否被封禁\n */\n async isBanned(_player: IPlayer) {\n return false;\n }\n\n run() {\n this.messageInstance?.on(\"message\", async (message: any, cb?: (err: Error | null, data?: any) => any) => {\n message.sender = message.sender ? this.searchPlayer(message.sender) || message.sender : null;\n try {\n switch (message.type) {\n case RecvMessageTypes.RoomList:\n return cb?.(null, this.rooms);\n case RecvMessageTypes.PlayerList:\n return cb?.(null, this.players);\n case RecvMessageTypes.RoomCreate:\n return await this.createRoom(message.sender, message.data);\n case RecvMessageTypes.PlayerJoin:\n return await this.joinPlayer(message.sender, message.data);\n case RecvMessageTypes.PlayerLeave:\n return await this.leavePlayer(message.sender, message.data);\n case RecvMessageTypes.PlayerStandUp:\n return await this.leaveSeat(message.sender, message.data);\n case RecvMessageTypes.RoomGet:\n return cb?.(null, this.searchRoom(message.data));\n case RecvMessageTypes.RoomStart:\n return await this.startRoom(message.sender, message.data);\n case RecvMessageTypes.RoomKick:\n return await this.kickPlayer(message.sender, message.data);\n case RecvMessageTypes.RoomTransfer:\n return await this.transferOwner(message.sender, message.data);\n case RecvMessageTypes.RoomClose:\n return await this.closeRoom(message.sender, message.data);\n case RecvMessageTypes.PlayerLogin:\n return await this.loginPlayer(message.data);\n case RecvMessageTypes.PlayerLogout:\n return await this.removePlayer(message.data);\n case MessageTypes.PlayerOffline:\n return await this.offlinePlayer(message.data);\n case RecvMessageTypes.PlayerReady:\n return await this.readyPlayer(message.sender, message.data);\n case RecvMessageTypes.PlayerUnready:\n return await this.unReadyPlayer(message.sender, message.data);\n case RecvMessageTypes.RoomPlayerCommand:\n return this.searchRoom(message.data)?.emit(\"player-command\", { ...message.data , sender: message.sender });\n case RecvMessageTypes.GlobalCommand:\n return this.emit(\"command\", { ...message.data , sender: message.sender });\n default:\n throw new Error('unknown message type.');\n }\n } catch (error) {\n cb?.(error as Error);\n if (message.sender) this.send({\n type: MessageTypes.PlayerError,\n data: {\n name: (error as Error).name, \n message: (error as Error).message,\n stack: (error as Error).stack,\n },\n sender: message.sender,\n });\n }\n });\n\n this.on('player', (player, online) => {\n this.send({ type: online ? MessageTypes.PlayerLogin : MessageTypes.PlayerLogout, data: player });\n });\n\n this.on('players', (players) => {\n this.send({ type: MessageTypes.PlayerList, data: players });\n });\n\n this.on('room', (room) => {\n this.send({ type: MessageTypes.RoomCreate, data: room });\n });\n\n this.on('room-player', (room) => {\n this.send({ type: MessageTypes.RoomUpdate, data: room });\n });\n\n this.on('rooms', (rooms) => {\n this.send({ type: MessageTypes.RoomList, data: rooms });\n });\n\n this.on('message', (data, sender) => {\n this.send({ type: MessageTypes.GlobalMessage, data, sender });\n });\n\n return this;\n }\n\n searchPlayer(player: string): Player | undefined;\n searchPlayer(player: IPlayerOptions | IRoomPlayerOptions): Player | undefined;\n\n searchPlayer(player: IPlayerOptions | IRoomPlayerOptions | string) {\n const playerId = typeof player === \"string\" ? player : player?.id;\n return this.players.find((target) => target.id === playerId);\n }\n\n searchRoom(room: string): Room | undefined;\n searchRoom(room: Partial<IRoomOptions>): Room | undefined;\n\n searchRoom(room: Partial<IRoomOptions> | string) {\n const roomId = typeof room === \"string\" ? room : room?.id;\n return this.rooms.find((target) => target.id === roomId);\n }\n\n async createRoom(sender: IPlayer, options: IRoomOptions) {\n if (!sender) {\n throw new Error('missing player information.');\n }\n\n if (!options.name) {\n throw new Error('missing room id or name.');\n }\n const roomInstance = this.searchRoom(options);\n if (roomInstance) {\n throw new Error('room already exists.');\n }\n\n if (this.rooms.some(r => r.players.some(p => p.id === sender?.id))) {\n throw new Error('you are already in a room.');\n }\n\n const room = new Room(options);\n room.setSender((type, message, sender) => {\n this.send({ type: `room.${type}` as MessageTypes, data: message, sender: room });\n });\n \n this.rooms.push(room);\n this.emit(\"room\", room);\n this.joinPlayer(sender, { roomId: room.id, ...sender }, true);\n return room;\n }\n\n async startRoom(sender: IPlayer, room: IRoom) {\n const roomInstance = this.searchRoom(room);\n if (!roomInstance) {\n throw new Error('room not found.');\n }\n roomInstance.start(sender);\n\n return this.emit(\"room-player\", roomInstance);\n }\n\n async closeRoom(sender: IPlayer | null, room: IRoom) {\n const roomIndex = this.rooms.findIndex((r) => r.id === room.id);\n const roomInstance = this.rooms[roomIndex];\n if (!roomInstance) {\n throw new Error('room not found.');\n }\n\n if (sender?.id && !sender.isAdmin) {\n const senderInRoom = roomInstance.searchPlayer(sender);\n if (!senderInRoom || !senderInRoom.isCreator) {\n throw new Error('permission denied.');\n }\n }\n\n room = this.rooms.splice(roomIndex, 1)[0];\n\n this.emit(\"rooms\", this.rooms);\n roomInstance.emit('close');\n return room;\n }\n\n async kickPlayer(sender: IPlayer, data: { roomId: string, playerId: string }) {\n const room = this.searchRoom(data.roomId);\n if (!room) {\n throw new Error('room not found.');\n }\n\n if (!sender.isAdmin) {\n const senderInRoom = room.searchPlayer(sender);\n if (!senderInRoom || !senderInRoom.isCreator) {\n throw new Error('permission denied.');\n }\n }\n\n const targetPlayer = room.players.find(p => p.id === data.playerId);\n if (!targetPlayer) {\n throw new Error('player not found in room.');\n }\n\n const roomPlayer = room.kickPlayer(targetPlayer);\n if (roomPlayer) this.emit(\"room-player\", room);\n return roomPlayer;\n }\n\n async transferOwner(sender: IPlayer, data: { roomId: string, playerId: string }) {\n const room = this.searchRoom(data.roomId);\n if (!room) {\n throw new Error('room not found.');\n }\n\n const creator = room.players.find(p => p.isCreator);\n if (!sender.isAdmin) {\n const senderInRoom = room.searchPlayer(sender);\n if (!senderInRoom || !senderInRoom.isCreator) {\n throw new Error('permission denied.');\n }\n } else {\n\n }\n\n const targetPlayer = room.players.find(p => p.id === data.playerId);\n if (!targetPlayer) {\n throw new Error('player not found in room.');\n }\n\n if (targetPlayer.id === sender.id) {\n return;\n }\n\n if (creator) creator.isCreator = false;\n targetPlayer.isCreator = true;\n\n this.emit(\"room-player\", room);\n return room;\n }\n\n async loginPlayer (player: IPlayerOptions, cb?: (data: { player: Player }) => void) {\n let playerInstance = this.searchPlayer(player);\n if (!playerInstance?.sender) {\n if (!playerInstance) {\n playerInstance = new Player(player);\n this.players.push(playerInstance);\n }\n playerInstance.isAdmin = await this.isAdmin(playerInstance);\n playerInstance.setSender((type, message) => {\n this.send({ type: `player.${type}` as MessageTypes, data: message, sender: playerInstance });\n });\n this.emit(\"player\", playerInstance, true);\n\n const room = this.rooms.find(r => r.players.some(p => p.id === playerInstance!.id));\n if (room) {\n const playerIndex = room.players.findIndex(p => p.id === playerInstance!.id);\n if (playerIndex >= 0) {\n const status = room?.status == RoomStatus.playing ? PlayerStatus.playing : PlayerStatus.online;\n playerInstance.status = status;\n playerInstance.attributes = Object.assign({}, room.players[playerIndex].attributes, playerInstance.attributes);\n Object.assign(room.players[playerIndex], playerInstance);\n room.emit('update', room);\n }\n }\n }\n\n playerInstance.emit(\"status\", playerInstance.status);\n\n cb?.({ player: playerInstance });\n return playerInstance;\n }\n\n async joinPlayer(sender: IPlayer, player: IRoomPlayerOptions, isCreator: boolean = false) {\n let playerInstance = this.searchPlayer(sender);\n if (!playerInstance) {\n playerInstance = await this.loginPlayer(sender);\n }\n\n if (!player.roomId) {\n throw new Error('missing room id.');\n }\n\n const room = this.rooms.find((room) => room.id === player.roomId);\n if (!room) {\n throw new Error('room not found.');\n }\n\n if (!isCreator && !room.players.some(p => p.isCreator)) {\n isCreator = true;\n }\n\n const roomPlayer = room.addPlayer(playerInstance, isCreator);\n if (roomPlayer) {\n this.emit(\"room-player\", room);\n }\n\n return roomPlayer;\n }\n\n async leavePlayer(sender: IPlayer, player: IRoomPlayerOptions) {\n if (!player.roomId) {\n throw new Error('missing room id.');\n }\n\n const room = this.rooms.find((room) => room.id === player.roomId);\n if (!room) {\n throw new Error('room not found.');\n }\n\n const playerInstance = room.searchPlayer(sender);\n if (!playerInstance) {\n throw new Error('player not in room.');\n }\n\n const roomPlayer = room.kickPlayer(playerInstance);\n\n if (roomPlayer) this.emit(\"room-player\", room);\n\n return roomPlayer;\n }\n \n async leaveSeat(sender: IPlayer, player: IRoomPlayerOptions) {\n if (!player.roomId) {\n throw new Error('missing room id.');\n }\n\n const room = this.rooms.find((room) => room.id === player.roomId);\n if (!room) {\n throw new Error('room not found.');\n }\n\n const playerInstance = room.searchPlayer(sender);\n if (!playerInstance) {\n throw new Error('player not in room.');\n }\n\n const roomPlayer = room.leaveSeat(playerInstance);\n if (roomPlayer) this.emit(\"room-player\", room);\n\n return roomPlayer;\n }\n\n async readyPlayer(sender: IPlayer, player: IRoomPlayer) {\n const playerInstance = this.searchPlayer(sender);\n if (!playerInstance) {\n throw new Error('player not found.');\n }\n\n if (!player.roomId) {\n throw new Error('missing room id.');\n }\n\n const room = this.rooms.find((room) => room.id === player.roomId);\n if (!room) {\n throw new Error('room not found.');\n }\n\n const roomPlayer = room.searchPlayer(playerInstance);\n \n if (!roomPlayer) {\n throw new Error('player not in room.');\n }\n\n roomPlayer.isReady = true;\n\n if (room.isReady) {\n room.emit(\"all-ready\", room.players);\n }\n\n playerInstance.status = PlayerStatus.ready;\n\n room.emit(\"player-ready\", { ...player, ...roomPlayer });\n room.emit('update', room);\n\n return this;\n }\n \n async unReadyPlayer(sender: IPlayer, player: IRoomPlayer) {\n const playerInstance = this.searchPlayer(sender);\n if (!playerInstance) {\n throw new Error('player not found.');\n }\n\n if (!player.roomId) {\n throw new Error('missing room id.');\n }\n\n const room = this.rooms.find((room) => room.id === player.roomId);\n if (!room) {\n throw new Error('room not found.');\n }\n\n const roomPlayer = room.searchPlayer(playerInstance);\n \n if (!roomPlayer) {\n throw new Error('player not in room.');\n }\n\n roomPlayer.isReady = false;\n playerInstance.status = PlayerStatus.unready;\n room.emit(\"player-unready\", { ...player, ...roomPlayer });\n room.emit('update', room);\n\n return this;\n }\n\n async removePlayer(sender: IPlayer) {\n const playerIndex = this.players.findIndex((p) => p.id === sender?.id);\n const player = this.players[playerIndex];\n if (playerIndex > -1) {\n this.players.splice(playerIndex, 1)[0];\n this.emit(\"player\", player, false);\n }\n return player;\n }\n\n async offlinePlayer(sender: IPlayer) {\n const room = this.rooms.find((room) => room.players.some(p => p.id === sender?.id));\n if (room) {\n setTimeout(() => {\n const playerInstance = room.players.find(p => p.id === sender.id && p.role === PlayerRole.player);\n if (this.players.some(p => p.id === sender.id) || !playerInstance) \n return; // player is online\n playerInstance.status = PlayerStatus.offline;\n room.emit(\"player-offline\", playerInstance);\n playerInstance.status = PlayerStatus.offline;\n room.emit('update', room);\n }, 60 * 1000); // 1 minute later\n }\n this.removePlayer(sender);\n return sender;\n }\n\n async send(message: IMessagePackage) {\n // send a message to the client\n if (message.type.startsWith('player.') && message.sender) {\n const player = message.sender as Player;\n // Send to all sockets of the player\n this.messageInstance?.send({ \n type: message.type, \n data: message.data, \n senderIds: [player.id]\n });\n }\n else if (message.type.startsWith('room.') && message.sender) {\n const room = message.sender as Room;\n this.messageInstance?.send({ \n type: message.type, \n data: message.data, \n senderIds: room.players.map(p => p.id)\n });\n } else {\n this.messageInstance?.send({ \n type: message.type, \n data: message.data, \n senderIds: this.players.map(p => p.id)\n });\n }\n }\n}\n\nexport * from \"@lib/models/message\";\nexport * from \"@lib/models/room\";\nexport * from \"@lib/models/player\";\nexport * from \"@lib/events\";"],"mappings":"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"}