tiaoom 0.0.3 → 0.0.6

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/src/index.cjs CHANGED
@@ -29,17 +29,47 @@ let events = require("events");
29
29
  events = __toESM(events);
30
30
 
31
31
  //#region lib/models/player.ts
32
+ /**
33
+ * 玩家状态枚举
34
+ */
32
35
  let PlayerStatus = /* @__PURE__ */ function(PlayerStatus$1) {
36
+ /**
37
+ * 已准备
38
+ */
33
39
  PlayerStatus$1["ready"] = "ready";
40
+ /**
41
+ * 未准备
42
+ */
34
43
  PlayerStatus$1["unready"] = "unready";
44
+ /**
45
+ * 在线
46
+ */
35
47
  PlayerStatus$1["online"] = "online";
48
+ /**
49
+ * 游戏中
50
+ */
36
51
  PlayerStatus$1["playing"] = "playing";
37
52
  return PlayerStatus$1;
38
53
  }({});
54
+ /**
55
+ * 玩家
56
+ */
39
57
  var Player = class extends events.default {
58
+ /**
59
+ * 监听玩家事件
60
+ * @param event 事件名,具体见 PlayEvents
61
+ * @param listener 监听器
62
+ * @returns this
63
+ */
40
64
  on(event, listener) {
41
65
  return super.on(event, listener);
42
66
  }
67
+ /**
68
+ * 触发玩家事件
69
+ * @param event 事件名,具体见 PlayEvents
70
+ * @param args 参数
71
+ * @returns 是否有监听器被触发
72
+ */
43
73
  emit(event, ...args) {
44
74
  return super.emit(event, ...args);
45
75
  }
@@ -79,6 +109,11 @@ var Player = class extends events.default {
79
109
  toString() {
80
110
  return JSON.stringify(this.toJSON());
81
111
  }
112
+ /**
113
+ * 设置发送者函数
114
+ * @param {(type: string, ...message: any) => void} sender 发送者函数
115
+ * @returns this
116
+ */
82
117
  setSender(sender) {
83
118
  this.sender = sender;
84
119
  return this;
@@ -87,17 +122,41 @@ var Player = class extends events.default {
87
122
 
88
123
  //#endregion
89
124
  //#region lib/models/room.ts
125
+ /**
126
+ * 房间玩家角色
127
+ */
90
128
  let PlayerRole = /* @__PURE__ */ function(PlayerRole$1) {
129
+ /**
130
+ * 玩家
131
+ */
91
132
  PlayerRole$1["player"] = "player";
133
+ /**
134
+ * 观众
135
+ */
92
136
  PlayerRole$1["watcher"] = "watcher";
93
137
  return PlayerRole$1;
94
138
  }({});
139
+ /**
140
+ * 房间状态
141
+ */
95
142
  let RoomStatus = /* @__PURE__ */ function(RoomStatus$1) {
143
+ /**
144
+ * 等待中
145
+ */
96
146
  RoomStatus$1["waiting"] = "waiting";
147
+ /**
148
+ * 已准备
149
+ */
97
150
  RoomStatus$1["ready"] = "ready";
151
+ /**
152
+ * 游戏中
153
+ */
98
154
  RoomStatus$1["playing"] = "playing";
99
155
  return RoomStatus$1;
100
156
  }({});
157
+ /**
158
+ * 房间玩家
159
+ */
101
160
  var RoomPlayer = class extends Player {
102
161
  constructor(player, role = PlayerRole.player) {
103
162
  super(player);
@@ -116,33 +175,72 @@ var RoomPlayer = class extends Player {
116
175
  };
117
176
  }
118
177
  };
178
+ /**
179
+ * 房间
180
+ */
119
181
  var Room = class extends events.default {
182
+ /**
183
+ * 监听房间事件
184
+ * @param event 事件名,具体见 RoomEvents
185
+ * @param listener 监听器
186
+ * @returns this
187
+ */
120
188
  on(event, listener) {
121
189
  return super.on(event, listener);
122
190
  }
191
+ /**
192
+ * 触发房间事件
193
+ * @param event 事件名,具体见 RoomEvents
194
+ * @param args 参数
195
+ * @returns 是否有监听器被触发
196
+ */
123
197
  emit(event, ...args) {
124
198
  return super.emit(event, ...args);
125
199
  }
200
+ /**
201
+ * 有效玩家列表(非观众)
202
+ */
126
203
  get validPlayers() {
127
204
  return this.players.filter((player) => player.role === PlayerRole.player);
128
205
  }
206
+ /**
207
+ * 观众列表
208
+ */
129
209
  get watchers() {
130
210
  return this.players.filter((player) => player.role === PlayerRole.watcher);
131
211
  }
212
+ /**
213
+ * 房间玩家是否已准备好
214
+ */
132
215
  get isReady() {
133
216
  return this.players.length >= this.minSize && this.players.every((target) => target.isReady || target.role === PlayerRole.watcher);
134
217
  }
218
+ /**
219
+ * 房间状态
220
+ */
135
221
  get status() {
136
222
  if (!this.isReady) return RoomStatus.waiting;
137
223
  if (this.players.findIndex((target) => target.status === PlayerStatus.playing) != -1) return RoomStatus.playing;
138
224
  return RoomStatus.ready;
139
225
  }
226
+ /**
227
+ * 房间是否在游戏中
228
+ */
140
229
  get isPlaying() {
141
230
  return this.status === RoomStatus.playing;
142
231
  }
232
+ /**
233
+ * 房间是否已满
234
+ */
143
235
  get isFull() {
144
236
  return this.validPlayers.length == this.size;
145
237
  }
238
+ /**
239
+ * 房主
240
+ */
241
+ get owner() {
242
+ return this.players.find((player) => player.isCreator);
243
+ }
146
244
  toJSON() {
147
245
  return {
148
246
  id: this.id,
@@ -187,6 +285,11 @@ var Room = class extends events.default {
187
285
  });
188
286
  });
189
287
  }
288
+ /**
289
+ * 设置房主
290
+ * @param {Player} player 玩家
291
+ * @returns this
292
+ */
190
293
  setCreator(player) {
191
294
  const roomPlayer = this.searchPlayer(player);
192
295
  if (roomPlayer) {
@@ -198,19 +301,32 @@ var Room = class extends events.default {
198
301
  }
199
302
  return this;
200
303
  }
304
+ /**
305
+ * 添加玩家
306
+ * @param {Player} player 玩家
307
+ * @param {boolean} isCreator 是否房主
308
+ * @returns 玩家实例
309
+ */
201
310
  addPlayer(player, isCreator = false) {
202
- if (this.players.some((p) => p.id == player.id)) return;
203
311
  let roomPlayer = this.searchPlayer(player);
204
- if (!roomPlayer) {
205
- roomPlayer = new RoomPlayer(player, this.isFull || this.isPlaying ? PlayerRole.watcher : PlayerRole.player);
206
- roomPlayer.isCreator = isCreator;
207
- roomPlayer.roomId = this.id;
208
- this.players.push(roomPlayer);
209
- this.emit("join", {
210
- roomId: this.id,
211
- ...roomPlayer
212
- });
312
+ if (roomPlayer) {
313
+ if (roomPlayer.role === PlayerRole.watcher && !this.isFull && !this.isPlaying) {
314
+ roomPlayer.role = PlayerRole.player;
315
+ this.emit("update", this);
316
+ }
317
+ return roomPlayer;
213
318
  }
319
+ if (isCreator) this.players.forEach((p) => {
320
+ p.isCreator = false;
321
+ });
322
+ roomPlayer = new RoomPlayer(player, this.isFull || this.isPlaying ? PlayerRole.watcher : PlayerRole.player);
323
+ roomPlayer.isCreator = isCreator;
324
+ roomPlayer.roomId = this.id;
325
+ this.players.push(roomPlayer);
326
+ this.emit("join", {
327
+ roomId: this.id,
328
+ ...roomPlayer
329
+ });
214
330
  return roomPlayer;
215
331
  }
216
332
  kickPlayer(player) {
@@ -234,6 +350,9 @@ var Room = class extends events.default {
234
350
  const playerId = typeof player === "string" ? player : player.id;
235
351
  return this.players.find((player$1) => player$1.id == playerId);
236
352
  }
353
+ /**
354
+ * 开始游戏
355
+ */
237
356
  start() {
238
357
  if (!this.isReady) throw new Error("room is not ready.");
239
358
  if (this.status === RoomStatus.playing) throw new Error("room is already started.");
@@ -244,6 +363,9 @@ var Room = class extends events.default {
244
363
  this.emit("update", this);
245
364
  return this.emit("start", this);
246
365
  }
366
+ /**
367
+ * 结束游戏
368
+ */
247
369
  end() {
248
370
  this.players.forEach((player) => {
249
371
  if (player.role != PlayerRole.player) return;
@@ -252,6 +374,10 @@ var Room = class extends events.default {
252
374
  this.emit("update", this);
253
375
  return this.emit("end", this);
254
376
  }
377
+ /**
378
+ * 设置消息发送器
379
+ * @param sender 消息发送器
380
+ */
255
381
  setSender(sender) {
256
382
  this.sender = sender;
257
383
  return this;
@@ -260,6 +386,9 @@ var Room = class extends events.default {
260
386
 
261
387
  //#endregion
262
388
  //#region lib/models/message.ts
389
+ /**
390
+ * 消息包类型枚举
391
+ */
263
392
  let MessageTypes = /* @__PURE__ */ function(MessageTypes$1) {
264
393
  MessageTypes$1["RoomList"] = "room.list";
265
394
  MessageTypes$1["RoomCreate"] = "room.create";
@@ -475,8 +604,7 @@ var Tiaoom = class extends events.EventEmitter {
475
604
  const room = this.rooms.find((room$1) => room$1.id === player.roomId);
476
605
  if (!room) throw new Error("room not found.");
477
606
  const roomPlayer = room.addPlayer(playerInstance, isCreator);
478
- if (!roomPlayer) throw new Error("room is full.");
479
- this.emit("room-player", room);
607
+ if (roomPlayer) this.emit("room-player", room);
480
608
  return roomPlayer;
481
609
  }
482
610
  leavePlayer(sender, player) {
package/src/index.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["EventEmitter","EventEmitter","player","EventEmitter","room"],"sources":["../lib/models/player.ts","../lib/models/room.ts","../lib/models/message.ts","../lib/index.ts"],"sourcesContent":["import { PlayerEvents } from \"@lib/events/player\";\nimport EventEmitter from \"events\";\n\nexport interface PlayerOptions {\n id: string;\n name: string;\n attributes?: any;\n sender?: (type: string, ...message: any) => void;\n}\n\nexport enum PlayerStatus {\n ready = 'ready',\n unready = 'unready',\n online = 'online',\n playing = 'playing',\n}\n\nexport interface IPlayer extends PlayerOptions {\n status: PlayerStatus;\n}\n\nexport class Player extends EventEmitter implements IPlayer {\n on<K extends keyof PlayerEvents>(event: K, listener: PlayerEvents[K]): this {\n return super.on(event, listener);\n }\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 status: PlayerStatus = PlayerStatus.online;\n sender?: (type: string, ...message: any) => void;\n\n constructor({ id = new Date().getTime().toString(), name = '', attributes, sender }: PlayerOptions) {\n super();\n this.id = id;\n this.name = name;\n this.attributes = attributes;\n this.sender = sender;\n\n this.on('status', (status: PlayerStatus) => {\n this.status = status;\n });\n \n const events: Array<keyof PlayerEvents> = ['command', 'message', 'join', 'leave', '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 };\n }\n\n toString() {\n return JSON.stringify(this.toJSON());\n }\n\n setSender(sender: (type: string, ...message: any) => void) {\n this.sender = sender;\n return this;\n }\n}","import { IPlayer, Player, PlayerOptions, PlayerStatus } from \"./player\";\nimport EventEmitter from \"events\";\nimport { RoomEvents } from \"@lib/events\";\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\nexport enum PlayerRole {\n player = 'player',\n watcher = 'watcher',\n}\n\nexport enum RoomStatus {\n waiting = 'waiting',\n ready = 'ready',\n playing = 'playing',\n}\n\nexport interface IRoom extends IRoomOptions {\n players: RoomPlayer[];\n}\n\nexport interface IRoomPlayerOptions extends PlayerOptions {\n roomId?: string;\n}\nexport interface IRoomPlayer extends IRoomPlayerOptions, IPlayer {\n isReady: boolean;\n role: PlayerRole;\n isCreator: boolean;\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: IPlayer | Player, role: PlayerRole = PlayerRole.player) {\n super(player);\n this.role = role;\n if (player instanceof Player && player.sender) super.setSender(player.sender);\n }\n\n toJSON() {\n return {\n ...super.toJSON(),\n role: this.role,\n isReady: this.isReady,\n isCreator: this.isCreator,\n };\n }\n}\n\nexport class Room extends EventEmitter implements IRoom {\n on<K extends keyof RoomEvents>(event: K, listener: RoomEvents[K]): this {\n return super.on(event, listener);\n }\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; // room id\n size: number = 10; // room size\n name: string = ''; // room name\n minSize: number = 2; // room min size\n attrs?: Record<string, any>; // other attributes\n players: RoomPlayer[] = []; // player list\n\n get validPlayers() {\n return this.players.filter((player) => player.role === PlayerRole.player);\n }\n\n get watchers() {\n return this.players.filter((player) => player.role === PlayerRole.watcher);\n }\n\n private sender?: (type: string, ...message: any) => void;\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 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 get isPlaying(): boolean {\n return this.status === RoomStatus.playing;\n }\n\n // is room full\n get isFull(): boolean {\n return this.validPlayers.length == this.size;\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({\n id = new Date().getTime().toString(), name = '', size = 10, minSize = 2, attrs\n }: IRoomOptions) {\n super();\n this.id = id;\n this.name = name;\n this.size = size;\n this.minSize = minSize;\n this.attrs = attrs;\n \n const events: Array<keyof RoomEvents> = ['message', 'command', 'start', 'end', 'close', 'error', '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 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 addPlayer(player: Player, isCreator: boolean = false) {\n if (this.players.some((p) => p.id == player.id)) return;\n let roomPlayer = this.searchPlayer(player);\n if (!roomPlayer) {\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\", { roomId: this.id, ...roomPlayer });\n }\n return roomPlayer;\n }\n\n kickPlayer(playerId: string): RoomPlayer;\n kickPlayer(player: IPlayer): RoomPlayer;\n\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 this.emit(\"leave\", { roomId: this.id, ...roomPlayer});\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 searchPlayer(playerId: string): RoomPlayer | undefined;\n searchPlayer(playerId: IPlayer): RoomPlayer | undefined;\n\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 start() {\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.emit('status', PlayerStatus.playing);\n });\n this.emit(\"update\", this);\n return this.emit(\"start\", this);\n }\n\n end() {\n this.players.forEach((player) => {\n if (player.role != PlayerRole.player) return;\n player.emit('status', PlayerStatus.unready);\n });\n this.emit(\"update\", this);\n return this.emit(\"end\", this);\n }\n\n setSender(sender: (type: string, ...message: any) => void) {\n this.sender = sender;\n return this;\n }\n}\n","import EventEmitter from \"events\";\nimport { IPlayer, PlayerOptions } from \"./player\";\nimport { IRoom, IRoomPlayer, IRoomOptions } from \"./room\";\nimport { MessageEvents } from \"@lib/events/message\";\n\nexport enum MessageTypes {\n RoomList = \"room.list\",\n RoomCreate = \"room.create\",\n RoomReady = \"room.ready\",\n RoomStart = \"room.start\",\n RoomEnd = \"room.end\",\n RoomClose = \"room.close\",\n RoomAllReady = \"room.allready\",\n RoomCommand = \"room.command\",\n RoomMessage = \"room.message\",\n PlayerOffline = \"player.offline\",\n PlayerList = \"player.list\",\n PlayerLogin = \"player.login\",\n PlayerLogout = \"player.logout\",\n PlayerJoin = \"player.join\",\n PlayerLeave = \"player.leave\",\n PlayerReady = \"player.ready\",\n PlayerUnready = \"player.unready\",\n PlayerCommand = \"player.command\",\n}\n\nexport interface MessagePackage {\n type: MessageTypes | string;\n data?: PlayerOptions | IRoomOptions | IPlayer | IRoom | IRoomPlayer | any;\n sender?: IPlayer | IRoom | IRoomPlayer;\n}\n\nexport interface Message extends EventEmitter {\n on<K extends keyof MessageEvents>(event: K, listener: MessageEvents[K]): this;\n emit<K extends keyof MessageEvents>(event: K, ...args: Parameters<MessageEvents[K]>): boolean;\n close(): void;\n send(message: MessagePackage): void;\n}\n","import { EventEmitter } from \"events\";\nimport { TiaoomEvents } from \"./events\";\nimport { Message } from \"./models/message\";\nimport { IRoom, IRoomPlayer, Room, IRoomOptions, IRoomPlayerOptions } from \"./models/room\";\nimport { IPlayer, Player, PlayerOptions, PlayerStatus } from \"./models/player\";\n\nexport interface ITiaoomOptions {\n socket: Message;\n}\n\nexport class Tiaoom extends EventEmitter {\n rooms: Room[] = []; // room list\n players: Player[] = []; // player list\n messageInstance?: Message;\n\n constructor({ socket }: ITiaoomOptions) {\n super();\n this.messageInstance = socket;\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 run() {\n this.messageInstance?.on(\"message\", (message: any, cb?: (err: Error | null, data?: any) => any) => {\n try {\n switch (message.type) {\n case \"room.list\":\n return cb?.(null, this.rooms);\n case \"player.list\":\n return cb?.(null, this.players);\n case \"room.create\":\n return this.createRoom(message.sender, message.data);\n case \"player.join\":\n return this.joinPlayer(message.sender, message.data);\n case \"player.leave\":\n return this.leavePlayer(message.sender, message.data);\n case \"room.get\":\n return cb?.(null, this.searchRoom(message.data));\n case \"room.start\":\n return this.startRoom(message.sender, message.data);\n case \"room.kick\":\n return this.kickPlayer(message.sender, message.data);\n case \"room.transfer\":\n return this.transferOwner(message.sender, message.data);\n case \"room.close\":\n return this.closeRoom(message.sender, message.data);\n case \"player.login\":\n return this.loginPlayer(message.data);\n case \"player.logout\":\n return this.removePlayer(message.data);\n case \"player.ready\":\n return this.readyPlayer(message.sender, message.data);\n case \"player.unready\":\n return this.unReadyPlayer(message.sender, message.data);\n case \"room.player-command\":\n return this.searchRoom(message.data)?.emit(\"player-command\", { ...message.data , sender: message.sender });\n case \"room.message\":\n return this.searchRoom(message.data)?.emit(\"message\", message.data);\n case \"global.command\":\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 }\n });\n\n this.on('player', (player, online) => {\n this.messageInstance?.send({ type: online ? 'player.login' : 'player.logout', data: player });\n });\n\n this.on('players', (players) => {\n this.messageInstance?.send({ type: 'player.list', data: players });\n });\n\n this.on('room', (room) => {\n this.messageInstance?.send({ type: 'room.create', data: room });\n });\n\n this.on('room-player', (room) => {\n this.messageInstance?.send({ type: 'room.update', data: room });\n });\n\n this.on('rooms', (rooms) => {\n this.messageInstance?.send({ type: 'room.list', data: rooms });\n });\n\n this.on('command', (data) => {\n this.messageInstance?.send({ type: 'global.command', data });\n });\n\n return this;\n }\n\n searchPlayer(player: string): Player | undefined;\n searchPlayer(player: PlayerOptions | IRoomPlayerOptions): Player | undefined;\n\n searchPlayer(player: PlayerOptions | 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 (!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) => {\n this.messageInstance?.send({ type: `room.${type}`, data: message, sender: room });\n });\n \n this.emit(\"room\", room);\n this.rooms.push(room);\n\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();\n\n return this.emit(\"room-player\", roomInstance);\n }\n\n closeRoom(sender: IPlayer, 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 (roomInstance.players.length && !roomInstance.players.some(p => p.id === sender.id && p.isCreator)) {\n throw new Error('only room creator can close the room.');\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 const senderInRoom = room.searchPlayer(sender);\n if (!senderInRoom || !senderInRoom.isCreator) {\n throw new Error('permission denied.');\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 senderInRoom = room.searchPlayer(sender);\n if (!senderInRoom || !senderInRoom.isCreator) {\n throw new Error('permission denied.');\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 senderInRoom.isCreator = false;\n targetPlayer.isCreator = true;\n\n this.emit(\"room-player\", room);\n return room;\n }\n\n loginPlayer (player: PlayerOptions, cb?: (data: { player: Player }) => void): Player {\n let playerInstance = this.searchPlayer(player);\n if (!playerInstance) {\n playerInstance = new Player(player);\n playerInstance.setSender((type, message) => {\n this.messageInstance?.send({ type: `player.${type}`, data: message, sender: playerInstance });\n });\n this.players.push(playerInstance);\n this.emit(\"player\", playerInstance, true);\n }\n \n playerInstance.emit(\"status\", PlayerStatus.online);\n cb?.({ player: playerInstance });\n return playerInstance;\n }\n\n joinPlayer(sender: IPlayer, player: IRoomPlayerOptions, isCreator: boolean = false) {\n let playerInstance = this.searchPlayer(sender);\n if (!playerInstance) {\n playerInstance = 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 const roomPlayer = room.addPlayer(playerInstance, isCreator);\n if (!roomPlayer) {\n throw new Error('room is full.');\n }\n\n this.emit(\"room-player\", room);\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 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.emit(\"status\", PlayerStatus.ready);\n\n room.emit(\"player-ready\", { ...player, ...roomPlayer });\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.emit(\"status\", PlayerStatus.unready);\n room.emit(\"player-unready\", roomPlayer);\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 if (this.rooms.some(r => r.searchPlayer(player))) {\n setTimeout(() => {\n if (this.players.some(p => p.id === sender.id)) return; // player is online\n this.rooms.filter(r => r.searchPlayer(player)).forEach(r => {\n this.leavePlayer(sender, { ...sender, roomId: r.id });\n });\n }, 5 * 60 * 1000); // 5 minutes later\n }\n }\n return player;\n }\n}\n\nexport * from \"./models/message\";\nexport * from \"./models/room\";\nexport * from \"./models/player\";\nexport * from \"./events\";"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","names":["EventEmitter","EventEmitter","player","EventEmitter","room"],"sources":["../lib/models/player.ts","../lib/models/room.ts","../lib/models/message.ts","../lib/index.ts"],"sourcesContent":["import { PlayerEvents } from \"@lib/events/player\";\nimport EventEmitter from \"events\";\n\n/**\n * 玩家选项接口\n */\nexport interface PlayerOptions {\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 * 玩家状态枚举\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 * 玩家接口\n */\nexport interface IPlayer extends PlayerOptions {\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 status: PlayerStatus = PlayerStatus.online;\n sender?: (type: string, ...message: any) => void;\n\n constructor({ id = new Date().getTime().toString(), name = '', attributes, sender }: PlayerOptions) {\n super();\n this.id = id;\n this.name = name;\n this.attributes = attributes;\n this.sender = sender;\n\n this.on('status', (status: PlayerStatus) => {\n this.status = status;\n });\n \n const events: Array<keyof PlayerEvents> = ['command', 'message', 'join', 'leave', '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 };\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, PlayerOptions, 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 * 房间状态\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 PlayerOptions {\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\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: IPlayer | Player, role: PlayerRole = PlayerRole.player) {\n super(player);\n this.role = role;\n if (player instanceof Player && player.sender) super.setSender(player.sender);\n }\n\n toJSON() {\n return {\n ...super.toJSON(),\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({\n id = new Date().getTime().toString(), name = '', size = 10, minSize = 2, attrs\n }: Partial<IRoomOptions>) {\n super();\n this.id = id;\n this.name = name;\n this.size = size;\n this.minSize = minSize;\n this.attrs = attrs;\n \n const events: Array<keyof RoomEvents> = ['message', 'command', 'start', 'end', 'close', 'error', '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 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\", { roomId: this.id, ...roomPlayer });\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 this.emit(\"leave\", { roomId: this.id, ...roomPlayer});\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() {\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.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.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 { IPlayer, PlayerOptions } from \"./player\";\nimport { IRoom, IRoomPlayer, IRoomOptions } from \"./room\";\nimport { MessageEvents } from \"@lib/events/message\";\n\n/**\n * 消息包类型枚举\n */\nexport enum MessageTypes {\n RoomList = \"room.list\",\n RoomCreate = \"room.create\",\n RoomReady = \"room.ready\",\n RoomStart = \"room.start\",\n RoomEnd = \"room.end\",\n RoomClose = \"room.close\",\n RoomAllReady = \"room.allready\",\n RoomCommand = \"room.command\",\n RoomMessage = \"room.message\",\n PlayerOffline = \"player.offline\",\n PlayerList = \"player.list\",\n PlayerLogin = \"player.login\",\n PlayerLogout = \"player.logout\",\n PlayerJoin = \"player.join\",\n PlayerLeave = \"player.leave\",\n PlayerReady = \"player.ready\",\n PlayerUnready = \"player.unready\",\n PlayerCommand = \"player.command\",\n}\n\n/**\n * 消息包接口\n */\nexport interface MessagePackage {\n /**\n * 消息类型\n */\n type: MessageTypes | string;\n /**\n * 消息数据\n */\n data?: PlayerOptions | IRoomOptions | IPlayer | IRoom | IRoomPlayer | any;\n /**\n * 消息发送者\n */\n sender?: IPlayer | IRoom | IRoomPlayer;\n}\n\n/**\n * 消息通信接口\n */\nexport interface Message extends EventEmitter {\n /**\n * 监听消息事件\n * @param event 事件名,具体见 MessageEvents\n * @param listener 监听器\n */\n on<K extends keyof MessageEvents>(event: K, listener: MessageEvents[K]): this;\n /**\n * 触发消息事件\n * @param event 事件名,具体见 MessageEvents\n * @param args 参数\n */\n emit<K extends keyof MessageEvents>(event: K, ...args: Parameters<MessageEvents[K]>): boolean;\n /**\n * 关闭连接\n */\n close(): void;\n /**\n * 发送消息包\n * @param message 消息包\n */\n send(message: MessagePackage): void;\n}\n","import { EventEmitter } from \"events\";\nimport { TiaoomEvents } from \"./events\";\nimport { Message } from \"./models/message\";\nimport { IRoom, IRoomPlayer, Room, IRoomOptions, IRoomPlayerOptions } from \"./models/room\";\nimport { IPlayer, Player, PlayerOptions, PlayerStatus } from \"./models/player\";\n\nexport interface ITiaoomOptions {\n socket: Message;\n}\n\nexport class Tiaoom extends EventEmitter {\n rooms: Room[] = []; // room list\n players: Player[] = []; // player list\n messageInstance?: Message;\n\n constructor({ socket }: ITiaoomOptions) {\n super();\n this.messageInstance = socket;\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 run() {\n this.messageInstance?.on(\"message\", (message: any, cb?: (err: Error | null, data?: any) => any) => {\n try {\n switch (message.type) {\n case \"room.list\":\n return cb?.(null, this.rooms);\n case \"player.list\":\n return cb?.(null, this.players);\n case \"room.create\":\n return this.createRoom(message.sender, message.data);\n case \"player.join\":\n return this.joinPlayer(message.sender, message.data);\n case \"player.leave\":\n return this.leavePlayer(message.sender, message.data);\n case \"room.get\":\n return cb?.(null, this.searchRoom(message.data));\n case \"room.start\":\n return this.startRoom(message.sender, message.data);\n case \"room.kick\":\n return this.kickPlayer(message.sender, message.data);\n case \"room.transfer\":\n return this.transferOwner(message.sender, message.data);\n case \"room.close\":\n return this.closeRoom(message.sender, message.data);\n case \"player.login\":\n return this.loginPlayer(message.data);\n case \"player.logout\":\n return this.removePlayer(message.data);\n case \"player.ready\":\n return this.readyPlayer(message.sender, message.data);\n case \"player.unready\":\n return this.unReadyPlayer(message.sender, message.data);\n case \"room.player-command\":\n return this.searchRoom(message.data)?.emit(\"player-command\", { ...message.data , sender: message.sender });\n case \"room.message\":\n return this.searchRoom(message.data)?.emit(\"message\", message.data);\n case \"global.command\":\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 }\n });\n\n this.on('player', (player, online) => {\n this.messageInstance?.send({ type: online ? 'player.login' : 'player.logout', data: player });\n });\n\n this.on('players', (players) => {\n this.messageInstance?.send({ type: 'player.list', data: players });\n });\n\n this.on('room', (room) => {\n this.messageInstance?.send({ type: 'room.create', data: room });\n });\n\n this.on('room-player', (room) => {\n this.messageInstance?.send({ type: 'room.update', data: room });\n });\n\n this.on('rooms', (rooms) => {\n this.messageInstance?.send({ type: 'room.list', data: rooms });\n });\n\n this.on('command', (data) => {\n this.messageInstance?.send({ type: 'global.command', data });\n });\n\n return this;\n }\n\n searchPlayer(player: string): Player | undefined;\n searchPlayer(player: PlayerOptions | IRoomPlayerOptions): Player | undefined;\n\n searchPlayer(player: PlayerOptions | 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 (!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) => {\n this.messageInstance?.send({ type: `room.${type}`, data: message, sender: room });\n });\n \n this.emit(\"room\", room);\n this.rooms.push(room);\n\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();\n\n return this.emit(\"room-player\", roomInstance);\n }\n\n closeRoom(sender: IPlayer, 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 (roomInstance.players.length && !roomInstance.players.some(p => p.id === sender.id && p.isCreator)) {\n throw new Error('only room creator can close the room.');\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 const senderInRoom = room.searchPlayer(sender);\n if (!senderInRoom || !senderInRoom.isCreator) {\n throw new Error('permission denied.');\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 senderInRoom = room.searchPlayer(sender);\n if (!senderInRoom || !senderInRoom.isCreator) {\n throw new Error('permission denied.');\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 senderInRoom.isCreator = false;\n targetPlayer.isCreator = true;\n\n this.emit(\"room-player\", room);\n return room;\n }\n\n loginPlayer (player: PlayerOptions, cb?: (data: { player: Player }) => void): Player {\n let playerInstance = this.searchPlayer(player);\n if (!playerInstance) {\n playerInstance = new Player(player);\n playerInstance.setSender((type, message) => {\n this.messageInstance?.send({ type: `player.${type}`, data: message, sender: playerInstance });\n });\n this.players.push(playerInstance);\n this.emit(\"player\", playerInstance, true);\n }\n \n playerInstance.emit(\"status\", PlayerStatus.online);\n cb?.({ player: playerInstance });\n return playerInstance;\n }\n\n joinPlayer(sender: IPlayer, player: IRoomPlayerOptions, isCreator: boolean = false) {\n let playerInstance = this.searchPlayer(sender);\n if (!playerInstance) {\n playerInstance = 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 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 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.emit(\"status\", PlayerStatus.ready);\n\n room.emit(\"player-ready\", { ...player, ...roomPlayer });\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.emit(\"status\", PlayerStatus.unready);\n room.emit(\"player-unready\", roomPlayer);\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 if (this.rooms.some(r => r.searchPlayer(player))) {\n setTimeout(() => {\n if (this.players.some(p => p.id === sender.id)) return; // player is online\n this.rooms.filter(r => r.searchPlayer(player)).forEach(r => {\n this.leavePlayer(sender, { ...sender, roomId: r.id });\n });\n }, 5 * 60 * 1000); // 5 minutes later\n }\n }\n return player;\n }\n}\n\nexport * from \"./models/message\";\nexport * from \"./models/room\";\nexport * from \"./models/player\";\nexport * from \"./events\";"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BA,IAAY,wDAAL;;;;AAIL;;;;AAIA;;;;AAIA;;;;AAIA;;;;;;AAgBF,IAAa,SAAb,cAA4BA,eAAgC;;;;;;;CAO1D,GAAiC,OAAU,UAAiC;AAC1E,SAAO,MAAM,GAAG,OAAO,SAAS;;;;;;;;CASlC,KAAmC,OAAU,GAAG,MAA4C;AAC1F,SAAO,MAAM,KAAK,OAAO,GAAG,KAAK;;CASnC,YAAY,EAAE,sBAAK,IAAI,MAAM,EAAC,SAAS,CAAC,UAAU,EAAE,OAAO,IAAI,YAAY,UAAyB;AAClG,SAAO;YAPI;cACE;gBAEQ,aAAa;AAKlC,OAAK,KAAK;AACV,OAAK,OAAO;AACZ,OAAK,aAAa;AAClB,OAAK,SAAS;AAEd,OAAK,GAAG,WAAW,WAAyB;AAC1C,QAAK,SAAS;IACd;AAGF,EAD0C;GAAC;GAAW;GAAW;GAAQ;GAAS;GAAS,CACpF,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;GACd;;CAGH,WAAW;AACT,SAAO,KAAK,UAAU,KAAK,QAAQ,CAAC;;;;;;;CAQtC,UAAU,QAAiD;AACzD,OAAK,SAAS;AACd,SAAO;;;;;;;;;AC7FX,IAAY,oDAAL;;;;AAIL;;;;AAIA;;;;;;AAMF,IAAY,oDAAL;;;;AAIL;;;;AAIA;;;;AAIA;;;;;;AA4CF,IAAa,aAAb,cAAgC,OAA8B;CAM5D,YAAY,QAA0B,OAAmB,WAAW,QAAQ;AAC1E,QAAM,OAAO;iBANI;cACA,WAAW;mBACT;AAKnB,OAAK,OAAO;AACZ,MAAI,kBAAkB,UAAU,OAAO,OAAQ,OAAM,UAAU,OAAO,OAAO;;CAG/E,SAAS;AACP,SAAO;GACL,GAAG,MAAM,QAAQ;GACjB,MAAM,KAAK;GACX,SAAS,KAAK;GACd,WAAW,KAAK;GACjB;;;;;;AAOL,IAAa,OAAb,cAA0BC,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,EACV,sBAAK,IAAI,MAAM,EAAC,SAAS,CAAC,UAAU,EAAE,OAAO,IAAI,OAAO,IAAI,UAAU,GAAG,SACjD;AACxB,SAAO;cAnFM;cACA;iBACG;iBAEM,EAAE;AAgFxB,OAAK,KAAK;AACV,OAAK,OAAO;AACZ,OAAK,OAAO;AACZ,OAAK,UAAU;AACf,OAAK,QAAQ;AAGb,EADwC;GAAC;GAAW;GAAW;GAAS;GAAO;GAAS;GAAS;GAAa;GAAkB;GAAgB;GAAQ;GAAQ,CACzJ,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,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,QAAQ,KAAK;GAAI,GAAG;GAAY,CAAC;AAErD,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,QAAK,KAAK,SAAU;IAAE,QAAQ,KAAK;IAAI,GAAG;IAAW,CAAC;AACtD,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,SAAS,OAAO;AAC9D,SAAO,KAAK,QAAQ,MAAM,aAAWC,SAAO,MAAM,SAAS;;;;;CAM7D,QAAQ;AACN,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,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,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;;;;;;;;;ACnWX,IAAY,wDAAL;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;AChBF,IAAa,SAAb,cAA4BC,oBAAa;CAKvC,YAAY,EAAE,UAA0B;AACtC,SAAO;eALO,EAAE;iBACE,EAAE;AAKpB,OAAK,kBAAkB;;CAGzB,GAAiC,OAAU,UAAiC;AAC1E,QAAM,GAAG,OAAO,SAAS;AACzB,SAAO;;CAGT,KAAmC,OAAU,GAAG,MAA4C;AAC1F,SAAO,MAAM,KAAK,OAAO,GAAG,KAAK;;CAGnC,MAAM;;AACJ,gCAAK,uFAAiB,GAAG,YAAY,SAAc,OAAgD;AACjG,OAAI;AACF,YAAQ,QAAQ,MAAhB;KACE,KAAK,YACH,gDAAO,GAAK,MAAM,KAAK,MAAM;KAC/B,KAAK,cACH,gDAAO,GAAK,MAAM,KAAK,QAAQ;KACjC,KAAK,cACH,QAAO,KAAK,WAAW,QAAQ,QAAQ,QAAQ,KAAK;KACtD,KAAK,cACH,QAAO,KAAK,WAAW,QAAQ,QAAQ,QAAQ,KAAK;KACtD,KAAK,eACH,QAAO,KAAK,YAAY,QAAQ,QAAQ,QAAQ,KAAK;KACvD,KAAK,WACH,gDAAO,GAAK,MAAM,KAAK,WAAW,QAAQ,KAAK,CAAC;KAClD,KAAK,aACH,QAAO,KAAK,UAAU,QAAQ,QAAQ,QAAQ,KAAK;KACrD,KAAK,YACH,QAAO,KAAK,WAAW,QAAQ,QAAQ,QAAQ,KAAK;KACtD,KAAK,gBACH,QAAO,KAAK,cAAc,QAAQ,QAAQ,QAAQ,KAAK;KACzD,KAAK,aACH,QAAO,KAAK,UAAU,QAAQ,QAAQ,QAAQ,KAAK;KACrD,KAAK,eACH,QAAO,KAAK,YAAY,QAAQ,KAAK;KACvC,KAAK,gBACH,QAAO,KAAK,aAAa,QAAQ,KAAK;KACxC,KAAK,eACH,QAAO,KAAK,YAAY,QAAQ,QAAQ,QAAQ,KAAK;KACvD,KAAK,iBACH,QAAO,KAAK,cAAc,QAAQ,QAAQ,QAAQ,KAAK;KACzD,KAAK;;AACH,iCAAO,KAAK,WAAW,QAAQ,KAAK,sEAAE,KAAK,kBAAkB;OAAE,GAAG,QAAQ;OAAO,QAAQ,QAAQ;OAAQ,CAAC;KAC5G,KAAK;;AACH,kCAAO,KAAK,WAAW,QAAQ,KAAK,wEAAE,KAAK,WAAW,QAAQ,KAAK;KACrE,KAAK,iBACH,QAAO,KAAK,KAAK,WAAW;MAAE,GAAG,QAAQ;MAAO,QAAQ,QAAQ;MAAQ,CAAC;KAC3E,QACE,OAAM,IAAI,MAAM,wBAAwB;;YAErC,OAAO;AACd,uCAAK,MAAe;;IAEtB;AAEF,OAAK,GAAG,WAAW,QAAQ,WAAW;;AACpC,kCAAK,yFAAiB,KAAK;IAAE,MAAM,SAAS,iBAAiB;IAAiB,MAAM;IAAQ,CAAC;IAC7F;AAEF,OAAK,GAAG,YAAY,YAAY;;AAC9B,kCAAK,yFAAiB,KAAK;IAAE,MAAM;IAAe,MAAM;IAAS,CAAC;IAClE;AAEF,OAAK,GAAG,SAAS,SAAS;;AACxB,kCAAK,yFAAiB,KAAK;IAAE,MAAM;IAAe,MAAM;IAAM,CAAC;IAC/D;AAEF,OAAK,GAAG,gBAAgB,SAAS;;AAC/B,kCAAK,yFAAiB,KAAK;IAAE,MAAM;IAAe,MAAM;IAAM,CAAC;IAC/D;AAEF,OAAK,GAAG,UAAU,UAAU;;AAC1B,kCAAK,yFAAiB,KAAK;IAAE,MAAM;IAAa,MAAM;IAAO,CAAC;IAC9D;AAEF,OAAK,GAAG,YAAY,SAAS;;AAC3B,kCAAK,yFAAiB,KAAK;IAAE,MAAM;IAAkB;IAAM,CAAC;IAC5D;AAEF,SAAO;;CAMT,aAAa,QAAqD;EAChE,MAAM,WAAW,OAAO,WAAW,WAAW,SAAS,OAAO;AAC9D,SAAO,KAAK,QAAQ,MAAM,WAAW,OAAO,OAAO,SAAS;;CAM9D,WAAW,MAAsC;EAC/C,MAAM,SAAS,OAAO,SAAS,WAAW,OAAO,KAAK;AACtD,SAAO,KAAK,MAAM,MAAM,WAAW,OAAO,OAAO,OAAO;;CAG1D,WAAW,QAAiB,SAAuB;AACjD,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,OAAO,OAAO,GAAG,CAAC,CAC/D,OAAM,IAAI,MAAM,6BAA6B;EAG/C,MAAM,OAAO,IAAI,KAAK,QAAQ;AAC9B,OAAK,WAAW,MAAM,YAAY;;AAChC,kCAAK,yFAAiB,KAAK;IAAE,MAAM,QAAQ;IAAQ,MAAM;IAAS,QAAQ;IAAM,CAAC;IACjF;AAEF,OAAK,KAAK,QAAQ,KAAK;AACvB,OAAK,MAAM,KAAK,KAAK;AAErB,OAAK,WAAW,QAAQ;GAAE,QAAQ,KAAK;GAAI,GAAG;GAAQ,EAAE,KAAK;AAC7D,SAAO;;CAGT,UAAU,QAAiB,MAAa;EACtC,MAAM,eAAe,KAAK,WAAW,KAAK;AAC1C,MAAI,CAAC,aACH,OAAM,IAAI,MAAM,kBAAkB;AAEpC,eAAa,OAAO;AAEpB,SAAO,KAAK,KAAK,eAAe,aAAa;;CAG/C,UAAU,QAAiB,MAAa;EACtC,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,MAAI,aAAa,QAAQ,UAAU,CAAC,aAAa,QAAQ,MAAK,MAAK,EAAE,OAAO,OAAO,MAAM,EAAE,UAAU,CACnG,OAAM,IAAI,MAAM,wCAAwC;AAG1D,SAAO,KAAK,MAAM,OAAO,WAAW,EAAE,CAAC;AAEvC,OAAK,KAAK,SAAS,KAAK,MAAM;AAC9B,eAAa,KAAK,QAAQ;AAC1B,SAAO;;CAGT,WAAW,QAAiB,MAA4C;EACtE,MAAM,OAAO,KAAK,WAAW,KAAK,OAAO;AACzC,MAAI,CAAC,KACH,OAAM,IAAI,MAAM,kBAAkB;EAGpC,MAAM,eAAe,KAAK,aAAa,OAAO;AAC9C,MAAI,CAAC,gBAAgB,CAAC,aAAa,UACjC,OAAM,IAAI,MAAM,qBAAqB;EAGvC,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,cAAc,QAAiB,MAA4C;EACzE,MAAM,OAAO,KAAK,WAAW,KAAK,OAAO;AACzC,MAAI,CAAC,KACH,OAAM,IAAI,MAAM,kBAAkB;EAGpC,MAAM,eAAe,KAAK,aAAa,OAAO;AAC9C,MAAI,CAAC,gBAAgB,CAAC,aAAa,UACjC,OAAM,IAAI,MAAM,qBAAqB;EAGvC,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,eAAa,YAAY;AACzB,eAAa,YAAY;AAEzB,OAAK,KAAK,eAAe,KAAK;AAC9B,SAAO;;CAGT,YAAa,QAAuB,IAAiD;EACnF,IAAI,iBAAiB,KAAK,aAAa,OAAO;AAC9C,MAAI,CAAC,gBAAgB;AACnB,oBAAiB,IAAI,OAAO,OAAO;AACnC,kBAAe,WAAW,MAAM,YAAY;;AAC1C,mCAAK,yFAAiB,KAAK;KAAE,MAAM,UAAU;KAAQ,MAAM;KAAS,QAAQ;KAAgB,CAAC;KAC7F;AACF,QAAK,QAAQ,KAAK,eAAe;AACjC,QAAK,KAAK,UAAU,gBAAgB,KAAK;;AAG3C,iBAAe,KAAK,UAAU,aAAa,OAAO;AAClD,qCAAK,EAAE,QAAQ,gBAAgB,CAAC;AAChC,SAAO;;CAGT,WAAW,QAAiB,QAA4B,YAAqB,OAAO;EAClF,IAAI,iBAAiB,KAAK,aAAa,OAAO;AAC9C,MAAI,CAAC,eACH,kBAAiB,KAAK,YAAY,OAAO;AAG3C,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;EAGpC,MAAM,aAAa,KAAK,UAAU,gBAAgB,UAAU;AAC5D,MAAI,WACF,MAAK,KAAK,eAAe,KAAK;AAGhC,SAAO;;CAGT,YAAY,QAAiB,QAA4B;AACvD,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,YAAY,QAAiB,QAAqB;EAChD,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,KAAK,UAAU,aAAa,MAAM;AAEjD,OAAK,KAAK,gBAAgB;GAAE,GAAG;GAAQ,GAAG;GAAY,CAAC;AAEvD,SAAO;;CAGT,cAAc,QAAiB,QAAqB;EAClD,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,KAAK,UAAU,aAAa,QAAQ;AACnD,OAAK,KAAK,kBAAkB,WAAW;AAEvC,SAAO;;CAGT,aAAa,QAAiB;EAC5B,MAAM,cAAc,KAAK,QAAQ,WAAW,MAAM,EAAE,OAAO,OAAO,GAAG;EACrE,MAAM,SAAS,KAAK,QAAQ;AAC5B,MAAI,cAAc,IAAI;AACpB,QAAK,QAAQ,OAAO,aAAa,EAAE,CAAC;AACpC,QAAK,KAAK,UAAU,QAAQ,MAAM;AAClC,OAAI,KAAK,MAAM,MAAK,MAAK,EAAE,aAAa,OAAO,CAAC,CAC9C,kBAAiB;AACf,QAAI,KAAK,QAAQ,MAAK,MAAK,EAAE,OAAO,OAAO,GAAG,CAAE;AAChD,SAAK,MAAM,QAAO,MAAK,EAAE,aAAa,OAAO,CAAC,CAAC,SAAQ,MAAK;AAC1D,UAAK,YAAY,QAAQ;MAAE,GAAG;MAAQ,QAAQ,EAAE;MAAI,CAAC;MACrD;MACD,MAAS,IAAK;;AAGrB,SAAO"}