tiaoom 0.0.1 → 0.0.2

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/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  </p>
4
4
 
5
5
  <h1 align="center">Tiaoom - a Tiaoable project</h1>
6
- <p align="center">组件化游戏房间管理系统</p>
6
+ <p align="center">组件化游戏房间管理开发包</p>
7
7
 
8
8
  ## ✨功能
9
9
  - 玩家注册与登录;
@@ -11,13 +11,41 @@
11
11
  - 房间内玩家实时互动;
12
12
  - 可扩展的游戏逻辑接口;
13
13
 
14
- ## 🎮 实现游戏
14
+ ## 🚀 快速开始
15
15
 
16
- 实现新的游戏只需编写三个文件:
16
+ - 安装包 `tiaoom`:
17
17
 
18
- - game/games/yourgame.js - 游戏逻辑入口与配置信息;
19
- - game/public/games/yourgame.js - 游戏前端组件;
20
- - game/views/games/yourgame.ejs - 游戏视图;
18
+ ```bash
19
+ npm install tiaoom
20
+ ```
21
+
22
+ 后端从 `tiaoom` 引入 `Tiaoom`,并继承实现通信方法:
23
+
24
+ ```typescript
25
+ import { Tiaoom } from 'tiaoom';
26
+
27
+ class YourGameServer extends Tiaoom {
28
+ // 实现通信方法
29
+ }
30
+ ```
31
+ > 具体见 `game/backend/src/controller.ts`
32
+
33
+ 前端则从 `tiaoom/client` 引入 `Tiaoom`,并继承实现通信方法:
34
+
35
+ ```typescript
36
+ import { Tiaoom } from 'tiaoom/client';
37
+ class YourGameClient extends Tiaoom {
38
+ // 实现通信方法
39
+ }
40
+ ```
41
+ > 具体见 `game/frontend/src/core/game.ts`
42
+
43
+ ## 🎮 实现游戏示例
44
+
45
+ 本仓库内置一个基于 Websocket 为通信协议的游戏服务,实现新的游戏只需编写三个文件:
46
+
47
+ - game/backend/src/games/yourgame.js - 游戏逻辑入口与配置信息;
48
+ - game/frontend/src/components/yourgame/YourGameRoom.vue - 游戏前端组件;
21
49
 
22
50
  完成后重启服务即可在前端选择运行游戏。
23
51
 
@@ -32,7 +60,7 @@
32
60
  1. 执行`npm install`;
33
61
  2. 使用 Visual Studio Code 运行调试(直接按下`F5`即可)。
34
62
 
35
- > 本地调试可移除 `game/src/index.ts` 中的`login: 'fishpi'`,即可切换为用户名登录模式。
63
+ > 本地调试可修改 `game/frontend/src/views/Login.vue` 中的`const loginType = ref('fishpi')` 为 `normal`,即可切换为用户名登录模式。
36
64
 
37
65
  ## 📁 目录与文件
38
66
  - .vscode - VSCode 调试配置
@@ -42,17 +70,20 @@
42
70
  - message.ts - 消息基础模型
43
71
  - player.ts - 玩家基础模型
44
72
  - room.ts - 房间基础模型
