diff --git a/@sammo/server/src/GameEngine.ts b/@sammo/server/src/GameEngine.ts index ee5c706..4bde7e5 100644 --- a/@sammo/server/src/GameEngine.ts +++ b/@sammo/server/src/GameEngine.ts @@ -55,9 +55,94 @@ export class GameEngine { private continueRun = true; + private prevSaveWaiter: Promise | null = null; + + + private async processGeneralTurn() { + const now = new Date(); + + let processedGeneralCount = 0; + + while (true) { + //장수턴 부터 처리 + const upcomingGeneral = this.rsc.popGeneralTurntimeQueue(); + if (!upcomingGeneral) { + break; + } + + const generalTurntime = upcomingGeneral.raw.turntime; + if (generalTurntime > now) { + break; + } + + //TODO: 턴 수행해야지! + + upcomingGeneral.updateTurntime(); + this.rsc.insertGeneralTurntimeQueue(upcomingGeneral, true); + this.rsc.gameEnv().update((env) => { + env.lastExecuted = generalTurntime; + }) + processedGeneralCount++; + } + + if (processedGeneralCount > 0) { + await this.prevSaveWaiter; + const lastExecuted = this.rsc.gameEnv().raw.lastExecuted; + this.prevSaveWaiter = this.rsc.saveAll().then(() => { + this.postStatus({ + type: 'update', + lastExecuted: lastExecuted.toISOString() + }); + }); + } + } + + private async processActions() { + //서버 이벤트 처리 + for (const [invoker, queue] of entriesWithType(this.actionQueue)) { + let processEventCount = 0; + + let responseQueue: (() => void)[] = []; + + while (!queue.isEmpty()) { + const action = must(queue.shift()); + + //TODO: action 처리 + const errorReason: string | undefined = undefined; + + const [ticketResolve, ticketRejected] = must_err( + this.queueWaiters.get(action.waiterSeq), + Error, `GameEngine: waiterSeq(${action.waiterSeq}) not found` + ); + + this.queueWaiters.delete(action.waiterSeq); + if (errorReason) { + responseQueue.push(() => { + ticketRejected(errorReason); + }); + } + else { + responseQueue.push(() => { + ticketResolve({ success: true }); + }); + } + + processEventCount++; + } + + if (processEventCount > 0) { + await this.prevSaveWaiter; + this.prevSaveWaiter = null; + await this.rsc.saveAll(); + for (const response of responseQueue) { + response(); + } + } + } + } + private async gameLoop(): Promise { let generalWaitTimer: ReturnType | null = null; - let prevSaveWaiter: Promise | null = null; while (this.continueRun) { //가장 빠른 장수 @@ -81,8 +166,8 @@ export class GameEngine { } } while (0); - for(const queue of Object.values(this.actionQueue)){ - if(!queue.isEmpty()){ + for (const queue of Object.values(this.actionQueue)) { + if (!queue.isEmpty()) { this.signal.notify(); break; } @@ -98,91 +183,17 @@ export class GameEngine { break; } - const now = new Date(); + await this.processGeneralTurn(); - let processedGeneralCount = 0; + await this.processActions(); - while (true) { - //장수턴 부터 처리 - const upcomingGeneral = this.rsc.popGeneralTurntimeQueue(); - if (!upcomingGeneral) { - break; - } - - const generalTurntime = upcomingGeneral.raw.turntime; - if (generalTurntime > now) { - break; - } - - //TODO: 턴 수행해야지! - - upcomingGeneral.updateTurntime(); - this.rsc.insertGeneralTurntimeQueue(upcomingGeneral, true); - this.rsc.gameEnv().update((env)=>{ - env.lastExecuted = generalTurntime; - }) - processedGeneralCount++; - } - - if (processedGeneralCount > 0) { - await prevSaveWaiter; - const lastExecuted = this.rsc.gameEnv().raw.lastExecuted; - prevSaveWaiter = this.rsc.saveAll().then(()=>{ - this.postStatus({ - type: 'update', - lastExecuted: lastExecuted.toISOString() - }); - }); - } - - //서버 이벤트 처리 - for (const [invoker, queue] of entriesWithType(this.actionQueue)) { - let processEventCount = 0; - - let responseQueue: (() => void)[] = []; - - while (!queue.isEmpty()) { - const action = must(queue.shift()); - - //TODO: action 처리 - const errorReason: string | undefined = undefined; - - const [ticketResolve, ticketRejected] = must_err( - this.queueWaiters.get(action.waiterSeq), - Error, `GameEngine: waiterSeq(${action.waiterSeq}) not found` - ); - - this.queueWaiters.delete(action.waiterSeq); - if (errorReason) { - responseQueue.push(() => { - ticketRejected(errorReason); - }); - } - else { - responseQueue.push(() => { - ticketResolve({ success: true }); - }); - } - - processEventCount++; - } - - if (processEventCount > 0) { - await prevSaveWaiter; - prevSaveWaiter = null; - await this.rsc.saveAll(); - for (const response of responseQueue) { - response(); - } - } - } } } private gameLoopPromise: Promise | null = null; - public static async initInstance(updateHandler: (msg: GameEngineMsg)=>void): Promise { + public static async initInstance(updateHandler: (msg: GameEngineMsg) => void): Promise { if (GameEngine.instance) { throw new Error('GameEngine is already initialized'); }