tiaoom 0.0.2 → 0.0.4

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,30 +175,63 @@ 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
  }
@@ -187,19 +279,44 @@ var Room = class extends events.default {
187
279
  });
188
280
  });
189
281
  }
282
+ /**
283
+ * 设置房主
284
+ * @param {Player} player 玩家
285
+ * @returns this
286
+ */
287
+ setCreator(player) {
288
+ const roomPlayer = this.searchPlayer(player);
289
+ if (roomPlayer) {
290
+ this.players.forEach((p) => {
291
+ p.isCreator = false;
292
+ });
293
+ roomPlayer.isCreator = true;
294
+ this.emit("update", this);
295
+ }
296
+ return this;
297
+ }
298
+ /**
299
+ *
300
+ * @param {Player} player 玩家
301
+ * @param {boolean} isCreator 是否房主
302
+ * @returns 玩家实例
303
+ */
190
304
  addPlayer(player, isCreator = false) {
191
305
  if (this.players.some((p) => p.id == player.id)) return;
192
306
  let roomPlayer = this.searchPlayer(player);
193
- if (!roomPlayer) {
194
- roomPlayer = new RoomPlayer(player, this.isFull || this.isPlaying ? PlayerRole.watcher : PlayerRole.player);
195
- roomPlayer.isCreator = isCreator;
196
- roomPlayer.roomId = this.id;
197
- this.players.push(roomPlayer);
198
- this.emit("join", {
199
- roomId: this.id,
200
- ...roomPlayer
201
- });
202
- }
307
+ if (roomPlayer) return;
308
+ if (this.isFull && !isCreator) throw new Error("room is full.");
309
+ if (isCreator) this.players.forEach((p) => {
310
+ p.isCreator = false;
311
+ });
312
+ roomPlayer = new RoomPlayer(player, this.isFull || this.isPlaying ? PlayerRole.watcher : PlayerRole.player);
313
+ roomPlayer.isCreator = isCreator;
314
+ roomPlayer.roomId = this.id;
315
+ this.players.push(roomPlayer);
316
+ this.emit("join", {
317
+ roomId: this.id,
318
+ ...roomPlayer
319
+ });
203
320
  return roomPlayer;
204
321
  }
205
322
  kickPlayer(player) {
@@ -223,6 +340,9 @@ var Room = class extends events.default {
223
340
  const playerId = typeof player === "string" ? player : player.id;
224
341
  return this.players.find((player$1) => player$1.id == playerId);
225
342
  }
343
+ /**
344
+ * 开始游戏
345
+ */
226
346
  start() {
227
347
  if (!this.isReady) throw new Error("room is not ready.");
228
348
  if (this.status === RoomStatus.playing) throw new Error("room is already started.");
@@ -233,6 +353,9 @@ var Room = class extends events.default {
233
353
  this.emit("update", this);
234
354
  return this.emit("start", this);
235
355
  }
356
+ /**
357
+ * 结束游戏
358
+ */
236
359
  end() {
237
360
  this.players.forEach((player) => {
238
361
  if (player.role != PlayerRole.player) return;
@@ -241,6 +364,10 @@ var Room = class extends events.default {
241
364
  this.emit("update", this);
242
365
  return this.emit("end", this);
243
366
  }
367
+ /**
368
+ * 设置消息发送器
369
+ * @param sender 消息发送器
370
+ */
244
371
  setSender(sender) {
245
372
  this.sender = sender;
246
373
  return this;
@@ -249,6 +376,9 @@ var Room = class extends events.default {
249
376
 
250
377
  //#endregion
251
378
  //#region lib/models/message.ts
379
+ /**
380
+ * 消息包类型枚举
381
+ */
252
382
  let MessageTypes = /* @__PURE__ */ function(MessageTypes$1) {
253
383
  MessageTypes$1["RoomList"] = "room.list";
254
384
  MessageTypes$1["RoomCreate"] = "room.create";
@@ -299,6 +429,8 @@ var Tiaoom = class extends events.EventEmitter {
299
429
  case "player.leave": return this.leavePlayer(message.sender, message.data);
300
430
  case "room.get": return cb === null || cb === void 0 ? void 0 : cb(null, this.searchRoom(message.data));
301
431
  case "room.start": return this.startRoom(message.sender, message.data);
432
+ case "room.kick": return this.kickPlayer(message.sender, message.data);
433
+ case "room.transfer": return this.transferOwner(message.sender, message.data);
302
434
  case "room.close": return this.closeRoom(message.sender, message.data);
303
435
  case "player.login": return this.loginPlayer(message.data);
304
436
  case "player.logout": return this.removePlayer(message.data);
@@ -412,6 +544,30 @@ var Tiaoom = class extends events.EventEmitter {
412
544
  roomInstance.emit("close");
413
545
  return room;
414
546
  }
547
+ kickPlayer(sender, data) {
548
+ const room = this.searchRoom(data.roomId);
549
+ if (!room) throw new Error("room not found.");
550
+ const senderInRoom = room.searchPlayer(sender);
551
+ if (!senderInRoom || !senderInRoom.isCreator) throw new Error("permission denied.");
552
+ const targetPlayer = room.players.find((p) => p.id === data.playerId);
553
+ if (!targetPlayer) throw new Error("player not found in room.");
554
+ const roomPlayer = room.kickPlayer(targetPlayer);
555
+ if (roomPlayer) this.emit("room-player", room);
556
+ return roomPlayer;
557
+ }
558
+ transferOwner(sender, data) {
559
+ const room = this.searchRoom(data.roomId);
560
+ if (!room) throw new Error("room not found.");
561
+ const senderInRoom = room.searchPlayer(sender);
562
+ if (!senderInRoom || !senderInRoom.isCreator) throw new Error("permission denied.");
563
+ const targetPlayer = room.players.find((p) => p.id === data.playerId);
564
+ if (!targetPlayer) throw new Error("player not found in room.");
565
+ if (targetPlayer.id === sender.id) return;
566
+ senderInRoom.isCreator = false;
567
+ targetPlayer.isCreator = true;
568
+ this.emit("room-player", room);
569
+ return room;
570
+ }
415
571
  loginPlayer(player, cb) {
416
572
  let playerInstance = this.searchPlayer(player);
417
573
  if (!playerInstance) {
@@ -438,8 +594,7 @@ var Tiaoom = class extends events.EventEmitter {
438
594
  const room = this.rooms.find((room$1) => room$1.id === player.roomId);
439
595
  if (!room) throw new Error("room not found.");
440
596
  const roomPlayer = room.addPlayer(playerInstance, isCreator);
441
- if (!roomPlayer) throw new Error("room is full.");
442
- this.emit("room-player", room);
597
+ if (roomPlayer) this.emit("room-player", room);
443
598
  return roomPlayer;
444
599
  }
445
600
  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 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.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 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 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 /**\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 if (this.players.some((p) => p.id == player.id)) return;\n let roomPlayer = this.searchPlayer(player);\n if (roomPlayer) return;\n\n if (this.isFull && !isCreator) {\n throw new Error('room is full.');\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":"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"}