tiaoom 0.0.28 → 0.0.29

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tiaoom",
3
- "version": "0.0.28",
3
+ "version": "0.0.29",
4
4
  "description": "",
5
5
  "main": "./src/index.cjs",
6
6
  "module": "./src/index.mjs",
@@ -23,7 +23,7 @@
23
23
  "README.md",
24
24
  "logo.png"
25
25
  ],
26
- "keywords": [],
26
+ "keywords": ["game", "framework", "multiplayer"],
27
27
  "author": "",
28
28
  "license": "MIT",
29
29
  "devDependencies": {
package/src/client.cjs CHANGED
@@ -1,2 +1,2 @@
1
- var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,a)=>(a=n==null?{}:e(i(n)),o(r||!n||!n.__esModule?t(a,`default`,{value:n,enumerable:!0}):a,n));let c=function(e){return e.RoomList=`room.list`,e.PlayerList=`player.list`,e.RoomCreate=`room.create`,e.PlayerJoin=`player.join`,e.PlayerLeave=`player.leave`,e.PlayerStandUp=`player.standup`,e.RoomGet=`room.get`,e.RoomStart=`room.start`,e.RoomKick=`room.kick`,e.RoomTransfer=`room.transfer`,e.RoomClose=`room.close`,e.PlayerLogin=`player.login`,e.PlayerLogout=`player.logout`,e.PlayerReady=`player.ready`,e.PlayerUnready=`player.unready`,e.RoomPlayerCommand=`room.player-command`,e.GlobalCommand=`global.command`,e}({}),l=function(e){return e.ready=`ready`,e.unready=`unready`,e.online=`online`,e.playing=`playing`,e}({}),u=function(e){return e.player=`player`,e.watcher=`watcher`,e.admin=`admin`,e}({}),d=function(e){return e.waiting=`waiting`,e.ready=`ready`,e.playing=`playing`,e}({});var f=class{constructor(e){this.id=e.id||Date.now().toString(),this.name=e.name||`玩家`+this.id,this.attributes=e.attributes||{},this.status=e.status||l.online,this.isAdmin=e.isAdmin||!1}},p=class extends f{constructor(e){super(e),this.role=e.role,this.isReady=e.isReady,this.isCreator=e.isCreator,this.roomId=e.roomId}},m=class{constructor(e){this.id=e.id,this.name=e.name,this.players=e.players.map(e=>new p(e)),this.size=e.size,this.minSize=e.minSize,this.status=e.status,this.attrs=e.attrs}},h=class{constructor(){this.listeners={},this.rooms=[],this.players=[],this.currentPlayer=null}run(){return this.connect(),this.onReady(()=>{this.send({type:c.RoomList}),this.send({type:c.PlayerList})}),this.on(`player.list`,e=>{this.players=e.map(e=>new f(e)),this.emit(`onPlayerList`,[...this.players])}),this.on(`player.login`,e=>{this.players.push(new f(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 m(e)),this.emit(`onRoomList`,[...this.rooms])}),this.on(`room.create`,e=>{this.rooms.push(new m(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 m(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 f(e),this.send({type:c.PlayerLogin,data:e}),this}createRoom({name:e,size:t,minSize:n,attrs:r}){return new Promise(i=>{this.send({type:c.RoomCreate,data:{name:e,size:t,minSize:n,attrs:r}}),this.on(`room.create`,e=>{i()})})}joinRoom(e,t){return this.send({type:c.PlayerJoin,data:{roomId:e,params:t}}),this}leaveRoom(e,t){return this.send({type:c.PlayerLeave,data:{roomId:e,params:t}}),this}leaveSeat(e,t){return this.send({type:c.PlayerStandUp,data:{roomId:e,params:t}}),this}kickPlayer(e,t,n){return this.send({type:c.RoomKick,data:{roomId:e,playerId:t,params:n}}),this}transferRoom(e,t,n){return this.send({type:c.RoomTransfer,data:{roomId:e,playerId:t,params:n}}),this}closeRoom(e,t){return this.send({type:c.RoomClose,data:{roomId:e,params:t}}),this}startGame(e,t){return this.send({type:c.RoomStart,data:{id:e,params:t}}),this}ready(e,t=!0,n){return this.send({type:t?c.PlayerReady:c.PlayerUnready,data:{roomId:e,params:n}}),this}command(e,t){return typeof e==`string`?this.send({type:c.RoomPlayerCommand,data:{id:e,...t}}):(t=e,this.send({type:c.GlobalCommand,data:t})),this}onReady(e){return this.on(`sys.ready`,e)}onError(e){return this.on(`global.error`,e),this}onMessage(e,t=!0){return t?this.on(`global.message`,e):this.off(`global.message`,e),this}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 m(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 m(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 m(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.MessageTypes=c,exports.Player=f,exports.PlayerRole=u,exports.PlayerStatus=l,exports.Room=m,exports.RoomPlayer=p,exports.RoomStatus=d,exports.Tiaoom=h;
1
+ var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,a)=>(a=n==null?{}:e(i(n)),o(r||!n||!n.__esModule?t(a,`default`,{value:n,enumerable:!0}):a,n));let c=function(e){return e.RoomList=`room.list`,e.PlayerList=`player.list`,e.RoomCreate=`room.create`,e.PlayerJoin=`player.join`,e.PlayerLeave=`player.leave`,e.PlayerStandUp=`player.standup`,e.RoomGet=`room.get`,e.RoomStart=`room.start`,e.RoomKick=`room.kick`,e.RoomTransfer=`room.transfer`,e.RoomClose=`room.close`,e.PlayerLogin=`player.login`,e.PlayerLogout=`player.logout`,e.PlayerReady=`player.ready`,e.PlayerUnready=`player.unready`,e.RoomPlayerCommand=`room.player-command`,e.GlobalCommand=`global.command`,e}({}),l=function(e){return e.ready=`ready`,e.unready=`unready`,e.online=`online`,e.playing=`playing`,e}({}),u=function(e){return e.player=`player`,e.watcher=`watcher`,e.admin=`admin`,e}({}),d=function(e){return e.waiting=`waiting`,e.ready=`ready`,e.playing=`playing`,e}({});var f=class{constructor(e){this.id=e.id||Date.now().toString(),this.name=e.name||`玩家`+this.id,this.attributes=e.attributes||{},this.status=e.status||l.online,this.isAdmin=e.isAdmin||!1}},p=class extends f{constructor(e){super(e),this.role=e.role,this.isReady=e.isReady,this.isCreator=e.isCreator,this.roomId=e.roomId}},m=class{constructor(e){this.id=e.id,this.name=e.name,this.players=e.players.map(e=>new p(e)),this.size=e.size,this.minSize=e.minSize,this.status=e.status,this.attrs=e.attrs}},h=class{constructor(){this.listeners={},this.rooms=[],this.players=[],this.currentPlayer=null}run(){return this.connect(),this.onReady(()=>{this.send({type:c.RoomList}),this.send({type:c.PlayerList})}),this.on(`player.list`,e=>{this.players=e.map(e=>new f(e)),this.emit(`onPlayerList`,[...this.players])}),this.on(`player.login`,e=>{this.players=this.players.filter(t=>t.id!==e.id),this.players.push(new f(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 m(e)),this.emit(`onRoomList`,[...this.rooms])}),this.on(`room.create`,e=>{this.rooms.push(new m(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 m(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 f(e),this.send({type:c.PlayerLogin,data:e}),this}createRoom({name:e,size:t,minSize:n,attrs:r}){return new Promise(i=>{this.send({type:c.RoomCreate,data:{name:e,size:t,minSize:n,attrs:r}}),this.on(`room.create`,e=>{i()})})}joinRoom(e,t){return this.send({type:c.PlayerJoin,data:{roomId:e,params:t}}),this}leaveRoom(e,t){return this.send({type:c.PlayerLeave,data:{roomId:e,params:t}}),this}leaveSeat(e,t){return this.send({type:c.PlayerStandUp,data:{roomId:e,params:t}}),this}kickPlayer(e,t,n){return this.send({type:c.RoomKick,data:{roomId:e,playerId:t,params:n}}),this}transferRoom(e,t,n){return this.send({type:c.RoomTransfer,data:{roomId:e,playerId:t,params:n}}),this}closeRoom(e,t){return this.send({type:c.RoomClose,data:{roomId:e,params:t}}),this}startGame(e,t){return this.send({type:c.RoomStart,data:{id:e,params:t}}),this}ready(e,t=!0,n){return this.send({type:t?c.PlayerReady:c.PlayerUnready,data:{roomId:e,params:n}}),this}command(e,t){return typeof e==`string`?this.send({type:c.RoomPlayerCommand,data:{id:e,...t}}):(t=e,this.send({type:c.GlobalCommand,data:t})),this}onReady(e){return this.on(`sys.ready`,e)}onError(e){return this.on(`global.error`,e),this}onMessage(e,t=!0){return t?this.on(`global.message`,e):this.off(`global.message`,e),this}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 m(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 m(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 m(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.MessageTypes=c,exports.Player=f,exports.PlayerRole=u,exports.PlayerStatus=l,exports.Room=m,exports.RoomPlayer=p,exports.RoomStatus=d,exports.Tiaoom=h;
2
2
  //# sourceMappingURL=client.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.cjs","names":["MessageTypes"],"sources":["../lib/models/message.ts","../lib/models/player.ts","../lib/models/room.ts","../lib/client.ts"],"sourcesContent":["import EventEmitter from \"events\";\nimport { IPlayer, IPlayerOptions } from \"./player\";\nimport { IRoom, IRoomPlayer, IRoomOptions } from \"./room\";\nimport { IMessageEmitterEvents, IMessageEvents } from \"@lib/events/message\";\n\n/**\n * 消息包类型枚举\n * player: 'command', 'message', 'join', 'leave', 'status'\n */\nexport enum MessageTypes {\n /**\n * 连接准备就绪事件\n */\n SysReady = \"sys.ready\",\n /**\n * 连接关闭事件\n */\n SysClose = \"sys.close\",\n /**\n * 错误事件\n */\n SysError = \"sys.error\",\n /**\n * 全局错误\n */\n GlobalError = \"global.error\",\n /**\n * 房间列表\n */\n RoomList = \"room.list\",\n /**\n * 房间创建\n */\n RoomCreate = \"room.create\",\n /**\n * 房间更新\n */\n RoomUpdate = \"room.update\",\n /**\n * 房间开始\n */\n RoomStart = \"room.start\",\n /**\n * 房间结束\n */\n RoomEnd = \"room.end\",\n /**\n * 房间关闭\n */\n RoomClose = \"room.close\",\n /**\n * 房间全部玩家已准备\n */\n RoomAllReady = \"room.all-ready\",\n /**\n * 房间命令\n */\n RoomCommand = \"room.command\",\n /**\n * 房间内玩家发送的指令\n */\n RoomPlayerCommand = \"room.player-command\",\n /**\n * 房间消息\n */\n RoomMessage = \"room.message\",\n /**\n * 玩家加入房间\n */\n RoomJoin = \"room.join\",\n /**\n * 玩家离开房间\n */\n RoomLeave = \"room.leave\",\n /**\n * 房间玩家准备\n */\n RoomPlayerReady = \"room.player-ready\",\n /**\n * 房间玩家取消准备\n */\n RoomPlayerUnready = \"room.player-unready\",\n /**\n * 玩家列表\n */\n PlayerList = \"player.list\",\n /**\n * 玩家登录\n */\n PlayerLogin = \"player.login\",\n /**\n * 玩家登出\n */\n PlayerLogout = \"player.logout\",\n /**\n * *玩家消息\n */\n PlayerMessage = \"player.message\",\n /**\n * *玩家命令\n */\n PlayerCommand = \"player.command\",\n /**\n * 玩家错误信息\n */\n PlayerError = \"player.error\",\n /**\n * 全局消息\n */\n GlobalMessage = \"global.message\",\n /**\n * 全局命令\n */\n GlobalCommand = \"global.command\",\n}\n\n/**\n * 客户端发送消息包类型枚举\n * player: 'command', 'message', 'join', 'leave', 'status'\n */\nexport enum RecvMessageTypes {\n /**\n * 房间列表\n */\n RoomList = \"room.list\",\n /**\n * 玩家列表\n */\n PlayerList = \"player.list\",\n /**\n * 房间创建\n */\n RoomCreate = \"room.create\",\n /**\n * 玩家加入房间\n */\n PlayerJoin = \"player.join\",\n /**\n * 玩家离开房间\n */\n PlayerLeave = \"player.leave\",\n /**\n * 玩家离开座位\n */\n PlayerStandUp = \"player.standup\",\n /**\n * 房间获取\n */\n RoomGet = \"room.get\",\n /**\n * 房间开始\n */\n RoomStart = \"room.start\",\n /**\n * 房间踢出玩家\n */\n RoomKick = \"room.kick\",\n /**\n * 房间转移\n */\n RoomTransfer = \"room.transfer\",\n /**\n * 房间关闭\n */\n RoomClose = \"room.close\", \n /**\n * 玩家登录\n */\n PlayerLogin = \"player.login\",\n /**\n * 玩家登出\n */\n PlayerLogout = \"player.logout\",\n /**\n * 玩家准备\n */\n PlayerReady = \"player.ready\",\n /**\n * 玩家取消准备\n */\n PlayerUnready = \"player.unready\",\n /**\n * 房间内玩家发送的指令\n */\n RoomPlayerCommand = \"room.player-command\",\n /**\n * 全局命令\n */\n GlobalCommand = \"global.command\",\n}\n\n/**\n * 消息包接口\n */\nexport interface IMessagePackage {\n /**\n * 消息类型\n */\n type: MessageTypes;\n /**\n * 消息数据\n */\n data?: IPlayerOptions | IRoomOptions | IPlayer | IRoom | IRoomPlayer | any\n /**\n * 发送者信息\n */\n sender?: IPlayer | IRoomPlayer | IRoom;\n}\n\n/**\n * 消息数据接口,包含发送者信息\n */\nexport interface IMessageData extends IMessagePackage {\n sender: IPlayer | IRoomPlayer | IRoom;\n}\n\n/**\n * 消息通信接口\n */\nexport interface IMessage extends EventEmitter<IMessageEmitterEvents> {\n /**\n * 监听消息事件\n * @param event 事件名,具体见 MessageEvents\n * @param listener 监听器\n */\n on<K extends keyof IMessageEvents>(event: K, listener: IMessageEvents[K]): this;\n /**\n * 触发消息事件\n * @param event 事件名,具体见 MessageEvents\n * @param args 参数\n */\n emit<K extends keyof IMessageEvents>(event: K, ...args: Parameters<IMessageEvents[K]>): boolean;\n /**\n * 关闭连接\n */\n close(): void;\n /**\n * 发送消息包\n * @param message 消息包\n */\n send(message: IMessagePackage): void;\n}\n","import { PlayerEvents } from \"@lib/events/player\";\nimport EventEmitter from \"events\";\n\n/**\n * 玩家选项接口\n */\nexport interface IPlayerOptions {\n /**\n * 玩家ID\n */\n id: string;\n /**\n * 玩家名称\n */\n name: string;\n /**\n * 玩家属性\n */\n attributes?: any;\n /**\n * 发送者函数\n */\n sender?: (type: string, ...message: any) => void;\n /**\n * 是否超级管理员\n */\n isAdmin?: boolean;\n}\n\n/**\n * 玩家状态枚举\n */\nexport enum PlayerStatus {\n /**\n * 已准备\n */\n ready = 'ready',\n /**\n * 未准备\n */\n unready = 'unready',\n /**\n * 在线\n */\n online = 'online',\n /**\n * 游戏中\n */\n playing = 'playing',\n}\n\n/**\n * 玩家接口\n */\nexport interface IPlayer extends IPlayerOptions {\n /**\n * 玩家状态\n */\n status: PlayerStatus;\n}\n\n/**\n * 玩家\n */\nexport class Player extends EventEmitter implements IPlayer {\n /**\n * 监听玩家事件\n * @param event 事件名,具体见 PlayEvents\n * @param listener 监听器\n * @returns this\n */\n on<K extends keyof PlayerEvents>(event: K, listener: PlayerEvents[K]): this {\n return super.on(event, listener);\n }\n\n /**\n * 触发玩家事件\n * @param event 事件名,具体见 PlayEvents\n * @param args 参数\n * @returns 是否有监听器被触发\n */\n emit<K extends keyof PlayerEvents>(event: K, ...args: Parameters<PlayerEvents[K]>): boolean {\n return super.emit(event, ...args);\n }\n \n id: string = \"\";\n name: string = \"\";\n attributes?: any;\n status: PlayerStatus = PlayerStatus.online;\n sender?: (type: string, ...message: any) => void;\n isAdmin: boolean = false;\n\n constructor(player: Partial<IPlayerOptions> | Player, status: PlayerStatus = PlayerStatus.online) {\n super();\n this.id = player.id || new Date().getTime().toString();\n this.name = player.name || \"\";\n this.attributes = player.attributes || {};\n this.sender = player.sender;\n\n if (player instanceof Player) this.status = player.status;\n\n this.status = status;\n\n this.on('status', (status: PlayerStatus) => {\n this.status = status;\n });\n \n const events: Array<keyof PlayerEvents> = ['command', 'message', 'status'];\n events.forEach((event) => {\n this.on(event, (...data: any) => {\n this.sender?.(event, ...data);\n });\n }); \n }\n\n toJSON() {\n return {\n id: this.id,\n name: this.name,\n attributes: this.attributes,\n status: this.status,\n isAdmin: this.isAdmin,\n };\n }\n\n toString() {\n return JSON.stringify(this.toJSON());\n }\n\n /**\n * 设置发送者函数\n * @param {(type: string, ...message: any) => void} sender 发送者函数\n * @returns this\n */\n setSender(sender: (type: string, ...message: any) => void) {\n this.sender = sender;\n return this;\n }\n}","import { IPlayer, Player, IPlayerOptions, PlayerStatus } from \"./player\";\nimport EventEmitter from \"events\";\nimport { RoomEvents } from \"@lib/events\";\n\n/**\n * 房间选项接口\n */\nexport interface IRoomOptions {\n /**\n * 房间号\n */\n id: string, \n /**\n * 房间名称\n */\n name: string,\n /**\n * 房间容量\n */\n size: number, \n /**\n * 最小容量\n */\n minSize: number,\n /**\n * 其他属性\n */\n attrs?: Record<string, any>,\n}\n\n/**\n * 房间玩家角色\n */\nexport enum PlayerRole {\n /**\n * 玩家\n */\n player = 'player',\n /**\n * 观众\n */\n watcher = 'watcher',\n /**\n * 管理员\n */\n admin = 'admin',\n}\n\n/**\n * 房间状态\n */\nexport enum RoomStatus {\n /**\n * 等待中\n */\n waiting = 'waiting',\n /**\n * 已准备\n */\n ready = 'ready',\n /**\n * 游戏中\n */\n playing = 'playing',\n}\n\n/**\n * 房间接口\n */\nexport interface IRoom extends IRoomOptions {\n /**\n * 房间玩家列表\n */\n players: RoomPlayer[];\n}\n\n/**\n * 房间玩家选项接口\n */\nexport interface IRoomPlayerOptions extends IPlayerOptions {\n /**\n * 房间Id\n */\n roomId?: string;\n}\n\n/**\n * 房间玩家接口\n */\nexport interface IRoomPlayer extends IRoomPlayerOptions, IPlayer {\n /**\n * 是否已准备\n */\n isReady: boolean;\n /**\n * 玩家角色\n */\n role: PlayerRole;\n /**\n * 是否为房主\n */\n isCreator: boolean;\n /**\n * 房间 Id\n */\n roomId: string;\n}\n\n/**\n * 房间玩家\n */\nexport class RoomPlayer extends Player implements IRoomPlayer {\n isReady: boolean = false;\n role: PlayerRole = PlayerRole.player;\n isCreator: boolean = false;\n roomId: string;\n\n constructor(player: Partial<IRoomPlayer>, role: PlayerRole = PlayerRole.player) {\n super(player);\n this.isReady = player.isReady || false;\n this.isCreator = player.isCreator || false;\n this.roomId = player.roomId || '';\n this.role = player.role || role;\n this.status = player.status || PlayerStatus.online;\n if (player instanceof Player && player.sender) super.setSender(player.sender);\n }\n\n toJSON() {\n return {\n ...super.toJSON(),\n role: this.role,\n isReady: this.isReady,\n isCreator: this.isCreator,\n };\n }\n}\n\n/**\n * 房间\n */\nexport class Room extends EventEmitter implements IRoom {\n /**\n * 监听房间事件\n * @param event 事件名,具体见 RoomEvents\n * @param listener 监听器\n * @returns this\n */\n on<K extends keyof RoomEvents>(event: K, listener: RoomEvents[K]): this {\n return super.on(event, listener);\n }\n\n /**\n * 触发房间事件\n * @param event 事件名,具体见 RoomEvents\n * @param args 参数\n * @returns 是否有监听器被触发\n */\n emit<K extends keyof RoomEvents>(event: K, ...args: Parameters<RoomEvents[K]>): boolean {\n return super.emit(event, ...args);\n }\n\n id: string;\n size: number = 10;\n name: string = '';\n minSize: number = 2;\n attrs?: Record<string, any>;\n players: RoomPlayer[] = [];\n\n /**\n * 有效玩家列表(非观众)\n */\n get validPlayers() {\n return this.players.filter((player) => player.role === PlayerRole.player);\n }\n\n /**\n * 观众列表\n */\n get watchers() {\n return this.players.filter((player) => player.role === PlayerRole.watcher);\n }\n\n /**\n * 消息发送器\n */\n private sender?: (type: string, ...message: any) => void;\n\n /**\n * 房间玩家是否已准备好\n */\n get isReady(): boolean {\n return this.players.length >= this.minSize\n && this.players.every((target) => target.isReady || target.role === PlayerRole.watcher); // is all player ready\n }\n\n /**\n * 房间状态\n */\n get status(): RoomStatus {\n if (!this.isReady) return RoomStatus.waiting;\n if (this.players.findIndex((target) => target.status === PlayerStatus.playing) != -1) return RoomStatus.playing;\n return RoomStatus.ready;\n }\n\n /**\n * 房间是否在游戏中\n */\n get isPlaying(): boolean {\n return this.status === RoomStatus.playing;\n }\n\n /**\n * 房间是否已满\n */\n get isFull(): boolean {\n return this.validPlayers.length == this.size;\n }\n\n /**\n * 房主\n */\n get owner(): RoomPlayer | undefined {\n const creator = this.players.find((player) => player.isCreator);\n return creator;\n }\n\n toJSON() {\n return {\n id: this.id,\n name: this.name,\n size: this.size || 10,\n minSize: this.minSize,\n status: this.status,\n players: this.players.map((player) => player.toJSON()),\n attrs: this.attrs,\n }\n }\n\n toString() {\n return JSON.stringify(this.toJSON());\n }\n\n constructor(room: Partial<IRoomOptions> | Room, players: RoomPlayer[] = []) {\n super();\n if (room instanceof Room) {\n this.players = room.players;\n this.players.forEach((p) => {\n p.roomId = room.id;\n });\n }\n\n this.id = room.id || new Date().getTime().toString();\n this.name = room.name || '';\n this.size = room.size || 10;\n this.minSize = room.minSize || 2;\n this.attrs = room.attrs;\n this.players = players;\n \n const events: Array<keyof RoomEvents> = ['message', 'command', 'start', 'end', 'all-ready', 'player-unready', 'player-ready', 'join', 'leave'];\n events.forEach((event) => {\n this.on(event, (...data: any) => {\n this.sender?.(event, ...data);\n });\n });\n }\n\n /**\n * 设置房主\n * @param {Player} player 玩家\n * @returns this\n */\n setCreator(player: Player) {\n const roomPlayer = this.searchPlayer(player);\n if (roomPlayer) {\n this.players.forEach((p) => {\n p.isCreator = false;\n });\n roomPlayer.isCreator = true;\n this.emit(\"update\", this);\n }\n return this;\n }\n\n /**\n * 添加玩家\n * @param {Player} player 玩家\n * @param {boolean} isCreator 是否房主\n * @returns 玩家实例 \n */\n addPlayer(player: Player, isCreator: boolean = false) {\n let roomPlayer = this.searchPlayer(player);\n if (roomPlayer) {\n if (roomPlayer.role === PlayerRole.watcher && !this.isFull && !this.isPlaying) {\n roomPlayer.role = PlayerRole.player;\n roomPlayer.isCreator = isCreator;\n this.emit(\"update\", this);\n }\n return roomPlayer;\n }\n\n if (isCreator) {\n this.players.forEach((p) => {\n p.isCreator = false;\n });\n }\n roomPlayer = new RoomPlayer(player, this.isFull || this.isPlaying ? PlayerRole.watcher : PlayerRole.player);\n roomPlayer.isCreator = isCreator;\n roomPlayer.roomId = this.id;\n this.players.push(roomPlayer);\n this.emit(\"join\", { ...roomPlayer, roomId: this.id });\n \n return roomPlayer;\n }\n\n /**\n * 离开座位\n * @param {string | IPlayer} player 玩家 / 玩家 id\n */\n leaveSeat(playerId: string): RoomPlayer;\n leaveSeat(player: IPlayer): RoomPlayer;\n leaveSeat(player: IPlayer | string) {\n const playerId = typeof player === \"string\" ? player : player.id;\n const roomPlayer = this.searchPlayer(playerId);\n if (roomPlayer && roomPlayer.role === PlayerRole.player) {\n roomPlayer.role = PlayerRole.watcher;\n roomPlayer.isReady = false;\n this.emit(\"leave\", { ...roomPlayer, roomId: this.id });\n if (roomPlayer.isCreator && this.validPlayers.length > 0) {\n this.validPlayers[0].isCreator = true;\n this.emit(\"update\", this);\n }\n }\n return roomPlayer!;\n }\n\n /**\n * 踢出玩家\n * @param {string | IPlayer} player 玩家 / 玩家 id\n */\n kickPlayer(playerId: string): RoomPlayer;\n kickPlayer(player: IPlayer): RoomPlayer;\n kickPlayer(player: IPlayer | string) {\n const playerId = typeof player === \"string\" ? player : player.id;\n const index = this.players.findIndex((p) => p.id == playerId);\n const roomPlayer = this.players[index];\n if (index > -1) {\n this.emit(\"leave\", { ...roomPlayer, roomId: this.id });\n this.players.splice(index, 1);\n if (roomPlayer.isCreator && this.players.length > 0) {\n this.players[0].isCreator = true;\n this.emit(\"update\", this);\n }\n }\n return roomPlayer;\n }\n\n /**\n * 搜索玩家\n * @param {string | IPlayer} player 玩家 / 玩家 id\n */\n searchPlayer(playerId: string): RoomPlayer | undefined;\n searchPlayer(player: IPlayer): RoomPlayer | undefined;\n searchPlayer(player: string | IPlayer) {\n const playerId = typeof player === \"string\" ? player : player?.id;\n return this.players.find((player) => player.id == playerId);\n }\n\n /**\n * 开始游戏\n */\n start(sender: IPlayer) {\n if (!this.isReady) {\n throw new Error('room is not ready.');\n }\n if (this.status === RoomStatus.playing) {\n throw new Error('room is already started.');\n }\n this.players.forEach((player) => {\n if (player.role != PlayerRole.player) return;\n player.emit('status', PlayerStatus.playing);\n });\n this.emit(\"update\", this);\n return this.emit(\"start\", this);\n }\n\n /**\n * 结束游戏\n */\n end() {\n this.players.forEach((player) => {\n if (player.role != PlayerRole.player) return;\n player.emit('status', PlayerStatus.unready);\n });\n this.emit(\"update\", this);\n return this.emit(\"end\", this);\n }\n\n /**\n * 设置消息发送器\n * @param sender 消息发送器\n */\n setSender(sender: (type: string, ...message: any) => void) {\n this.sender = sender;\n return this;\n }\n}\n","import { IRoomOptions, PlayerRole, RoomStatus, PlayerStatus, RecvMessageTypes as MessageTypes } from \"@lib/index\";\nexport { RoomStatus, PlayerStatus, PlayerRole, MessageTypes };\nexport type { IRoomOptions };\n\nexport 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 error 错误信息\n */\n \"global.error\": (error: Error) => void;\n /**\n * 全局命令事件\n * @param data 命令内容\n */\n \"global.command\": (data: any & { sender: Player }) => void;\n /**\n * 全局消息事件\n * @param message 消息内容\n */\n \"global.message\": (message: string, 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\": (status: PlayerStatus) => 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: { content: string, sender?: Player }) => void;\n /**\n * 玩家错误事件\n */\n \"player.error\": (error: Error) => 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\": (player: RoomPlayer & { roomId: string }) => void;\n /**\n * 玩家离开房间事件\n * @param room 房间信息\n * @param player 玩家信息\n */\n \"room.leave\": (player: RoomPlayer & { roomId: string }) => 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: { content: string; sender?: RoomPlayer }) => void;\n /**\n * 房间玩家准备事件\n * @param player 玩家信息\n * @param roomId 房间ID(可选)\n */\n \"room.player-ready\": (player: RoomPlayer) => void;\n /**\n * 房间玩家取消准备事件\n * @param player 玩家信息\n * @param roomId 房间ID(可选)\n */\n \"room.player-unready\": (player: RoomPlayer) => 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: PlayerStatus;\n isAdmin: boolean;\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 || PlayerStatus.online;\n this.isAdmin = player.isAdmin || false;\n }\n}\n\nexport class RoomPlayer extends Player {\n role: PlayerRole;\n isReady: boolean;\n isCreator: boolean;\n roomId: string;\n constructor(player: RoomPlayer) {\n super(player);\n this.role = player.role;\n this.isReady = player.isReady;\n this.isCreator = player.isCreator;\n this.roomId = player.roomId;\n }\n}\n\nexport class Room {\n id: string;\n name: string;\n players: RoomPlayer[];\n size: number;\n minSize: number;\n status: RoomStatus;\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: MessageTypes.RoomList });\n this.send({ type: MessageTypes.PlayerList });\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: MessageTypes, 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: MessageTypes.PlayerLogin, 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 }: Omit<IRoomOptions, 'id'>) {\n return new Promise<void>((resolve) => {\n this.send({ type: MessageTypes.RoomCreate, 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 * @param {object} params 加入参数\n */\n joinRoom(roomId: string, params?: any) {\n this.send({ type: MessageTypes.PlayerJoin, data: { roomId, params } });\n return this;\n }\n\n /**\n * 离开房间\n * @param {string} roomId 房间ID\n * @param {object} params 离开参数\n */\n leaveRoom(roomId: string, params?: any) {\n this.send({ type: MessageTypes.PlayerLeave, data: { roomId, params } });\n return this;\n }\n\n /**\n * 离开座位\n * @param {string} roomId 房间ID\n * @param {object} params 离开参数\n */\n leaveSeat(roomId: string, params?: any) {\n this.send({ type: MessageTypes.PlayerStandUp, data: { roomId, params } });\n return this;\n }\n\n /**\n * 踢出玩家\n * @param {string} roomId 房间ID\n * @param {string} playerId 玩家ID\n * @param {object} params 额外参数\n */\n kickPlayer(roomId: string, playerId: string, params?: any) {\n this.send({ type: MessageTypes.RoomKick, data: { roomId, playerId, params } });\n return this;\n }\n\n /**\n * 转让房主\n * @param {string} roomId 房间ID\n * @param {string} playerId 目标玩家ID\n * @param {object} params 额外参数\n */\n transferRoom(roomId: string, playerId: string, params?: any) {\n this.send({ type: MessageTypes.RoomTransfer, data: { roomId, playerId, params } });\n return this;\n }\n\n /**\n * 关闭房间\n * @param {string} roomId 房间ID\n * @param {object} params 额外参数\n * @returns \n */\n closeRoom(roomId: string, params?: any) {\n this.send({ type: MessageTypes.RoomClose, data: { roomId, params } });\n return this;\n }\n\n /**\n * 开始游戏\n * @param {string} id 房间ID\n */\n startGame(id: string, params?: any) {\n this.send({ type: MessageTypes.RoomStart, data: { id, params } });\n return this;\n }\n\n /**\n * 准备/取消准备\n * @param {string} roomId 房间ID\n * @param {boolean} isReady 是否准备\n */\n ready(roomId: string, isReady=true, params?: any) {\n this.send({ type: isReady ? MessageTypes.PlayerReady : MessageTypes.PlayerUnready, data: { roomId, params } });\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: MessageTypes.GlobalCommand, data: command });\n } else {\n this.send({ type: MessageTypes.RoomPlayerCommand, data: { id: roomId, ...command } });\n }\n return this;\n }\n\n /**\n * 连接准备监听\n * @param {function} cb 监听函数\n */\n onReady(cb: () => void) {\n return this.on(\"sys.ready\", cb);\n }\n\n /**\n * 全局错误监听\n * @param {function} cb 监听函数\n */\n onError(cb: (error: Error) => void) {\n this.on(\"global.error\", cb);\n return this;\n }\n\n /**\n * 全局消息监听\n * @param {function} cb 监听函数\n */\n onMessage(cb: (message: string, sender?: Player) => void, on=true) {\n if (on) this.on(\"global.message\", cb);\n else this.off(\"global.message\", cb);\n return this;\n }\n\n /**\n * 玩家列表变更监听\n * @param {function} cb 监听函数\n */\n onPlayerList(cb: (players: Player[]) => 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: (rooms: Room[]) => 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: (player: RoomPlayer) => 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: (player: RoomPlayer) => 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: (player: RoomPlayer) => 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: (player: RoomPlayer) => 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: (status: PlayerStatus) => 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: (room: Room) => 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: (room: Room) => 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: (room: Room) => 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: (message: { content: string, sender?: RoomPlayer }) => 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: (message: { content: string, sender?: Player }) => 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: (command: any & { sender?: Player }) => 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: (command: any & { sender?: Player }) => 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 {TiaoomEvents[K]} 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 {TiaoomEvents[K]} 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 {Parameters<TiaoomEvents[K]>} 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":["MessageTypes"],"sources":["../lib/models/message.ts","../lib/models/player.ts","../lib/models/room.ts","../lib/client.ts"],"sourcesContent":["import EventEmitter from \"events\";\nimport { IPlayer, IPlayerOptions } from \"./player\";\nimport { IRoom, IRoomPlayer, IRoomOptions } from \"./room\";\nimport { IMessageEmitterEvents, IMessageEvents } from \"@lib/events/message\";\n\n/**\n * 消息包类型枚举\n * player: 'command', 'message', 'join', 'leave', 'status'\n */\nexport enum MessageTypes {\n /**\n * 连接准备就绪事件\n */\n SysReady = \"sys.ready\",\n /**\n * 连接关闭事件\n */\n SysClose = \"sys.close\",\n /**\n * 错误事件\n */\n SysError = \"sys.error\",\n /**\n * 全局错误\n */\n GlobalError = \"global.error\",\n /**\n * 房间列表\n */\n RoomList = \"room.list\",\n /**\n * 房间创建\n */\n RoomCreate = \"room.create\",\n /**\n * 房间更新\n */\n RoomUpdate = \"room.update\",\n /**\n * 房间开始\n */\n RoomStart = \"room.start\",\n /**\n * 房间结束\n */\n RoomEnd = \"room.end\",\n /**\n * 房间关闭\n */\n RoomClose = \"room.close\",\n /**\n * 房间全部玩家已准备\n */\n RoomAllReady = \"room.all-ready\",\n /**\n * 房间命令\n */\n RoomCommand = \"room.command\",\n /**\n * 房间内玩家发送的指令\n */\n RoomPlayerCommand = \"room.player-command\",\n /**\n * 房间消息\n */\n RoomMessage = \"room.message\",\n /**\n * 玩家加入房间\n */\n RoomJoin = \"room.join\",\n /**\n * 玩家离开房间\n */\n RoomLeave = \"room.leave\",\n /**\n * 房间玩家准备\n */\n RoomPlayerReady = \"room.player-ready\",\n /**\n * 房间玩家取消准备\n */\n RoomPlayerUnready = \"room.player-unready\",\n /**\n * 玩家列表\n */\n PlayerList = \"player.list\",\n /**\n * 玩家登录\n */\n PlayerLogin = \"player.login\",\n /**\n * 玩家登出\n */\n PlayerLogout = \"player.logout\",\n /**\n * 玩家离线\n */\n PlayerOffline = \"player.offline\",\n /**\n * *玩家消息\n */\n PlayerMessage = \"player.message\",\n /**\n * *玩家命令\n */\n PlayerCommand = \"player.command\",\n /**\n * 玩家错误信息\n */\n PlayerError = \"player.error\",\n /**\n * 全局消息\n */\n GlobalMessage = \"global.message\",\n /**\n * 全局命令\n */\n GlobalCommand = \"global.command\",\n}\n\n/**\n * 客户端发送消息包类型枚举\n * player: 'command', 'message', 'join', 'leave', 'status'\n */\nexport enum RecvMessageTypes {\n /**\n * 房间列表\n */\n RoomList = \"room.list\",\n /**\n * 玩家列表\n */\n PlayerList = \"player.list\",\n /**\n * 房间创建\n */\n RoomCreate = \"room.create\",\n /**\n * 玩家加入房间\n */\n PlayerJoin = \"player.join\",\n /**\n * 玩家离开房间\n */\n PlayerLeave = \"player.leave\",\n /**\n * 玩家离开座位\n */\n PlayerStandUp = \"player.standup\",\n /**\n * 房间获取\n */\n RoomGet = \"room.get\",\n /**\n * 房间开始\n */\n RoomStart = \"room.start\",\n /**\n * 房间踢出玩家\n */\n RoomKick = \"room.kick\",\n /**\n * 房间转移\n */\n RoomTransfer = \"room.transfer\",\n /**\n * 房间关闭\n */\n RoomClose = \"room.close\", \n /**\n * 玩家登录\n */\n PlayerLogin = \"player.login\",\n /**\n * 玩家登出\n */\n PlayerLogout = \"player.logout\",\n /**\n * 玩家准备\n */\n PlayerReady = \"player.ready\",\n /**\n * 玩家取消准备\n */\n PlayerUnready = \"player.unready\",\n /**\n * 房间内玩家发送的指令\n */\n RoomPlayerCommand = \"room.player-command\",\n /**\n * 全局命令\n */\n GlobalCommand = \"global.command\",\n}\n\n/**\n * 消息包接口\n */\nexport interface IMessagePackage {\n /**\n * 消息类型\n */\n type: MessageTypes;\n /**\n * 消息数据\n */\n data?: IPlayerOptions | IRoomOptions | IPlayer | IRoom | IRoomPlayer | any\n /**\n * 发送者信息\n */\n sender?: IPlayer | IRoomPlayer | IRoom;\n}\n\n/**\n * 消息数据接口,包含发送者信息\n */\nexport interface IMessageData extends IMessagePackage {\n sender: IPlayer | IRoomPlayer | IRoom;\n}\n\n/**\n * 消息通信接口\n */\nexport interface IMessage extends EventEmitter<IMessageEmitterEvents> {\n /**\n * 监听消息事件\n * @param event 事件名,具体见 MessageEvents\n * @param listener 监听器\n */\n on<K extends keyof IMessageEvents>(event: K, listener: IMessageEvents[K]): this;\n /**\n * 触发消息事件\n * @param event 事件名,具体见 MessageEvents\n * @param args 参数\n */\n emit<K extends keyof IMessageEvents>(event: K, ...args: Parameters<IMessageEvents[K]>): boolean;\n /**\n * 关闭连接\n */\n close(): void;\n /**\n * 发送消息包\n * @param message 消息包\n */\n send(message: IMessagePackage): void;\n}\n","import { PlayerEvents } from \"@lib/events/player\";\nimport EventEmitter from \"events\";\n\n/**\n * 玩家选项接口\n */\nexport interface IPlayerOptions {\n /**\n * 玩家ID\n */\n id: string;\n /**\n * 玩家名称\n */\n name: string;\n /**\n * 玩家属性\n */\n attributes?: any;\n /**\n * 发送者函数\n */\n sender?: (type: string, ...message: any) => void;\n /**\n * 是否超级管理员\n */\n isAdmin?: boolean;\n}\n\n/**\n * 玩家状态枚举\n */\nexport enum PlayerStatus {\n /**\n * 已准备\n */\n ready = 'ready',\n /**\n * 未准备\n */\n unready = 'unready',\n /**\n * 在线\n */\n online = 'online',\n /**\n * 游戏中\n */\n playing = 'playing',\n}\n\n/**\n * 玩家接口\n */\nexport interface IPlayer extends IPlayerOptions {\n /**\n * 玩家状态\n */\n status: PlayerStatus;\n}\n\n/**\n * 玩家\n */\nexport class Player extends EventEmitter implements IPlayer {\n /**\n * 监听玩家事件\n * @param event 事件名,具体见 PlayEvents\n * @param listener 监听器\n * @returns this\n */\n on<K extends keyof PlayerEvents>(event: K, listener: PlayerEvents[K]): this {\n return super.on(event, listener);\n }\n\n /**\n * 触发玩家事件\n * @param event 事件名,具体见 PlayEvents\n * @param args 参数\n * @returns 是否有监听器被触发\n */\n emit<K extends keyof PlayerEvents>(event: K, ...args: Parameters<PlayerEvents[K]>): boolean {\n return super.emit(event, ...args);\n }\n \n id: string = \"\";\n name: string = \"\";\n attributes?: any;\n status: PlayerStatus = PlayerStatus.online;\n sender?: (type: string, ...message: any) => void;\n isAdmin: boolean = false;\n\n constructor(player: Partial<IPlayerOptions> | Player, status: PlayerStatus = PlayerStatus.online) {\n super();\n this.id = player.id || new Date().getTime().toString();\n this.name = player.name || \"\";\n this.attributes = player.attributes || {};\n this.sender = player.sender;\n\n if (player instanceof Player) this.status = player.status;\n\n this.status = status;\n\n this.on('status', (status: PlayerStatus) => {\n this.status = status;\n });\n \n const events: Array<keyof PlayerEvents> = ['command', 'message', 'status'];\n events.forEach((event) => {\n this.on(event, (...data: any) => {\n this.sender?.(event, ...data);\n });\n }); \n }\n\n toJSON() {\n return {\n id: this.id,\n name: this.name,\n attributes: this.attributes,\n status: this.status,\n isAdmin: this.isAdmin,\n };\n }\n\n toString() {\n return JSON.stringify(this.toJSON());\n }\n\n /**\n * 设置发送者函数\n * @param {(type: string, ...message: any) => void} sender 发送者函数\n * @returns this\n */\n setSender(sender: (type: string, ...message: any) => void) {\n this.sender = sender;\n return this;\n }\n}","import { IPlayer, Player, IPlayerOptions, PlayerStatus } from \"./player\";\nimport EventEmitter from \"events\";\nimport { RoomEvents } from \"@lib/events\";\n\n/**\n * 房间选项接口\n */\nexport interface IRoomOptions {\n /**\n * 房间号\n */\n id: string, \n /**\n * 房间名称\n */\n name: string,\n /**\n * 房间容量\n */\n size: number, \n /**\n * 最小容量\n */\n minSize: number,\n /**\n * 其他属性\n */\n attrs?: Record<string, any>,\n}\n\n/**\n * 房间玩家角色\n */\nexport enum PlayerRole {\n /**\n * 玩家\n */\n player = 'player',\n /**\n * 观众\n */\n watcher = 'watcher',\n /**\n * 管理员\n */\n admin = 'admin',\n}\n\n/**\n * 房间状态\n */\nexport enum RoomStatus {\n /**\n * 等待中\n */\n waiting = 'waiting',\n /**\n * 已准备\n */\n ready = 'ready',\n /**\n * 游戏中\n */\n playing = 'playing',\n}\n\n/**\n * 房间接口\n */\nexport interface IRoom extends IRoomOptions {\n /**\n * 房间玩家列表\n */\n players: RoomPlayer[];\n}\n\n/**\n * 房间玩家选项接口\n */\nexport interface IRoomPlayerOptions extends IPlayerOptions {\n /**\n * 房间Id\n */\n roomId?: string;\n}\n\n/**\n * 房间玩家接口\n */\nexport interface IRoomPlayer extends IRoomPlayerOptions, IPlayer {\n /**\n * 是否已准备\n */\n isReady: boolean;\n /**\n * 玩家角色\n */\n role: PlayerRole;\n /**\n * 是否为房主\n */\n isCreator: boolean;\n /**\n * 房间 Id\n */\n roomId: string;\n}\n\n/**\n * 房间玩家\n */\nexport class RoomPlayer extends Player implements IRoomPlayer {\n isReady: boolean = false;\n role: PlayerRole = PlayerRole.player;\n isCreator: boolean = false;\n roomId: string;\n\n constructor(player: Partial<IRoomPlayer>, role: PlayerRole = PlayerRole.player) {\n super(player);\n this.isReady = player.isReady || false;\n this.isCreator = player.isCreator || false;\n this.roomId = player.roomId || '';\n this.role = player.role || role;\n this.status = player.status || PlayerStatus.online;\n if (player instanceof Player && player.sender) super.setSender(player.sender);\n }\n\n toJSON() {\n return {\n ...super.toJSON(),\n role: this.role,\n isReady: this.isReady,\n isCreator: this.isCreator,\n };\n }\n}\n\n/**\n * 房间\n */\nexport class Room extends EventEmitter implements IRoom {\n /**\n * 监听房间事件\n * @param event 事件名,具体见 RoomEvents\n * @param listener 监听器\n * @returns this\n */\n on<K extends keyof RoomEvents>(event: K, listener: RoomEvents[K]): this {\n return super.on(event, listener);\n }\n\n /**\n * 触发房间事件\n * @param event 事件名,具体见 RoomEvents\n * @param args 参数\n * @returns 是否有监听器被触发\n */\n emit<K extends keyof RoomEvents>(event: K, ...args: Parameters<RoomEvents[K]>): boolean {\n return super.emit(event, ...args);\n }\n\n id: string;\n size: number = 10;\n name: string = '';\n minSize: number = 2;\n attrs?: Record<string, any>;\n players: RoomPlayer[] = [];\n\n /**\n * 有效玩家列表(非观众)\n */\n get validPlayers() {\n return this.players.filter((player) => player.role === PlayerRole.player);\n }\n\n /**\n * 观众列表\n */\n get watchers() {\n return this.players.filter((player) => player.role === PlayerRole.watcher);\n }\n\n /**\n * 消息发送器\n */\n private sender?: (type: string, ...message: any) => void;\n\n /**\n * 房间玩家是否已准备好\n */\n get isReady(): boolean {\n return this.players.length >= this.minSize\n && this.players.every((target) => target.isReady || target.role === PlayerRole.watcher); // is all player ready\n }\n\n /**\n * 房间状态\n */\n get status(): RoomStatus {\n if (!this.isReady) return RoomStatus.waiting;\n if (this.players.findIndex((target) => target.status === PlayerStatus.playing) != -1) return RoomStatus.playing;\n return RoomStatus.ready;\n }\n\n /**\n * 房间是否在游戏中\n */\n get isPlaying(): boolean {\n return this.status === RoomStatus.playing;\n }\n\n /**\n * 房间是否已满\n */\n get isFull(): boolean {\n return this.validPlayers.length == this.size;\n }\n\n /**\n * 房主\n */\n get owner(): RoomPlayer | undefined {\n const creator = this.players.find((player) => player.isCreator);\n return creator;\n }\n\n toJSON() {\n return {\n id: this.id,\n name: this.name,\n size: this.size || 10,\n minSize: this.minSize,\n status: this.status,\n players: this.players.map((player) => player.toJSON()),\n attrs: this.attrs,\n }\n }\n\n toString() {\n return JSON.stringify(this.toJSON());\n }\n\n constructor(room: Partial<IRoomOptions> | Room, players: RoomPlayer[] = []) {\n super();\n if (room instanceof Room) {\n this.players = room.players;\n this.players.forEach((p) => {\n p.roomId = room.id;\n });\n }\n\n this.id = room.id || new Date().getTime().toString();\n this.name = room.name || '';\n this.size = room.size || 10;\n this.minSize = room.minSize || 2;\n this.attrs = room.attrs;\n this.players = players;\n \n const events: Array<keyof RoomEvents> = ['message', 'command', 'start', 'end', 'all-ready', 'player-unready', 'player-ready', 'join', 'leave'];\n events.forEach((event) => {\n this.on(event, (...data: any) => {\n this.sender?.(event, ...data);\n });\n });\n }\n\n /**\n * 设置房主\n * @param {Player} player 玩家\n * @returns this\n */\n setCreator(player: Player) {\n const roomPlayer = this.searchPlayer(player);\n if (roomPlayer) {\n this.players.forEach((p) => {\n p.isCreator = false;\n });\n roomPlayer.isCreator = true;\n this.emit(\"update\", this);\n }\n return this;\n }\n\n /**\n * 添加玩家\n * @param {Player} player 玩家\n * @param {boolean} isCreator 是否房主\n * @returns 玩家实例 \n */\n addPlayer(player: Player, isCreator: boolean = false) {\n let roomPlayer = this.searchPlayer(player);\n if (roomPlayer) {\n if (roomPlayer.role === PlayerRole.watcher && !this.isFull && !this.isPlaying) {\n roomPlayer.role = PlayerRole.player;\n roomPlayer.isCreator = isCreator;\n this.emit(\"update\", this);\n }\n return roomPlayer;\n }\n\n if (isCreator) {\n this.players.forEach((p) => {\n p.isCreator = false;\n });\n }\n roomPlayer = new RoomPlayer(player, this.isFull || this.isPlaying ? PlayerRole.watcher : PlayerRole.player);\n roomPlayer.isCreator = isCreator;\n roomPlayer.roomId = this.id;\n this.players.push(roomPlayer);\n this.emit(\"join\", { ...roomPlayer, roomId: this.id });\n \n return roomPlayer;\n }\n\n /**\n * 离开座位\n * @param {string | IPlayer} player 玩家 / 玩家 id\n */\n leaveSeat(playerId: string): RoomPlayer;\n leaveSeat(player: IPlayer): RoomPlayer;\n leaveSeat(player: IPlayer | string) {\n const playerId = typeof player === \"string\" ? player : player.id;\n const roomPlayer = this.searchPlayer(playerId);\n if (roomPlayer && roomPlayer.role === PlayerRole.player) {\n roomPlayer.role = PlayerRole.watcher;\n roomPlayer.isReady = false;\n this.emit(\"leave\", { ...roomPlayer, roomId: this.id });\n if (roomPlayer.isCreator && this.validPlayers.length > 0) {\n this.validPlayers[0].isCreator = true;\n this.emit(\"update\", this);\n }\n }\n return roomPlayer!;\n }\n\n /**\n * 踢出玩家\n * @param {string | IPlayer} player 玩家 / 玩家 id\n */\n kickPlayer(playerId: string): RoomPlayer;\n kickPlayer(player: IPlayer): RoomPlayer;\n kickPlayer(player: IPlayer | string) {\n const playerId = typeof player === \"string\" ? player : player.id;\n const index = this.players.findIndex((p) => p.id == playerId);\n const roomPlayer = this.players[index];\n if (index > -1) {\n this.emit(\"leave\", { ...roomPlayer, roomId: this.id });\n this.players.splice(index, 1);\n if (roomPlayer.isCreator && this.players.length > 0) {\n this.players[0].isCreator = true;\n this.emit(\"update\", this);\n }\n }\n return roomPlayer;\n }\n\n /**\n * 搜索玩家\n * @param {string | IPlayer} player 玩家 / 玩家 id\n */\n searchPlayer(playerId: string): RoomPlayer | undefined;\n searchPlayer(player: IPlayer): RoomPlayer | undefined;\n searchPlayer(player: string | IPlayer) {\n const playerId = typeof player === \"string\" ? player : player?.id;\n return this.players.find((player) => player.id == playerId);\n }\n\n /**\n * 开始游戏\n */\n start(sender: IPlayer) {\n if (!this.isReady) {\n throw new Error('room is not ready.');\n }\n if (this.status === RoomStatus.playing) {\n throw new Error('room is already started.');\n }\n this.players.forEach((player) => {\n if (player.role != PlayerRole.player) return;\n player.emit('status', PlayerStatus.playing);\n });\n this.emit(\"update\", this);\n return this.emit(\"start\", this);\n }\n\n /**\n * 结束游戏\n */\n end() {\n this.players.forEach((player) => {\n if (player.role != PlayerRole.player) return;\n player.emit('status', PlayerStatus.unready);\n });\n this.emit(\"update\", this);\n return this.emit(\"end\", this);\n }\n\n /**\n * 设置消息发送器\n * @param sender 消息发送器\n */\n setSender(sender: (type: string, ...message: any) => void) {\n this.sender = sender;\n return this;\n }\n}\n","import { IRoomOptions, PlayerRole, RoomStatus, PlayerStatus, RecvMessageTypes as MessageTypes } from \"@lib/index\";\nexport { RoomStatus, PlayerStatus, PlayerRole, MessageTypes };\nexport type { IRoomOptions };\n\nexport 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 error 错误信息\n */\n \"global.error\": (error: Error) => void;\n /**\n * 全局命令事件\n * @param data 命令内容\n */\n \"global.command\": (data: any & { sender: Player }) => void;\n /**\n * 全局消息事件\n * @param message 消息内容\n */\n \"global.message\": (message: string, 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\": (status: PlayerStatus) => 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: { content: string, sender?: Player }) => void;\n /**\n * 玩家错误事件\n */\n \"player.error\": (error: Error) => 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\": (player: RoomPlayer & { roomId: string }) => void;\n /**\n * 玩家离开房间事件\n * @param room 房间信息\n * @param player 玩家信息\n */\n \"room.leave\": (player: RoomPlayer & { roomId: string }) => 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: { content: string; sender?: RoomPlayer }) => void;\n /**\n * 房间玩家准备事件\n * @param player 玩家信息\n * @param roomId 房间ID(可选)\n */\n \"room.player-ready\": (player: RoomPlayer) => void;\n /**\n * 房间玩家取消准备事件\n * @param player 玩家信息\n * @param roomId 房间ID(可选)\n */\n \"room.player-unready\": (player: RoomPlayer) => 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: PlayerStatus;\n isAdmin: boolean;\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 || PlayerStatus.online;\n this.isAdmin = player.isAdmin || false;\n }\n}\n\nexport class RoomPlayer extends Player {\n role: PlayerRole;\n isReady: boolean;\n isCreator: boolean;\n roomId: string;\n constructor(player: RoomPlayer) {\n super(player);\n this.role = player.role;\n this.isReady = player.isReady;\n this.isCreator = player.isCreator;\n this.roomId = player.roomId;\n }\n}\n\nexport class Room {\n id: string;\n name: string;\n players: RoomPlayer[];\n size: number;\n minSize: number;\n status: RoomStatus;\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: MessageTypes.RoomList });\n this.send({ type: MessageTypes.PlayerList });\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 = this.players.filter(p => p.id !== player.id);\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: MessageTypes, 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: MessageTypes.PlayerLogin, 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 }: Omit<IRoomOptions, 'id'>) {\n return new Promise<void>((resolve) => {\n this.send({ type: MessageTypes.RoomCreate, 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 * @param {object} params 加入参数\n */\n joinRoom(roomId: string, params?: any) {\n this.send({ type: MessageTypes.PlayerJoin, data: { roomId, params } });\n return this;\n }\n\n /**\n * 离开房间\n * @param {string} roomId 房间ID\n * @param {object} params 离开参数\n */\n leaveRoom(roomId: string, params?: any) {\n this.send({ type: MessageTypes.PlayerLeave, data: { roomId, params } });\n return this;\n }\n\n /**\n * 离开座位\n * @param {string} roomId 房间ID\n * @param {object} params 离开参数\n */\n leaveSeat(roomId: string, params?: any) {\n this.send({ type: MessageTypes.PlayerStandUp, data: { roomId, params } });\n return this;\n }\n\n /**\n * 踢出玩家\n * @param {string} roomId 房间ID\n * @param {string} playerId 玩家ID\n * @param {object} params 额外参数\n */\n kickPlayer(roomId: string, playerId: string, params?: any) {\n this.send({ type: MessageTypes.RoomKick, data: { roomId, playerId, params } });\n return this;\n }\n\n /**\n * 转让房主\n * @param {string} roomId 房间ID\n * @param {string} playerId 目标玩家ID\n * @param {object} params 额外参数\n */\n transferRoom(roomId: string, playerId: string, params?: any) {\n this.send({ type: MessageTypes.RoomTransfer, data: { roomId, playerId, params } });\n return this;\n }\n\n /**\n * 关闭房间\n * @param {string} roomId 房间ID\n * @param {object} params 额外参数\n * @returns \n */\n closeRoom(roomId: string, params?: any) {\n this.send({ type: MessageTypes.RoomClose, data: { roomId, params } });\n return this;\n }\n\n /**\n * 开始游戏\n * @param {string} id 房间ID\n */\n startGame(id: string, params?: any) {\n this.send({ type: MessageTypes.RoomStart, data: { id, params } });\n return this;\n }\n\n /**\n * 准备/取消准备\n * @param {string} roomId 房间ID\n * @param {boolean} isReady 是否准备\n */\n ready(roomId: string, isReady=true, params?: any) {\n this.send({ type: isReady ? MessageTypes.PlayerReady : MessageTypes.PlayerUnready, data: { roomId, params } });\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: MessageTypes.GlobalCommand, data: command });\n } else {\n this.send({ type: MessageTypes.RoomPlayerCommand, data: { id: roomId, ...command } });\n }\n return this;\n }\n\n /**\n * 连接准备监听\n * @param {function} cb 监听函数\n */\n onReady(cb: () => void) {\n return this.on(\"sys.ready\", cb);\n }\n\n /**\n * 全局错误监听\n * @param {function} cb 监听函数\n */\n onError(cb: (error: Error) => void) {\n this.on(\"global.error\", cb);\n return this;\n }\n\n /**\n * 全局消息监听\n * @param {function} cb 监听函数\n */\n onMessage(cb: (message: string, sender?: Player) => void, on=true) {\n if (on) this.on(\"global.message\", cb);\n else this.off(\"global.message\", cb);\n return this;\n }\n\n /**\n * 玩家列表变更监听\n * @param {function} cb 监听函数\n */\n onPlayerList(cb: (players: Player[]) => 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: (rooms: Room[]) => 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: (player: RoomPlayer) => 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: (player: RoomPlayer) => 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: (player: RoomPlayer) => 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: (player: RoomPlayer) => 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: (status: PlayerStatus) => 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: (room: Room) => 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: (room: Room) => 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: (room: Room) => 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: (message: { content: string, sender?: RoomPlayer }) => 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: (message: { content: string, sender?: Player }) => 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: (command: any & { sender?: Player }) => 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: (command: any & { sender?: Player }) => 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 {TiaoomEvents[K]} 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 {TiaoomEvents[K]} 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 {Parameters<TiaoomEvents[K]>} 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,2 +1,2 @@
1
- var Tiaoom=(function(e){Object.create,Object.defineProperty,Object.getOwnPropertyDescriptor,Object.getOwnPropertyNames,Object.getPrototypeOf,Object.prototype.hasOwnProperty;let t=function(e){return e.RoomList=`room.list`,e.PlayerList=`player.list`,e.RoomCreate=`room.create`,e.PlayerJoin=`player.join`,e.PlayerLeave=`player.leave`,e.PlayerStandUp=`player.standup`,e.RoomGet=`room.get`,e.RoomStart=`room.start`,e.RoomKick=`room.kick`,e.RoomTransfer=`room.transfer`,e.RoomClose=`room.close`,e.PlayerLogin=`player.login`,e.PlayerLogout=`player.logout`,e.PlayerReady=`player.ready`,e.PlayerUnready=`player.unready`,e.RoomPlayerCommand=`room.player-command`,e.GlobalCommand=`global.command`,e}({}),n=function(e){return e.ready=`ready`,e.unready=`unready`,e.online=`online`,e.playing=`playing`,e}({}),r=function(e){return e.player=`player`,e.watcher=`watcher`,e.admin=`admin`,e}({}),i=function(e){return e.waiting=`waiting`,e.ready=`ready`,e.playing=`playing`,e}({});var a=class{constructor(e){this.id=e.id||Date.now().toString(),this.name=e.name||`玩家`+this.id,this.attributes=e.attributes||{},this.status=e.status||n.online,this.isAdmin=e.isAdmin||!1}},o=class extends a{constructor(e){super(e),this.role=e.role,this.isReady=e.isReady,this.isCreator=e.isCreator,this.roomId=e.roomId}},s=class{constructor(e){this.id=e.id,this.name=e.name,this.players=e.players.map(e=>new o(e)),this.size=e.size,this.minSize=e.minSize,this.status=e.status,this.attrs=e.attrs}},c=class{constructor(){this.listeners={},this.rooms=[],this.players=[],this.currentPlayer=null}run(){return this.connect(),this.onReady(()=>{this.send({type:t.RoomList}),this.send({type:t.PlayerList})}),this.on(`player.list`,e=>{this.players=e.map(e=>new a(e)),this.emit(`onPlayerList`,[...this.players])}),this.on(`player.login`,e=>{this.players.push(new a(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 s(e)),this.emit(`onRoomList`,[...this.rooms])}),this.on(`room.create`,e=>{this.rooms.push(new s(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 s(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 a(e),this.send({type:t.PlayerLogin,data:e}),this}createRoom({name:e,size:n,minSize:r,attrs:i}){return new Promise(a=>{this.send({type:t.RoomCreate,data:{name:e,size:n,minSize:r,attrs:i}}),this.on(`room.create`,e=>{a()})})}joinRoom(e,n){return this.send({type:t.PlayerJoin,data:{roomId:e,params:n}}),this}leaveRoom(e,n){return this.send({type:t.PlayerLeave,data:{roomId:e,params:n}}),this}leaveSeat(e,n){return this.send({type:t.PlayerStandUp,data:{roomId:e,params:n}}),this}kickPlayer(e,n,r){return this.send({type:t.RoomKick,data:{roomId:e,playerId:n,params:r}}),this}transferRoom(e,n,r){return this.send({type:t.RoomTransfer,data:{roomId:e,playerId:n,params:r}}),this}closeRoom(e,n){return this.send({type:t.RoomClose,data:{roomId:e,params:n}}),this}startGame(e,n){return this.send({type:t.RoomStart,data:{id:e,params:n}}),this}ready(e,n=!0,r){return this.send({type:n?t.PlayerReady:t.PlayerUnready,data:{roomId:e,params:r}}),this}command(e,n){return typeof e==`string`?this.send({type:t.RoomPlayerCommand,data:{id:e,...n}}):(n=e,this.send({type:t.GlobalCommand,data:n})),this}onReady(e){return this.on(`sys.ready`,e)}onError(e){return this.on(`global.error`,e),this}onMessage(e,t=!0){return t?this.on(`global.message`,e):this.off(`global.message`,e),this}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 s(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 s(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 s(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.MessageTypes=t,e.Player=a,e.PlayerRole=r,e.PlayerStatus=n,e.Room=s,e.RoomPlayer=o,e.RoomStatus=i,e.Tiaoom=c,e})({});
1
+ var Tiaoom=(function(e){Object.create,Object.defineProperty,Object.getOwnPropertyDescriptor,Object.getOwnPropertyNames,Object.getPrototypeOf,Object.prototype.hasOwnProperty;let t=function(e){return e.RoomList=`room.list`,e.PlayerList=`player.list`,e.RoomCreate=`room.create`,e.PlayerJoin=`player.join`,e.PlayerLeave=`player.leave`,e.PlayerStandUp=`player.standup`,e.RoomGet=`room.get`,e.RoomStart=`room.start`,e.RoomKick=`room.kick`,e.RoomTransfer=`room.transfer`,e.RoomClose=`room.close`,e.PlayerLogin=`player.login`,e.PlayerLogout=`player.logout`,e.PlayerReady=`player.ready`,e.PlayerUnready=`player.unready`,e.RoomPlayerCommand=`room.player-command`,e.GlobalCommand=`global.command`,e}({}),n=function(e){return e.ready=`ready`,e.unready=`unready`,e.online=`online`,e.playing=`playing`,e}({}),r=function(e){return e.player=`player`,e.watcher=`watcher`,e.admin=`admin`,e}({}),i=function(e){return e.waiting=`waiting`,e.ready=`ready`,e.playing=`playing`,e}({});var a=class{constructor(e){this.id=e.id||Date.now().toString(),this.name=e.name||`玩家`+this.id,this.attributes=e.attributes||{},this.status=e.status||n.online,this.isAdmin=e.isAdmin||!1}},o=class extends a{constructor(e){super(e),this.role=e.role,this.isReady=e.isReady,this.isCreator=e.isCreator,this.roomId=e.roomId}},s=class{constructor(e){this.id=e.id,this.name=e.name,this.players=e.players.map(e=>new o(e)),this.size=e.size,this.minSize=e.minSize,this.status=e.status,this.attrs=e.attrs}},c=class{constructor(){this.listeners={},this.rooms=[],this.players=[],this.currentPlayer=null}run(){return this.connect(),this.onReady(()=>{this.send({type:t.RoomList}),this.send({type:t.PlayerList})}),this.on(`player.list`,e=>{this.players=e.map(e=>new a(e)),this.emit(`onPlayerList`,[...this.players])}),this.on(`player.login`,e=>{this.players=this.players.filter(t=>t.id!==e.id),this.players.push(new a(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 s(e)),this.emit(`onRoomList`,[...this.rooms])}),this.on(`room.create`,e=>{this.rooms.push(new s(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 s(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 a(e),this.send({type:t.PlayerLogin,data:e}),this}createRoom({name:e,size:n,minSize:r,attrs:i}){return new Promise(a=>{this.send({type:t.RoomCreate,data:{name:e,size:n,minSize:r,attrs:i}}),this.on(`room.create`,e=>{a()})})}joinRoom(e,n){return this.send({type:t.PlayerJoin,data:{roomId:e,params:n}}),this}leaveRoom(e,n){return this.send({type:t.PlayerLeave,data:{roomId:e,params:n}}),this}leaveSeat(e,n){return this.send({type:t.PlayerStandUp,data:{roomId:e,params:n}}),this}kickPlayer(e,n,r){return this.send({type:t.RoomKick,data:{roomId:e,playerId:n,params:r}}),this}transferRoom(e,n,r){return this.send({type:t.RoomTransfer,data:{roomId:e,playerId:n,params:r}}),this}closeRoom(e,n){return this.send({type:t.RoomClose,data:{roomId:e,params:n}}),this}startGame(e,n){return this.send({type:t.RoomStart,data:{id:e,params:n}}),this}ready(e,n=!0,r){return this.send({type:n?t.PlayerReady:t.PlayerUnready,data:{roomId:e,params:r}}),this}command(e,n){return typeof e==`string`?this.send({type:t.RoomPlayerCommand,data:{id:e,...n}}):(n=e,this.send({type:t.GlobalCommand,data:n})),this}onReady(e){return this.on(`sys.ready`,e)}onError(e){return this.on(`global.error`,e),this}onMessage(e,t=!0){return t?this.on(`global.message`,e):this.off(`global.message`,e),this}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 s(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 s(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 s(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.MessageTypes=t,e.Player=a,e.PlayerRole=r,e.PlayerStatus=n,e.Room=s,e.RoomPlayer=o,e.RoomStatus=i,e.Tiaoom=c,e})({});
2
2
  //# sourceMappingURL=client.iife.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.iife.js","names":["MessageTypes"],"sources":["../lib/models/message.ts","../lib/models/player.ts","../lib/models/room.ts","../lib/client.ts"],"sourcesContent":["import EventEmitter from \"events\";\nimport { IPlayer, IPlayerOptions } from \"./player\";\nimport { IRoom, IRoomPlayer, IRoomOptions } from \"./room\";\nimport { IMessageEmitterEvents, IMessageEvents } from \"@lib/events/message\";\n\n/**\n * 消息包类型枚举\n * player: 'command', 'message', 'join', 'leave', 'status'\n */\nexport enum MessageTypes {\n /**\n * 连接准备就绪事件\n */\n SysReady = \"sys.ready\",\n /**\n * 连接关闭事件\n */\n SysClose = \"sys.close\",\n /**\n * 错误事件\n */\n SysError = \"sys.error\",\n /**\n * 全局错误\n */\n GlobalError = \"global.error\",\n /**\n * 房间列表\n */\n RoomList = \"room.list\",\n /**\n * 房间创建\n */\n RoomCreate = \"room.create\",\n /**\n * 房间更新\n */\n RoomUpdate = \"room.update\",\n /**\n * 房间开始\n */\n RoomStart = \"room.start\",\n /**\n * 房间结束\n */\n RoomEnd = \"room.end\",\n /**\n * 房间关闭\n */\n RoomClose = \"room.close\",\n /**\n * 房间全部玩家已准备\n */\n RoomAllReady = \"room.all-ready\",\n /**\n * 房间命令\n */\n RoomCommand = \"room.command\",\n /**\n * 房间内玩家发送的指令\n */\n RoomPlayerCommand = \"room.player-command\",\n /**\n * 房间消息\n */\n RoomMessage = \"room.message\",\n /**\n * 玩家加入房间\n */\n RoomJoin = \"room.join\",\n /**\n * 玩家离开房间\n */\n RoomLeave = \"room.leave\",\n /**\n * 房间玩家准备\n */\n RoomPlayerReady = \"room.player-ready\",\n /**\n * 房间玩家取消准备\n */\n RoomPlayerUnready = \"room.player-unready\",\n /**\n * 玩家列表\n */\n PlayerList = \"player.list\",\n /**\n * 玩家登录\n */\n PlayerLogin = \"player.login\",\n /**\n * 玩家登出\n */\n PlayerLogout = \"player.logout\",\n /**\n * *玩家消息\n */\n PlayerMessage = \"player.message\",\n /**\n * *玩家命令\n */\n PlayerCommand = \"player.command\",\n /**\n * 玩家错误信息\n */\n PlayerError = \"player.error\",\n /**\n * 全局消息\n */\n GlobalMessage = \"global.message\",\n /**\n * 全局命令\n */\n GlobalCommand = \"global.command\",\n}\n\n/**\n * 客户端发送消息包类型枚举\n * player: 'command', 'message', 'join', 'leave', 'status'\n */\nexport enum RecvMessageTypes {\n /**\n * 房间列表\n */\n RoomList = \"room.list\",\n /**\n * 玩家列表\n */\n PlayerList = \"player.list\",\n /**\n * 房间创建\n */\n RoomCreate = \"room.create\",\n /**\n * 玩家加入房间\n */\n PlayerJoin = \"player.join\",\n /**\n * 玩家离开房间\n */\n PlayerLeave = \"player.leave\",\n /**\n * 玩家离开座位\n */\n PlayerStandUp = \"player.standup\",\n /**\n * 房间获取\n */\n RoomGet = \"room.get\",\n /**\n * 房间开始\n */\n RoomStart = \"room.start\",\n /**\n * 房间踢出玩家\n */\n RoomKick = \"room.kick\",\n /**\n * 房间转移\n */\n RoomTransfer = \"room.transfer\",\n /**\n * 房间关闭\n */\n RoomClose = \"room.close\", \n /**\n * 玩家登录\n */\n PlayerLogin = \"player.login\",\n /**\n * 玩家登出\n */\n PlayerLogout = \"player.logout\",\n /**\n * 玩家准备\n */\n PlayerReady = \"player.ready\",\n /**\n * 玩家取消准备\n */\n PlayerUnready = \"player.unready\",\n /**\n * 房间内玩家发送的指令\n */\n RoomPlayerCommand = \"room.player-command\",\n /**\n * 全局命令\n */\n GlobalCommand = \"global.command\",\n}\n\n/**\n * 消息包接口\n */\nexport interface IMessagePackage {\n /**\n * 消息类型\n */\n type: MessageTypes;\n /**\n * 消息数据\n */\n data?: IPlayerOptions | IRoomOptions | IPlayer | IRoom | IRoomPlayer | any\n /**\n * 发送者信息\n */\n sender?: IPlayer | IRoomPlayer | IRoom;\n}\n\n/**\n * 消息数据接口,包含发送者信息\n */\nexport interface IMessageData extends IMessagePackage {\n sender: IPlayer | IRoomPlayer | IRoom;\n}\n\n/**\n * 消息通信接口\n */\nexport interface IMessage extends EventEmitter<IMessageEmitterEvents> {\n /**\n * 监听消息事件\n * @param event 事件名,具体见 MessageEvents\n * @param listener 监听器\n */\n on<K extends keyof IMessageEvents>(event: K, listener: IMessageEvents[K]): this;\n /**\n * 触发消息事件\n * @param event 事件名,具体见 MessageEvents\n * @param args 参数\n */\n emit<K extends keyof IMessageEvents>(event: K, ...args: Parameters<IMessageEvents[K]>): boolean;\n /**\n * 关闭连接\n */\n close(): void;\n /**\n * 发送消息包\n * @param message 消息包\n */\n send(message: IMessagePackage): void;\n}\n","import { PlayerEvents } from \"@lib/events/player\";\nimport EventEmitter from \"events\";\n\n/**\n * 玩家选项接口\n */\nexport interface IPlayerOptions {\n /**\n * 玩家ID\n */\n id: string;\n /**\n * 玩家名称\n */\n name: string;\n /**\n * 玩家属性\n */\n attributes?: any;\n /**\n * 发送者函数\n */\n sender?: (type: string, ...message: any) => void;\n /**\n * 是否超级管理员\n */\n isAdmin?: boolean;\n}\n\n/**\n * 玩家状态枚举\n */\nexport enum PlayerStatus {\n /**\n * 已准备\n */\n ready = 'ready',\n /**\n * 未准备\n */\n unready = 'unready',\n /**\n * 在线\n */\n online = 'online',\n /**\n * 游戏中\n */\n playing = 'playing',\n}\n\n/**\n * 玩家接口\n */\nexport interface IPlayer extends IPlayerOptions {\n /**\n * 玩家状态\n */\n status: PlayerStatus;\n}\n\n/**\n * 玩家\n */\nexport class Player extends EventEmitter implements IPlayer {\n /**\n * 监听玩家事件\n * @param event 事件名,具体见 PlayEvents\n * @param listener 监听器\n * @returns this\n */\n on<K extends keyof PlayerEvents>(event: K, listener: PlayerEvents[K]): this {\n return super.on(event, listener);\n }\n\n /**\n * 触发玩家事件\n * @param event 事件名,具体见 PlayEvents\n * @param args 参数\n * @returns 是否有监听器被触发\n */\n emit<K extends keyof PlayerEvents>(event: K, ...args: Parameters<PlayerEvents[K]>): boolean {\n return super.emit(event, ...args);\n }\n \n id: string = \"\";\n name: string = \"\";\n attributes?: any;\n status: PlayerStatus = PlayerStatus.online;\n sender?: (type: string, ...message: any) => void;\n isAdmin: boolean = false;\n\n constructor(player: Partial<IPlayerOptions> | Player, status: PlayerStatus = PlayerStatus.online) {\n super();\n this.id = player.id || new Date().getTime().toString();\n this.name = player.name || \"\";\n this.attributes = player.attributes || {};\n this.sender = player.sender;\n\n if (player instanceof Player) this.status = player.status;\n\n this.status = status;\n\n this.on('status', (status: PlayerStatus) => {\n this.status = status;\n });\n \n const events: Array<keyof PlayerEvents> = ['command', 'message', 'status'];\n events.forEach((event) => {\n this.on(event, (...data: any) => {\n this.sender?.(event, ...data);\n });\n }); \n }\n\n toJSON() {\n return {\n id: this.id,\n name: this.name,\n attributes: this.attributes,\n status: this.status,\n isAdmin: this.isAdmin,\n };\n }\n\n toString() {\n return JSON.stringify(this.toJSON());\n }\n\n /**\n * 设置发送者函数\n * @param {(type: string, ...message: any) => void} sender 发送者函数\n * @returns this\n */\n setSender(sender: (type: string, ...message: any) => void) {\n this.sender = sender;\n return this;\n }\n}","import { IPlayer, Player, IPlayerOptions, PlayerStatus } from \"./player\";\nimport EventEmitter from \"events\";\nimport { RoomEvents } from \"@lib/events\";\n\n/**\n * 房间选项接口\n */\nexport interface IRoomOptions {\n /**\n * 房间号\n */\n id: string, \n /**\n * 房间名称\n */\n name: string,\n /**\n * 房间容量\n */\n size: number, \n /**\n * 最小容量\n */\n minSize: number,\n /**\n * 其他属性\n */\n attrs?: Record<string, any>,\n}\n\n/**\n * 房间玩家角色\n */\nexport enum PlayerRole {\n /**\n * 玩家\n */\n player = 'player',\n /**\n * 观众\n */\n watcher = 'watcher',\n /**\n * 管理员\n */\n admin = 'admin',\n}\n\n/**\n * 房间状态\n */\nexport enum RoomStatus {\n /**\n * 等待中\n */\n waiting = 'waiting',\n /**\n * 已准备\n */\n ready = 'ready',\n /**\n * 游戏中\n */\n playing = 'playing',\n}\n\n/**\n * 房间接口\n */\nexport interface IRoom extends IRoomOptions {\n /**\n * 房间玩家列表\n */\n players: RoomPlayer[];\n}\n\n/**\n * 房间玩家选项接口\n */\nexport interface IRoomPlayerOptions extends IPlayerOptions {\n /**\n * 房间Id\n */\n roomId?: string;\n}\n\n/**\n * 房间玩家接口\n */\nexport interface IRoomPlayer extends IRoomPlayerOptions, IPlayer {\n /**\n * 是否已准备\n */\n isReady: boolean;\n /**\n * 玩家角色\n */\n role: PlayerRole;\n /**\n * 是否为房主\n */\n isCreator: boolean;\n /**\n * 房间 Id\n */\n roomId: string;\n}\n\n/**\n * 房间玩家\n */\nexport class RoomPlayer extends Player implements IRoomPlayer {\n isReady: boolean = false;\n role: PlayerRole = PlayerRole.player;\n isCreator: boolean = false;\n roomId: string;\n\n constructor(player: Partial<IRoomPlayer>, role: PlayerRole = PlayerRole.player) {\n super(player);\n this.isReady = player.isReady || false;\n this.isCreator = player.isCreator || false;\n this.roomId = player.roomId || '';\n this.role = player.role || role;\n this.status = player.status || PlayerStatus.online;\n if (player instanceof Player && player.sender) super.setSender(player.sender);\n }\n\n toJSON() {\n return {\n ...super.toJSON(),\n role: this.role,\n isReady: this.isReady,\n isCreator: this.isCreator,\n };\n }\n}\n\n/**\n * 房间\n */\nexport class Room extends EventEmitter implements IRoom {\n /**\n * 监听房间事件\n * @param event 事件名,具体见 RoomEvents\n * @param listener 监听器\n * @returns this\n */\n on<K extends keyof RoomEvents>(event: K, listener: RoomEvents[K]): this {\n return super.on(event, listener);\n }\n\n /**\n * 触发房间事件\n * @param event 事件名,具体见 RoomEvents\n * @param args 参数\n * @returns 是否有监听器被触发\n */\n emit<K extends keyof RoomEvents>(event: K, ...args: Parameters<RoomEvents[K]>): boolean {\n return super.emit(event, ...args);\n }\n\n id: string;\n size: number = 10;\n name: string = '';\n minSize: number = 2;\n attrs?: Record<string, any>;\n players: RoomPlayer[] = [];\n\n /**\n * 有效玩家列表(非观众)\n */\n get validPlayers() {\n return this.players.filter((player) => player.role === PlayerRole.player);\n }\n\n /**\n * 观众列表\n */\n get watchers() {\n return this.players.filter((player) => player.role === PlayerRole.watcher);\n }\n\n /**\n * 消息发送器\n */\n private sender?: (type: string, ...message: any) => void;\n\n /**\n * 房间玩家是否已准备好\n */\n get isReady(): boolean {\n return this.players.length >= this.minSize\n && this.players.every((target) => target.isReady || target.role === PlayerRole.watcher); // is all player ready\n }\n\n /**\n * 房间状态\n */\n get status(): RoomStatus {\n if (!this.isReady) return RoomStatus.waiting;\n if (this.players.findIndex((target) => target.status === PlayerStatus.playing) != -1) return RoomStatus.playing;\n return RoomStatus.ready;\n }\n\n /**\n * 房间是否在游戏中\n */\n get isPlaying(): boolean {\n return this.status === RoomStatus.playing;\n }\n\n /**\n * 房间是否已满\n */\n get isFull(): boolean {\n return this.validPlayers.length == this.size;\n }\n\n /**\n * 房主\n */\n get owner(): RoomPlayer | undefined {\n const creator = this.players.find((player) => player.isCreator);\n return creator;\n }\n\n toJSON() {\n return {\n id: this.id,\n name: this.name,\n size: this.size || 10,\n minSize: this.minSize,\n status: this.status,\n players: this.players.map((player) => player.toJSON()),\n attrs: this.attrs,\n }\n }\n\n toString() {\n return JSON.stringify(this.toJSON());\n }\n\n constructor(room: Partial<IRoomOptions> | Room, players: RoomPlayer[] = []) {\n super();\n if (room instanceof Room) {\n this.players = room.players;\n this.players.forEach((p) => {\n p.roomId = room.id;\n });\n }\n\n this.id = room.id || new Date().getTime().toString();\n this.name = room.name || '';\n this.size = room.size || 10;\n this.minSize = room.minSize || 2;\n this.attrs = room.attrs;\n this.players = players;\n \n const events: Array<keyof RoomEvents> = ['message', 'command', 'start', 'end', 'all-ready', 'player-unready', 'player-ready', 'join', 'leave'];\n events.forEach((event) => {\n this.on(event, (...data: any) => {\n this.sender?.(event, ...data);\n });\n });\n }\n\n /**\n * 设置房主\n * @param {Player} player 玩家\n * @returns this\n */\n setCreator(player: Player) {\n const roomPlayer = this.searchPlayer(player);\n if (roomPlayer) {\n this.players.forEach((p) => {\n p.isCreator = false;\n });\n roomPlayer.isCreator = true;\n this.emit(\"update\", this);\n }\n return this;\n }\n\n /**\n * 添加玩家\n * @param {Player} player 玩家\n * @param {boolean} isCreator 是否房主\n * @returns 玩家实例 \n */\n addPlayer(player: Player, isCreator: boolean = false) {\n let roomPlayer = this.searchPlayer(player);\n if (roomPlayer) {\n if (roomPlayer.role === PlayerRole.watcher && !this.isFull && !this.isPlaying) {\n roomPlayer.role = PlayerRole.player;\n roomPlayer.isCreator = isCreator;\n this.emit(\"update\", this);\n }\n return roomPlayer;\n }\n\n if (isCreator) {\n this.players.forEach((p) => {\n p.isCreator = false;\n });\n }\n roomPlayer = new RoomPlayer(player, this.isFull || this.isPlaying ? PlayerRole.watcher : PlayerRole.player);\n roomPlayer.isCreator = isCreator;\n roomPlayer.roomId = this.id;\n this.players.push(roomPlayer);\n this.emit(\"join\", { ...roomPlayer, roomId: this.id });\n \n return roomPlayer;\n }\n\n /**\n * 离开座位\n * @param {string | IPlayer} player 玩家 / 玩家 id\n */\n leaveSeat(playerId: string): RoomPlayer;\n leaveSeat(player: IPlayer): RoomPlayer;\n leaveSeat(player: IPlayer | string) {\n const playerId = typeof player === \"string\" ? player : player.id;\n const roomPlayer = this.searchPlayer(playerId);\n if (roomPlayer && roomPlayer.role === PlayerRole.player) {\n roomPlayer.role = PlayerRole.watcher;\n roomPlayer.isReady = false;\n this.emit(\"leave\", { ...roomPlayer, roomId: this.id });\n if (roomPlayer.isCreator && this.validPlayers.length > 0) {\n this.validPlayers[0].isCreator = true;\n this.emit(\"update\", this);\n }\n }\n return roomPlayer!;\n }\n\n /**\n * 踢出玩家\n * @param {string | IPlayer} player 玩家 / 玩家 id\n */\n kickPlayer(playerId: string): RoomPlayer;\n kickPlayer(player: IPlayer): RoomPlayer;\n kickPlayer(player: IPlayer | string) {\n const playerId = typeof player === \"string\" ? player : player.id;\n const index = this.players.findIndex((p) => p.id == playerId);\n const roomPlayer = this.players[index];\n if (index > -1) {\n this.emit(\"leave\", { ...roomPlayer, roomId: this.id });\n this.players.splice(index, 1);\n if (roomPlayer.isCreator && this.players.length > 0) {\n this.players[0].isCreator = true;\n this.emit(\"update\", this);\n }\n }\n return roomPlayer;\n }\n\n /**\n * 搜索玩家\n * @param {string | IPlayer} player 玩家 / 玩家 id\n */\n searchPlayer(playerId: string): RoomPlayer | undefined;\n searchPlayer(player: IPlayer): RoomPlayer | undefined;\n searchPlayer(player: string | IPlayer) {\n const playerId = typeof player === \"string\" ? player : player?.id;\n return this.players.find((player) => player.id == playerId);\n }\n\n /**\n * 开始游戏\n */\n start(sender: IPlayer) {\n if (!this.isReady) {\n throw new Error('room is not ready.');\n }\n if (this.status === RoomStatus.playing) {\n throw new Error('room is already started.');\n }\n this.players.forEach((player) => {\n if (player.role != PlayerRole.player) return;\n player.emit('status', PlayerStatus.playing);\n });\n this.emit(\"update\", this);\n return this.emit(\"start\", this);\n }\n\n /**\n * 结束游戏\n */\n end() {\n this.players.forEach((player) => {\n if (player.role != PlayerRole.player) return;\n player.emit('status', PlayerStatus.unready);\n });\n this.emit(\"update\", this);\n return this.emit(\"end\", this);\n }\n\n /**\n * 设置消息发送器\n * @param sender 消息发送器\n */\n setSender(sender: (type: string, ...message: any) => void) {\n this.sender = sender;\n return this;\n }\n}\n","import { IRoomOptions, PlayerRole, RoomStatus, PlayerStatus, RecvMessageTypes as MessageTypes } from \"@lib/index\";\nexport { RoomStatus, PlayerStatus, PlayerRole, MessageTypes };\nexport type { IRoomOptions };\n\nexport 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 error 错误信息\n */\n \"global.error\": (error: Error) => void;\n /**\n * 全局命令事件\n * @param data 命令内容\n */\n \"global.command\": (data: any & { sender: Player }) => void;\n /**\n * 全局消息事件\n * @param message 消息内容\n */\n \"global.message\": (message: string, 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\": (status: PlayerStatus) => 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: { content: string, sender?: Player }) => void;\n /**\n * 玩家错误事件\n */\n \"player.error\": (error: Error) => 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\": (player: RoomPlayer & { roomId: string }) => void;\n /**\n * 玩家离开房间事件\n * @param room 房间信息\n * @param player 玩家信息\n */\n \"room.leave\": (player: RoomPlayer & { roomId: string }) => 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: { content: string; sender?: RoomPlayer }) => void;\n /**\n * 房间玩家准备事件\n * @param player 玩家信息\n * @param roomId 房间ID(可选)\n */\n \"room.player-ready\": (player: RoomPlayer) => void;\n /**\n * 房间玩家取消准备事件\n * @param player 玩家信息\n * @param roomId 房间ID(可选)\n */\n \"room.player-unready\": (player: RoomPlayer) => 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: PlayerStatus;\n isAdmin: boolean;\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 || PlayerStatus.online;\n this.isAdmin = player.isAdmin || false;\n }\n}\n\nexport class RoomPlayer extends Player {\n role: PlayerRole;\n isReady: boolean;\n isCreator: boolean;\n roomId: string;\n constructor(player: RoomPlayer) {\n super(player);\n this.role = player.role;\n this.isReady = player.isReady;\n this.isCreator = player.isCreator;\n this.roomId = player.roomId;\n }\n}\n\nexport class Room {\n id: string;\n name: string;\n players: RoomPlayer[];\n size: number;\n minSize: number;\n status: RoomStatus;\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: MessageTypes.RoomList });\n this.send({ type: MessageTypes.PlayerList });\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: MessageTypes, 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: MessageTypes.PlayerLogin, 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 }: Omit<IRoomOptions, 'id'>) {\n return new Promise<void>((resolve) => {\n this.send({ type: MessageTypes.RoomCreate, 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 * @param {object} params 加入参数\n */\n joinRoom(roomId: string, params?: any) {\n this.send({ type: MessageTypes.PlayerJoin, data: { roomId, params } });\n return this;\n }\n\n /**\n * 离开房间\n * @param {string} roomId 房间ID\n * @param {object} params 离开参数\n */\n leaveRoom(roomId: string, params?: any) {\n this.send({ type: MessageTypes.PlayerLeave, data: { roomId, params } });\n return this;\n }\n\n /**\n * 离开座位\n * @param {string} roomId 房间ID\n * @param {object} params 离开参数\n */\n leaveSeat(roomId: string, params?: any) {\n this.send({ type: MessageTypes.PlayerStandUp, data: { roomId, params } });\n return this;\n }\n\n /**\n * 踢出玩家\n * @param {string} roomId 房间ID\n * @param {string} playerId 玩家ID\n * @param {object} params 额外参数\n */\n kickPlayer(roomId: string, playerId: string, params?: any) {\n this.send({ type: MessageTypes.RoomKick, data: { roomId, playerId, params } });\n return this;\n }\n\n /**\n * 转让房主\n * @param {string} roomId 房间ID\n * @param {string} playerId 目标玩家ID\n * @param {object} params 额外参数\n */\n transferRoom(roomId: string, playerId: string, params?: any) {\n this.send({ type: MessageTypes.RoomTransfer, data: { roomId, playerId, params } });\n return this;\n }\n\n /**\n * 关闭房间\n * @param {string} roomId 房间ID\n * @param {object} params 额外参数\n * @returns \n */\n closeRoom(roomId: string, params?: any) {\n this.send({ type: MessageTypes.RoomClose, data: { roomId, params } });\n return this;\n }\n\n /**\n * 开始游戏\n * @param {string} id 房间ID\n */\n startGame(id: string, params?: any) {\n this.send({ type: MessageTypes.RoomStart, data: { id, params } });\n return this;\n }\n\n /**\n * 准备/取消准备\n * @param {string} roomId 房间ID\n * @param {boolean} isReady 是否准备\n */\n ready(roomId: string, isReady=true, params?: any) {\n this.send({ type: isReady ? MessageTypes.PlayerReady : MessageTypes.PlayerUnready, data: { roomId, params } });\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: MessageTypes.GlobalCommand, data: command });\n } else {\n this.send({ type: MessageTypes.RoomPlayerCommand, data: { id: roomId, ...command } });\n }\n return this;\n }\n\n /**\n * 连接准备监听\n * @param {function} cb 监听函数\n */\n onReady(cb: () => void) {\n return this.on(\"sys.ready\", cb);\n }\n\n /**\n * 全局错误监听\n * @param {function} cb 监听函数\n */\n onError(cb: (error: Error) => void) {\n this.on(\"global.error\", cb);\n return this;\n }\n\n /**\n * 全局消息监听\n * @param {function} cb 监听函数\n */\n onMessage(cb: (message: string, sender?: Player) => void, on=true) {\n if (on) this.on(\"global.message\", cb);\n else this.off(\"global.message\", cb);\n return this;\n }\n\n /**\n * 玩家列表变更监听\n * @param {function} cb 监听函数\n */\n onPlayerList(cb: (players: Player[]) => 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: (rooms: Room[]) => 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: (player: RoomPlayer) => 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: (player: RoomPlayer) => 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: (player: RoomPlayer) => 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: (player: RoomPlayer) => 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: (status: PlayerStatus) => 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: (room: Room) => 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: (room: Room) => 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: (room: Room) => 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: (message: { content: string, sender?: RoomPlayer }) => 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: (message: { content: string, sender?: Player }) => 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: (command: any & { sender?: Player }) => 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: (command: any & { sender?: Player }) => 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 {TiaoomEvents[K]} 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 {TiaoomEvents[K]} 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 {Parameters<TiaoomEvents[K]>} 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":["MessageTypes"],"sources":["../lib/models/message.ts","../lib/models/player.ts","../lib/models/room.ts","../lib/client.ts"],"sourcesContent":["import EventEmitter from \"events\";\nimport { IPlayer, IPlayerOptions } from \"./player\";\nimport { IRoom, IRoomPlayer, IRoomOptions } from \"./room\";\nimport { IMessageEmitterEvents, IMessageEvents } from \"@lib/events/message\";\n\n/**\n * 消息包类型枚举\n * player: 'command', 'message', 'join', 'leave', 'status'\n */\nexport enum MessageTypes {\n /**\n * 连接准备就绪事件\n */\n SysReady = \"sys.ready\",\n /**\n * 连接关闭事件\n */\n SysClose = \"sys.close\",\n /**\n * 错误事件\n */\n SysError = \"sys.error\",\n /**\n * 全局错误\n */\n GlobalError = \"global.error\",\n /**\n * 房间列表\n */\n RoomList = \"room.list\",\n /**\n * 房间创建\n */\n RoomCreate = \"room.create\",\n /**\n * 房间更新\n */\n RoomUpdate = \"room.update\",\n /**\n * 房间开始\n */\n RoomStart = \"room.start\",\n /**\n * 房间结束\n */\n RoomEnd = \"room.end\",\n /**\n * 房间关闭\n */\n RoomClose = \"room.close\",\n /**\n * 房间全部玩家已准备\n */\n RoomAllReady = \"room.all-ready\",\n /**\n * 房间命令\n */\n RoomCommand = \"room.command\",\n /**\n * 房间内玩家发送的指令\n */\n RoomPlayerCommand = \"room.player-command\",\n /**\n * 房间消息\n */\n RoomMessage = \"room.message\",\n /**\n * 玩家加入房间\n */\n RoomJoin = \"room.join\",\n /**\n * 玩家离开房间\n */\n RoomLeave = \"room.leave\",\n /**\n * 房间玩家准备\n */\n RoomPlayerReady = \"room.player-ready\",\n /**\n * 房间玩家取消准备\n */\n RoomPlayerUnready = \"room.player-unready\",\n /**\n * 玩家列表\n */\n PlayerList = \"player.list\",\n /**\n * 玩家登录\n */\n PlayerLogin = \"player.login\",\n /**\n * 玩家登出\n */\n PlayerLogout = \"player.logout\",\n /**\n * 玩家离线\n */\n PlayerOffline = \"player.offline\",\n /**\n * *玩家消息\n */\n PlayerMessage = \"player.message\",\n /**\n * *玩家命令\n */\n PlayerCommand = \"player.command\",\n /**\n * 玩家错误信息\n */\n PlayerError = \"player.error\",\n /**\n * 全局消息\n */\n GlobalMessage = \"global.message\",\n /**\n * 全局命令\n */\n GlobalCommand = \"global.command\",\n}\n\n/**\n * 客户端发送消息包类型枚举\n * player: 'command', 'message', 'join', 'leave', 'status'\n */\nexport enum RecvMessageTypes {\n /**\n * 房间列表\n */\n RoomList = \"room.list\",\n /**\n * 玩家列表\n */\n PlayerList = \"player.list\",\n /**\n * 房间创建\n */\n RoomCreate = \"room.create\",\n /**\n * 玩家加入房间\n */\n PlayerJoin = \"player.join\",\n /**\n * 玩家离开房间\n */\n PlayerLeave = \"player.leave\",\n /**\n * 玩家离开座位\n */\n PlayerStandUp = \"player.standup\",\n /**\n * 房间获取\n */\n RoomGet = \"room.get\",\n /**\n * 房间开始\n */\n RoomStart = \"room.start\",\n /**\n * 房间踢出玩家\n */\n RoomKick = \"room.kick\",\n /**\n * 房间转移\n */\n RoomTransfer = \"room.transfer\",\n /**\n * 房间关闭\n */\n RoomClose = \"room.close\", \n /**\n * 玩家登录\n */\n PlayerLogin = \"player.login\",\n /**\n * 玩家登出\n */\n PlayerLogout = \"player.logout\",\n /**\n * 玩家准备\n */\n PlayerReady = \"player.ready\",\n /**\n * 玩家取消准备\n */\n PlayerUnready = \"player.unready\",\n /**\n * 房间内玩家发送的指令\n */\n RoomPlayerCommand = \"room.player-command\",\n /**\n * 全局命令\n */\n GlobalCommand = \"global.command\",\n}\n\n/**\n * 消息包接口\n */\nexport interface IMessagePackage {\n /**\n * 消息类型\n */\n type: MessageTypes;\n /**\n * 消息数据\n */\n data?: IPlayerOptions | IRoomOptions | IPlayer | IRoom | IRoomPlayer | any\n /**\n * 发送者信息\n */\n sender?: IPlayer | IRoomPlayer | IRoom;\n}\n\n/**\n * 消息数据接口,包含发送者信息\n */\nexport interface IMessageData extends IMessagePackage {\n sender: IPlayer | IRoomPlayer | IRoom;\n}\n\n/**\n * 消息通信接口\n */\nexport interface IMessage extends EventEmitter<IMessageEmitterEvents> {\n /**\n * 监听消息事件\n * @param event 事件名,具体见 MessageEvents\n * @param listener 监听器\n */\n on<K extends keyof IMessageEvents>(event: K, listener: IMessageEvents[K]): this;\n /**\n * 触发消息事件\n * @param event 事件名,具体见 MessageEvents\n * @param args 参数\n */\n emit<K extends keyof IMessageEvents>(event: K, ...args: Parameters<IMessageEvents[K]>): boolean;\n /**\n * 关闭连接\n */\n close(): void;\n /**\n * 发送消息包\n * @param message 消息包\n */\n send(message: IMessagePackage): void;\n}\n","import { PlayerEvents } from \"@lib/events/player\";\nimport EventEmitter from \"events\";\n\n/**\n * 玩家选项接口\n */\nexport interface IPlayerOptions {\n /**\n * 玩家ID\n */\n id: string;\n /**\n * 玩家名称\n */\n name: string;\n /**\n * 玩家属性\n */\n attributes?: any;\n /**\n * 发送者函数\n */\n sender?: (type: string, ...message: any) => void;\n /**\n * 是否超级管理员\n */\n isAdmin?: boolean;\n}\n\n/**\n * 玩家状态枚举\n */\nexport enum PlayerStatus {\n /**\n * 已准备\n */\n ready = 'ready',\n /**\n * 未准备\n */\n unready = 'unready',\n /**\n * 在线\n */\n online = 'online',\n /**\n * 游戏中\n */\n playing = 'playing',\n}\n\n/**\n * 玩家接口\n */\nexport interface IPlayer extends IPlayerOptions {\n /**\n * 玩家状态\n */\n status: PlayerStatus;\n}\n\n/**\n * 玩家\n */\nexport class Player extends EventEmitter implements IPlayer {\n /**\n * 监听玩家事件\n * @param event 事件名,具体见 PlayEvents\n * @param listener 监听器\n * @returns this\n */\n on<K extends keyof PlayerEvents>(event: K, listener: PlayerEvents[K]): this {\n return super.on(event, listener);\n }\n\n /**\n * 触发玩家事件\n * @param event 事件名,具体见 PlayEvents\n * @param args 参数\n * @returns 是否有监听器被触发\n */\n emit<K extends keyof PlayerEvents>(event: K, ...args: Parameters<PlayerEvents[K]>): boolean {\n return super.emit(event, ...args);\n }\n \n id: string = \"\";\n name: string = \"\";\n attributes?: any;\n status: PlayerStatus = PlayerStatus.online;\n sender?: (type: string, ...message: any) => void;\n isAdmin: boolean = false;\n\n constructor(player: Partial<IPlayerOptions> | Player, status: PlayerStatus = PlayerStatus.online) {\n super();\n this.id = player.id || new Date().getTime().toString();\n this.name = player.name || \"\";\n this.attributes = player.attributes || {};\n this.sender = player.sender;\n\n if (player instanceof Player) this.status = player.status;\n\n this.status = status;\n\n this.on('status', (status: PlayerStatus) => {\n this.status = status;\n });\n \n const events: Array<keyof PlayerEvents> = ['command', 'message', 'status'];\n events.forEach((event) => {\n this.on(event, (...data: any) => {\n this.sender?.(event, ...data);\n });\n }); \n }\n\n toJSON() {\n return {\n id: this.id,\n name: this.name,\n attributes: this.attributes,\n status: this.status,\n isAdmin: this.isAdmin,\n };\n }\n\n toString() {\n return JSON.stringify(this.toJSON());\n }\n\n /**\n * 设置发送者函数\n * @param {(type: string, ...message: any) => void} sender 发送者函数\n * @returns this\n */\n setSender(sender: (type: string, ...message: any) => void) {\n this.sender = sender;\n return this;\n }\n}","import { IPlayer, Player, IPlayerOptions, PlayerStatus } from \"./player\";\nimport EventEmitter from \"events\";\nimport { RoomEvents } from \"@lib/events\";\n\n/**\n * 房间选项接口\n */\nexport interface IRoomOptions {\n /**\n * 房间号\n */\n id: string, \n /**\n * 房间名称\n */\n name: string,\n /**\n * 房间容量\n */\n size: number, \n /**\n * 最小容量\n */\n minSize: number,\n /**\n * 其他属性\n */\n attrs?: Record<string, any>,\n}\n\n/**\n * 房间玩家角色\n */\nexport enum PlayerRole {\n /**\n * 玩家\n */\n player = 'player',\n /**\n * 观众\n */\n watcher = 'watcher',\n /**\n * 管理员\n */\n admin = 'admin',\n}\n\n/**\n * 房间状态\n */\nexport enum RoomStatus {\n /**\n * 等待中\n */\n waiting = 'waiting',\n /**\n * 已准备\n */\n ready = 'ready',\n /**\n * 游戏中\n */\n playing = 'playing',\n}\n\n/**\n * 房间接口\n */\nexport interface IRoom extends IRoomOptions {\n /**\n * 房间玩家列表\n */\n players: RoomPlayer[];\n}\n\n/**\n * 房间玩家选项接口\n */\nexport interface IRoomPlayerOptions extends IPlayerOptions {\n /**\n * 房间Id\n */\n roomId?: string;\n}\n\n/**\n * 房间玩家接口\n */\nexport interface IRoomPlayer extends IRoomPlayerOptions, IPlayer {\n /**\n * 是否已准备\n */\n isReady: boolean;\n /**\n * 玩家角色\n */\n role: PlayerRole;\n /**\n * 是否为房主\n */\n isCreator: boolean;\n /**\n * 房间 Id\n */\n roomId: string;\n}\n\n/**\n * 房间玩家\n */\nexport class RoomPlayer extends Player implements IRoomPlayer {\n isReady: boolean = false;\n role: PlayerRole = PlayerRole.player;\n isCreator: boolean = false;\n roomId: string;\n\n constructor(player: Partial<IRoomPlayer>, role: PlayerRole = PlayerRole.player) {\n super(player);\n this.isReady = player.isReady || false;\n this.isCreator = player.isCreator || false;\n this.roomId = player.roomId || '';\n this.role = player.role || role;\n this.status = player.status || PlayerStatus.online;\n if (player instanceof Player && player.sender) super.setSender(player.sender);\n }\n\n toJSON() {\n return {\n ...super.toJSON(),\n role: this.role,\n isReady: this.isReady,\n isCreator: this.isCreator,\n };\n }\n}\n\n/**\n * 房间\n */\nexport class Room extends EventEmitter implements IRoom {\n /**\n * 监听房间事件\n * @param event 事件名,具体见 RoomEvents\n * @param listener 监听器\n * @returns this\n */\n on<K extends keyof RoomEvents>(event: K, listener: RoomEvents[K]): this {\n return super.on(event, listener);\n }\n\n /**\n * 触发房间事件\n * @param event 事件名,具体见 RoomEvents\n * @param args 参数\n * @returns 是否有监听器被触发\n */\n emit<K extends keyof RoomEvents>(event: K, ...args: Parameters<RoomEvents[K]>): boolean {\n return super.emit(event, ...args);\n }\n\n id: string;\n size: number = 10;\n name: string = '';\n minSize: number = 2;\n attrs?: Record<string, any>;\n players: RoomPlayer[] = [];\n\n /**\n * 有效玩家列表(非观众)\n */\n get validPlayers() {\n return this.players.filter((player) => player.role === PlayerRole.player);\n }\n\n /**\n * 观众列表\n */\n get watchers() {\n return this.players.filter((player) => player.role === PlayerRole.watcher);\n }\n\n /**\n * 消息发送器\n */\n private sender?: (type: string, ...message: any) => void;\n\n /**\n * 房间玩家是否已准备好\n */\n get isReady(): boolean {\n return this.players.length >= this.minSize\n && this.players.every((target) => target.isReady || target.role === PlayerRole.watcher); // is all player ready\n }\n\n /**\n * 房间状态\n */\n get status(): RoomStatus {\n if (!this.isReady) return RoomStatus.waiting;\n if (this.players.findIndex((target) => target.status === PlayerStatus.playing) != -1) return RoomStatus.playing;\n return RoomStatus.ready;\n }\n\n /**\n * 房间是否在游戏中\n */\n get isPlaying(): boolean {\n return this.status === RoomStatus.playing;\n }\n\n /**\n * 房间是否已满\n */\n get isFull(): boolean {\n return this.validPlayers.length == this.size;\n }\n\n /**\n * 房主\n */\n get owner(): RoomPlayer | undefined {\n const creator = this.players.find((player) => player.isCreator);\n return creator;\n }\n\n toJSON() {\n return {\n id: this.id,\n name: this.name,\n size: this.size || 10,\n minSize: this.minSize,\n status: this.status,\n players: this.players.map((player) => player.toJSON()),\n attrs: this.attrs,\n }\n }\n\n toString() {\n return JSON.stringify(this.toJSON());\n }\n\n constructor(room: Partial<IRoomOptions> | Room, players: RoomPlayer[] = []) {\n super();\n if (room instanceof Room) {\n this.players = room.players;\n this.players.forEach((p) => {\n p.roomId = room.id;\n });\n }\n\n this.id = room.id || new Date().getTime().toString();\n this.name = room.name || '';\n this.size = room.size || 10;\n this.minSize = room.minSize || 2;\n this.attrs = room.attrs;\n this.players = players;\n \n const events: Array<keyof RoomEvents> = ['message', 'command', 'start', 'end', 'all-ready', 'player-unready', 'player-ready', 'join', 'leave'];\n events.forEach((event) => {\n this.on(event, (...data: any) => {\n this.sender?.(event, ...data);\n });\n });\n }\n\n /**\n * 设置房主\n * @param {Player} player 玩家\n * @returns this\n */\n setCreator(player: Player) {\n const roomPlayer = this.searchPlayer(player);\n if (roomPlayer) {\n this.players.forEach((p) => {\n p.isCreator = false;\n });\n roomPlayer.isCreator = true;\n this.emit(\"update\", this);\n }\n return this;\n }\n\n /**\n * 添加玩家\n * @param {Player} player 玩家\n * @param {boolean} isCreator 是否房主\n * @returns 玩家实例 \n */\n addPlayer(player: Player, isCreator: boolean = false) {\n let roomPlayer = this.searchPlayer(player);\n if (roomPlayer) {\n if (roomPlayer.role === PlayerRole.watcher && !this.isFull && !this.isPlaying) {\n roomPlayer.role = PlayerRole.player;\n roomPlayer.isCreator = isCreator;\n this.emit(\"update\", this);\n }\n return roomPlayer;\n }\n\n if (isCreator) {\n this.players.forEach((p) => {\n p.isCreator = false;\n });\n }\n roomPlayer = new RoomPlayer(player, this.isFull || this.isPlaying ? PlayerRole.watcher : PlayerRole.player);\n roomPlayer.isCreator = isCreator;\n roomPlayer.roomId = this.id;\n this.players.push(roomPlayer);\n this.emit(\"join\", { ...roomPlayer, roomId: this.id });\n \n return roomPlayer;\n }\n\n /**\n * 离开座位\n * @param {string | IPlayer} player 玩家 / 玩家 id\n */\n leaveSeat(playerId: string): RoomPlayer;\n leaveSeat(player: IPlayer): RoomPlayer;\n leaveSeat(player: IPlayer | string) {\n const playerId = typeof player === \"string\" ? player : player.id;\n const roomPlayer = this.searchPlayer(playerId);\n if (roomPlayer && roomPlayer.role === PlayerRole.player) {\n roomPlayer.role = PlayerRole.watcher;\n roomPlayer.isReady = false;\n this.emit(\"leave\", { ...roomPlayer, roomId: this.id });\n if (roomPlayer.isCreator && this.validPlayers.length > 0) {\n this.validPlayers[0].isCreator = true;\n this.emit(\"update\", this);\n }\n }\n return roomPlayer!;\n }\n\n /**\n * 踢出玩家\n * @param {string | IPlayer} player 玩家 / 玩家 id\n */\n kickPlayer(playerId: string): RoomPlayer;\n kickPlayer(player: IPlayer): RoomPlayer;\n kickPlayer(player: IPlayer | string) {\n const playerId = typeof player === \"string\" ? player : player.id;\n const index = this.players.findIndex((p) => p.id == playerId);\n const roomPlayer = this.players[index];\n if (index > -1) {\n this.emit(\"leave\", { ...roomPlayer, roomId: this.id });\n this.players.splice(index, 1);\n if (roomPlayer.isCreator && this.players.length > 0) {\n this.players[0].isCreator = true;\n this.emit(\"update\", this);\n }\n }\n return roomPlayer;\n }\n\n /**\n * 搜索玩家\n * @param {string | IPlayer} player 玩家 / 玩家 id\n */\n searchPlayer(playerId: string): RoomPlayer | undefined;\n searchPlayer(player: IPlayer): RoomPlayer | undefined;\n searchPlayer(player: string | IPlayer) {\n const playerId = typeof player === \"string\" ? player : player?.id;\n return this.players.find((player) => player.id == playerId);\n }\n\n /**\n * 开始游戏\n */\n start(sender: IPlayer) {\n if (!this.isReady) {\n throw new Error('room is not ready.');\n }\n if (this.status === RoomStatus.playing) {\n throw new Error('room is already started.');\n }\n this.players.forEach((player) => {\n if (player.role != PlayerRole.player) return;\n player.emit('status', PlayerStatus.playing);\n });\n this.emit(\"update\", this);\n return this.emit(\"start\", this);\n }\n\n /**\n * 结束游戏\n */\n end() {\n this.players.forEach((player) => {\n if (player.role != PlayerRole.player) return;\n player.emit('status', PlayerStatus.unready);\n });\n this.emit(\"update\", this);\n return this.emit(\"end\", this);\n }\n\n /**\n * 设置消息发送器\n * @param sender 消息发送器\n */\n setSender(sender: (type: string, ...message: any) => void) {\n this.sender = sender;\n return this;\n }\n}\n","import { IRoomOptions, PlayerRole, RoomStatus, PlayerStatus, RecvMessageTypes as MessageTypes } from \"@lib/index\";\nexport { RoomStatus, PlayerStatus, PlayerRole, MessageTypes };\nexport type { IRoomOptions };\n\nexport 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 error 错误信息\n */\n \"global.error\": (error: Error) => void;\n /**\n * 全局命令事件\n * @param data 命令内容\n */\n \"global.command\": (data: any & { sender: Player }) => void;\n /**\n * 全局消息事件\n * @param message 消息内容\n */\n \"global.message\": (message: string, 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\": (status: PlayerStatus) => 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: { content: string, sender?: Player }) => void;\n /**\n * 玩家错误事件\n */\n \"player.error\": (error: Error) => 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\": (player: RoomPlayer & { roomId: string }) => void;\n /**\n * 玩家离开房间事件\n * @param room 房间信息\n * @param player 玩家信息\n */\n \"room.leave\": (player: RoomPlayer & { roomId: string }) => 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: { content: string; sender?: RoomPlayer }) => void;\n /**\n * 房间玩家准备事件\n * @param player 玩家信息\n * @param roomId 房间ID(可选)\n */\n \"room.player-ready\": (player: RoomPlayer) => void;\n /**\n * 房间玩家取消准备事件\n * @param player 玩家信息\n * @param roomId 房间ID(可选)\n */\n \"room.player-unready\": (player: RoomPlayer) => 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: PlayerStatus;\n isAdmin: boolean;\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 || PlayerStatus.online;\n this.isAdmin = player.isAdmin || false;\n }\n}\n\nexport class RoomPlayer extends Player {\n role: PlayerRole;\n isReady: boolean;\n isCreator: boolean;\n roomId: string;\n constructor(player: RoomPlayer) {\n super(player);\n this.role = player.role;\n this.isReady = player.isReady;\n this.isCreator = player.isCreator;\n this.roomId = player.roomId;\n }\n}\n\nexport class Room {\n id: string;\n name: string;\n players: RoomPlayer[];\n size: number;\n minSize: number;\n status: RoomStatus;\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: MessageTypes.RoomList });\n this.send({ type: MessageTypes.PlayerList });\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 = this.players.filter(p => p.id !== player.id);\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: MessageTypes, 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: MessageTypes.PlayerLogin, 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 }: Omit<IRoomOptions, 'id'>) {\n return new Promise<void>((resolve) => {\n this.send({ type: MessageTypes.RoomCreate, 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 * @param {object} params 加入参数\n */\n joinRoom(roomId: string, params?: any) {\n this.send({ type: MessageTypes.PlayerJoin, data: { roomId, params } });\n return this;\n }\n\n /**\n * 离开房间\n * @param {string} roomId 房间ID\n * @param {object} params 离开参数\n */\n leaveRoom(roomId: string, params?: any) {\n this.send({ type: MessageTypes.PlayerLeave, data: { roomId, params } });\n return this;\n }\n\n /**\n * 离开座位\n * @param {string} roomId 房间ID\n * @param {object} params 离开参数\n */\n leaveSeat(roomId: string, params?: any) {\n this.send({ type: MessageTypes.PlayerStandUp, data: { roomId, params } });\n return this;\n }\n\n /**\n * 踢出玩家\n * @param {string} roomId 房间ID\n * @param {string} playerId 玩家ID\n * @param {object} params 额外参数\n */\n kickPlayer(roomId: string, playerId: string, params?: any) {\n this.send({ type: MessageTypes.RoomKick, data: { roomId, playerId, params } });\n return this;\n }\n\n /**\n * 转让房主\n * @param {string} roomId 房间ID\n * @param {string} playerId 目标玩家ID\n * @param {object} params 额外参数\n */\n transferRoom(roomId: string, playerId: string, params?: any) {\n this.send({ type: MessageTypes.RoomTransfer, data: { roomId, playerId, params } });\n return this;\n }\n\n /**\n * 关闭房间\n * @param {string} roomId 房间ID\n * @param {object} params 额外参数\n * @returns \n */\n closeRoom(roomId: string, params?: any) {\n this.send({ type: MessageTypes.RoomClose, data: { roomId, params } });\n return this;\n }\n\n /**\n * 开始游戏\n * @param {string} id 房间ID\n */\n startGame(id: string, params?: any) {\n this.send({ type: MessageTypes.RoomStart, data: { id, params } });\n return this;\n }\n\n /**\n * 准备/取消准备\n * @param {string} roomId 房间ID\n * @param {boolean} isReady 是否准备\n */\n ready(roomId: string, isReady=true, params?: any) {\n this.send({ type: isReady ? MessageTypes.PlayerReady : MessageTypes.PlayerUnready, data: { roomId, params } });\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: MessageTypes.GlobalCommand, data: command });\n } else {\n this.send({ type: MessageTypes.RoomPlayerCommand, data: { id: roomId, ...command } });\n }\n return this;\n }\n\n /**\n * 连接准备监听\n * @param {function} cb 监听函数\n */\n onReady(cb: () => void) {\n return this.on(\"sys.ready\", cb);\n }\n\n /**\n * 全局错误监听\n * @param {function} cb 监听函数\n */\n onError(cb: (error: Error) => void) {\n this.on(\"global.error\", cb);\n return this;\n }\n\n /**\n * 全局消息监听\n * @param {function} cb 监听函数\n */\n onMessage(cb: (message: string, sender?: Player) => void, on=true) {\n if (on) this.on(\"global.message\", cb);\n else this.off(\"global.message\", cb);\n return this;\n }\n\n /**\n * 玩家列表变更监听\n * @param {function} cb 监听函数\n */\n onPlayerList(cb: (players: Player[]) => 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: (rooms: Room[]) => 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: (player: RoomPlayer) => 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: (player: RoomPlayer) => 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: (player: RoomPlayer) => 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: (player: RoomPlayer) => 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: (status: PlayerStatus) => 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: (room: Room) => 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: (room: Room) => 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: (room: Room) => 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: (message: { content: string, sender?: RoomPlayer }) => 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: (message: { content: string, sender?: Player }) => 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: (command: any & { sender?: Player }) => 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: (command: any & { sender?: Player }) => 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 {TiaoomEvents[K]} 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 {TiaoomEvents[K]} 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 {Parameters<TiaoomEvents[K]>} 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
- let e=function(e){return e.RoomList=`room.list`,e.PlayerList=`player.list`,e.RoomCreate=`room.create`,e.PlayerJoin=`player.join`,e.PlayerLeave=`player.leave`,e.PlayerStandUp=`player.standup`,e.RoomGet=`room.get`,e.RoomStart=`room.start`,e.RoomKick=`room.kick`,e.RoomTransfer=`room.transfer`,e.RoomClose=`room.close`,e.PlayerLogin=`player.login`,e.PlayerLogout=`player.logout`,e.PlayerReady=`player.ready`,e.PlayerUnready=`player.unready`,e.RoomPlayerCommand=`room.player-command`,e.GlobalCommand=`global.command`,e}({}),t=function(e){return e.ready=`ready`,e.unready=`unready`,e.online=`online`,e.playing=`playing`,e}({}),n=function(e){return e.player=`player`,e.watcher=`watcher`,e.admin=`admin`,e}({}),r=function(e){return e.waiting=`waiting`,e.ready=`ready`,e.playing=`playing`,e}({});var i=class{constructor(e){this.id=e.id||Date.now().toString(),this.name=e.name||`玩家`+this.id,this.attributes=e.attributes||{},this.status=e.status||t.online,this.isAdmin=e.isAdmin||!1}},a=class extends i{constructor(e){super(e),this.role=e.role,this.isReady=e.isReady,this.isCreator=e.isCreator,this.roomId=e.roomId}},o=class{constructor(e){this.id=e.id,this.name=e.name,this.players=e.players.map(e=>new a(e)),this.size=e.size,this.minSize=e.minSize,this.status=e.status,this.attrs=e.attrs}},s=class{constructor(){this.listeners={},this.rooms=[],this.players=[],this.currentPlayer=null}run(){return this.connect(),this.onReady(()=>{this.send({type:e.RoomList}),this.send({type:e.PlayerList})}),this.on(`player.list`,e=>{this.players=e.map(e=>new i(e)),this.emit(`onPlayerList`,[...this.players])}),this.on(`player.login`,e=>{this.players.push(new i(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 o(e)),this.emit(`onRoomList`,[...this.rooms])}),this.on(`room.create`,e=>{this.rooms.push(new o(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 o(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 i(t),this.send({type:e.PlayerLogin,data:t}),this}createRoom({name:t,size:n,minSize:r,attrs:i}){return new Promise(a=>{this.send({type:e.RoomCreate,data:{name:t,size:n,minSize:r,attrs:i}}),this.on(`room.create`,e=>{a()})})}joinRoom(t,n){return this.send({type:e.PlayerJoin,data:{roomId:t,params:n}}),this}leaveRoom(t,n){return this.send({type:e.PlayerLeave,data:{roomId:t,params:n}}),this}leaveSeat(t,n){return this.send({type:e.PlayerStandUp,data:{roomId:t,params:n}}),this}kickPlayer(t,n,r){return this.send({type:e.RoomKick,data:{roomId:t,playerId:n,params:r}}),this}transferRoom(t,n,r){return this.send({type:e.RoomTransfer,data:{roomId:t,playerId:n,params:r}}),this}closeRoom(t,n){return this.send({type:e.RoomClose,data:{roomId:t,params:n}}),this}startGame(t,n){return this.send({type:e.RoomStart,data:{id:t,params:n}}),this}ready(t,n=!0,r){return this.send({type:n?e.PlayerReady:e.PlayerUnready,data:{roomId:t,params:r}}),this}command(t,n){return typeof t==`string`?this.send({type:e.RoomPlayerCommand,data:{id:t,...n}}):(n=t,this.send({type:e.GlobalCommand,data:n})),this}onReady(e){return this.on(`sys.ready`,e)}onError(e){return this.on(`global.error`,e),this}onMessage(e,t=!0){return t?this.on(`global.message`,e):this.off(`global.message`,e),this}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 o(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 o(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 o(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 MessageTypes,i as Player,n as PlayerRole,t as PlayerStatus,o as Room,a as RoomPlayer,r as RoomStatus,s as Tiaoom};
1
+ let e=function(e){return e.RoomList=`room.list`,e.PlayerList=`player.list`,e.RoomCreate=`room.create`,e.PlayerJoin=`player.join`,e.PlayerLeave=`player.leave`,e.PlayerStandUp=`player.standup`,e.RoomGet=`room.get`,e.RoomStart=`room.start`,e.RoomKick=`room.kick`,e.RoomTransfer=`room.transfer`,e.RoomClose=`room.close`,e.PlayerLogin=`player.login`,e.PlayerLogout=`player.logout`,e.PlayerReady=`player.ready`,e.PlayerUnready=`player.unready`,e.RoomPlayerCommand=`room.player-command`,e.GlobalCommand=`global.command`,e}({}),t=function(e){return e.ready=`ready`,e.unready=`unready`,e.online=`online`,e.playing=`playing`,e}({}),n=function(e){return e.player=`player`,e.watcher=`watcher`,e.admin=`admin`,e}({}),r=function(e){return e.waiting=`waiting`,e.ready=`ready`,e.playing=`playing`,e}({});var i=class{constructor(e){this.id=e.id||Date.now().toString(),this.name=e.name||`玩家`+this.id,this.attributes=e.attributes||{},this.status=e.status||t.online,this.isAdmin=e.isAdmin||!1}},a=class extends i{constructor(e){super(e),this.role=e.role,this.isReady=e.isReady,this.isCreator=e.isCreator,this.roomId=e.roomId}},o=class{constructor(e){this.id=e.id,this.name=e.name,this.players=e.players.map(e=>new a(e)),this.size=e.size,this.minSize=e.minSize,this.status=e.status,this.attrs=e.attrs}},s=class{constructor(){this.listeners={},this.rooms=[],this.players=[],this.currentPlayer=null}run(){return this.connect(),this.onReady(()=>{this.send({type:e.RoomList}),this.send({type:e.PlayerList})}),this.on(`player.list`,e=>{this.players=e.map(e=>new i(e)),this.emit(`onPlayerList`,[...this.players])}),this.on(`player.login`,e=>{this.players=this.players.filter(t=>t.id!==e.id),this.players.push(new i(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 o(e)),this.emit(`onRoomList`,[...this.rooms])}),this.on(`room.create`,e=>{this.rooms.push(new o(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 o(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 i(t),this.send({type:e.PlayerLogin,data:t}),this}createRoom({name:t,size:n,minSize:r,attrs:i}){return new Promise(a=>{this.send({type:e.RoomCreate,data:{name:t,size:n,minSize:r,attrs:i}}),this.on(`room.create`,e=>{a()})})}joinRoom(t,n){return this.send({type:e.PlayerJoin,data:{roomId:t,params:n}}),this}leaveRoom(t,n){return this.send({type:e.PlayerLeave,data:{roomId:t,params:n}}),this}leaveSeat(t,n){return this.send({type:e.PlayerStandUp,data:{roomId:t,params:n}}),this}kickPlayer(t,n,r){return this.send({type:e.RoomKick,data:{roomId:t,playerId:n,params:r}}),this}transferRoom(t,n,r){return this.send({type:e.RoomTransfer,data:{roomId:t,playerId:n,params:r}}),this}closeRoom(t,n){return this.send({type:e.RoomClose,data:{roomId:t,params:n}}),this}startGame(t,n){return this.send({type:e.RoomStart,data:{id:t,params:n}}),this}ready(t,n=!0,r){return this.send({type:n?e.PlayerReady:e.PlayerUnready,data:{roomId:t,params:r}}),this}command(t,n){return typeof t==`string`?this.send({type:e.RoomPlayerCommand,data:{id:t,...n}}):(n=t,this.send({type:e.GlobalCommand,data:n})),this}onReady(e){return this.on(`sys.ready`,e)}onError(e){return this.on(`global.error`,e),this}onMessage(e,t=!0){return t?this.on(`global.message`,e):this.off(`global.message`,e),this}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 o(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 o(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 o(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 MessageTypes,i as Player,n as PlayerRole,t as PlayerStatus,o as Room,a as RoomPlayer,r as RoomStatus,s as Tiaoom};
2
2
  //# sourceMappingURL=client.mjs.map