diff --git a/packages/backend/src/core/GlobalEventService.ts b/packages/backend/src/core/GlobalEventService.ts index 896149f238..e599912e2b 100644 --- a/packages/backend/src/core/GlobalEventService.ts +++ b/packages/backend/src/core/GlobalEventService.ts @@ -181,8 +181,8 @@ export interface ReversiGameEventTypes { value: any; }; log: Reversi.Serializer.Log & { id: string | null }; - syncState: { - crc32: string; + heatbeat: { + userId: MiUser['id']; }; started: { game: Packed<'ReversiGameDetailed'>; diff --git a/packages/backend/src/core/ReversiService.ts b/packages/backend/src/core/ReversiService.ts index 9fe7255e48..e626cbaf19 100644 --- a/packages/backend/src/core/ReversiService.ts +++ b/packages/backend/src/core/ReversiService.ts @@ -405,6 +405,11 @@ export class ReversiService implements OnApplicationShutdown, OnModuleInit { return this.reversiGamesRepository.findOneBy({ id }); } + @bindThis + public async heatbeat(game: MiReversiGame, user: MiUser) { + this.globalEventService.publishReversiGameStream(game.id, 'heatbeat', { userId: user.id }); + } + @bindThis public dispose(): void { } diff --git a/packages/backend/src/server/api/stream/channels/reversi-game.ts b/packages/backend/src/server/api/stream/channels/reversi-game.ts index 2d8c396db9..c5d05e5cfb 100644 --- a/packages/backend/src/server/api/stream/channels/reversi-game.ts +++ b/packages/backend/src/server/api/stream/channels/reversi-game.ts @@ -46,7 +46,7 @@ class ReversiGameChannel extends Channel { case 'ready': this.ready(body); break; case 'updateSettings': this.updateSettings(body.key, body.value); break; case 'putStone': this.putStone(body.pos, body.id); break; - case 'syncState': this.syncState(body.crc32); break; + case 'heatbeat': this.heatbeat(body.crc32); break; } } @@ -83,15 +83,21 @@ class ReversiGameChannel extends Channel { } @bindThis - private async syncState(crc32: string | number) { + private async heatbeat(crc32?: string | number | null) { // TODO: キャッシュしたい const game = await this.reversiGamesRepository.findOneBy({ id: this.gameId! }); if (game == null) throw new Error('game not found'); if (!game.isStarted) return; - if (crc32.toString() !== game.crc32) { - this.send('rescue', await this.reversiGameEntityService.packDetail(game, this.user)); + if (crc32 != null) { + if (crc32.toString() !== game.crc32) { + this.send('rescue', await this.reversiGameEntityService.packDetail(game, this.user)); + } + } + + if (this.user && (game.user1Id === this.user.id || game.user2Id === this.user.id)) { + this.reversiService.heatbeat(game, this.user); } } diff --git a/packages/frontend/src/pages/reversi/game.board.vue b/packages/frontend/src/pages/reversi/game.board.vue index 3a24777db8..2f09cf39e8 100644 --- a/packages/frontend/src/pages/reversi/game.board.vue +++ b/packages/frontend/src/pages/reversi/game.board.vue @@ -22,7 +22,7 @@ SPDX-License-Identifier: AGPL-3.0-only
-
{{ i18n.ts._reversi.opponentTurn }}
+
{{ i18n.ts._reversi.opponentTurn }}({{ i18n.ts.notResponding }})
{{ i18n.ts._reversi.myTurn }}