45
- - index.ts - 类库入口
46
- - game - 游戏示例入口
47
- - games - 各个游戏逻辑实现
48
- - src - 游戏后端服务
49
- - login - 登录服务
50
- - controller.ts - 游戏房间控制器
51
- - socket.ts - 游戏通信实现
52
- - index.ts - 游戏服务入口
53
- - views - 游戏视图文件
54
- - games - 各个游戏视图
55
- - index.ejs - 游戏主视图
56
- - login.ejs - 登录视图
57
- - public - 游戏前端脚本与样式
58
- - games - 各个游戏前端脚本
73
+ - client - 前端类库入口
74
+ - index.ts - 后端类库入口
75
+ - game - 游戏示例
76
+ - backend - 后端实现
77
+ - src
78
+ - controller.ts - 后端控制器实现
79
+ - index.ts - 后端入口
80
+ - games - 游戏逻辑实现
81
+ - frontend - 前端实现
82
+ - public - 静态资源
83
+ - src
84
+ - assets - 资源文件
85
+ - components - 游戏组件文件
86
+ - core - 前端核心类库实现
87
+ - views - 视图文件
88
+ - App.vue - 根组件
89
+ - main.ts - 前端入口
package/package.json CHANGED
@@ -1,10 +1,17 @@
1
1
  {
2
2
  "name": "tiaoom",
3
- "version": "0.0.1",
3
+ "version": "0.0.2",
4
4
  "description": "",
5
5
  "main": "./src/index.cjs",
6
6
  "module": "./src/index.mjs",
7
- "types": "./src/index.d.ts",
7
+ "types": "./src/index.d.cts",
8
+ "typesVersions": {
9
+ "*": {
10
+ "client": [
11
+ "./src/client.d.ts"
12
+ ]
13
+ }
14
+ },
8
15
  "scripts": {
9
16
  "prepare": "npm run build",
10
17
  "test": "node -r tsconfig-paths/register -r ts-node/register ./game/index.ts",
package/src/client.cjs CHANGED
@@ -1,2 +1,2 @@
1
- var e=class{constructor(e){this.id=e.id,this.name=e.name,this.attributes=e.attributes,this.status=e.status}},t=class extends e{constructor(e){super(e),this.role=e.role,this.isReady=e.isReady,this.isCreator=e.isCreator}},n=class{constructor(e){this.id=e.id,this.name=e.name,this.players=e.players.map(e=>new t(e)),this.size=e.size,this.minSize=e.minSize,this.status=e.status,this.attrs=e.attrs}},r=class{constructor(){this.listeners={},this.rooms=[],this.players=[],this.currentPlayer=null}run(){return this.connect(),this.onReady(()=>{this.send({type:`room.list`}),this.send({type:`player.list`})}),this.on(`player.list`,t=>{this.players=t.map(t=>new e(t)),this.emit(`onPlayerList`,[...this.players])}),this.on(`player.login`,t=>{this.players.push(new e(t)),this.emit(`onPlayerList`,[...this.players])}),this.on(`player.logout`,e=>{this.players=this.players.filter(t=>t.id!==e.id),this.emit(`onPlayerList`,[...this.players])}),this.on(`room.list`,e=>{this.rooms=e.map(e=>new n(e)),this.emit(`onRoomList`,[...this.rooms])}),this.on(`room.create`,e=>{this.rooms.push(new n(e)),this.emit(`onRoomList`,this.rooms)}),this.on(`room.update`,e=>{let t=this.rooms.find(t=>t.id===e.id);t?Object.assign(t,e):this.rooms.push(new n(e)),this.emit(`onRoomList`,this.rooms)}),this.on(`room.close`,e=>{this.rooms=this.rooms.filter(t=>t.id!==e.id),this.emit(`onRoomList`,this.rooms)}),this.on(`room.update`,e=>{let t=this.rooms.find(t=>t.id===e.id);t&&(Object.assign(t,e),this.emit(`onRoomList`,this.rooms))}),this}connect(){throw Error(`Must be implement connect method`)}send(e){throw Error(`Must be implement send method`)}login(t){return this.currentPlayer=new e(t),this.send({type:`player.login`,data:t}),this}createRoom({name:e,size:t,minSize:n,attrs:r}){return new Promise(i=>{this.send({type:`room.create`,data:{name:e,size:t,minSize:n,attrs:r}}),this.on(`room.create`,e=>{i()})})}joinRoom(e){return this.send({type:`player.join`,data:{roomId:e}}),this}leaveRoom(e){return this.send({type:`player.leave`,data:{roomId:e}}),this}startGame(e){return this.send({type:`room.start`,data:{id:e}}),this}ready(e,t=!0){return this.send({type:t?`player.ready`:`player.unready`,data:{roomId:e}}),this}command(e,t){return typeof e==`string`?this.send({type:`room.player-command`,data:{id:e,...t}}):(t=e,this.send({type:`global.command`,data:t})),this}onReady(e){return this.on(`sys.ready`,e)}onPlayerList(e){return this.on(`onPlayerList`,e),this}onRoomList(e,t=!0){return t?this.on(`onRoomList`,e):this.off(`onRoomList`,e),this}onPlayerJoin(e,t=!0){return t?this.on(`room.join`,e):this.off(`room.join`,e),this}onPlayerLeave(e,t=!0){return t?this.on(`room.leave`,e):this.off(`room.leave`,e),this}onPlayerReady(e,t=!0){return t?this.on(`room.player-ready`,e):this.off(`room.player-ready`,e),this}onPlayerUnready(e,t=!0){return t?this.on(`room.player-unready`,e):this.off(`room.player-unready`,e),this}onPlayerStatus(e,t=!0){return t?this.on(`player.status`,e):this.off(`player.status`,e),this}onRoomStart(e,t=!0){return this.listeners[`room.start`]||this.on(`room.start`,e=>this.emit(`onRoomStart`,new n(e))),t?this.on(`onRoomStart`,e):this.off(`onRoomStart`,e),this}onRoomEnd(e,t=!0){return this.listeners[`room.end`]||this.on(`room.end`,e=>this.emit(`onRoomEnd`,new n(e))),t?this.on(`onRoomEnd`,e):this.off(`onRoomEnd`,e),this}onRoomAllReady(e,t=!0){return this.listeners[`room.all-ready`]||this.on(`room.all-ready`,e=>this.emit(`onRoomAllReady`,new n(e))),t?this.on(`onRoomAllReady`,e):this.off(`onRoomAllReady`,e),this}onRoomMessage(e,t=!0){return t?this.on(`room.message`,e):this.off(`room.message`,e),this}onPlayerMessage(e,t=!0){return t?this.on(`player.message`,e):this.off(`player.message`,e),this}onRoomCommand(e,t=!0){return t?this.on(`room.command`,e):this.off(`room.command`,e),this}onPlayerCommand(e,t=!0){return t?this.on(`player.command`,e):this.off(`player.command`,e),this}on(e,t){return this.listeners[e]=this.listeners[e]||[],this.listeners[e].push(t),this}off(e,t){let n=this.listeners[e]||[],r=n.indexOf(t);return r!==-1&&n.splice(r,1),this}emit(e,...t){return(this.listeners[e]||[]).forEach(e=>e(...t)),this}};exports.Player=e,exports.Room=n,exports.RoomPlayer=t,exports.Tiaoom=r;
1
+ var e=class{constructor(e){this.id=e.id||Date.now().toString(),this.name=e.name||`玩家`+this.id,this.attributes=e.attributes||{},this.status=e.status||`online`}},t=class extends e{constructor(e){super(e),this.role=e.role,this.isReady=e.isReady,this.isCreator=e.isCreator}},n=class{constructor(e){this.id=e.id,this.name=e.name,this.players=e.players.map(e=>new t(e)),this.size=e.size,this.minSize=e.minSize,this.status=e.status,this.attrs=e.attrs}},r=class{constructor(){this.listeners={},this.rooms=[],this.players=[],this.currentPlayer=null}run(){return this.connect(),this.onReady(()=>{this.send({type:`room.list`}),this.send({type:`player.list`})}),this.on(`player.list`,t=>{this.players=t.map(t=>new e(t)),this.emit(`onPlayerList`,[...this.players])}),this.on(`player.login`,t=>{this.players.push(new e(t)),this.emit(`onPlayerList`,[...this.players])}),this.on(`player.logout`,e=>{this.players=this.players.filter(t=>t.id!==e.id),this.emit(`onPlayerList`,[...this.players])}),this.on(`room.list`,e=>{this.rooms=e.map(e=>new n(e)),this.emit(`onRoomList`,[...this.rooms])}),this.on(`room.create`,e=>{this.rooms.push(new n(e)),this.emit(`onRoomList`,this.rooms)}),this.on(`room.update`,e=>{let t=this.rooms.find(t=>t.id===e.id);t?Object.assign(t,e):this.rooms.push(new n(e)),this.emit(`onRoomList`,this.rooms)}),this.on(`room.close`,e=>{this.rooms=this.rooms.filter(t=>t.id!==e.id),this.emit(`onRoomList`,this.rooms)}),this.on(`room.update`,e=>{let t=this.rooms.find(t=>t.id===e.id);t&&(Object.assign(t,e),this.emit(`onRoomList`,this.rooms))}),this}connect(){throw Error(`Must be implement connect method`)}send(e){throw Error(`Must be implement send method`)}login(t){return this.currentPlayer=new e(t),this.send({type:`player.login`,data:t}),this}createRoom({name:e,size:t,minSize:n,attrs:r}){return new Promise(i=>{this.send({type:`room.create`,data:{name:e,size:t,minSize:n,attrs:r}}),this.on(`room.create`,e=>{i()})})}joinRoom(e){return this.send({type:`player.join`,data:{roomId:e}}),this}leaveRoom(e){return this.send({type:`player.leave`,data:{roomId:e}}),this}startGame(e){return this.send({type:`room.start`,data:{id:e}}),this}ready(e,t=!0){return this.send({type:t?`player.ready`:`player.unready`,data:{roomId:e}}),this}command(e,t){return typeof e==`string`?this.send({type:`room.player-command`,data:{id:e,...t}}):(t=e,this.send({type:`global.command`,data:t})),this}onReady(e){return this.on(`sys.ready`,e)}onPlayerList(e){return this.on(`onPlayerList`,e),this}onRoomList(e,t=!0){return t?this.on(`onRoomList`,e):this.off(`onRoomList`,e),this}onPlayerJoin(e,t=!0){return t?this.on(`room.join`,e):this.off(`room.join`,e),this}onPlayerLeave(e,t=!0){return t?this.on(`room.leave`,e):this.off(`room.leave`,e),this}onPlayerReady(e,t=!0){return t?this.on(`room.player-ready`,e):this.off(`room.player-ready`,e),this}onPlayerUnready(e,t=!0){return t?this.on(`room.player-unready`,e):this.off(`room.player-unready`,e),this}onPlayerStatus(e,t=!0){return t?this.on(`player.status`,e):this.off(`player.status`,e),this}onRoomStart(e,t=!0){return this.listeners[`room.start`]||this.on(`room.start`,e=>this.emit(`onRoomStart`,new n(e))),t?this.on(`onRoomStart`,e):this.off(`onRoomStart`,e),this}onRoomEnd(e,t=!0){return this.listeners[`room.end`]||this.on(`room.end`,e=>this.emit(`onRoomEnd`,new n(e))),t?this.on(`onRoomEnd`,e):this.off(`onRoomEnd`,e),this}onRoomAllReady(e,t=!0){return this.listeners[`room.all-ready`]||this.on(`room.all-ready`,e=>this.emit(`onRoomAllReady`,new n(e))),t?this.on(`onRoomAllReady`,e):this.off(`onRoomAllReady`,e),this}onRoomMessage(e,t=!0){return t?this.on(`room.message`,e):this.off(`room.message`,e),this}onPlayerMessage(e,t=!0){return t?this.on(`player.message`,e):this.off(`player.message`,e),this}onRoomCommand(e,t=!0){return t?this.on(`room.command`,e):this.off(`room.command`,e),this}onPlayerCommand(e,t=!0){return t?this.on(`player.command`,e):this.off(`player.command`,e),this}on(e,t){return this.listeners[e]=this.listeners[e]||[],this.listeners[e].push(t),this}off(e,t){let n=this.listeners[e]||[],r=n.indexOf(t);return r!==-1&&n.splice(r,1),this}emit(e,...t){return(this.listeners[e]||[]).forEach(e=>e(...t)),this}};exports.Player=e,exports.Room=n,exports.RoomPlayer=t,exports.Tiaoom=r;
2
2
  //# sourceMappingURL=client.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.cjs","names":[],"sources":["../lib/client.ts"],"sourcesContent":["export type TiaoomEvents = {\n /**\n * 连接准备就绪事件\n */\n \"sys.ready\": () => void;\n /**\n * 连接错误事件\n * @param error 错误信息\n */\n \"sys.error\": (error: any) => void;\n /**\n * 连接关闭事件\n */\n \"sys.close\": () => void;\n /**\n * 全局命令事件\n * @param data 命令内容\n */\n \"global.command\": (data: any & { sender: Player }) => void;\n /**\n * 玩家列表更新事件\n * @param players 玩家列表\n */\n \"player.list\": (players: Player[]) => void;\n /**\n * 玩家登录事件\n * @param player 玩家信息\n */\n \"player.login\": (player: Player) => void;\n /**\n * 玩家登出事件\n * @param player 玩家信息\n */\n \"player.logout\": (player: Player) => void;\n /**\n * 玩家状态更新事件\n * @param player 玩家信息\n * @param status 状态\n * @param roomId 房间ID(可选)\n */\n \"player.status\": (player: Player, status: string, roomId?: string) => void;\n /**\n * 玩家命令事件\n * @param command 命令内容\n */\n \"player.command\": (command: any & { sender: Player }) => void;\n /**\n * 玩家消息事件\n * @param message 消息内容\n */\n \"player.message\": (message: any & { sender: Player }) => void;\n /**\n * 房间列表更新事件\n * @param rooms 房间列表\n */\n \"room.list\": (rooms: Room[]) => void;\n /**\n * 房间创建事件\n * @param room 房间信息\n */\n \"room.create\": (room: Room) => void;\n /**\n * 房间更新事件\n * @param room 房间信息\n */\n \"room.update\": (room: Room) => void;\n /**\n * 房间关闭事件\n * @param room 房间信息\n */\n \"room.close\": (room: Room) => void;\n /**\n * 玩家加入房间事件\n * @param room 房间信息\n * @param player 玩家信息\n */\n \"room.join\": (room: Room, player: Player) => void;\n /**\n * 玩家离开房间事件\n * @param room 房间信息\n * @param player 玩家信息\n */\n \"room.leave\": (room: Room, player: Player) => void;\n /**\n * 房间开始游戏事件\n * @param room 房间信息\n */\n \"room.start\": (room: Room) => void;\n /**\n * 房间结束游戏事件\n * @param room 房间信息\n */\n \"room.end\": (room: Room) => void;\n /**\n * 房间玩家全部准备事件\n * @param room 房间信息\n */\n \"room.all-ready\": (room: Room) => void;\n /**\n * 房间命令事件\n * @param command 命令内容\n */\n \"room.command\": (command: any & { sender: Player }) => void;\n /**\n * 房间消息事件\n * @param message 消息内容\n */\n \"room.message\": (message: any & { sender: Player }) => void;\n /**\n * 房间玩家准备事件\n * @param player 玩家信息\n * @param roomId 房间ID(可选)\n */\n \"room.player-ready\": (player: Player, roomId?: string) => void;\n /**\n * 房间玩家取消准备事件\n * @param player 玩家信息\n * @param roomId 房间ID(可选)\n */\n \"room.player-unready\": (player: Player, roomId?: string) => void;\n /**\n * 玩家列表更新事件(内部)\n * @param players 玩家列表\n */\n \"onPlayerList\": (players: Player[]) => void;\n /**\n * 房间列表更新事件(内部)\n * @param rooms 房间列表\n */\n \"onRoomList\": (rooms: Room[]) => void;\n /**\n * 房间开始游戏事件(内部)\n * @param room 房间信息\n */\n \"onRoomStart\": (room: Room) => void;\n /**\n * 房间结束游戏事件(内部)\n * @param room 房间信息\n */\n \"onRoomEnd\": (room: Room) => void;\n /**\n * 房间玩家全部准备事件(内部)\n * @param room 房间信息\n */\n \"onRoomAllReady\": (room: Room) => void;\n};\n\nexport class Player {\n id: string;\n name: string;\n attributes: Record<string, any>;\n status: string;\n constructor(player: Player) {\n this.id = player.id;\n this.name = player.name;\n this.attributes = player.attributes;\n this.status = player.status;\n }\n}\n\nexport class RoomPlayer extends Player {\n role: string;\n isReady: boolean;\n isCreator: boolean;\n constructor(player: RoomPlayer) {\n super(player);\n this.role = player.role;\n this.isReady = player.isReady;\n this.isCreator = player.isCreator;\n }\n}\n\nexport class Room {\n id: string;\n name: string;\n players: RoomPlayer[];\n size: number;\n minSize: number;\n status: string;\n attrs: Record<string, any>;\n constructor(room: Room) {\n this.id = room.id;\n this.name = room.name;\n this.players = room.players.map(player => new RoomPlayer(player));\n this.size = room.size;\n this.minSize = room.minSize;\n this.status = room.status;\n this.attrs = room.attrs;\n }\n}\n\n/**\n * Tiaoom 客户端\n * @description 用于连接 Tiaoom 服务器并进行游戏交互,如创建房间、加入房间、发送命令等。\n * 需继承后实现具体的连接和消息发送逻辑。\n */\nexport class Tiaoom {\n listeners: Record<string, Function[]>;\n rooms: Room[];\n players: Player[];\n currentPlayer: Player | null;\n constructor() {\n this.listeners = {};\n this.rooms = [];\n this.players = [];\n this.currentPlayer = null;\n }\n\n /**\n * 启动游戏\n */\n run() {\n this.connect();\n this.onReady(() => {\n this.send({ type: \"room.list\" });\n this.send({ type: \"player.list\" });\n });\n\n this.on(\"player.list\", (players) => {\n this.players = players.map(player => new Player(player));\n this.emit('onPlayerList', [...this.players]);\n });\n this.on(\"player.login\", (player) => {\n this.players.push(new Player(player));\n this.emit('onPlayerList', [...this.players]);\n });\n this.on(\"player.logout\", (player) => {\n this.players = this.players.filter(p => p.id !== player.id);\n this.emit('onPlayerList', [...this.players]);\n });\n\n\n this.on(\"room.list\", (rooms) => {\n this.rooms = rooms.map(room => new Room(room));\n this.emit('onRoomList', [...this.rooms]);\n });\n this.on(\"room.create\", (room) => {\n this.rooms.push(new Room(room));\n this.emit('onRoomList', this.rooms);\n });\n this.on(\"room.update\", (room) => {\n const existingRoom = this.rooms.find(r => r.id === room.id);\n if (!existingRoom) {\n this.rooms.push(new Room(room));\n } else {\n Object.assign(existingRoom, room);\n }\n this.emit('onRoomList', this.rooms);\n });\n this.on(\"room.close\", (room) => {\n this.rooms = this.rooms.filter(r => r.id !== room.id);\n this.emit('onRoomList', this.rooms);\n });\n this.on(\"room.update\", (room) => {\n const updatedRoom = this.rooms.find(r => r.id === room.id);\n if (updatedRoom) {\n Object.assign(updatedRoom, room);\n this.emit('onRoomList', this.rooms);\n }\n });\n\n return this;\n }\n\n /**\n * 连接服务器实现\n */\n connect() {\n throw new Error('Must be implement connect method');\n }\n\n /**\n * 发送消息实现\n */\n send(_: { type: string, data?: any }) {\n throw new Error('Must be implement send method');\n }\n\n /**\n * 登录\n * @param {Player} player 玩家信息\n */\n login(player: Player) {\n this.currentPlayer = new Player(player);\n this.send({ type: \"player.login\", data: player });\n return this;\n }\n\n /**\n * 创建房间\n * @param {string} name 房间名称\n * @param {number} size 房间人数上限\n * @param {number} minSize 房间人数下限\n * @param {object} attrs 房间属性\n */\n createRoom({ name, size, minSize, attrs }: { name: string, size: number, minSize: number, attrs?: Record<string, any> }) {\n return new Promise<void>((resolve) => {\n this.send({ type: \"room.create\", data: { name, size, minSize, attrs } });\n this.on(\"room.create\", (room) => {\n resolve();\n });\n });\n }\n\n /**\n * 加入房间\n * @param {string} roomId 房间ID\n */\n joinRoom(roomId: string) {\n this.send({ type: \"player.join\", data: { roomId } });\n return this;\n }\n\n /**\n * 离开房间\n * @param {string} roomId 房间ID\n */\n leaveRoom(roomId: string) {\n this.send({ type: \"player.leave\", data: { roomId } });\n return this;\n }\n\n /**\n * 开始游戏\n * @param {string} id 房间ID\n */\n startGame(id: string) {\n this.send({ type: \"room.start\", data: { id } });\n return this;\n }\n\n /**\n * 准备/取消准备\n * @param {string} roomId 房间ID\n * @param {boolean} isReady 是否准备\n */\n ready(roomId: string, isReady=true) {\n this.send({ type: isReady ? \"player.ready\" : \"player.unready\", data: { roomId } });\n return this;\n }\n\n /**\n * 发送房间指令\n * @param {string} roomId 房间ID\n * @param {any} command 指令内容\n */\n command(command: any): this;\n command(roomId: string, command: any): this;\n command(roomId: string | any, command?: any) {\n if (typeof roomId != 'string') {\n command = roomId;\n this.send({ type: \"global.command\", data: command });\n } else {\n this.send({ type: \"room.player-command\", data: { id: roomId, ...command } });\n }\n return this;\n }\n\n /**\n * 连接准备监听\n * @param {function} cb 监听函数\n */\n onReady(cb: (...args: any[]) => void) {\n return this.on(\"sys.ready\", cb);\n }\n\n /**\n * 玩家列表变更监听\n * @param {function} cb 监听函数\n */\n onPlayerList(cb: (...args: any[]) => void) {\n this.on(\"onPlayerList\", cb);\n return this;\n }\n\n /**\n * 房间列表变更监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onRoomList(cb: (...args: any[]) => void, on=true) {\n if (on) this.on(\"onRoomList\", cb);\n else this.off(\"onRoomList\", cb);\n return this;\n }\n\n /**\n * 玩家加入监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onPlayerJoin(cb: (...args: any[]) => void, on=true) {\n if (on) this.on(\"room.join\", cb);\n else this.off(\"room.join\", cb);\n return this;\n }\n\n /**\n * 玩家离开监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onPlayerLeave(cb: (...args: any[]) => void, on=true) {\n if (on) this.on(\"room.leave\", cb);\n else this.off(\"room.leave\", cb);\n return this;\n }\n\n /**\n * 玩家准备监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onPlayerReady(cb: (...args: any[]) => void, on=true) {\n if (on) this.on(\"room.player-ready\", cb);\n else this.off(\"room.player-ready\", cb);\n return this;\n }\n\n /**\n * 玩家取消准备监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onPlayerUnready(cb: (...args: any[]) => void, on=true) {\n if (on) this.on(\"room.player-unready\", cb);\n else this.off(\"room.player-unready\", cb);\n return this;\n }\n\n /**\n * 玩家状态更新监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onPlayerStatus(cb: (...args: any[]) => void, on=true) {\n if (on) this.on(\"player.status\", cb);\n else this.off(\"player.status\", cb);\n return this;\n }\n\n /**\n * 房间开始游戏监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onRoomStart(cb: (...args: any[]) => void, on=true) {\n if (!this.listeners[\"room.start\"]) {\n this.on(\"room.start\", (room) => this.emit(\"onRoomStart\", new Room(room)));\n }\n if (on) this.on(\"onRoomStart\", cb);\n else this.off(\"onRoomStart\", cb);\n return this;\n }\n\n /**\n * 房间结束游戏监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns\n */\n onRoomEnd(cb: (...args: any[]) => void, on=true) {\n if (!this.listeners[\"room.end\"]) {\n this.on(\"room.end\", (room) => this.emit(\"onRoomEnd\", new Room(room)));\n }\n if (on) this.on(\"onRoomEnd\", cb);\n else this.off(\"onRoomEnd\", cb);\n return this;\n }\n\n /**\n * 房间全部准备监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onRoomAllReady(cb: (...args: any[]) => void, on=true) {\n if (!this.listeners[\"room.all-ready\"]) {\n this.on(\"room.all-ready\", (room) => this.emit(\"onRoomAllReady\", new Room(room)));\n }\n if (on) this.on(\"onRoomAllReady\", cb);\n else this.off(\"onRoomAllReady\", cb);\n return this;\n }\n\n /**\n * 房间消息监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onRoomMessage(cb: (...args: any[]) => void, on=true) {\n if (on) this.on(\"room.message\", cb);\n else this.off(\"room.message\", cb);\n return this;\n }\n\n /**\n * 玩家消息监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onPlayerMessage(cb: (...args: any[]) => void, on=true) {\n if (on) this.on(\"player.message\", cb);\n else this.off(\"player.message\", cb);\n return this;\n }\n\n /**\n * 房间指令监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onRoomCommand(cb: (...args: any[]) => void, on=true) {\n if (on) this.on(\"room.command\", cb);\n else this.off(\"room.command\", cb);\n return this;\n }\n\n /**\n * 玩家指令监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onPlayerCommand(cb: (...args: any[]) => void, on=true) {\n if (on) this.on(\"player.command\", cb);\n else this.off(\"player.command\", cb);\n return this;\n }\n\n /**\n * 事件监听\n * @param {string} event 事件名称\n * @param {function} listener 监听函数\n * @returns \n */\n on<K extends keyof TiaoomEvents>(event: K, listener: TiaoomEvents[K]): this {\n this.listeners[event] = this.listeners[event] || [];\n this.listeners[event].push(listener);\n return this;\n }\n\n /**\n * 事件取消监听\n * @param {string} event 事件名称\n * @param {function} listener 监听函数\n * @returns \n */\n off<K extends keyof TiaoomEvents>(event: K, listener: TiaoomEvents[K]): this {\n const listeners = this.listeners[event] || [];\n const index = listeners.indexOf(listener);\n if (index !== -1) {\n listeners.splice(index, 1);\n }\n return this;\n }\n\n /**\n * 事件触发\n * @param {string} event 事件名称\n * @param {...any} args 参数\n * @returns \n */\n emit<K extends keyof TiaoomEvents>(event: K, ...args: Parameters<TiaoomEvents[K]>): this {\n const listeners = this.listeners[event] || [];\n listeners.forEach(listener => listener(...args));\n return this;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"client.cjs","names":[],"sources":["../lib/client.ts"],"sourcesContent":["export type TiaoomEvents = {\n /**\n * 连接准备就绪事件\n */\n \"sys.ready\": () => void;\n /**\n * 连接错误事件\n * @param error 错误信息\n */\n \"sys.error\": (error: any) => void;\n /**\n * 连接关闭事件\n */\n \"sys.close\": () => void;\n /**\n * 全局命令事件\n * @param data 命令内容\n */\n \"global.command\": (data: any & { sender: Player }) => void;\n /**\n * 玩家列表更新事件\n * @param players 玩家列表\n */\n \"player.list\": (players: Player[]) => void;\n /**\n * 玩家登录事件\n * @param player 玩家信息\n */\n \"player.login\": (player: Player) => void;\n /**\n * 玩家登出事件\n * @param player 玩家信息\n */\n \"player.logout\": (player: Player) => void;\n /**\n * 玩家状态更新事件\n * @param player 玩家信息\n * @param status 状态\n * @param roomId 房间ID(可选)\n */\n \"player.status\": (player: Player, status: string, roomId?: string) => void;\n /**\n * 玩家命令事件\n * @param command 命令内容\n */\n \"player.command\": (command: any & { sender: Player }) => void;\n /**\n * 玩家消息事件\n * @param message 消息内容\n */\n \"player.message\": (message: any & { sender: Player }) => void;\n /**\n * 房间列表更新事件\n * @param rooms 房间列表\n */\n \"room.list\": (rooms: Room[]) => void;\n /**\n * 房间创建事件\n * @param room 房间信息\n */\n \"room.create\": (room: Room) => void;\n /**\n * 房间更新事件\n * @param room 房间信息\n */\n \"room.update\": (room: Room) => void;\n /**\n * 房间关闭事件\n * @param room 房间信息\n */\n \"room.close\": (room: Room) => void;\n /**\n * 玩家加入房间事件\n * @param room 房间信息\n * @param player 玩家信息\n */\n \"room.join\": (room: Room, player: Player) => void;\n /**\n * 玩家离开房间事件\n * @param room 房间信息\n * @param player 玩家信息\n */\n \"room.leave\": (room: Room, player: Player) => void;\n /**\n * 房间开始游戏事件\n * @param room 房间信息\n */\n \"room.start\": (room: Room) => void;\n /**\n * 房间结束游戏事件\n * @param room 房间信息\n */\n \"room.end\": (room: Room) => void;\n /**\n * 房间玩家全部准备事件\n * @param room 房间信息\n */\n \"room.all-ready\": (room: Room) => void;\n /**\n * 房间命令事件\n * @param command 命令内容\n */\n \"room.command\": (command: any & { sender: Player }) => void;\n /**\n * 房间消息事件\n * @param message 消息内容\n */\n \"room.message\": (message: any & { sender: Player }) => void;\n /**\n * 房间玩家准备事件\n * @param player 玩家信息\n * @param roomId 房间ID(可选)\n */\n \"room.player-ready\": (player: Player, roomId?: string) => void;\n /**\n * 房间玩家取消准备事件\n * @param player 玩家信息\n * @param roomId 房间ID(可选)\n */\n \"room.player-unready\": (player: Player, roomId?: string) => void;\n /**\n * 玩家列表更新事件(内部)\n * @param players 玩家列表\n */\n \"onPlayerList\": (players: Player[]) => void;\n /**\n * 房间列表更新事件(内部)\n * @param rooms 房间列表\n */\n \"onRoomList\": (rooms: Room[]) => void;\n /**\n * 房间开始游戏事件(内部)\n * @param room 房间信息\n */\n \"onRoomStart\": (room: Room) => void;\n /**\n * 房间结束游戏事件(内部)\n * @param room 房间信息\n */\n \"onRoomEnd\": (room: Room) => void;\n /**\n * 房间玩家全部准备事件(内部)\n * @param room 房间信息\n */\n \"onRoomAllReady\": (room: Room) => void;\n};\n\nexport class Player {\n id: string;\n name: string;\n attributes: Record<string, any>;\n status: string;\n constructor(player: Partial<Player>) {\n this.id = player.id || Date.now().toString();\n this.name = player.name || '玩家' + this.id;\n this.attributes = player.attributes || {};\n this.status = player.status || 'online';\n }\n}\n\nexport class RoomPlayer extends Player {\n role: string;\n isReady: boolean;\n isCreator: boolean;\n constructor(player: RoomPlayer) {\n super(player);\n this.role = player.role;\n this.isReady = player.isReady;\n this.isCreator = player.isCreator;\n }\n}\n\nexport class Room {\n id: string;\n name: string;\n players: RoomPlayer[];\n size: number;\n minSize: number;\n status: string;\n attrs: Record<string, any>;\n constructor(room: Room) {\n this.id = room.id;\n this.name = room.name;\n this.players = room.players.map(player => new RoomPlayer(player));\n this.size = room.size;\n this.minSize = room.minSize;\n this.status = room.status;\n this.attrs = room.attrs;\n }\n}\n\n/**\n * Tiaoom 客户端\n * @description 用于连接 Tiaoom 服务器并进行游戏交互,如创建房间、加入房间、发送命令等。\n * 需继承后实现具体的连接和消息发送逻辑。\n */\nexport class Tiaoom {\n listeners: Record<string, Function[]>;\n rooms: Room[];\n players: Player[];\n currentPlayer: Player | null;\n constructor() {\n this.listeners = {};\n this.rooms = [];\n this.players = [];\n this.currentPlayer = null;\n }\n\n /**\n * 启动游戏\n */\n run() {\n this.connect();\n this.onReady(() => {\n this.send({ type: \"room.list\" });\n this.send({ type: \"player.list\" });\n });\n\n this.on(\"player.list\", (players) => {\n this.players = players.map(player => new Player(player));\n this.emit('onPlayerList', [...this.players]);\n });\n this.on(\"player.login\", (player) => {\n this.players.push(new Player(player));\n this.emit('onPlayerList', [...this.players]);\n });\n this.on(\"player.logout\", (player) => {\n this.players = this.players.filter(p => p.id !== player.id);\n this.emit('onPlayerList', [...this.players]);\n });\n\n\n this.on(\"room.list\", (rooms) => {\n this.rooms = rooms.map(room => new Room(room));\n this.emit('onRoomList', [...this.rooms]);\n });\n this.on(\"room.create\", (room) => {\n this.rooms.push(new Room(room));\n this.emit('onRoomList', this.rooms);\n });\n this.on(\"room.update\", (room) => {\n const existingRoom = this.rooms.find(r => r.id === room.id);\n if (!existingRoom) {\n this.rooms.push(new Room(room));\n } else {\n Object.assign(existingRoom, room);\n }\n this.emit('onRoomList', this.rooms);\n });\n this.on(\"room.close\", (room) => {\n this.rooms = this.rooms.filter(r => r.id !== room.id);\n this.emit('onRoomList', this.rooms);\n });\n this.on(\"room.update\", (room) => {\n const updatedRoom = this.rooms.find(r => r.id === room.id);\n if (updatedRoom) {\n Object.assign(updatedRoom, room);\n this.emit('onRoomList', this.rooms);\n }\n });\n\n return this;\n }\n\n /**\n * 连接服务器实现\n */\n connect() {\n throw new Error('Must be implement connect method');\n }\n\n /**\n * 发送消息实现\n */\n send(_: { type: string, data?: any }) {\n throw new Error('Must be implement send method');\n }\n\n /**\n * 登录\n * @param {Player} player 玩家信息\n */\n login(player: Player) {\n this.currentPlayer = new Player(player);\n this.send({ type: \"player.login\", data: player });\n return this;\n }\n\n /**\n * 创建房间\n * @param {string} name 房间名称\n * @param {number} size 房间人数上限\n * @param {number} minSize 房间人数下限\n * @param {object} attrs 房间属性\n */\n createRoom({ name, size, minSize, attrs }: { name: string, size: number, minSize: number, attrs?: Record<string, any> }) {\n return new Promise<void>((resolve) => {\n this.send({ type: \"room.create\", data: { name, size, minSize, attrs } });\n this.on(\"room.create\", (room) => {\n resolve();\n });\n });\n }\n\n /**\n * 加入房间\n * @param {string} roomId 房间ID\n */\n joinRoom(roomId: string) {\n this.send({ type: \"player.join\", data: { roomId } });\n return this;\n }\n\n /**\n * 离开房间\n * @param {string} roomId 房间ID\n */\n leaveRoom(roomId: string) {\n this.send({ type: \"player.leave\", data: { roomId } });\n return this;\n }\n\n /**\n * 开始游戏\n * @param {string} id 房间ID\n */\n startGame(id: string) {\n this.send({ type: \"room.start\", data: { id } });\n return this;\n }\n\n /**\n * 准备/取消准备\n * @param {string} roomId 房间ID\n * @param {boolean} isReady 是否准备\n */\n ready(roomId: string, isReady=true) {\n this.send({ type: isReady ? \"player.ready\" : \"player.unready\", data: { roomId } });\n return this;\n }\n\n /**\n * 发送房间指令\n * @param {string} roomId 房间ID\n * @param {any} command 指令内容\n */\n command(command: any): this;\n command(roomId: string, command: any): this;\n command(roomId: string | any, command?: any) {\n if (typeof roomId != 'string') {\n command = roomId;\n this.send({ type: \"global.command\", data: command });\n } else {\n this.send({ type: \"room.player-command\", data: { id: roomId, ...command } });\n }\n return this;\n }\n\n /**\n * 连接准备监听\n * @param {function} cb 监听函数\n */\n onReady(cb: (...args: any[]) => void) {\n return this.on(\"sys.ready\", cb);\n }\n\n /**\n * 玩家列表变更监听\n * @param {function} cb 监听函数\n */\n onPlayerList(cb: (...args: any[]) => void) {\n this.on(\"onPlayerList\", cb);\n return this;\n }\n\n /**\n * 房间列表变更监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onRoomList(cb: (...args: any[]) => void, on=true) {\n if (on) this.on(\"onRoomList\", cb);\n else this.off(\"onRoomList\", cb);\n return this;\n }\n\n /**\n * 玩家加入监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onPlayerJoin(cb: (...args: any[]) => void, on=true) {\n if (on) this.on(\"room.join\", cb);\n else this.off(\"room.join\", cb);\n return this;\n }\n\n /**\n * 玩家离开监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onPlayerLeave(cb: (...args: any[]) => void, on=true) {\n if (on) this.on(\"room.leave\", cb);\n else this.off(\"room.leave\", cb);\n return this;\n }\n\n /**\n * 玩家准备监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onPlayerReady(cb: (...args: any[]) => void, on=true) {\n if (on) this.on(\"room.player-ready\", cb);\n else this.off(\"room.player-ready\", cb);\n return this;\n }\n\n /**\n * 玩家取消准备监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onPlayerUnready(cb: (...args: any[]) => void, on=true) {\n if (on) this.on(\"room.player-unready\", cb);\n else this.off(\"room.player-unready\", cb);\n return this;\n }\n\n /**\n * 玩家状态更新监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onPlayerStatus(cb: (...args: any[]) => void, on=true) {\n if (on) this.on(\"player.status\", cb);\n else this.off(\"player.status\", cb);\n return this;\n }\n\n /**\n * 房间开始游戏监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onRoomStart(cb: (...args: any[]) => void, on=true) {\n if (!this.listeners[\"room.start\"]) {\n this.on(\"room.start\", (room) => this.emit(\"onRoomStart\", new Room(room)));\n }\n if (on) this.on(\"onRoomStart\", cb);\n else this.off(\"onRoomStart\", cb);\n return this;\n }\n\n /**\n * 房间结束游戏监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns\n */\n onRoomEnd(cb: (...args: any[]) => void, on=true) {\n if (!this.listeners[\"room.end\"]) {\n this.on(\"room.end\", (room) => this.emit(\"onRoomEnd\", new Room(room)));\n }\n if (on) this.on(\"onRoomEnd\", cb);\n else this.off(\"onRoomEnd\", cb);\n return this;\n }\n\n /**\n * 房间全部准备监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onRoomAllReady(cb: (...args: any[]) => void, on=true) {\n if (!this.listeners[\"room.all-ready\"]) {\n this.on(\"room.all-ready\", (room) => this.emit(\"onRoomAllReady\", new Room(room)));\n }\n if (on) this.on(\"onRoomAllReady\", cb);\n else this.off(\"onRoomAllReady\", cb);\n return this;\n }\n\n /**\n * 房间消息监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onRoomMessage(cb: (...args: any[]) => void, on=true) {\n if (on) this.on(\"room.message\", cb);\n else this.off(\"room.message\", cb);\n return this;\n }\n\n /**\n * 玩家消息监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onPlayerMessage(cb: (...args: any[]) => void, on=true) {\n if (on) this.on(\"player.message\", cb);\n else this.off(\"player.message\", cb);\n return this;\n }\n\n /**\n * 房间指令监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onRoomCommand(cb: (...args: any[]) => void, on=true) {\n if (on) this.on(\"room.command\", cb);\n else this.off(\"room.command\", cb);\n return this;\n }\n\n /**\n * 玩家指令监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onPlayerCommand(cb: (...args: any[]) => void, on=true) {\n if (on) this.on(\"player.command\", cb);\n else this.off(\"player.command\", cb);\n return this;\n }\n\n /**\n * 事件监听\n * @param {string} event 事件名称\n * @param {function} listener 监听函数\n * @returns \n */\n on<K extends keyof TiaoomEvents>(event: K, listener: TiaoomEvents[K]): this {\n this.listeners[event] = this.listeners[event] || [];\n this.listeners[event].push(listener);\n return this;\n }\n\n /**\n * 事件取消监听\n * @param {string} event 事件名称\n * @param {function} listener 监听函数\n * @returns \n */\n off<K extends keyof TiaoomEvents>(event: K, listener: TiaoomEvents[K]): this {\n const listeners = this.listeners[event] || [];\n const index = listeners.indexOf(listener);\n if (index !== -1) {\n listeners.splice(index, 1);\n }\n return this;\n }\n\n /**\n * 事件触发\n * @param {string} event 事件名称\n * @param {...any} args 参数\n * @returns \n */\n emit<K extends keyof TiaoomEvents>(event: K, ...args: Parameters<TiaoomEvents[K]>): this {\n const listeners = this.listeners[event] || [];\n listeners.forEach(listener => listener(...args));\n return this;\n }\n}\n"],"mappings":"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"}
package/src/client.d.cts CHANGED
@@ -160,7 +160,7 @@ declare class Player {
160
160
  name: string;
161
161
  attributes: Record<string, any>;
162
162
  status: string;
163
- constructor(player: Player);
163
+ constructor(player: Partial<Player>);
164
164
  }
165
165
  declare class RoomPlayer extends Player {
166
166
  role: string;
package/src/client.d.mts CHANGED
@@ -160,7 +160,7 @@ declare class Player {
160
160
  name: string;
161
161
  attributes: Record<string, any>;
162
162
  status: string;
163
- constructor(player: Player);
163
+ constructor(player: Partial<Player>);
164
164
  }
165
165
  declare class RoomPlayer extends Player {
166
166
  role: string;
@@ -1,2 +1,2 @@
1
- var Tiaoom=(function(e){var t=class{constructor(e){this.id=e.id,this.name=e.name,this.attributes=e.attributes,this.status=e.status}},n=class extends t{constructor(e){super(e),this.role=e.role,this.isReady=e.isReady,this.isCreator=e.isCreator}},r=class{constructor(e){this.id=e.id,this.name=e.name,this.players=e.players.map(e=>new n(e)),this.size=e.size,this.minSize=e.minSize,this.status=e.status,this.attrs=e.attrs}},i=class{constructor(){this.listeners={},this.rooms=[],this.players=[],this.currentPlayer=null}run(){return this.connect(),this.onReady(()=>{this.send({type:`room.list`}),this.send({type:`player.list`})}),this.on(`player.list`,e=>{this.players=e.map(e=>new t(e)),this.emit(`onPlayerList`,[...this.players])}),this.on(`player.login`,e=>{this.players.push(new t(e)),this.emit(`onPlayerList`,[...this.players])}),this.on(`player.logout`,e=>{this.players=this.players.filter(t=>t.id!==e.id),this.emit(`onPlayerList`,[...this.players])}),this.on(`room.list`,e=>{this.rooms=e.map(e=>new r(e)),this.emit(`onRoomList`,[...this.rooms])}),this.on(`room.create`,e=>{this.rooms.push(new r(e)),this.emit(`onRoomList`,this.rooms)}),this.on(`room.update`,e=>{let t=this.rooms.find(t=>t.id===e.id);t?Object.assign(t,e):this.rooms.push(new r(e)),this.emit(`onRoomList`,this.rooms)}),this.on(`room.close`,e=>{this.rooms=this.rooms.filter(t=>t.id!==e.id),this.emit(`onRoomList`,this.rooms)}),this.on(`room.update`,e=>{let t=this.rooms.find(t=>t.id===e.id);t&&(Object.assign(t,e),this.emit(`onRoomList`,this.rooms))}),this}connect(){throw Error(`Must be implement connect method`)}send(e){throw Error(`Must be implement send method`)}login(e){return this.currentPlayer=new t(e),this.send({type:`player.login`,data:e}),this}createRoom({name:e,size:t,minSize:n,attrs:r}){return new Promise(i=>{this.send({type:`room.create`,data:{name:e,size:t,minSize:n,attrs:r}}),this.on(`room.create`,e=>{i()})})}joinRoom(e){return this.send({type:`player.join`,data:{roomId:e}}),this}leaveRoom(e){return this.send({type:`player.leave`,data:{roomId:e}}),this}startGame(e){return this.send({type:`room.start`,data:{id:e}}),this}ready(e,t=!0){return this.send({type:t?`player.ready`:`player.unready`,data:{roomId:e}}),this}command(e,t){return typeof e==`string`?this.send({type:`room.player-command`,data:{id:e,...t}}):(t=e,this.send({type:`global.command`,data:t})),this}onReady(e){return this.on(`sys.ready`,e)}onPlayerList(e){return this.on(`onPlayerList`,e),this}onRoomList(e,t=!0){return t?this.on(`onRoomList`,e):this.off(`onRoomList`,e),this}onPlayerJoin(e,t=!0){return t?this.on(`room.join`,e):this.off(`room.join`,e),this}onPlayerLeave(e,t=!0){return t?this.on(`room.leave`,e):this.off(`room.leave`,e),this}onPlayerReady(e,t=!0){return t?this.on(`room.player-ready`,e):this.off(`room.player-ready`,e),this}onPlayerUnready(e,t=!0){return t?this.on(`room.player-unready`,e):this.off(`room.player-unready`,e),this}onPlayerStatus(e,t=!0){return t?this.on(`player.status`,e):this.off(`player.status`,e),this}onRoomStart(e,t=!0){return this.listeners[`room.start`]||this.on(`room.start`,e=>this.emit(`onRoomStart`,new r(e))),t?this.on(`onRoomStart`,e):this.off(`onRoomStart`,e),this}onRoomEnd(e,t=!0){return this.listeners[`room.end`]||this.on(`room.end`,e=>this.emit(`onRoomEnd`,new r(e))),t?this.on(`onRoomEnd`,e):this.off(`onRoomEnd`,e),this}onRoomAllReady(e,t=!0){return this.listeners[`room.all-ready`]||this.on(`room.all-ready`,e=>this.emit(`onRoomAllReady`,new r(e))),t?this.on(`onRoomAllReady`,e):this.off(`onRoomAllReady`,e),this}onRoomMessage(e,t=!0){return t?this.on(`room.message`,e):this.off(`room.message`,e),this}onPlayerMessage(e,t=!0){return t?this.on(`player.message`,e):this.off(`player.message`,e),this}onRoomCommand(e,t=!0){return t?this.on(`room.command`,e):this.off(`room.command`,e),this}onPlayerCommand(e,t=!0){return t?this.on(`player.command`,e):this.off(`player.command`,e),this}on(e,t){return this.listeners[e]=this.listeners[e]||[],this.listeners[e].push(t),this}off(e,t){let n=this.listeners[e]||[],r=n.indexOf(t);return r!==-1&&n.splice(r,1),this}emit(e,...t){return(this.listeners[e]||[]).forEach(e=>e(...t)),this}};return e.Player=t,e.Room=r,e.RoomPlayer=n,e.Tiaoom=i,e})({});
1
+ var Tiaoom=(function(e){var t=class{constructor(e){this.id=e.id||Date.now().toString(),this.name=e.name||`玩家`+this.id,this.attributes=e.attributes||{},this.status=e.status||`online`}},n=class extends t{constructor(e){super(e),this.role=e.role,this.isReady=e.isReady,this.isCreator=e.isCreator}},r=class{constructor(e){this.id=e.id,this.name=e.name,this.players=e.players.map(e=>new n(e)),this.size=e.size,this.minSize=e.minSize,this.status=e.status,this.attrs=e.attrs}},i=class{constructor(){this.listeners={},this.rooms=[],this.players=[],this.currentPlayer=null}run(){return this.connect(),this.onReady(()=>{this.send({type:`room.list`}),this.send({type:`player.list`})}),this.on(`player.list`,e=>{this.players=e.map(e=>new t(e)),this.emit(`onPlayerList`,[...this.players])}),this.on(`player.login`,e=>{this.players.push(new t(e)),this.emit(`onPlayerList`,[...this.players])}),this.on(`player.logout`,e=>{this.players=this.players.filter(t=>t.id!==e.id),this.emit(`onPlayerList`,[...this.players])}),this.on(`room.list`,e=>{this.rooms=e.map(e=>new r(e)),this.emit(`onRoomList`,[...this.rooms])}),this.on(`room.create`,e=>{this.rooms.push(new r(e)),this.emit(`onRoomList`,this.rooms)}),this.on(`room.update`,e=>{let t=this.rooms.find(t=>t.id===e.id);t?Object.assign(t,e):this.rooms.push(new r(e)),this.emit(`onRoomList`,this.rooms)}),this.on(`room.close`,e=>{this.rooms=this.rooms.filter(t=>t.id!==e.id),this.emit(`onRoomList`,this.rooms)}),this.on(`room.update`,e=>{let t=this.rooms.find(t=>t.id===e.id);t&&(Object.assign(t,e),this.emit(`onRoomList`,this.rooms))}),this}connect(){throw Error(`Must be implement connect method`)}send(e){throw Error(`Must be implement send method`)}login(e){return this.currentPlayer=new t(e),this.send({type:`player.login`,data:e}),this}createRoom({name:e,size:t,minSize:n,attrs:r}){return new Promise(i=>{this.send({type:`room.create`,data:{name:e,size:t,minSize:n,attrs:r}}),this.on(`room.create`,e=>{i()})})}joinRoom(e){return this.send({type:`player.join`,data:{roomId:e}}),this}leaveRoom(e){return this.send({type:`player.leave`,data:{roomId:e}}),this}startGame(e){return this.send({type:`room.start`,data:{id:e}}),this}ready(e,t=!0){return this.send({type:t?`player.ready`:`player.unready`,data:{roomId:e}}),this}command(e,t){return typeof e==`string`?this.send({type:`room.player-command`,data:{id:e,...t}}):(t=e,this.send({type:`global.command`,data:t})),this}onReady(e){return this.on(`sys.ready`,e)}onPlayerList(e){return this.on(`onPlayerList`,e),this}onRoomList(e,t=!0){return t?this.on(`onRoomList`,e):this.off(`onRoomList`,e),this}onPlayerJoin(e,t=!0){return t?this.on(`room.join`,e):this.off(`room.join`,e),this}onPlayerLeave(e,t=!0){return t?this.on(`room.leave`,e):this.off(`room.leave`,e),this}onPlayerReady(e,t=!0){return t?this.on(`room.player-ready`,e):this.off(`room.player-ready`,e),this}onPlayerUnready(e,t=!0){return t?this.on(`room.player-unready`,e):this.off(`room.player-unready`,e),this}onPlayerStatus(e,t=!0){return t?this.on(`player.status`,e):this.off(`player.status`,e),this}onRoomStart(e,t=!0){return this.listeners[`room.start`]||this.on(`room.start`,e=>this.emit(`onRoomStart`,new r(e))),t?this.on(`onRoomStart`,e):this.off(`onRoomStart`,e),this}onRoomEnd(e,t=!0){return this.listeners[`room.end`]||this.on(`room.end`,e=>this.emit(`onRoomEnd`,new r(e))),t?this.on(`onRoomEnd`,e):this.off(`onRoomEnd`,e),this}onRoomAllReady(e,t=!0){return this.listeners[`room.all-ready`]||this.on(`room.all-ready`,e=>this.emit(`onRoomAllReady`,new r(e))),t?this.on(`onRoomAllReady`,e):this.off(`onRoomAllReady`,e),this}onRoomMessage(e,t=!0){return t?this.on(`room.message`,e):this.off(`room.message`,e),this}onPlayerMessage(e,t=!0){return t?this.on(`player.message`,e):this.off(`player.message`,e),this}onRoomCommand(e,t=!0){return t?this.on(`room.command`,e):this.off(`room.command`,e),this}onPlayerCommand(e,t=!0){return t?this.on(`player.command`,e):this.off(`player.command`,e),this}on(e,t){return this.listeners[e]=this.listeners[e]||[],this.listeners[e].push(t),this}off(e,t){let n=this.listeners[e]||[],r=n.indexOf(t);return r!==-1&&n.splice(r,1),this}emit(e,...t){return(this.listeners[e]||[]).forEach(e=>e(...t)),this}};return e.Player=t,e.Room=r,e.RoomPlayer=n,e.Tiaoom=i,e})({});
2
2
  //# sourceMappingURL=client.iife.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.iife.js","names":[],"sources":["../lib/client.ts"],"sourcesContent":["export type TiaoomEvents = {\n /**\n * 连接准备就绪事件\n */\n \"sys.ready\": () => void;\n /**\n * 连接错误事件\n * @param error 错误信息\n */\n \"sys.error\": (error: any) => void;\n /**\n * 连接关闭事件\n */\n \"sys.close\": () => void;\n /**\n * 全局命令事件\n * @param data 命令内容\n */\n \"global.command\": (data: any & { sender: Player }) => void;\n /**\n * 玩家列表更新事件\n * @param players 玩家列表\n */\n \"player.list\": (players: Player[]) => void;\n /**\n * 玩家登录事件\n * @param player 玩家信息\n */\n \"player.login\": (player: Player) => void;\n /**\n * 玩家登出事件\n * @param player 玩家信息\n */\n \"player.logout\": (player: Player) => void;\n /**\n * 玩家状态更新事件\n * @param player 玩家信息\n * @param status 状态\n * @param roomId 房间ID(可选)\n */\n \"player.status\": (player: Player, status: string, roomId?: string) => void;\n /**\n * 玩家命令事件\n * @param command 命令内容\n */\n \"player.command\": (command: any & { sender: Player }) => void;\n /**\n * 玩家消息事件\n * @param message 消息内容\n */\n \"player.message\": (message: any & { sender: Player }) => void;\n /**\n * 房间列表更新事件\n * @param rooms 房间列表\n */\n \"room.list\": (rooms: Room[]) => void;\n /**\n * 房间创建事件\n * @param room 房间信息\n */\n \"room.create\": (room: Room) => void;\n /**\n * 房间更新事件\n * @param room 房间信息\n */\n \"room.update\": (room: Room) => void;\n /**\n * 房间关闭事件\n * @param room 房间信息\n */\n \"room.close\": (room: Room) => void;\n /**\n * 玩家加入房间事件\n * @param room 房间信息\n * @param player 玩家信息\n */\n \"room.join\": (room: Room, player: Player) => void;\n /**\n * 玩家离开房间事件\n * @param room 房间信息\n * @param player 玩家信息\n */\n \"room.leave\": (room: Room, player: Player) => void;\n /**\n * 房间开始游戏事件\n * @param room 房间信息\n */\n \"room.start\": (room: Room) => void;\n /**\n * 房间结束游戏事件\n * @param room 房间信息\n */\n \"room.end\": (room: Room) => void;\n /**\n * 房间玩家全部准备事件\n * @param room 房间信息\n */\n \"room.all-ready\": (room: Room) => void;\n /**\n * 房间命令事件\n * @param command 命令内容\n */\n \"room.command\": (command: any & { sender: Player }) => void;\n /**\n * 房间消息事件\n * @param message 消息内容\n */\n \"room.message\": (message: any & { sender: Player }) => void;\n /**\n * 房间玩家准备事件\n * @param player 玩家信息\n * @param roomId 房间ID(可选)\n */\n \"room.player-ready\": (player: Player, roomId?: string) => void;\n /**\n * 房间玩家取消准备事件\n * @param player 玩家信息\n * @param roomId 房间ID(可选)\n */\n \"room.player-unready\": (player: Player, roomId?: string) => void;\n /**\n * 玩家列表更新事件(内部)\n * @param players 玩家列表\n */\n \"onPlayerList\": (players: Player[]) => void;\n /**\n * 房间列表更新事件(内部)\n * @param rooms 房间列表\n */\n \"onRoomList\": (rooms: Room[]) => void;\n /**\n * 房间开始游戏事件(内部)\n * @param room 房间信息\n */\n \"onRoomStart\": (room: Room) => void;\n /**\n * 房间结束游戏事件(内部)\n * @param room 房间信息\n */\n \"onRoomEnd\": (room: Room) => void;\n /**\n * 房间玩家全部准备事件(内部)\n * @param room 房间信息\n */\n \"onRoomAllReady\": (room: Room) => void;\n};\n\nexport class Player {\n id: string;\n name: string;\n attributes: Record<string, any>;\n status: string;\n constructor(player: Player) {\n this.id = player.id;\n this.name = player.name;\n this.attributes = player.attributes;\n this.status = player.status;\n }\n}\n\nexport class RoomPlayer extends Player {\n role: string;\n isReady: boolean;\n isCreator: boolean;\n constructor(player: RoomPlayer) {\n super(player);\n this.role = player.role;\n this.isReady = player.isReady;\n this.isCreator = player.isCreator;\n }\n}\n\nexport class Room {\n id: string;\n name: string;\n players: RoomPlayer[];\n size: number;\n minSize: number;\n status: string;\n attrs: Record<string, any>;\n constructor(room: Room) {\n this.id = room.id;\n this.name = room.name;\n this.players = room.players.map(player => new RoomPlayer(player));\n this.size = room.size;\n this.minSize = room.minSize;\n this.status = room.status;\n this.attrs = room.attrs;\n }\n}\n\n/**\n * Tiaoom 客户端\n * @description 用于连接 Tiaoom 服务器并进行游戏交互,如创建房间、加入房间、发送命令等。\n * 需继承后实现具体的连接和消息发送逻辑。\n */\nexport class Tiaoom {\n listeners: Record<string, Function[]>;\n rooms: Room[];\n players: Player[];\n currentPlayer: Player | null;\n constructor() {\n this.listeners = {};\n this.rooms = [];\n this.players = [];\n this.currentPlayer = null;\n }\n\n /**\n * 启动游戏\n */\n run() {\n this.connect();\n this.onReady(() => {\n this.send({ type: \"room.list\" });\n this.send({ type: \"player.list\" });\n });\n\n this.on(\"player.list\", (players) => {\n this.players = players.map(player => new Player(player));\n this.emit('onPlayerList', [...this.players]);\n });\n this.on(\"player.login\", (player) => {\n this.players.push(new Player(player));\n this.emit('onPlayerList', [...this.players]);\n });\n this.on(\"player.logout\", (player) => {\n this.players = this.players.filter(p => p.id !== player.id);\n this.emit('onPlayerList', [...this.players]);\n });\n\n\n this.on(\"room.list\", (rooms) => {\n this.rooms = rooms.map(room => new Room(room));\n this.emit('onRoomList', [...this.rooms]);\n });\n this.on(\"room.create\", (room) => {\n this.rooms.push(new Room(room));\n this.emit('onRoomList', this.rooms);\n });\n this.on(\"room.update\", (room) => {\n const existingRoom = this.rooms.find(r => r.id === room.id);\n if (!existingRoom) {\n this.rooms.push(new Room(room));\n } else {\n Object.assign(existingRoom, room);\n }\n this.emit('onRoomList', this.rooms);\n });\n this.on(\"room.close\", (room) => {\n this.rooms = this.rooms.filter(r => r.id !== room.id);\n this.emit('onRoomList', this.rooms);\n });\n this.on(\"room.update\", (room) => {\n const updatedRoom = this.rooms.find(r => r.id === room.id);\n if (updatedRoom) {\n Object.assign(updatedRoom, room);\n this.emit('onRoomList', this.rooms);\n }\n });\n\n return this;\n }\n\n /**\n * 连接服务器实现\n */\n connect() {\n throw new Error('Must be implement connect method');\n }\n\n /**\n * 发送消息实现\n */\n send(_: { type: string, data?: any }) {\n throw new Error('Must be implement send method');\n }\n\n /**\n * 登录\n * @param {Player} player 玩家信息\n */\n login(player: Player) {\n this.currentPlayer = new Player(player);\n this.send({ type: \"player.login\", data: player });\n return this;\n }\n\n /**\n * 创建房间\n * @param {string} name 房间名称\n * @param {number} size 房间人数上限\n * @param {number} minSize 房间人数下限\n * @param {object} attrs 房间属性\n */\n createRoom({ name, size, minSize, attrs }: { name: string, size: number, minSize: number, attrs?: Record<string, any> }) {\n return new Promise<void>((resolve) => {\n this.send({ type: \"room.create\", data: { name, size, minSize, attrs } });\n this.on(\"room.create\", (room) => {\n resolve();\n });\n });\n }\n\n /**\n * 加入房间\n * @param {string} roomId 房间ID\n */\n joinRoom(roomId: string) {\n this.send({ type: \"player.join\", data: { roomId } });\n return this;\n }\n\n /**\n * 离开房间\n * @param {string} roomId 房间ID\n */\n leaveRoom(roomId: string) {\n this.send({ type: \"player.leave\", data: { roomId } });\n return this;\n }\n\n /**\n * 开始游戏\n * @param {string} id 房间ID\n */\n startGame(id: string) {\n this.send({ type: \"room.start\", data: { id } });\n return this;\n }\n\n /**\n * 准备/取消准备\n * @param {string} roomId 房间ID\n * @param {boolean} isReady 是否准备\n */\n ready(roomId: string, isReady=true) {\n this.send({ type: isReady ? \"player.ready\" : \"player.unready\", data: { roomId } });\n return this;\n }\n\n /**\n * 发送房间指令\n * @param {string} roomId 房间ID\n * @param {any} command 指令内容\n */\n command(command: any): this;\n command(roomId: string, command: any): this;\n command(roomId: string | any, command?: any) {\n if (typeof roomId != 'string') {\n command = roomId;\n this.send({ type: \"global.command\", data: command });\n } else {\n this.send({ type: \"room.player-command\", data: { id: roomId, ...command } });\n }\n return this;\n }\n\n /**\n * 连接准备监听\n * @param {function} cb 监听函数\n */\n onReady(cb: (...args: any[]) => void) {\n return this.on(\"sys.ready\", cb);\n }\n\n /**\n * 玩家列表变更监听\n * @param {function} cb 监听函数\n */\n onPlayerList(cb: (...args: any[]) => void) {\n this.on(\"onPlayerList\", cb);\n return this;\n }\n\n /**\n * 房间列表变更监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onRoomList(cb: (...args: any[]) => void, on=true) {\n if (on) this.on(\"onRoomList\", cb);\n else this.off(\"onRoomList\", cb);\n return this;\n }\n\n /**\n * 玩家加入监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onPlayerJoin(cb: (...args: any[]) => void, on=true) {\n if (on) this.on(\"room.join\", cb);\n else this.off(\"room.join\", cb);\n return this;\n }\n\n /**\n * 玩家离开监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onPlayerLeave(cb: (...args: any[]) => void, on=true) {\n if (on) this.on(\"room.leave\", cb);\n else this.off(\"room.leave\", cb);\n return this;\n }\n\n /**\n * 玩家准备监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onPlayerReady(cb: (...args: any[]) => void, on=true) {\n if (on) this.on(\"room.player-ready\", cb);\n else this.off(\"room.player-ready\", cb);\n return this;\n }\n\n /**\n * 玩家取消准备监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onPlayerUnready(cb: (...args: any[]) => void, on=true) {\n if (on) this.on(\"room.player-unready\", cb);\n else this.off(\"room.player-unready\", cb);\n return this;\n }\n\n /**\n * 玩家状态更新监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onPlayerStatus(cb: (...args: any[]) => void, on=true) {\n if (on) this.on(\"player.status\", cb);\n else this.off(\"player.status\", cb);\n return this;\n }\n\n /**\n * 房间开始游戏监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onRoomStart(cb: (...args: any[]) => void, on=true) {\n if (!this.listeners[\"room.start\"]) {\n this.on(\"room.start\", (room) => this.emit(\"onRoomStart\", new Room(room)));\n }\n if (on) this.on(\"onRoomStart\", cb);\n else this.off(\"onRoomStart\", cb);\n return this;\n }\n\n /**\n * 房间结束游戏监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns\n */\n onRoomEnd(cb: (...args: any[]) => void, on=true) {\n if (!this.listeners[\"room.end\"]) {\n this.on(\"room.end\", (room) => this.emit(\"onRoomEnd\", new Room(room)));\n }\n if (on) this.on(\"onRoomEnd\", cb);\n else this.off(\"onRoomEnd\", cb);\n return this;\n }\n\n /**\n * 房间全部准备监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onRoomAllReady(cb: (...args: any[]) => void, on=true) {\n if (!this.listeners[\"room.all-ready\"]) {\n this.on(\"room.all-ready\", (room) => this.emit(\"onRoomAllReady\", new Room(room)));\n }\n if (on) this.on(\"onRoomAllReady\", cb);\n else this.off(\"onRoomAllReady\", cb);\n return this;\n }\n\n /**\n * 房间消息监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onRoomMessage(cb: (...args: any[]) => void, on=true) {\n if (on) this.on(\"room.message\", cb);\n else this.off(\"room.message\", cb);\n return this;\n }\n\n /**\n * 玩家消息监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onPlayerMessage(cb: (...args: any[]) => void, on=true) {\n if (on) this.on(\"player.message\", cb);\n else this.off(\"player.message\", cb);\n return this;\n }\n\n /**\n * 房间指令监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onRoomCommand(cb: (...args: any[]) => void, on=true) {\n if (on) this.on(\"room.command\", cb);\n else this.off(\"room.command\", cb);\n return this;\n }\n\n /**\n * 玩家指令监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onPlayerCommand(cb: (...args: any[]) => void, on=true) {\n if (on) this.on(\"player.command\", cb);\n else this.off(\"player.command\", cb);\n return this;\n }\n\n /**\n * 事件监听\n * @param {string} event 事件名称\n * @param {function} listener 监听函数\n * @returns \n */\n on<K extends keyof TiaoomEvents>(event: K, listener: TiaoomEvents[K]): this {\n this.listeners[event] = this.listeners[event] || [];\n this.listeners[event].push(listener);\n return this;\n }\n\n /**\n * 事件取消监听\n * @param {string} event 事件名称\n * @param {function} listener 监听函数\n * @returns \n */\n off<K extends keyof TiaoomEvents>(event: K, listener: TiaoomEvents[K]): this {\n const listeners = this.listeners[event] || [];\n const index = listeners.indexOf(listener);\n if (index !== -1) {\n listeners.splice(index, 1);\n }\n return this;\n }\n\n /**\n * 事件触发\n * @param {string} event 事件名称\n * @param {...any} args 参数\n * @returns \n */\n emit<K extends keyof TiaoomEvents>(event: K, ...args: Parameters<TiaoomEvents[K]>): this {\n const listeners = this.listeners[event] || [];\n listeners.forEach(listener => listener(...args));\n return this;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"client.iife.js","names":[],"sources":["../lib/client.ts"],"sourcesContent":["export type TiaoomEvents = {\n /**\n * 连接准备就绪事件\n */\n \"sys.ready\": () => void;\n /**\n * 连接错误事件\n * @param error 错误信息\n */\n \"sys.error\": (error: any) => void;\n /**\n * 连接关闭事件\n */\n \"sys.close\": () => void;\n /**\n * 全局命令事件\n * @param data 命令内容\n */\n \"global.command\": (data: any & { sender: Player }) => void;\n /**\n * 玩家列表更新事件\n * @param players 玩家列表\n */\n \"player.list\": (players: Player[]) => void;\n /**\n * 玩家登录事件\n * @param player 玩家信息\n */\n \"player.login\": (player: Player) => void;\n /**\n * 玩家登出事件\n * @param player 玩家信息\n */\n \"player.logout\": (player: Player) => void;\n /**\n * 玩家状态更新事件\n * @param player 玩家信息\n * @param status 状态\n * @param roomId 房间ID(可选)\n */\n \"player.status\": (player: Player, status: string, roomId?: string) => void;\n /**\n * 玩家命令事件\n * @param command 命令内容\n */\n \"player.command\": (command: any & { sender: Player }) => void;\n /**\n * 玩家消息事件\n * @param message 消息内容\n */\n \"player.message\": (message: any & { sender: Player }) => void;\n /**\n * 房间列表更新事件\n * @param rooms 房间列表\n */\n \"room.list\": (rooms: Room[]) => void;\n /**\n * 房间创建事件\n * @param room 房间信息\n */\n \"room.create\": (room: Room) => void;\n /**\n * 房间更新事件\n * @param room 房间信息\n */\n \"room.update\": (room: Room) => void;\n /**\n * 房间关闭事件\n * @param room 房间信息\n */\n \"room.close\": (room: Room) => void;\n /**\n * 玩家加入房间事件\n * @param room 房间信息\n * @param player 玩家信息\n */\n \"room.join\": (room: Room, player: Player) => void;\n /**\n * 玩家离开房间事件\n * @param room 房间信息\n * @param player 玩家信息\n */\n \"room.leave\": (room: Room, player: Player) => void;\n /**\n * 房间开始游戏事件\n * @param room 房间信息\n */\n \"room.start\": (room: Room) => void;\n /**\n * 房间结束游戏事件\n * @param room 房间信息\n */\n \"room.end\": (room: Room) => void;\n /**\n * 房间玩家全部准备事件\n * @param room 房间信息\n */\n \"room.all-ready\": (room: Room) => void;\n /**\n * 房间命令事件\n * @param command 命令内容\n */\n \"room.command\": (command: any & { sender: Player }) => void;\n /**\n * 房间消息事件\n * @param message 消息内容\n */\n \"room.message\": (message: any & { sender: Player }) => void;\n /**\n * 房间玩家准备事件\n * @param player 玩家信息\n * @param roomId 房间ID(可选)\n */\n \"room.player-ready\": (player: Player, roomId?: string) => void;\n /**\n * 房间玩家取消准备事件\n * @param player 玩家信息\n * @param roomId 房间ID(可选)\n */\n \"room.player-unready\": (player: Player, roomId?: string) => void;\n /**\n * 玩家列表更新事件(内部)\n * @param players 玩家列表\n */\n \"onPlayerList\": (players: Player[]) => void;\n /**\n * 房间列表更新事件(内部)\n * @param rooms 房间列表\n */\n \"onRoomList\": (rooms: Room[]) => void;\n /**\n * 房间开始游戏事件(内部)\n * @param room 房间信息\n */\n \"onRoomStart\": (room: Room) => void;\n /**\n * 房间结束游戏事件(内部)\n * @param room 房间信息\n */\n \"onRoomEnd\": (room: Room) => void;\n /**\n * 房间玩家全部准备事件(内部)\n * @param room 房间信息\n */\n \"onRoomAllReady\": (room: Room) => void;\n};\n\nexport class Player {\n id: string;\n name: string;\n attributes: Record<string, any>;\n status: string;\n constructor(player: Partial<Player>) {\n this.id = player.id || Date.now().toString();\n this.name = player.name || '玩家' + this.id;\n this.attributes = player.attributes || {};\n this.status = player.status || 'online';\n }\n}\n\nexport class RoomPlayer extends Player {\n role: string;\n isReady: boolean;\n isCreator: boolean;\n constructor(player: RoomPlayer) {\n super(player);\n this.role = player.role;\n this.isReady = player.isReady;\n this.isCreator = player.isCreator;\n }\n}\n\nexport class Room {\n id: string;\n name: string;\n players: RoomPlayer[];\n size: number;\n minSize: number;\n status: string;\n attrs: Record<string, any>;\n constructor(room: Room) {\n this.id = room.id;\n this.name = room.name;\n this.players = room.players.map(player => new RoomPlayer(player));\n this.size = room.size;\n this.minSize = room.minSize;\n this.status = room.status;\n this.attrs = room.attrs;\n }\n}\n\n/**\n * Tiaoom 客户端\n * @description 用于连接 Tiaoom 服务器并进行游戏交互,如创建房间、加入房间、发送命令等。\n * 需继承后实现具体的连接和消息发送逻辑。\n */\nexport class Tiaoom {\n listeners: Record<string, Function[]>;\n rooms: Room[];\n players: Player[];\n currentPlayer: Player | null;\n constructor() {\n this.listeners = {};\n this.rooms = [];\n this.players = [];\n this.currentPlayer = null;\n }\n\n /**\n * 启动游戏\n */\n run() {\n this.connect();\n this.onReady(() => {\n this.send({ type: \"room.list\" });\n this.send({ type: \"player.list\" });\n });\n\n this.on(\"player.list\", (players) => {\n this.players = players.map(player => new Player(player));\n this.emit('onPlayerList', [...this.players]);\n });\n this.on(\"player.login\", (player) => {\n this.players.push(new Player(player));\n this.emit('onPlayerList', [...this.players]);\n });\n this.on(\"player.logout\", (player) => {\n this.players = this.players.filter(p => p.id !== player.id);\n this.emit('onPlayerList', [...this.players]);\n });\n\n\n this.on(\"room.list\", (rooms) => {\n this.rooms = rooms.map(room => new Room(room));\n this.emit('onRoomList', [...this.rooms]);\n });\n this.on(\"room.create\", (room) => {\n this.rooms.push(new Room(room));\n this.emit('onRoomList', this.rooms);\n });\n this.on(\"room.update\", (room) => {\n const existingRoom = this.rooms.find(r => r.id === room.id);\n if (!existingRoom) {\n this.rooms.push(new Room(room));\n } else {\n Object.assign(existingRoom, room);\n }\n this.emit('onRoomList', this.rooms);\n });\n this.on(\"room.close\", (room) => {\n this.rooms = this.rooms.filter(r => r.id !== room.id);\n this.emit('onRoomList', this.rooms);\n });\n this.on(\"room.update\", (room) => {\n const updatedRoom = this.rooms.find(r => r.id === room.id);\n if (updatedRoom) {\n Object.assign(updatedRoom, room);\n this.emit('onRoomList', this.rooms);\n }\n });\n\n return this;\n }\n\n /**\n * 连接服务器实现\n */\n connect() {\n throw new Error('Must be implement connect method');\n }\n\n /**\n * 发送消息实现\n */\n send(_: { type: string, data?: any }) {\n throw new Error('Must be implement send method');\n }\n\n /**\n * 登录\n * @param {Player} player 玩家信息\n */\n login(player: Player) {\n this.currentPlayer = new Player(player);\n this.send({ type: \"player.login\", data: player });\n return this;\n }\n\n /**\n * 创建房间\n * @param {string} name 房间名称\n * @param {number} size 房间人数上限\n * @param {number} minSize 房间人数下限\n * @param {object} attrs 房间属性\n */\n createRoom({ name, size, minSize, attrs }: { name: string, size: number, minSize: number, attrs?: Record<string, any> }) {\n return new Promise<void>((resolve) => {\n this.send({ type: \"room.create\", data: { name, size, minSize, attrs } });\n this.on(\"room.create\", (room) => {\n resolve();\n });\n });\n }\n\n /**\n * 加入房间\n * @param {string} roomId 房间ID\n */\n joinRoom(roomId: string) {\n this.send({ type: \"player.join\", data: { roomId } });\n return this;\n }\n\n /**\n * 离开房间\n * @param {string} roomId 房间ID\n */\n leaveRoom(roomId: string) {\n this.send({ type: \"player.leave\", data: { roomId } });\n return this;\n }\n\n /**\n * 开始游戏\n * @param {string} id 房间ID\n */\n startGame(id: string) {\n this.send({ type: \"room.start\", data: { id } });\n return this;\n }\n\n /**\n * 准备/取消准备\n * @param {string} roomId 房间ID\n * @param {boolean} isReady 是否准备\n */\n ready(roomId: string, isReady=true) {\n this.send({ type: isReady ? \"player.ready\" : \"player.unready\", data: { roomId } });\n return this;\n }\n\n /**\n * 发送房间指令\n * @param {string} roomId 房间ID\n * @param {any} command 指令内容\n */\n command(command: any): this;\n command(roomId: string, command: any): this;\n command(roomId: string | any, command?: any) {\n if (typeof roomId != 'string') {\n command = roomId;\n this.send({ type: \"global.command\", data: command });\n } else {\n this.send({ type: \"room.player-command\", data: { id: roomId, ...command } });\n }\n return this;\n }\n\n /**\n * 连接准备监听\n * @param {function} cb 监听函数\n */\n onReady(cb: (...args: any[]) => void) {\n return this.on(\"sys.ready\", cb);\n }\n\n /**\n * 玩家列表变更监听\n * @param {function} cb 监听函数\n */\n onPlayerList(cb: (...args: any[]) => void) {\n this.on(\"onPlayerList\", cb);\n return this;\n }\n\n /**\n * 房间列表变更监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onRoomList(cb: (...args: any[]) => void, on=true) {\n if (on) this.on(\"onRoomList\", cb);\n else this.off(\"onRoomList\", cb);\n return this;\n }\n\n /**\n * 玩家加入监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onPlayerJoin(cb: (...args: any[]) => void, on=true) {\n if (on) this.on(\"room.join\", cb);\n else this.off(\"room.join\", cb);\n return this;\n }\n\n /**\n * 玩家离开监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onPlayerLeave(cb: (...args: any[]) => void, on=true) {\n if (on) this.on(\"room.leave\", cb);\n else this.off(\"room.leave\", cb);\n return this;\n }\n\n /**\n * 玩家准备监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onPlayerReady(cb: (...args: any[]) => void, on=true) {\n if (on) this.on(\"room.player-ready\", cb);\n else this.off(\"room.player-ready\", cb);\n return this;\n }\n\n /**\n * 玩家取消准备监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onPlayerUnready(cb: (...args: any[]) => void, on=true) {\n if (on) this.on(\"room.player-unready\", cb);\n else this.off(\"room.player-unready\", cb);\n return this;\n }\n\n /**\n * 玩家状态更新监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onPlayerStatus(cb: (...args: any[]) => void, on=true) {\n if (on) this.on(\"player.status\", cb);\n else this.off(\"player.status\", cb);\n return this;\n }\n\n /**\n * 房间开始游戏监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onRoomStart(cb: (...args: any[]) => void, on=true) {\n if (!this.listeners[\"room.start\"]) {\n this.on(\"room.start\", (room) => this.emit(\"onRoomStart\", new Room(room)));\n }\n if (on) this.on(\"onRoomStart\", cb);\n else this.off(\"onRoomStart\", cb);\n return this;\n }\n\n /**\n * 房间结束游戏监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns\n */\n onRoomEnd(cb: (...args: any[]) => void, on=true) {\n if (!this.listeners[\"room.end\"]) {\n this.on(\"room.end\", (room) => this.emit(\"onRoomEnd\", new Room(room)));\n }\n if (on) this.on(\"onRoomEnd\", cb);\n else this.off(\"onRoomEnd\", cb);\n return this;\n }\n\n /**\n * 房间全部准备监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onRoomAllReady(cb: (...args: any[]) => void, on=true) {\n if (!this.listeners[\"room.all-ready\"]) {\n this.on(\"room.all-ready\", (room) => this.emit(\"onRoomAllReady\", new Room(room)));\n }\n if (on) this.on(\"onRoomAllReady\", cb);\n else this.off(\"onRoomAllReady\", cb);\n return this;\n }\n\n /**\n * 房间消息监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onRoomMessage(cb: (...args: any[]) => void, on=true) {\n if (on) this.on(\"room.message\", cb);\n else this.off(\"room.message\", cb);\n return this;\n }\n\n /**\n * 玩家消息监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onPlayerMessage(cb: (...args: any[]) => void, on=true) {\n if (on) this.on(\"player.message\", cb);\n else this.off(\"player.message\", cb);\n return this;\n }\n\n /**\n * 房间指令监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onRoomCommand(cb: (...args: any[]) => void, on=true) {\n if (on) this.on(\"room.command\", cb);\n else this.off(\"room.command\", cb);\n return this;\n }\n\n /**\n * 玩家指令监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onPlayerCommand(cb: (...args: any[]) => void, on=true) {\n if (on) this.on(\"player.command\", cb);\n else this.off(\"player.command\", cb);\n return this;\n }\n\n /**\n * 事件监听\n * @param {string} event 事件名称\n * @param {function} listener 监听函数\n * @returns \n */\n on<K extends keyof TiaoomEvents>(event: K, listener: TiaoomEvents[K]): this {\n this.listeners[event] = this.listeners[event] || [];\n this.listeners[event].push(listener);\n return this;\n }\n\n /**\n * 事件取消监听\n * @param {string} event 事件名称\n * @param {function} listener 监听函数\n * @returns \n */\n off<K extends keyof TiaoomEvents>(event: K, listener: TiaoomEvents[K]): this {\n const listeners = this.listeners[event] || [];\n const index = listeners.indexOf(listener);\n if (index !== -1) {\n listeners.splice(index, 1);\n }\n return this;\n }\n\n /**\n * 事件触发\n * @param {string} event 事件名称\n * @param {...any} args 参数\n * @returns \n */\n emit<K extends keyof TiaoomEvents>(event: K, ...args: Parameters<TiaoomEvents[K]>): this {\n const listeners = this.listeners[event] || [];\n listeners.forEach(listener => listener(...args));\n return this;\n }\n}\n"],"mappings":"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"}
package/src/client.mjs CHANGED
@@ -1,2 +1,2 @@
1
- var e=class{constructor(e){this.id=e.id,this.name=e.name,this.attributes=e.attributes,this.status=e.status}},t=class extends e{constructor(e){super(e),this.role=e.role,this.isReady=e.isReady,this.isCreator=e.isCreator}},n=class{constructor(e){this.id=e.id,this.name=e.name,this.players=e.players.map(e=>new t(e)),this.size=e.size,this.minSize=e.minSize,this.status=e.status,this.attrs=e.attrs}},r=class{constructor(){this.listeners={},this.rooms=[],this.players=[],this.currentPlayer=null}run(){return this.connect(),this.onReady(()=>{this.send({type:`room.list`}),this.send({type:`player.list`})}),this.on(`player.list`,t=>{this.players=t.map(t=>new e(t)),this.emit(`onPlayerList`,[...this.players])}),this.on(`player.login`,t=>{this.players.push(new e(t)),this.emit(`onPlayerList`,[...this.players])}),this.on(`player.logout`,e=>{this.players=this.players.filter(t=>t.id!==e.id),this.emit(`onPlayerList`,[...this.players])}),this.on(`room.list`,e=>{this.rooms=e.map(e=>new n(e)),this.emit(`onRoomList`,[...this.rooms])}),this.on(`room.create`,e=>{this.rooms.push(new n(e)),this.emit(`onRoomList`,this.rooms)}),this.on(`room.update`,e=>{let t=this.rooms.find(t=>t.id===e.id);t?Object.assign(t,e):this.rooms.push(new n(e)),this.emit(`onRoomList`,this.rooms)}),this.on(`room.close`,e=>{this.rooms=this.rooms.filter(t=>t.id!==e.id),this.emit(`onRoomList`,this.rooms)}),this.on(`room.update`,e=>{let t=this.rooms.find(t=>t.id===e.id);t&&(Object.assign(t,e),this.emit(`onRoomList`,this.rooms))}),this}connect(){throw Error(`Must be implement connect method`)}send(e){throw Error(`Must be implement send method`)}login(t){return this.currentPlayer=new e(t),this.send({type:`player.login`,data:t}),this}createRoom({name:e,size:t,minSize:n,attrs:r}){return new Promise(i=>{this.send({type:`room.create`,data:{name:e,size:t,minSize:n,attrs:r}}),this.on(`room.create`,e=>{i()})})}joinRoom(e){return this.send({type:`player.join`,data:{roomId:e}}),this}leaveRoom(e){return this.send({type:`player.leave`,data:{roomId:e}}),this}startGame(e){return this.send({type:`room.start`,data:{id:e}}),this}ready(e,t=!0){return this.send({type:t?`player.ready`:`player.unready`,data:{roomId:e}}),this}command(e,t){return typeof e==`string`?this.send({type:`room.player-command`,data:{id:e,...t}}):(t=e,this.send({type:`global.command`,data:t})),this}onReady(e){return this.on(`sys.ready`,e)}onPlayerList(e){return this.on(`onPlayerList`,e),this}onRoomList(e,t=!0){return t?this.on(`onRoomList`,e):this.off(`onRoomList`,e),this}onPlayerJoin(e,t=!0){return t?this.on(`room.join`,e):this.off(`room.join`,e),this}onPlayerLeave(e,t=!0){return t?this.on(`room.leave`,e):this.off(`room.leave`,e),this}onPlayerReady(e,t=!0){return t?this.on(`room.player-ready`,e):this.off(`room.player-ready`,e),this}onPlayerUnready(e,t=!0){return t?this.on(`room.player-unready`,e):this.off(`room.player-unready`,e),this}onPlayerStatus(e,t=!0){return t?this.on(`player.status`,e):this.off(`player.status`,e),this}onRoomStart(e,t=!0){return this.listeners[`room.start`]||this.on(`room.start`,e=>this.emit(`onRoomStart`,new n(e))),t?this.on(`onRoomStart`,e):this.off(`onRoomStart`,e),this}onRoomEnd(e,t=!0){return this.listeners[`room.end`]||this.on(`room.end`,e=>this.emit(`onRoomEnd`,new n(e))),t?this.on(`onRoomEnd`,e):this.off(`onRoomEnd`,e),this}onRoomAllReady(e,t=!0){return this.listeners[`room.all-ready`]||this.on(`room.all-ready`,e=>this.emit(`onRoomAllReady`,new n(e))),t?this.on(`onRoomAllReady`,e):this.off(`onRoomAllReady`,e),this}onRoomMessage(e,t=!0){return t?this.on(`room.message`,e):this.off(`room.message`,e),this}onPlayerMessage(e,t=!0){return t?this.on(`player.message`,e):this.off(`player.message`,e),this}onRoomCommand(e,t=!0){return t?this.on(`room.command`,e):this.off(`room.command`,e),this}onPlayerCommand(e,t=!0){return t?this.on(`player.command`,e):this.off(`player.command`,e),this}on(e,t){return this.listeners[e]=this.listeners[e]||[],this.listeners[e].push(t),this}off(e,t){let n=this.listeners[e]||[],r=n.indexOf(t);return r!==-1&&n.splice(r,1),this}emit(e,...t){return(this.listeners[e]||[]).forEach(e=>e(...t)),this}};export{e as Player,n as Room,t as RoomPlayer,r as Tiaoom};
1
+ var e=class{constructor(e){this.id=e.id||Date.now().toString(),this.name=e.name||`玩家`+this.id,this.attributes=e.attributes||{},this.status=e.status||`online`}},t=class extends e{constructor(e){super(e),this.role=e.role,this.isReady=e.isReady,this.isCreator=e.isCreator}},n=class{constructor(e){this.id=e.id,this.name=e.name,this.players=e.players.map(e=>new t(e)),this.size=e.size,this.minSize=e.minSize,this.status=e.status,this.attrs=e.attrs}},r=class{constructor(){this.listeners={},this.rooms=[],this.players=[],this.currentPlayer=null}run(){return this.connect(),this.onReady(()=>{this.send({type:`room.list`}),this.send({type:`player.list`})}),this.on(`player.list`,t=>{this.players=t.map(t=>new e(t)),this.emit(`onPlayerList`,[...this.players])}),this.on(`player.login`,t=>{this.players.push(new e(t)),this.emit(`onPlayerList`,[...this.players])}),this.on(`player.logout`,e=>{this.players=this.players.filter(t=>t.id!==e.id),this.emit(`onPlayerList`,[...this.players])}),this.on(`room.list`,e=>{this.rooms=e.map(e=>new n(e)),this.emit(`onRoomList`,[...this.rooms])}),this.on(`room.create`,e=>{this.rooms.push(new n(e)),this.emit(`onRoomList`,this.rooms)}),this.on(`room.update`,e=>{let t=this.rooms.find(t=>t.id===e.id);t?Object.assign(t,e):this.rooms.push(new n(e)),this.emit(`onRoomList`,this.rooms)}),this.on(`room.close`,e=>{this.rooms=this.rooms.filter(t=>t.id!==e.id),this.emit(`onRoomList`,this.rooms)}),this.on(`room.update`,e=>{let t=this.rooms.find(t=>t.id===e.id);t&&(Object.assign(t,e),this.emit(`onRoomList`,this.rooms))}),this}connect(){throw Error(`Must be implement connect method`)}send(e){throw Error(`Must be implement send method`)}login(t){return this.currentPlayer=new e(t),this.send({type:`player.login`,data:t}),this}createRoom({name:e,size:t,minSize:n,attrs:r}){return new Promise(i=>{this.send({type:`room.create`,data:{name:e,size:t,minSize:n,attrs:r}}),this.on(`room.create`,e=>{i()})})}joinRoom(e){return this.send({type:`player.join`,data:{roomId:e}}),this}leaveRoom(e){return this.send({type:`player.leave`,data:{roomId:e}}),this}startGame(e){return this.send({type:`room.start`,data:{id:e}}),this}ready(e,t=!0){return this.send({type:t?`player.ready`:`player.unready`,data:{roomId:e}}),this}command(e,t){return typeof e==`string`?this.send({type:`room.player-command`,data:{id:e,...t}}):(t=e,this.send({type:`global.command`,data:t})),this}onReady(e){return this.on(`sys.ready`,e)}onPlayerList(e){return this.on(`onPlayerList`,e),this}onRoomList(e,t=!0){return t?this.on(`onRoomList`,e):this.off(`onRoomList`,e),this}onPlayerJoin(e,t=!0){return t?this.on(`room.join`,e):this.off(`room.join`,e),this}onPlayerLeave(e,t=!0){return t?this.on(`room.leave`,e):this.off(`room.leave`,e),this}onPlayerReady(e,t=!0){return t?this.on(`room.player-ready`,e):this.off(`room.player-ready`,e),this}onPlayerUnready(e,t=!0){return t?this.on(`room.player-unready`,e):this.off(`room.player-unready`,e),this}onPlayerStatus(e,t=!0){return t?this.on(`player.status`,e):this.off(`player.status`,e),this}onRoomStart(e,t=!0){return this.listeners[`room.start`]||this.on(`room.start`,e=>this.emit(`onRoomStart`,new n(e))),t?this.on(`onRoomStart`,e):this.off(`onRoomStart`,e),this}onRoomEnd(e,t=!0){return this.listeners[`room.end`]||this.on(`room.end`,e=>this.emit(`onRoomEnd`,new n(e))),t?this.on(`onRoomEnd`,e):this.off(`onRoomEnd`,e),this}onRoomAllReady(e,t=!0){return this.listeners[`room.all-ready`]||this.on(`room.all-ready`,e=>this.emit(`onRoomAllReady`,new n(e))),t?this.on(`onRoomAllReady`,e):this.off(`onRoomAllReady`,e),this}onRoomMessage(e,t=!0){return t?this.on(`room.message`,e):this.off(`room.message`,e),this}onPlayerMessage(e,t=!0){return t?this.on(`player.message`,e):this.off(`player.message`,e),this}onRoomCommand(e,t=!0){return t?this.on(`room.command`,e):this.off(`room.command`,e),this}onPlayerCommand(e,t=!0){return t?this.on(`player.command`,e):this.off(`player.command`,e),this}on(e,t){return this.listeners[e]=this.listeners[e]||[],this.listeners[e].push(t),this}off(e,t){let n=this.listeners[e]||[],r=n.indexOf(t);return r!==-1&&n.splice(r,1),this}emit(e,...t){return(this.listeners[e]||[]).forEach(e=>e(...t)),this}};export{e as Player,n as Room,t as RoomPlayer,r as Tiaoom};
2
2
  //# sourceMappingURL=client.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.mjs","names":[],"sources":["../lib/client.ts"],"sourcesContent":["export type TiaoomEvents = {\n /**\n * 连接准备就绪事件\n */\n \"sys.ready\": () => void;\n /**\n * 连接错误事件\n * @param error 错误信息\n */\n \"sys.error\": (error: any) => void;\n /**\n * 连接关闭事件\n */\n \"sys.close\": () => void;\n /**\n * 全局命令事件\n * @param data 命令内容\n */\n \"global.command\": (data: any & { sender: Player }) => void;\n /**\n * 玩家列表更新事件\n * @param players 玩家列表\n */\n \"player.list\": (players: Player[]) => void;\n /**\n * 玩家登录事件\n * @param player 玩家信息\n */\n \"player.login\": (player: Player) => void;\n /**\n * 玩家登出事件\n * @param player 玩家信息\n */\n \"player.logout\": (player: Player) => void;\n /**\n * 玩家状态更新事件\n * @param player 玩家信息\n * @param status 状态\n * @param roomId 房间ID(可选)\n */\n \"player.status\": (player: Player, status: string, roomId?: string) => void;\n /**\n * 玩家命令事件\n * @param command 命令内容\n */\n \"player.command\": (command: any & { sender: Player }) => void;\n /**\n * 玩家消息事件\n * @param message 消息内容\n */\n \"player.message\": (message: any & { sender: Player }) => void;\n /**\n * 房间列表更新事件\n * @param rooms 房间列表\n */\n \"room.list\": (rooms: Room[]) => void;\n /**\n * 房间创建事件\n * @param room 房间信息\n */\n \"room.create\": (room: Room) => void;\n /**\n * 房间更新事件\n * @param room 房间信息\n */\n \"room.update\": (room: Room) => void;\n /**\n * 房间关闭事件\n * @param room 房间信息\n */\n \"room.close\": (room: Room) => void;\n /**\n * 玩家加入房间事件\n * @param room 房间信息\n * @param player 玩家信息\n */\n \"room.join\": (room: Room, player: Player) => void;\n /**\n * 玩家离开房间事件\n * @param room 房间信息\n * @param player 玩家信息\n */\n \"room.leave\": (room: Room, player: Player) => void;\n /**\n * 房间开始游戏事件\n * @param room 房间信息\n */\n \"room.start\": (room: Room) => void;\n /**\n * 房间结束游戏事件\n * @param room 房间信息\n */\n \"room.end\": (room: Room) => void;\n /**\n * 房间玩家全部准备事件\n * @param room 房间信息\n */\n \"room.all-ready\": (room: Room) => void;\n /**\n * 房间命令事件\n * @param command 命令内容\n */\n \"room.command\": (command: any & { sender: Player }) => void;\n /**\n * 房间消息事件\n * @param message 消息内容\n */\n \"room.message\": (message: any & { sender: Player }) => void;\n /**\n * 房间玩家准备事件\n * @param player 玩家信息\n * @param roomId 房间ID(可选)\n */\n \"room.player-ready\": (player: Player, roomId?: string) => void;\n /**\n * 房间玩家取消准备事件\n * @param player 玩家信息\n * @param roomId 房间ID(可选)\n */\n \"room.player-unready\": (player: Player, roomId?: string) => void;\n /**\n * 玩家列表更新事件(内部)\n * @param players 玩家列表\n */\n \"onPlayerList\": (players: Player[]) => void;\n /**\n * 房间列表更新事件(内部)\n * @param rooms 房间列表\n */\n \"onRoomList\": (rooms: Room[]) => void;\n /**\n * 房间开始游戏事件(内部)\n * @param room 房间信息\n */\n \"onRoomStart\": (room: Room) => void;\n /**\n * 房间结束游戏事件(内部)\n * @param room 房间信息\n */\n \"onRoomEnd\": (room: Room) => void;\n /**\n * 房间玩家全部准备事件(内部)\n * @param room 房间信息\n */\n \"onRoomAllReady\": (room: Room) => void;\n};\n\nexport class Player {\n id: string;\n name: string;\n attributes: Record<string, any>;\n status: string;\n constructor(player: Player) {\n this.id = player.id;\n this.name = player.name;\n this.attributes = player.attributes;\n this.status = player.status;\n }\n}\n\nexport class RoomPlayer extends Player {\n role: string;\n isReady: boolean;\n isCreator: boolean;\n constructor(player: RoomPlayer) {\n super(player);\n this.role = player.role;\n this.isReady = player.isReady;\n this.isCreator = player.isCreator;\n }\n}\n\nexport class Room {\n id: string;\n name: string;\n players: RoomPlayer[];\n size: number;\n minSize: number;\n status: string;\n attrs: Record<string, any>;\n constructor(room: Room) {\n this.id = room.id;\n this.name = room.name;\n this.players = room.players.map(player => new RoomPlayer(player));\n this.size = room.size;\n this.minSize = room.minSize;\n this.status = room.status;\n this.attrs = room.attrs;\n }\n}\n\n/**\n * Tiaoom 客户端\n * @description 用于连接 Tiaoom 服务器并进行游戏交互,如创建房间、加入房间、发送命令等。\n * 需继承后实现具体的连接和消息发送逻辑。\n */\nexport class Tiaoom {\n listeners: Record<string, Function[]>;\n rooms: Room[];\n players: Player[];\n currentPlayer: Player | null;\n constructor() {\n this.listeners = {};\n this.rooms = [];\n this.players = [];\n this.currentPlayer = null;\n }\n\n /**\n * 启动游戏\n */\n run() {\n this.connect();\n this.onReady(() => {\n this.send({ type: \"room.list\" });\n this.send({ type: \"player.list\" });\n });\n\n this.on(\"player.list\", (players) => {\n this.players = players.map(player => new Player(player));\n this.emit('onPlayerList', [...this.players]);\n });\n this.on(\"player.login\", (player) => {\n this.players.push(new Player(player));\n this.emit('onPlayerList', [...this.players]);\n });\n this.on(\"player.logout\", (player) => {\n this.players = this.players.filter(p => p.id !== player.id);\n this.emit('onPlayerList', [...this.players]);\n });\n\n\n this.on(\"room.list\", (rooms) => {\n this.rooms = rooms.map(room => new Room(room));\n this.emit('onRoomList', [...this.rooms]);\n });\n this.on(\"room.create\", (room) => {\n this.rooms.push(new Room(room));\n this.emit('onRoomList', this.rooms);\n });\n this.on(\"room.update\", (room) => {\n const existingRoom = this.rooms.find(r => r.id === room.id);\n if (!existingRoom) {\n this.rooms.push(new Room(room));\n } else {\n Object.assign(existingRoom, room);\n }\n this.emit('onRoomList', this.rooms);\n });\n this.on(\"room.close\", (room) => {\n this.rooms = this.rooms.filter(r => r.id !== room.id);\n this.emit('onRoomList', this.rooms);\n });\n this.on(\"room.update\", (room) => {\n const updatedRoom = this.rooms.find(r => r.id === room.id);\n if (updatedRoom) {\n Object.assign(updatedRoom, room);\n this.emit('onRoomList', this.rooms);\n }\n });\n\n return this;\n }\n\n /**\n * 连接服务器实现\n */\n connect() {\n throw new Error('Must be implement connect method');\n }\n\n /**\n * 发送消息实现\n */\n send(_: { type: string, data?: any }) {\n throw new Error('Must be implement send method');\n }\n\n /**\n * 登录\n * @param {Player} player 玩家信息\n */\n login(player: Player) {\n this.currentPlayer = new Player(player);\n this.send({ type: \"player.login\", data: player });\n return this;\n }\n\n /**\n * 创建房间\n * @param {string} name 房间名称\n * @param {number} size 房间人数上限\n * @param {number} minSize 房间人数下限\n * @param {object} attrs 房间属性\n */\n createRoom({ name, size, minSize, attrs }: { name: string, size: number, minSize: number, attrs?: Record<string, any> }) {\n return new Promise<void>((resolve) => {\n this.send({ type: \"room.create\", data: { name, size, minSize, attrs } });\n this.on(\"room.create\", (room) => {\n resolve();\n });\n });\n }\n\n /**\n * 加入房间\n * @param {string} roomId 房间ID\n */\n joinRoom(roomId: string) {\n this.send({ type: \"player.join\", data: { roomId } });\n return this;\n }\n\n /**\n * 离开房间\n * @param {string} roomId 房间ID\n */\n leaveRoom(roomId: string) {\n this.send({ type: \"player.leave\", data: { roomId } });\n return this;\n }\n\n /**\n * 开始游戏\n * @param {string} id 房间ID\n */\n startGame(id: string) {\n this.send({ type: \"room.start\", data: { id } });\n return this;\n }\n\n /**\n * 准备/取消准备\n * @param {string} roomId 房间ID\n * @param {boolean} isReady 是否准备\n */\n ready(roomId: string, isReady=true) {\n this.send({ type: isReady ? \"player.ready\" : \"player.unready\", data: { roomId } });\n return this;\n }\n\n /**\n * 发送房间指令\n * @param {string} roomId 房间ID\n * @param {any} command 指令内容\n */\n command(command: any): this;\n command(roomId: string, command: any): this;\n command(roomId: string | any, command?: any) {\n if (typeof roomId != 'string') {\n command = roomId;\n this.send({ type: \"global.command\", data: command });\n } else {\n this.send({ type: \"room.player-command\", data: { id: roomId, ...command } });\n }\n return this;\n }\n\n /**\n * 连接准备监听\n * @param {function} cb 监听函数\n */\n onReady(cb: (...args: any[]) => void) {\n return this.on(\"sys.ready\", cb);\n }\n\n /**\n * 玩家列表变更监听\n * @param {function} cb 监听函数\n */\n onPlayerList(cb: (...args: any[]) => void) {\n this.on(\"onPlayerList\", cb);\n return this;\n }\n\n /**\n * 房间列表变更监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onRoomList(cb: (...args: any[]) => void, on=true) {\n if (on) this.on(\"onRoomList\", cb);\n else this.off(\"onRoomList\", cb);\n return this;\n }\n\n /**\n * 玩家加入监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onPlayerJoin(cb: (...args: any[]) => void, on=true) {\n if (on) this.on(\"room.join\", cb);\n else this.off(\"room.join\", cb);\n return this;\n }\n\n /**\n * 玩家离开监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onPlayerLeave(cb: (...args: any[]) => void, on=true) {\n if (on) this.on(\"room.leave\", cb);\n else this.off(\"room.leave\", cb);\n return this;\n }\n\n /**\n * 玩家准备监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onPlayerReady(cb: (...args: any[]) => void, on=true) {\n if (on) this.on(\"room.player-ready\", cb);\n else this.off(\"room.player-ready\", cb);\n return this;\n }\n\n /**\n * 玩家取消准备监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onPlayerUnready(cb: (...args: any[]) => void, on=true) {\n if (on) this.on(\"room.player-unready\", cb);\n else this.off(\"room.player-unready\", cb);\n return this;\n }\n\n /**\n * 玩家状态更新监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onPlayerStatus(cb: (...args: any[]) => void, on=true) {\n if (on) this.on(\"player.status\", cb);\n else this.off(\"player.status\", cb);\n return this;\n }\n\n /**\n * 房间开始游戏监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onRoomStart(cb: (...args: any[]) => void, on=true) {\n if (!this.listeners[\"room.start\"]) {\n this.on(\"room.start\", (room) => this.emit(\"onRoomStart\", new Room(room)));\n }\n if (on) this.on(\"onRoomStart\", cb);\n else this.off(\"onRoomStart\", cb);\n return this;\n }\n\n /**\n * 房间结束游戏监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns\n */\n onRoomEnd(cb: (...args: any[]) => void, on=true) {\n if (!this.listeners[\"room.end\"]) {\n this.on(\"room.end\", (room) => this.emit(\"onRoomEnd\", new Room(room)));\n }\n if (on) this.on(\"onRoomEnd\", cb);\n else this.off(\"onRoomEnd\", cb);\n return this;\n }\n\n /**\n * 房间全部准备监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onRoomAllReady(cb: (...args: any[]) => void, on=true) {\n if (!this.listeners[\"room.all-ready\"]) {\n this.on(\"room.all-ready\", (room) => this.emit(\"onRoomAllReady\", new Room(room)));\n }\n if (on) this.on(\"onRoomAllReady\", cb);\n else this.off(\"onRoomAllReady\", cb);\n return this;\n }\n\n /**\n * 房间消息监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onRoomMessage(cb: (...args: any[]) => void, on=true) {\n if (on) this.on(\"room.message\", cb);\n else this.off(\"room.message\", cb);\n return this;\n }\n\n /**\n * 玩家消息监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onPlayerMessage(cb: (...args: any[]) => void, on=true) {\n if (on) this.on(\"player.message\", cb);\n else this.off(\"player.message\", cb);\n return this;\n }\n\n /**\n * 房间指令监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onRoomCommand(cb: (...args: any[]) => void, on=true) {\n if (on) this.on(\"room.command\", cb);\n else this.off(\"room.command\", cb);\n return this;\n }\n\n /**\n * 玩家指令监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onPlayerCommand(cb: (...args: any[]) => void, on=true) {\n if (on) this.on(\"player.command\", cb);\n else this.off(\"player.command\", cb);\n return this;\n }\n\n /**\n * 事件监听\n * @param {string} event 事件名称\n * @param {function} listener 监听函数\n * @returns \n */\n on<K extends keyof TiaoomEvents>(event: K, listener: TiaoomEvents[K]): this {\n this.listeners[event] = this.listeners[event] || [];\n this.listeners[event].push(listener);\n return this;\n }\n\n /**\n * 事件取消监听\n * @param {string} event 事件名称\n * @param {function} listener 监听函数\n * @returns \n */\n off<K extends keyof TiaoomEvents>(event: K, listener: TiaoomEvents[K]): this {\n const listeners = this.listeners[event] || [];\n const index = listeners.indexOf(listener);\n if (index !== -1) {\n listeners.splice(index, 1);\n }\n return this;\n }\n\n /**\n * 事件触发\n * @param {string} event 事件名称\n * @param {...any} args 参数\n * @returns \n */\n emit<K extends keyof TiaoomEvents>(event: K, ...args: Parameters<TiaoomEvents[K]>): this {\n const listeners = this.listeners[event] || [];\n listeners.forEach(listener => listener(...args));\n return this;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"client.mjs","names":[],"sources":["../lib/client.ts"],"sourcesContent":["export type TiaoomEvents = {\n /**\n * 连接准备就绪事件\n */\n \"sys.ready\": () => void;\n /**\n * 连接错误事件\n * @param error 错误信息\n */\n \"sys.error\": (error: any) => void;\n /**\n * 连接关闭事件\n */\n \"sys.close\": () => void;\n /**\n * 全局命令事件\n * @param data 命令内容\n */\n \"global.command\": (data: any & { sender: Player }) => void;\n /**\n * 玩家列表更新事件\n * @param players 玩家列表\n */\n \"player.list\": (players: Player[]) => void;\n /**\n * 玩家登录事件\n * @param player 玩家信息\n */\n \"player.login\": (player: Player) => void;\n /**\n * 玩家登出事件\n * @param player 玩家信息\n */\n \"player.logout\": (player: Player) => void;\n /**\n * 玩家状态更新事件\n * @param player 玩家信息\n * @param status 状态\n * @param roomId 房间ID(可选)\n */\n \"player.status\": (player: Player, status: string, roomId?: string) => void;\n /**\n * 玩家命令事件\n * @param command 命令内容\n */\n \"player.command\": (command: any & { sender: Player }) => void;\n /**\n * 玩家消息事件\n * @param message 消息内容\n */\n \"player.message\": (message: any & { sender: Player }) => void;\n /**\n * 房间列表更新事件\n * @param rooms 房间列表\n */\n \"room.list\": (rooms: Room[]) => void;\n /**\n * 房间创建事件\n * @param room 房间信息\n */\n \"room.create\": (room: Room) => void;\n /**\n * 房间更新事件\n * @param room 房间信息\n */\n \"room.update\": (room: Room) => void;\n /**\n * 房间关闭事件\n * @param room 房间信息\n */\n \"room.close\": (room: Room) => void;\n /**\n * 玩家加入房间事件\n * @param room 房间信息\n * @param player 玩家信息\n */\n \"room.join\": (room: Room, player: Player) => void;\n /**\n * 玩家离开房间事件\n * @param room 房间信息\n * @param player 玩家信息\n */\n \"room.leave\": (room: Room, player: Player) => void;\n /**\n * 房间开始游戏事件\n * @param room 房间信息\n */\n \"room.start\": (room: Room) => void;\n /**\n * 房间结束游戏事件\n * @param room 房间信息\n */\n \"room.end\": (room: Room) => void;\n /**\n * 房间玩家全部准备事件\n * @param room 房间信息\n */\n \"room.all-ready\": (room: Room) => void;\n /**\n * 房间命令事件\n * @param command 命令内容\n */\n \"room.command\": (command: any & { sender: Player }) => void;\n /**\n * 房间消息事件\n * @param message 消息内容\n */\n \"room.message\": (message: any & { sender: Player }) => void;\n /**\n * 房间玩家准备事件\n * @param player 玩家信息\n * @param roomId 房间ID(可选)\n */\n \"room.player-ready\": (player: Player, roomId?: string) => void;\n /**\n * 房间玩家取消准备事件\n * @param player 玩家信息\n * @param roomId 房间ID(可选)\n */\n \"room.player-unready\": (player: Player, roomId?: string) => void;\n /**\n * 玩家列表更新事件(内部)\n * @param players 玩家列表\n */\n \"onPlayerList\": (players: Player[]) => void;\n /**\n * 房间列表更新事件(内部)\n * @param rooms 房间列表\n */\n \"onRoomList\": (rooms: Room[]) => void;\n /**\n * 房间开始游戏事件(内部)\n * @param room 房间信息\n */\n \"onRoomStart\": (room: Room) => void;\n /**\n * 房间结束游戏事件(内部)\n * @param room 房间信息\n */\n \"onRoomEnd\": (room: Room) => void;\n /**\n * 房间玩家全部准备事件(内部)\n * @param room 房间信息\n */\n \"onRoomAllReady\": (room: Room) => void;\n};\n\nexport class Player {\n id: string;\n name: string;\n attributes: Record<string, any>;\n status: string;\n constructor(player: Partial<Player>) {\n this.id = player.id || Date.now().toString();\n this.name = player.name || '玩家' + this.id;\n this.attributes = player.attributes || {};\n this.status = player.status || 'online';\n }\n}\n\nexport class RoomPlayer extends Player {\n role: string;\n isReady: boolean;\n isCreator: boolean;\n constructor(player: RoomPlayer) {\n super(player);\n this.role = player.role;\n this.isReady = player.isReady;\n this.isCreator = player.isCreator;\n }\n}\n\nexport class Room {\n id: string;\n name: string;\n players: RoomPlayer[];\n size: number;\n minSize: number;\n status: string;\n attrs: Record<string, any>;\n constructor(room: Room) {\n this.id = room.id;\n this.name = room.name;\n this.players = room.players.map(player => new RoomPlayer(player));\n this.size = room.size;\n this.minSize = room.minSize;\n this.status = room.status;\n this.attrs = room.attrs;\n }\n}\n\n/**\n * Tiaoom 客户端\n * @description 用于连接 Tiaoom 服务器并进行游戏交互,如创建房间、加入房间、发送命令等。\n * 需继承后实现具体的连接和消息发送逻辑。\n */\nexport class Tiaoom {\n listeners: Record<string, Function[]>;\n rooms: Room[];\n players: Player[];\n currentPlayer: Player | null;\n constructor() {\n this.listeners = {};\n this.rooms = [];\n this.players = [];\n this.currentPlayer = null;\n }\n\n /**\n * 启动游戏\n */\n run() {\n this.connect();\n this.onReady(() => {\n this.send({ type: \"room.list\" });\n this.send({ type: \"player.list\" });\n });\n\n this.on(\"player.list\", (players) => {\n this.players = players.map(player => new Player(player));\n this.emit('onPlayerList', [...this.players]);\n });\n this.on(\"player.login\", (player) => {\n this.players.push(new Player(player));\n this.emit('onPlayerList', [...this.players]);\n });\n this.on(\"player.logout\", (player) => {\n this.players = this.players.filter(p => p.id !== player.id);\n this.emit('onPlayerList', [...this.players]);\n });\n\n\n this.on(\"room.list\", (rooms) => {\n this.rooms = rooms.map(room => new Room(room));\n this.emit('onRoomList', [...this.rooms]);\n });\n this.on(\"room.create\", (room) => {\n this.rooms.push(new Room(room));\n this.emit('onRoomList', this.rooms);\n });\n this.on(\"room.update\", (room) => {\n const existingRoom = this.rooms.find(r => r.id === room.id);\n if (!existingRoom) {\n this.rooms.push(new Room(room));\n } else {\n Object.assign(existingRoom, room);\n }\n this.emit('onRoomList', this.rooms);\n });\n this.on(\"room.close\", (room) => {\n this.rooms = this.rooms.filter(r => r.id !== room.id);\n this.emit('onRoomList', this.rooms);\n });\n this.on(\"room.update\", (room) => {\n const updatedRoom = this.rooms.find(r => r.id === room.id);\n if (updatedRoom) {\n Object.assign(updatedRoom, room);\n this.emit('onRoomList', this.rooms);\n }\n });\n\n return this;\n }\n\n /**\n * 连接服务器实现\n */\n connect() {\n throw new Error('Must be implement connect method');\n }\n\n /**\n * 发送消息实现\n */\n send(_: { type: string, data?: any }) {\n throw new Error('Must be implement send method');\n }\n\n /**\n * 登录\n * @param {Player} player 玩家信息\n */\n login(player: Player) {\n this.currentPlayer = new Player(player);\n this.send({ type: \"player.login\", data: player });\n return this;\n }\n\n /**\n * 创建房间\n * @param {string} name 房间名称\n * @param {number} size 房间人数上限\n * @param {number} minSize 房间人数下限\n * @param {object} attrs 房间属性\n */\n createRoom({ name, size, minSize, attrs }: { name: string, size: number, minSize: number, attrs?: Record<string, any> }) {\n return new Promise<void>((resolve) => {\n this.send({ type: \"room.create\", data: { name, size, minSize, attrs } });\n this.on(\"room.create\", (room) => {\n resolve();\n });\n });\n }\n\n /**\n * 加入房间\n * @param {string} roomId 房间ID\n */\n joinRoom(roomId: string) {\n this.send({ type: \"player.join\", data: { roomId } });\n return this;\n }\n\n /**\n * 离开房间\n * @param {string} roomId 房间ID\n */\n leaveRoom(roomId: string) {\n this.send({ type: \"player.leave\", data: { roomId } });\n return this;\n }\n\n /**\n * 开始游戏\n * @param {string} id 房间ID\n */\n startGame(id: string) {\n this.send({ type: \"room.start\", data: { id } });\n return this;\n }\n\n /**\n * 准备/取消准备\n * @param {string} roomId 房间ID\n * @param {boolean} isReady 是否准备\n */\n ready(roomId: string, isReady=true) {\n this.send({ type: isReady ? \"player.ready\" : \"player.unready\", data: { roomId } });\n return this;\n }\n\n /**\n * 发送房间指令\n * @param {string} roomId 房间ID\n * @param {any} command 指令内容\n */\n command(command: any): this;\n command(roomId: string, command: any): this;\n command(roomId: string | any, command?: any) {\n if (typeof roomId != 'string') {\n command = roomId;\n this.send({ type: \"global.command\", data: command });\n } else {\n this.send({ type: \"room.player-command\", data: { id: roomId, ...command } });\n }\n return this;\n }\n\n /**\n * 连接准备监听\n * @param {function} cb 监听函数\n */\n onReady(cb: (...args: any[]) => void) {\n return this.on(\"sys.ready\", cb);\n }\n\n /**\n * 玩家列表变更监听\n * @param {function} cb 监听函数\n */\n onPlayerList(cb: (...args: any[]) => void) {\n this.on(\"onPlayerList\", cb);\n return this;\n }\n\n /**\n * 房间列表变更监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onRoomList(cb: (...args: any[]) => void, on=true) {\n if (on) this.on(\"onRoomList\", cb);\n else this.off(\"onRoomList\", cb);\n return this;\n }\n\n /**\n * 玩家加入监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onPlayerJoin(cb: (...args: any[]) => void, on=true) {\n if (on) this.on(\"room.join\", cb);\n else this.off(\"room.join\", cb);\n return this;\n }\n\n /**\n * 玩家离开监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onPlayerLeave(cb: (...args: any[]) => void, on=true) {\n if (on) this.on(\"room.leave\", cb);\n else this.off(\"room.leave\", cb);\n return this;\n }\n\n /**\n * 玩家准备监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onPlayerReady(cb: (...args: any[]) => void, on=true) {\n if (on) this.on(\"room.player-ready\", cb);\n else this.off(\"room.player-ready\", cb);\n return this;\n }\n\n /**\n * 玩家取消准备监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onPlayerUnready(cb: (...args: any[]) => void, on=true) {\n if (on) this.on(\"room.player-unready\", cb);\n else this.off(\"room.player-unready\", cb);\n return this;\n }\n\n /**\n * 玩家状态更新监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onPlayerStatus(cb: (...args: any[]) => void, on=true) {\n if (on) this.on(\"player.status\", cb);\n else this.off(\"player.status\", cb);\n return this;\n }\n\n /**\n * 房间开始游戏监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onRoomStart(cb: (...args: any[]) => void, on=true) {\n if (!this.listeners[\"room.start\"]) {\n this.on(\"room.start\", (room) => this.emit(\"onRoomStart\", new Room(room)));\n }\n if (on) this.on(\"onRoomStart\", cb);\n else this.off(\"onRoomStart\", cb);\n return this;\n }\n\n /**\n * 房间结束游戏监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns\n */\n onRoomEnd(cb: (...args: any[]) => void, on=true) {\n if (!this.listeners[\"room.end\"]) {\n this.on(\"room.end\", (room) => this.emit(\"onRoomEnd\", new Room(room)));\n }\n if (on) this.on(\"onRoomEnd\", cb);\n else this.off(\"onRoomEnd\", cb);\n return this;\n }\n\n /**\n * 房间全部准备监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onRoomAllReady(cb: (...args: any[]) => void, on=true) {\n if (!this.listeners[\"room.all-ready\"]) {\n this.on(\"room.all-ready\", (room) => this.emit(\"onRoomAllReady\", new Room(room)));\n }\n if (on) this.on(\"onRoomAllReady\", cb);\n else this.off(\"onRoomAllReady\", cb);\n return this;\n }\n\n /**\n * 房间消息监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onRoomMessage(cb: (...args: any[]) => void, on=true) {\n if (on) this.on(\"room.message\", cb);\n else this.off(\"room.message\", cb);\n return this;\n }\n\n /**\n * 玩家消息监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onPlayerMessage(cb: (...args: any[]) => void, on=true) {\n if (on) this.on(\"player.message\", cb);\n else this.off(\"player.message\", cb);\n return this;\n }\n\n /**\n * 房间指令监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onRoomCommand(cb: (...args: any[]) => void, on=true) {\n if (on) this.on(\"room.command\", cb);\n else this.off(\"room.command\", cb);\n return this;\n }\n\n /**\n * 玩家指令监听\n * @param {function} cb 监听函数\n * @param {boolean} on 开启/关闭监听\n * @returns \n */\n onPlayerCommand(cb: (...args: any[]) => void, on=true) {\n if (on) this.on(\"player.command\", cb);\n else this.off(\"player.command\", cb);\n return this;\n }\n\n /**\n * 事件监听\n * @param {string} event 事件名称\n * @param {function} listener 监听函数\n * @returns \n */\n on<K extends keyof TiaoomEvents>(event: K, listener: TiaoomEvents[K]): this {\n this.listeners[event] = this.listeners[event] || [];\n this.listeners[event].push(listener);\n return this;\n }\n\n /**\n * 事件取消监听\n * @param {string} event 事件名称\n * @param {function} listener 监听函数\n * @returns \n */\n off<K extends keyof TiaoomEvents>(event: K, listener: TiaoomEvents[K]): this {\n const listeners = this.listeners[event] || [];\n const index = listeners.indexOf(listener);\n if (index !== -1) {\n listeners.splice(index, 1);\n }\n return this;\n }\n\n /**\n * 事件触发\n * @param {string} event 事件名称\n * @param {...any} args 参数\n * @returns \n */\n emit<K extends keyof TiaoomEvents>(event: K, ...args: Parameters<TiaoomEvents[K]>): this {\n const listeners = this.listeners[event] || [];\n listeners.forEach(listener => listener(...args));\n return this;\n }\n}\n"],"mappings":"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"}
package/src/index.cjs CHANGED
@@ -63,7 +63,8 @@ var Player = class extends events.default {
63
63
  "status"
64
64
  ].forEach((event) => {
65
65
  this.on(event, (...data) => {
66
- this.sender?.(event, ...data);
66
+ var _this$sender;
67
+ (_this$sender = this.sender) === null || _this$sender === void 0 || _this$sender.call(this, event, ...data);
67
68
  });
68
69
  });
69
70
  }
@@ -181,7 +182,8 @@ var Room = class extends events.default {
181
182
  "leave"
182
183
  ].forEach((event) => {
183
184
  this.on(event, (...data) => {
184
- this.sender?.(event, ...data);
185
+ var _this$sender;
186
+ (_this$sender = this.sender) === null || _this$sender === void 0 || _this$sender.call(this, event, ...data);
185
187
  });
186
188
  });
187
189
  }
@@ -286,26 +288,31 @@ var Tiaoom = class extends events.EventEmitter {
286
288
  return super.emit(event, ...args);
287
289
  }
288
290
  run() {
289
- this.messageInstance?.on("message", (message, cb) => {
291
+ var _this$messageInstance;
292
+ (_this$messageInstance = this.messageInstance) === null || _this$messageInstance === void 0 || _this$messageInstance.on("message", (message, cb) => {
290
293
  try {
291
294
  switch (message.type) {
292
- case "room.list": return cb?.(null, this.rooms);
293
- case "player.list": return cb?.(null, this.players);
295
+ case "room.list": return cb === null || cb === void 0 ? void 0 : cb(null, this.rooms);
296
+ case "player.list": return cb === null || cb === void 0 ? void 0 : cb(null, this.players);
294
297
  case "room.create": return this.createRoom(message.sender, message.data);
295
298
  case "player.join": return this.joinPlayer(message.sender, message.data);
296
299
  case "player.leave": return this.leavePlayer(message.sender, message.data);
297
- case "room.get": return cb?.(null, this.searchRoom(message.data));
300
+ case "room.get": return cb === null || cb === void 0 ? void 0 : cb(null, this.searchRoom(message.data));
298
301
  case "room.start": return this.startRoom(message.sender, message.data);
299
302
  case "room.close": return this.closeRoom(message.sender, message.data);
300
303
  case "player.login": return this.loginPlayer(message.data);
301
304
  case "player.logout": return this.removePlayer(message.data);
302
305
  case "player.ready": return this.readyPlayer(message.sender, message.data);
303
306
  case "player.unready": return this.unReadyPlayer(message.sender, message.data);
304
- case "room.player-command": return this.searchRoom(message.data)?.emit("player-command", {
305
- ...message.data,
306
- sender: message.sender
307
- });
308
- case "room.message": return this.searchRoom(message.data)?.emit("message", message.data);
307
+ case "room.player-command":
308
+ var _this$searchRoom;
309
+ return (_this$searchRoom = this.searchRoom(message.data)) === null || _this$searchRoom === void 0 ? void 0 : _this$searchRoom.emit("player-command", {
310
+ ...message.data,
311
+ sender: message.sender
312
+ });
313
+ case "room.message":
314
+ var _this$searchRoom2;
315
+ return (_this$searchRoom2 = this.searchRoom(message.data)) === null || _this$searchRoom2 === void 0 ? void 0 : _this$searchRoom2.emit("message", message.data);
309
316
  case "global.command": return this.emit("command", {
310
317
  ...message.data,
311
318
  sender: message.sender
@@ -313,41 +320,47 @@ var Tiaoom = class extends events.EventEmitter {
313
320
  default: throw new Error("unknown message type.");
314
321
  }
315
322
  } catch (error) {
316
- cb?.(error);
323
+ cb === null || cb === void 0 || cb(error);
317
324
  }
318
325
  });
319
326
  this.on("player", (player, online) => {
320
- this.messageInstance?.send({
327
+ var _this$messageInstance2;
328
+ (_this$messageInstance2 = this.messageInstance) === null || _this$messageInstance2 === void 0 || _this$messageInstance2.send({
321
329
  type: online ? "player.login" : "player.logout",
322
330
  data: player
323
331
  });
324
332
  });
325
333
  this.on("players", (players) => {
326
- this.messageInstance?.send({
334
+ var _this$messageInstance3;
335
+ (_this$messageInstance3 = this.messageInstance) === null || _this$messageInstance3 === void 0 || _this$messageInstance3.send({
327
336
  type: "player.list",
328
337
  data: players
329
338
  });
330
339
  });
331
340
  this.on("room", (room) => {
332
- this.messageInstance?.send({
341
+ var _this$messageInstance4;
342
+ (_this$messageInstance4 = this.messageInstance) === null || _this$messageInstance4 === void 0 || _this$messageInstance4.send({
333
343
  type: "room.create",
334
344
  data: room
335
345
  });
336
346
  });
337
347
  this.on("room-player", (room) => {
338
- this.messageInstance?.send({
348
+ var _this$messageInstance5;
349
+ (_this$messageInstance5 = this.messageInstance) === null || _this$messageInstance5 === void 0 || _this$messageInstance5.send({
339
350
  type: "room.update",
340
351
  data: room
341
352
  });
342
353
  });
343
354
  this.on("rooms", (rooms) => {
344
- this.messageInstance?.send({
355
+ var _this$messageInstance6;
356
+ (_this$messageInstance6 = this.messageInstance) === null || _this$messageInstance6 === void 0 || _this$messageInstance6.send({
345
357
  type: "room.list",
346
358
  data: rooms
347
359
  });
348
360
  });
349
361
  this.on("command", (data) => {
350
- this.messageInstance?.send({
362
+ var _this$messageInstance7;
363
+ (_this$messageInstance7 = this.messageInstance) === null || _this$messageInstance7 === void 0 || _this$messageInstance7.send({
351
364
  type: "global.command",
352
365
  data
353
366
  });
@@ -368,7 +381,8 @@ var Tiaoom = class extends events.EventEmitter {
368
381
  if (this.rooms.some((r) => r.players.some((p) => p.id === sender.id))) throw new Error("you are already in a room.");
369
382
  const room = new Room(options);
370
383
  room.setSender((type, message) => {
371
- this.messageInstance?.send({
384
+ var _this$messageInstance8;
385
+ (_this$messageInstance8 = this.messageInstance) === null || _this$messageInstance8 === void 0 || _this$messageInstance8.send({
372
386
  type: `room.${type}`,
373
387
  data: message,
374
388
  sender: room
@@ -403,7 +417,8 @@ var Tiaoom = class extends events.EventEmitter {
403
417
  if (!playerInstance) {
404
418
  playerInstance = new Player(player);
405
419
  playerInstance.setSender((type, message) => {
406
- this.messageInstance?.send({
420
+ var _this$messageInstance9;
421
+ (_this$messageInstance9 = this.messageInstance) === null || _this$messageInstance9 === void 0 || _this$messageInstance9.send({
407
422
  type: `player.${type}`,
408
423
  data: message,
409
424
  sender: playerInstance
@@ -413,7 +428,7 @@ var Tiaoom = class extends events.EventEmitter {
413
428
  this.emit("player", playerInstance, true);
414
429
  }
415
430
  playerInstance.emit("status", PlayerStatus.online);
416
- cb?.({ player: playerInstance });
431
+ cb === null || cb === void 0 || cb({ player: playerInstance });
417
432
  return playerInstance;
418
433
  }
419
434
  joinPlayer(sender, player, isCreator = false) {
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\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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"}
package/src/index.mjs CHANGED
@@ -35,7 +35,8 @@ var Player = class extends EventEmitter$1 {
35
35
  "status"
36
36
  ].forEach((event) => {
37
37
  this.on(event, (...data) => {
38
- this.sender?.(event, ...data);
38
+ var _this$sender;
39
+ (_this$sender = this.sender) === null || _this$sender === void 0 || _this$sender.call(this, event, ...data);
39
40
  });
40
41
  });
41
42
  }
@@ -153,7 +154,8 @@ var Room = class extends EventEmitter$1 {
153
154
  "leave"
154
155
  ].forEach((event) => {
155
156
  this.on(event, (...data) => {
156
- this.sender?.(event, ...data);
157
+ var _this$sender;
158
+ (_this$sender = this.sender) === null || _this$sender === void 0 || _this$sender.call(this, event, ...data);
157
159
  });
158
160
  });
159
161
  }
@@ -258,26 +260,31 @@ var Tiaoom = class extends EventEmitter {
258
260
  return super.emit(event, ...args);
259
261
  }
260
262
  run() {
261
- this.messageInstance?.on("message", (message, cb) => {
263
+ var _this$messageInstance;
264
+ (_this$messageInstance = this.messageInstance) === null || _this$messageInstance === void 0 || _this$messageInstance.on("message", (message, cb) => {
262
265
  try {
263
266
  switch (message.type) {
264
- case "room.list": return cb?.(null, this.rooms);
265
- case "player.list": return cb?.(null, this.players);
267
+ case "room.list": return cb === null || cb === void 0 ? void 0 : cb(null, this.rooms);
268
+ case "player.list": return cb === null || cb === void 0 ? void 0 : cb(null, this.players);
266
269
  case "room.create": return this.createRoom(message.sender, message.data);
267
270
  case "player.join": return this.joinPlayer(message.sender, message.data);
268
271
  case "player.leave": return this.leavePlayer(message.sender, message.data);
269
- case "room.get": return cb?.(null, this.searchRoom(message.data));
272
+ case "room.get": return cb === null || cb === void 0 ? void 0 : cb(null, this.searchRoom(message.data));
270
273
  case "room.start": return this.startRoom(message.sender, message.data);
271
274
  case "room.close": return this.closeRoom(message.sender, message.data);
272
275
  case "player.login": return this.loginPlayer(message.data);
273
276
  case "player.logout": return this.removePlayer(message.data);
274
277
  case "player.ready": return this.readyPlayer(message.sender, message.data);
275
278
  case "player.unready": return this.unReadyPlayer(message.sender, message.data);
276
- case "room.player-command": return this.searchRoom(message.data)?.emit("player-command", {
277
- ...message.data,
278
- sender: message.sender
279
- });
280
- case "room.message": return this.searchRoom(message.data)?.emit("message", message.data);
279
+ case "room.player-command":
280
+ var _this$searchRoom;
281
+ return (_this$searchRoom = this.searchRoom(message.data)) === null || _this$searchRoom === void 0 ? void 0 : _this$searchRoom.emit("player-command", {
282
+ ...message.data,
283
+ sender: message.sender
284
+ });
285
+ case "room.message":
286
+ var _this$searchRoom2;
287
+ return (_this$searchRoom2 = this.searchRoom(message.data)) === null || _this$searchRoom2 === void 0 ? void 0 : _this$searchRoom2.emit("message", message.data);
281
288
  case "global.command": return this.emit("command", {
282
289
  ...message.data,
283
290
  sender: message.sender
@@ -285,41 +292,47 @@ var Tiaoom = class extends EventEmitter {
285
292
  default: throw new Error("unknown message type.");
286
293
  }
287
294
  } catch (error) {
288
- cb?.(error);
295
+ cb === null || cb === void 0 || cb(error);
289
296
  }
290
297
  });
291
298
  this.on("player", (player, online) => {
292
- this.messageInstance?.send({
299
+ var _this$messageInstance2;
300
+ (_this$messageInstance2 = this.messageInstance) === null || _this$messageInstance2 === void 0 || _this$messageInstance2.send({
293
301
  type: online ? "player.login" : "player.logout",
294
302
  data: player
295
303
  });
296
304
  });
297
305
  this.on("players", (players) => {
298
- this.messageInstance?.send({
306
+ var _this$messageInstance3;
307
+ (_this$messageInstance3 = this.messageInstance) === null || _this$messageInstance3 === void 0 || _this$messageInstance3.send({
299
308
  type: "player.list",
300
309
  data: players
301
310
  });
302
311
  });
303
312
  this.on("room", (room) => {
304
- this.messageInstance?.send({
313
+ var _this$messageInstance4;
314
+ (_this$messageInstance4 = this.messageInstance) === null || _this$messageInstance4 === void 0 || _this$messageInstance4.send({
305
315
  type: "room.create",
306
316
  data: room
307
317
  });
308
318
  });
309
319
  this.on("room-player", (room) => {
310
- this.messageInstance?.send({
320
+ var _this$messageInstance5;
321
+ (_this$messageInstance5 = this.messageInstance) === null || _this$messageInstance5 === void 0 || _this$messageInstance5.send({
311
322
  type: "room.update",
312
323
  data: room
313
324
  });
314
325
  });
315
326
  this.on("rooms", (rooms) => {
316
- this.messageInstance?.send({
327
+ var _this$messageInstance6;
328
+ (_this$messageInstance6 = this.messageInstance) === null || _this$messageInstance6 === void 0 || _this$messageInstance6.send({
317
329
  type: "room.list",
318
330
  data: rooms
319
331
  });
320
332
  });
321
333
  this.on("command", (data) => {
322
- this.messageInstance?.send({
334
+ var _this$messageInstance7;
335
+ (_this$messageInstance7 = this.messageInstance) === null || _this$messageInstance7 === void 0 || _this$messageInstance7.send({
323
336
  type: "global.command",
324
337
  data
325
338
  });
@@ -340,7 +353,8 @@ var Tiaoom = class extends EventEmitter {
340
353
  if (this.rooms.some((r) => r.players.some((p) => p.id === sender.id))) throw new Error("you are already in a room.");
341
354
  const room = new Room(options);
342
355
  room.setSender((type, message) => {
343
- this.messageInstance?.send({
356
+ var _this$messageInstance8;
357
+ (_this$messageInstance8 = this.messageInstance) === null || _this$messageInstance8 === void 0 || _this$messageInstance8.send({
344
358
  type: `room.${type}`,
345
359
  data: message,
346
360
  sender: room
@@ -375,7 +389,8 @@ var Tiaoom = class extends EventEmitter {
375
389
  if (!playerInstance) {
376
390
  playerInstance = new Player(player);
377
391
  playerInstance.setSender((type, message) => {
378
- this.messageInstance?.send({
392
+ var _this$messageInstance9;
393
+ (_this$messageInstance9 = this.messageInstance) === null || _this$messageInstance9 === void 0 || _this$messageInstance9.send({
379
394
  type: `player.${type}`,
380
395
  data: message,
381
396
  sender: playerInstance
@@ -385,7 +400,7 @@ var Tiaoom = class extends EventEmitter {
385
400
  this.emit("player", playerInstance, true);
386
401
  }
387
402
  playerInstance.emit("status", PlayerStatus.online);
388
- cb?.({ player: playerInstance });
403
+ cb === null || cb === void 0 || cb({ player: playerInstance });
389
404
  return playerInstance;
390
405
  }
391
406
  joinPlayer(sender, player, isCreator = false) {
package/src/index.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["EventEmitter","EventEmitter","player","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.mjs","names":["EventEmitter","EventEmitter","player","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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"}