diff --git a/src/constants/ClockNameConst.ts b/src/constants/ClockNameConst.ts new file mode 100644 index 0000000..9cf61b1 --- /dev/null +++ b/src/constants/ClockNameConst.ts @@ -0,0 +1,8 @@ +export class ClockNameConst { + /** + * 房间自动关闭 + * @type {string} + */ + public static readonly ROOM_LIFE_CLOCK = 'room_life_clock' + +} diff --git a/src/global.d.ts b/src/global.d.ts index 7b60d3a..aa1cbb0 100644 --- a/src/global.d.ts +++ b/src/global.d.ts @@ -32,6 +32,59 @@ declare module 'colyseus' { * @param data */ bUserReconnect(data?: any): void; + + // >>>>>>>>> End of extend send message <<<<<<<<<<<<< + + // >>>>>>>>> Begin of extend schedule functions <<<<<<<<<<<<< + /** + * 添加一个计时器 + * @param millisecond + * @param handler + * @param name + */ + beginSchedule(millisecond: number, handler: Function, name: string): void; + + /** + * 判断某个定时器是否active + * @param {string} name + * @return {boolean} + */ + scheduleActive(name: string): boolean; + + /** + * 暂停所有激活的定时器 + */ + pauseAllSchedule(): string[]; + + /** + * 恢复所有暂停了的定时器 + */ + resumeAllSchedule(): string[]; + + /** + * 取消某个计时器 + */ + stopSchedule(name: string): number; + + /** + * 暂停某个计时器 + */ + pauseSchedule(name: string): number; + + /** + * 恢复某个计时器 + */ + resumeSchedule(name: string): number; + + /** + * 给某个计时器增加n秒 + * @param name + * @param millisecond + * @param reason + */ + addScheduleTime(millisecond: number, reason?: string, name?: string): void; + + // >>>>>>>>> End of extend schedule functions <<<<<<<<<<<<< } } diff --git a/src/rooms/PuzzleMathRoom.ts b/src/rooms/PuzzleMathRoom.ts index b790295..1bb3161 100644 --- a/src/rooms/PuzzleMathRoom.ts +++ b/src/rooms/PuzzleMathRoom.ts @@ -1,17 +1,20 @@ import { Client, Room } from 'colyseus' import { Dispatcher } from '@colyseus/command' import { IncomingMessage } from 'http' -import { debugRoom, msgLog } from '../common/Debug' +import { debugRoom, error, msgLog } from '../common/Debug' import { OnJoinCommand } from './commands/OnJoinCommand' import { Player } from './schema/Player' import { BeginGameCommand } from './commands/BeginGameCommand' import { PuzzleGameState } from './schema/PuzzleGameState' import { EndGameCommand } from './commands/EndGameCommand' import { GameStateConst } from '../constants/GameStateConst' - +import { Delayed } from '@gamestdio/timer/lib/Delayed' +import { ClockNameConst } from '../constants/ClockNameConst' export class PuzzleMathRoom extends Room { dispatcher = new Dispatcher(this) + // 用于游戏过程中各种计时器, 使用该计时器的前提是, 只针对当前操作玩家 + gameClock: Map = new Map() async onAuth(client: Client, options: any, request: IncomingMessage) { debugRoom(options) @@ -19,13 +22,27 @@ export class PuzzleMathRoom extends Room { return true } onCreate(options: any) { - this.autoDispose = false + let cs = new PuzzleGameState() this.setState(cs) + this.clock.start() this.onMessage('*', (client, type, message) => { msgLog(client.sessionId, 'sent', type, JSON.stringify(message)) }) + /** + * 如果创建房间时, 传入maxTime, 则关闭房间的自动销毁功能, 改为按maxTime来定时销毁 + * 一般这种情况下, game svr端会在业务逻辑处理完后, 调用解散房间的接口, + * 但安全起见, 防止因game svr程序出错而出现僵尸房间的情况 + */ + if ( options.maxTime ) { + this.autoDispose = false + let self = this + this.beginSchedule(options.maxTime * 1000, async function (){ + await self.disconnect() + }.bind(this), ClockNameConst.ROOM_LIFE_CLOCK) + } + } onJoin(client: Client, options: any) { @@ -59,6 +76,10 @@ export class PuzzleMathRoom extends Room { onDispose() { this.dispatcher.stop() + for (let [, clock] of this.gameClock) { + clock.clear() + } + this.gameClock.clear() } /** @@ -134,4 +155,130 @@ export class PuzzleMathRoom extends Room { updateRound(round: number) { this.state.round = round } + + + /** + * 添加一个计时器 + * @param millisecond + * @param handler + * @param name + */ + beginSchedule(millisecond: number, handler: Function, name: string): void { + debugRoom(`begin schedule: `, name, millisecond / 1000) + if (this.gameClock.has(name) && this.gameClock.get(name)?.active) { + error(`当前已存在进行中的gameClock: ${ name }`) + this.gameClock.get(name).clear() + this.gameClock.delete(name) + } + let self = this + let timeOverFun = function () { + handler && handler() + } + this.gameClock.set(name, this.clock.setTimeout(timeOverFun, millisecond, name)) + } + + /** + * 取消某个计时器 + */ + stopSchedule(name: string): number { + debugRoom(`manual stop schedule: ${ name }`) + if (!this.gameClock.has(name)) { + return -1 + } + let clock = this.gameClock.get(name) + if (!clock.active) { + this.gameClock.delete(name) + return -1 + } + let time = clock.elapsedTime + clock.clear() + this.gameClock.delete(name) + return time + } + scheduleActive(name: string): boolean { + return this.gameClock.has(name) && this.gameClock.get(name).active + } + pauseAllSchedule() { + let result: string[] = [] + for (let [name, clock] of this.gameClock) { + if (clock.active) { + result.push(name) + clock.pause() + } + } + return result + } + resumeAllSchedule(): string[] { + let result: string[] = [] + for (let [name, clock] of this.gameClock) { + if (clock.active && clock.paused) { + result.push(name) + clock.resume() + } + } + return result + } + + /** + * 暂停某个计时器, 返回这个机器器的剩余时间 + * @param {string} name + * @return {number} + */ + pauseSchedule(name: string) { + if (!this.gameClock.has(name)) { + return -1 + } + let clock = this.gameClock.get(name) + if (!clock.active) { + return -1 + } + clock.pause() + return clock.elapsedTime + } + + /** + * 恢复某个计时器, 返回这个机器器的剩余时间 + * @param {string} name + * @return {number} + */ + resumeSchedule(name: string) { + if (!this.gameClock.has(name)) { + return -1 + } + let clock = this.gameClock.get(name) + if (!clock.active) { + return -1 + } + clock.resume() + return clock.time - clock.elapsedTime + } + + /** + * 给某个计时器增加n秒 + * @param name + * @param millisecond + * @param reason + */ + addScheduleTime(millisecond: number, reason?: string, name?: string): void { + let current + let currentName = name + if (!name) { + for (let [id, clock] of this.gameClock) { + if (clock.active) { + current = clock + currentName = id + break + } + } + } else { + if (this.gameClock.has(name)) { + current = this.gameClock.get(name) + } + } + debugRoom(`add schedule for ${ currentName }, time: ${ millisecond / 1000 }, reason: ${ reason }`) + if (current) { + current.time += millisecond + debugRoom(`schedule for ${ name } remain: ${ (current.time - current.elapsedTime) / 1000 }`) + } + } }