Skip to content

Feature/in game websocket - #82

Merged
cimura merged 21 commits into
developfrom
feature/in-game-websocket
Jun 29, 2026
Merged

cimura merged 21 commits into
developfrom
feature/in-game-websocket

Conversation

@taka2162

@taka2162 taka2162 commented Jun 27, 2026 •

Copy link
Copy Markdown
Collaborator

概要

フロントエンド単体で動いていたゲームロジックをバックエンド主体で動かし、Server Authoritative な動作を目指しました。

変更内容

新機能

  • WebSocket接続確立時のJWT認証
  • ゲーム開始前のカウントダウン
  • サーバーでのゲームロジック管理(当たり判定、移動処理など)
  • 結果画面でのランキング表示

旧仕様の変更

  • 煙エフェクトを削除(シンプルにするため)
  • ゲーム中のカメラ操作を禁止(移動との連動が複雑になるため)
  • デバッグのため、2人揃ったらゲーム開始(今後はロビーのデータに合わせる)

その他

  • プロジェクトルート+shared/にpackage.jsonを配置、frontend/backendコンテナでshared/の内容を含めてビルドする 1
    • 各Dockerfile/docker-composeの編集(shared/のビルド対応)
    • Makefileの編集(migrateコマンドのワーキングディレクトリ指定)
  • 旧ローカルゲームロジックを削除 2

動作確認方法

ブラウザでウィンドウを2つ用意し確認してください。(シークレットモードなどを使用)

  1. ウィンドウを2つ用意
  2. https://localhost:8443 にアクセス
  3. SignUp画面から新規登録 (アカウント登録をしないとWebSocket通信ができません)
  4. https://localhost:8443/game/1 にアクセス(末尾の数字がroomIdです。ロビーと未接続のため適当な数字を入力すれば入れます)
  5. カウントダウンがスタート
  6. どちらかのウィンドウでキャラを動かすと、もう片方に反映されることを確認
  7. 残り1人 or 相打ち になったら結果画面が表示される

やっていないこと

  • NPCモードの実装
  • frontendでの滑らかな移動処理(60fpsで移動)
  • 共通の定数をshared/へまとめる(ビルド処理が複雑になるため)
  • websocket再接続時の処理(リロードなど)
  • backend主体の時間計測処理(現在はブラウザのタイマーがズレていたら正常に動作しない)
  • 変更したbackendのテスト
  • ログの英語化

※今後別Issueで対応します

その他

シンプルな実装にするために省いた機能がいくつかあります。今後デザインを確立していくときに必要であれば追加していく予定です。
変更差分が大きくなってしまいました🙇

Summary by CodeRabbit

Summary by CodeRabbit

  • 新機能
    • JWT認証付きWebSocketで、ボンバーマンをルーム同期し 参加/入力 を反映
    • カウントダウン表示 と 対戦結果オーバーレイ(勝敗/ランキング)を追加
    • ゲーム画面を ルームID連携の新UI(タッチ/キーボード入力)に刷新
  • 改善
    • 爆発演出の状態反映を整理し 表示更新を安定化
    • 通信のタイムアウトを延長し 切断されにくく
  • その他
    • テスト/ESLint/環境設定 を調整

Footnotes

  1. dockerでfrontend/package.jsonを元にnpm installしたいときは以下のように-wオプションを付けてワーキングディレクトリを指定してください。backendも同様です。
    docker exec -w /app/frontend frontend npm install ↩

  2. 今後ソースを参照するときのためにgit tagを追加しました。
    tag: archive-local-game-logic ↩

@taka2162 taka2162 self-assigned this Jun 27, 2026
@coderabbitai

coderabbitai Bot commented Jun 27, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 72df487a-e839-4fe0-87bf-8eedd61bab34

📥 Commits

Reviewing files that changed from the base of the PR and between 3bd7775 and 378c94d.

📒 Files selected for processing (3)
  • backend/src/game/game.gateway.spec.ts
  • backend/src/game/game.gateway.ts
  • frontend/src/hooks/useGameSocket.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • backend/src/game/game.gateway.spec.ts
  • backend/src/game/game.gateway.ts
  • frontend/src/hooks/useGameSocket.ts

📝 Walkthrough

Walkthrough

共有イベント型とワークスペース設定が追加され、バックエンドは WebSocket ゲートウェイとゲームサービスで試合進行を扱うようになった。フロントエンドはソケット駆動の状態管理、入力、結果表示、描画、プレビューに更新された。実行環境と Docker 設定も monorepo 構成へ調整された。

Changes

ボンバーマン共有契約とゲームフロー移行

Layer / File(s) Summary
共有契約とワークスペース
package.json, shared/package.json, shared/game-events.types.ts, backend/package.json, frontend/package.json, backend/tsconfig.json, Makefile, backend/eslint.config.mjs, docker/backend/Dockerfile, docker/frontend/Dockerfile, docker/docker-compose.yml, docker/nginx/conf/nginx.conf, frontend/vite.config.ts
共有イベント型、ワークスペース定義、依存参照、TypeScript 対象範囲、移行コマンド、Docker、nginx、Vite の実行設定が monorepo 構成に合わせて更新された。
Gateway 認証とイベント配線
backend/src/auth/interfaces/jwt-payload.interface.ts, backend/src/auth/jwt.strategy.ts, backend/src/app.module.ts, backend/src/game/game.module.ts, backend/src/game/game.gateway.ts, backend/src/game/game.gateway.spec.ts, backend/src/game/game.service.spec.ts
JWT ペイロード型が分離され、GameModule/GameGateway がアプリに組み込まれ、接続認証と参加/退出/入力/爆弾イベントが GameService に渡されるようになった。
ゲーム定数とセッション初期化
backend/src/game/constants/game-constants.ts, backend/src/game/game.types.ts, backend/src/game/logic/map.logic.ts, backend/src/game/logic/player.logic.ts, backend/src/game/logic/movement.logic.ts, backend/src/game/logic/bomb.logic.ts
ゲーム定数、セッション型、初期マップ生成、開始位置と色割り当て、移動判定、爆弾設置/爆発処理が追加された。
試合ループと終了判定
backend/src/game/logic/end.logic.ts, backend/src/game/game.service.ts
終了判定、ルーム作成、カウントダウン、ゲームループ、tick 更新、終了処理、ルーム解放が追加された。
クライアント状態と入力
frontend/src/types/game.ts, frontend/src/constants/game-constants.ts, frontend/src/game/bomb-explosion.ts, frontend/src/game/ranking-logic.ts, frontend/src/stores/gameStore.ts, frontend/src/hooks/useInputManager.ts, frontend/src/hooks/useGameInput.ts, frontend/src/hooks/useGamePhaseTransition.ts, frontend/src/hooks/useGameSocket.ts, frontend/src/components/game/TouchControls.tsx, frontend/src/components/game/GameCanvas.tsx, frontend/src/components/game/GameCountdownOverlay.tsx, frontend/src/components/game/GameResultOverlay.tsx, frontend/src/pages/GameRoomPage.tsx, frontend/src/hooks/useLobbySocket.ts
クライアントのゲーム型、ストア、入力送信、ソケット同期、結果表示、カウントダウン表示、ルーム画面の接続が更新された。
描画とプレビュー
frontend/src/components/game/constants/scene-constants.ts, frontend/src/components/game/utils/map-colors.ts, frontend/src/components/game/preview/*, frontend/src/components/game/BombermanCharacter.tsx, frontend/src/components/game/BombermanEffects.tsx, frontend/src/components/game/BombermanScene.tsx, frontend/src/pages/WaitingRoom.tsx, frontend/src/App.css, frontend/src/game/bomberman/BombermanGame.ts, frontend/src/game/bomberman/MockBombermanApi.ts, frontend/src/game/bomberman/bombermanMap.ts, frontend/src/game/bomberman/bombermanRules.ts, frontend/src/game/bomberman/bombermanTypes.ts, frontend/src/game/engine/GameLoop.ts, frontend/src/game/engine/InputManager.ts
シーン定数、破壊可能タイルの色、プレビュー用マップ、レンダリング、待機画面参照、Tailwind 入口と旧ボンバーマン実装の削除が反映された。

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant useInputManager
  participant useGameInput
  participant Socket
  participant GameGateway
  participant GameService
  participant useGameStore
  User->>useInputManager: keydown / keyup / blur
  useInputManager->>useGameInput: emitTouchInput(input)
  useGameInput->>Socket: emit player:input / bomb:place
  Socket->>GameGateway: player:input / bomb:place
  GameGateway->>GameService: handlePlayerInput / handleBombPlace
  GameService-->>Socket: game:init / game:state / bomb:explode / game:end
  Socket-->>useGameStore: state updates
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Possibly related issues

Suggested reviewers

  • rt6500
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 4.76% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed in-game websocket 機能の追加を示しており、変更内容の主軸と一致しています。
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/in-game-websocket

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 20

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
frontend/src/pages/GameRoomPage.tsx (1)

27-50: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

存在しない部屋を仮ルームで埋めないでください。

この PR ではローカルゲーム実装を外しているので、未知の roomId で currentRoom を捏造すると不正な URL でもゲーム画面に進めてしまいます。そのまま game:join も飛ぶため、ここはロビーへ戻すか not-found を表示した方が安全です。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/pages/GameRoomPage.tsx` around lines 27 - 50, The fallback in
GameRoomPage for an unknown roomId should not create a synthetic room object
anymore, since that lets invalid URLs enter the game flow. Update the logic
around the room lookup and setCurrentRoom usage so that when rooms.find(...)
returns nothing, the page redirects back to the lobby or renders a not-found
state instead of populating a fake local room. Keep the real room path unchanged
for valid room matches.
🧹 Nitpick comments (1)
backend/src/game/game.service.spec.ts (1)

15-17: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

このテストでは今回の回帰を拾えません。

定義確認だけだと、追加された game:countdown → game:state → game:end の配線や rankings payload の形が崩れても通ります。少なくとも room 開始/終了時の emit 順序と payload を固定するテストを 1 本入れておくと、この PR の主経路を守れます。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/src/game/game.service.spec.ts` around lines 15 - 17, The current
GameService spec only checks that the service is defined, so it will not catch
regressions in the new event flow. Add a focused test in game.service.spec.ts
around GameService that verifies the room lifecycle emits game:countdown, then
game:state, then game:end in that order, and asserts the rankings payload shape
stays consistent. Use the existing GameService setup/methods to drive start/end
behavior so the main path is covered even if the wiring changes.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@backend/src/game/game.gateway.spec.ts`:
- Around line 1-2: The GameGateway test module is missing required DI mocks,
causing compile() to fail because GameGateway depends on GameService and
JwtService. Update the Test.createTestingModule setup in GameGateway spec to add
both dependencies under providers with mock implementations, and keep the
GameGateway setup aligned with its constructor injection so the test can resolve
successfully.

In `@backend/src/game/game.gateway.ts`:
- Around line 79-80: handleJoin/handleLeave では client.data.roomId
の更新だけでなく、既存の参加状態も必ず解除してください。GameGateway の handleJoin と game:leave の処理で、現在の
roomId がある場合は先に client.leave(previousRoomId) を呼んで旧 room を抜け、その後に
client.data.roomId をクリアまたは新しい roomId に更新するようにしてください。これにより GameGateway の room
切り替え時に古い room の参加状態が残らないようにします。

In `@backend/src/game/game.service.ts`:
- Around line 31-34: In GameService’s room join flow, the current unconditional
addPlayerToRoom call is overwriting active match state for both new joins during
an ongoing phase and re-joins with the same playerId. Update the join logic to
validate the room phase before admitting a player, and if the playerId already
exists, restore the existing player state instead of reinitializing
alive/position/stats. Also adjust removePlayerFromRoom so a disconnected player
cannot be implicitly revived by a later join unless the intended reconnection
path explicitly allows it.
- Around line 69-70: The player input handling in game.service.ts allows stale
`player:input` events to overwrite newer state because `seq` is stored without
any ordering check. Update the input update path in the relevant service method
that writes to `room.playerInputs[playerId]` so it compares the incoming `seq`
against the currently stored sequence for that player and ignores any input with
an equal or lower `seq`; only accept and persist newer inputs to keep
server-authoritative movement from rewinding.
- Around line 124-133: In GameService, the countdown cleanup only runs when
result.isEmpty, so a room that drops below the minimum players during countdown
keeps progressing. Update the player-removal flow in the relevant method around
stopGameLoop() and countdownTimerId handling to also detect when the room falls
under the required player count, clear the countdown timer, stop the game loop,
and roll the room phase back from countdown to the appropriate waiting state so
clients can observe the cancellation.

In `@backend/src/game/logic/bomb.logic.ts`:
- Around line 84-99: The bomb explosion hit check in the room.players loop
currently uses only Math.round(p.position.x/z), so it can disagree with the
player collision logic used elsewhere. Update the affectedTiles.some check in
bomb.logic.ts to evaluate overlap using the same player hitbox/collision size as
movement.logic.ts, rather than the player center point, and keep the
alive/kills/survivalTime updates unchanged.

In `@backend/src/game/logic/player.logic.ts`:
- Around line 16-18: The player spawn logic in player.logic.ts is using
Object.keys(room.players).length in the start-position/color selection path, so
a leaving player can cause the next joiner to reuse an occupied slot. Update the
logic around START_POSITIONS and PLAYER_COLORS to choose the first unused slot
based on existing player assignments rather than current player count, and make
sure the same unique slot is reserved until the player is removed.
- Around line 63-67: The waiting-room disconnect path in player.logic.ts removes
the player from room.players but leaves room.stats[playerId] behind, so stale
entries can later be included by evaluateGameEnd(). Update the disconnect
handling in the same block that deletes room.players/playerInputs to also remove
the matching entry from room.stats for the departing player. Keep the fix
localized around the waiting-state cleanup logic so the rankings data stays
consistent before game start.

In `@docker/backend/Dockerfile`:
- Line 16: The backend container startup path no longer runs Prisma migrations,
so a fresh Compose-up can start the API before the schema is applied. Update the
startup flow in the Docker backend entrypoint, around the CMD in the Dockerfile
and any related start script used by the backend workspace, so migrations run
automatically before `npm run start:dev`. Keep the existing manual Makefile
command as a fallback, but restore an automatic migration step for `prisma
migrate dev` or the equivalent startup migration command.

In `@docker/nginx/conf/nginx.conf`:
- Around line 36-43: Add the same long proxy timeout settings to the Socket.IO
proxy block so `/socket.io/` stays connected during idle periods; update the
`location /socket.io/` section in `nginx.conf` to mirror the timeout behavior
already used for `/api/`, alongside the existing WebSocket headers in that
block.

In `@frontend/src/components/game/BombermanScene.tsx`:
- Around line 208-216: The bomb material selection in BombermanScene is still
using the placeholder ownerId check against 'local-player', so self-owned bombs
are classified incorrectly. Update the bomb rendering logic in the map over
gameState.bombs to compare bomb.ownerId against the real myPlayerId saved by
game:init, and read that value from the store or props instead of the temporary
string. Keep the existing localBombMaterial/enemyBombMaterial branch, but base
it on the actual player ID field used throughout the scene.

In `@frontend/src/hooks/useGameInput.ts`:
- Line 1: The useGameInput hook imports MutableRefObject as a value import, but
with verbatimModuleSyntax enabled this must be a type-only import. Update the
React import in useGameInput so MutableRefObject is brought in via import type,
while keeping useCallback, useRef, and useState as normal imports.

In `@frontend/src/hooks/useGamePhaseTransition.ts`:
- Around line 13-27: The phase transition logic in useGamePhaseTransition is
incorrectly using Date.now() against countdown.startsAt to decide when to switch
to playing, which makes start timing depend on the client clock. Update the hook
so gamePhase changes only from a server-authoritative start signal, or derive
the comparison from the existing server-client time offset captured at
connection time instead of local time. Keep the timer/setGamePhase flow in
useGamePhaseTransition, but base its trigger on synchronized server timing so
useGameInput is gated consistently across clients.

In `@frontend/src/hooks/useGameSocket.ts`:
- Around line 128-140: The cleanup in useGameSocket only resets
gameState-related fields, so gamePhase and countdown from the previous room
persist across unmounts. Update the unmount logic in useEffect to also clear the
state used by GameCountdownOverlay and useGamePhaseTransition, keeping the reset
alongside setGameState, setMyPlayerId, setResultStats, and setErrorMessage so a
fresh session starts from a clean phase/countdown state.
- Around line 16-111: In useGameSocket, the connection/join failure path is
never updating the error UI because setErrorMessage is unused; wire socket
connection/auth/join failure handling into this hook so errors from io() or the
game:join flow set a meaningful errorMessage and switch the game phase to
ended/error state. Use the existing useGameSocket effect and its socket listener
setup/cleanup to add the failure handler, and make sure GameResultOverlay can
receive the ERROR state instead of leaving the screen stalled.

In `@frontend/src/hooks/useInputManager.ts`:
- Around line 24-41: The input state in useInputManager is tracking only
Direction values, which causes duplicate bindings like W and ArrowUp to cancel
each other incorrectly. Update the key handling in
useInputManager/getDirectionFromKey so active presses are tracked by the actual
key code or by per-direction press counts, and only send stop when the last key
for that direction is released. Make sure the pressed/released logic in the
keyboard event handlers uses this new tracking instead of a single
Direction-only set.

In `@frontend/src/hooks/useLobbySocket.ts`:
- Line 6: useLobbySocket の BACKEND_URL フォールバックが同一オリジン前提の Socket.IO
ルーティングを壊しているため、VITE_BACKEND_URL 未設定時は localhost:3000
ではなく現在のオリジンを使うように修正してください。useLobbySocket 内の Socket.IO 接続先決定ロジックで、BACKEND_URL
の既定値をブラウザの同一オリジンに合わせるか、相対パスで /socket.io/ を利用する形に変更し、HTTPS 配信時でも mixed content
にならないようにしてください。

In `@frontend/vite.config.ts`:
- Around line 7-16: The dev server config in Vite is overriding server.host by
setting it twice, which prevents binding beyond localhost. Update the
configuration in vite.config.ts so server.host is set only once to the intended
value for container access, and move the WebSocket-related settings (protocol
and clientPort) under server.ws instead of keeping them at the top level. Use
the existing server config block as the place to separate host handling from the
ws settings.

In `@shared/game-events.types.ts`:
- Around line 89-92: The game:end payload in game-events.types.ts currently uses
rankings as Record<string, PlayerStats>, which loses ordering and leaves result
display dependent on insertion/join order. Update the event contract and the
backend/src/game/logic/end.logic.ts flow so game end results are sent as a
server-sorted ordered list or include an explicit rank field in each entry,
using the existing game:end and room.stats handling as the main points to
change.
- Around line 36-42: `PlayerStats` の shape が shared と backend で重複しているので、shared
側の `PlayerStats` を唯一の定義元にし、backend/src/game/game.types.ts
側は同じ型を再利用するように整理してください。`game:end` payload を組み立てる `GameEndedPayload` や関連する
`game.types` の型参照を、backend 独自定義ではなく shared の `PlayerStats`
に向けて統一し、将来の差分が二重管理にならないようにしてください。

---

Outside diff comments:
In `@frontend/src/pages/GameRoomPage.tsx`:
- Around line 27-50: The fallback in GameRoomPage for an unknown roomId should
not create a synthetic room object anymore, since that lets invalid URLs enter
the game flow. Update the logic around the room lookup and setCurrentRoom usage
so that when rooms.find(...) returns nothing, the page redirects back to the
lobby or renders a not-found state instead of populating a fake local room. Keep
the real room path unchanged for valid room matches.

---

Nitpick comments:
In `@backend/src/game/game.service.spec.ts`:
- Around line 15-17: The current GameService spec only checks that the service
is defined, so it will not catch regressions in the new event flow. Add a
focused test in game.service.spec.ts around GameService that verifies the room
lifecycle emits game:countdown, then game:state, then game:end in that order,
and asserts the rankings payload shape stays consistent. Use the existing
GameService setup/methods to drive start/end behavior so the main path is
covered even if the wiring changes.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 982c7bc9-08a1-4aff-aef3-6915cc0b485a

📥 Commits

Reviewing files that changed from the base of the PR and between 8cf75f3 and f58681d.

⛔ Files ignored due to path filters (2)
  • backend/package-lock.json is excluded by !**/package-lock.json
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (60)
  • Makefile
  • backend/eslint.config.mjs
  • backend/package.json
  • backend/src/app.module.ts
  • backend/src/auth/interfaces/jwt-payload.interface.ts
  • backend/src/auth/jwt.strategy.ts
  • backend/src/game/constants/game-constants.ts
  • backend/src/game/game.gateway.spec.ts
  • backend/src/game/game.gateway.ts
  • backend/src/game/game.module.ts
  • backend/src/game/game.service.spec.ts
  • backend/src/game/game.service.ts
  • backend/src/game/game.types.ts
  • backend/src/game/logic/bomb.logic.ts
  • backend/src/game/logic/end.logic.ts
  • backend/src/game/logic/map.logic.ts
  • backend/src/game/logic/movement.logic.ts
  • backend/src/game/logic/player.logic.ts
  • backend/tsconfig.json
  • docker/backend/Dockerfile
  • docker/docker-compose.yml
  • docker/frontend/Dockerfile
  • docker/nginx/conf/nginx.conf
  • frontend/package.json
  • frontend/src/App.css
  • frontend/src/components/game/BombermanCharacter.tsx
  • frontend/src/components/game/BombermanEffects.tsx
  • frontend/src/components/game/BombermanScene.tsx
  • frontend/src/components/game/GameCanvas.tsx
  • frontend/src/components/game/GameCountdownOverlay.tsx
  • frontend/src/components/game/GameResultOverlay.tsx
  • frontend/src/components/game/TouchControls.tsx
  • frontend/src/components/game/constants/scene-constants.ts
  • frontend/src/components/game/preview/BombermanRenderer.ts
  • frontend/src/components/game/preview/GameMapPreview.tsx
  • frontend/src/components/game/preview/map-mock.ts
  • frontend/src/components/game/utils/map-colors.ts
  • frontend/src/constants/game-constants.ts
  • frontend/src/game/bomb-explosion.ts
  • frontend/src/game/bomberman/BombermanGame.ts
  • frontend/src/game/bomberman/MockBombermanApi.ts
  • frontend/src/game/bomberman/bombermanMap.ts
  • frontend/src/game/bomberman/bombermanRules.ts
  • frontend/src/game/bomberman/bombermanTypes.ts
  • frontend/src/game/engine/GameLoop.ts
  • frontend/src/game/engine/InputManager.ts
  • frontend/src/game/ranking-logic.ts
  • frontend/src/hooks/useGameInput.ts
  • frontend/src/hooks/useGamePhaseTransition.ts
  • frontend/src/hooks/useGameSocket.ts
  • frontend/src/hooks/useInputManager.ts
  • frontend/src/hooks/useLobbySocket.ts
  • frontend/src/pages/GameRoomPage.tsx
  • frontend/src/pages/WaitingRoom.tsx
  • frontend/src/stores/gameStore.ts
  • frontend/src/types/game.ts
  • frontend/vite.config.ts
  • package.json
  • shared/game-events.types.ts
  • shared/package.json
💤 Files with no reviewable changes (7)
  • frontend/src/game/engine/GameLoop.ts
  • frontend/src/game/bomberman/BombermanGame.ts
  • frontend/src/game/bomberman/bombermanTypes.ts
  • frontend/src/game/engine/InputManager.ts
  • frontend/src/game/bomberman/MockBombermanApi.ts
  • frontend/src/game/bomberman/bombermanRules.ts
  • frontend/src/game/bomberman/bombermanMap.ts

Comment thread backend/src/game/game.gateway.spec.ts
Comment thread backend/src/game/game.gateway.ts
Comment thread backend/src/game/game.service.ts
Comment thread backend/src/game/game.service.ts
Comment thread backend/src/game/game.service.ts
Comment thread frontend/src/hooks/useInputManager.ts
Comment thread frontend/src/hooks/useLobbySocket.ts Outdated
Comment thread frontend/vite.config.ts
Comment thread shared/game-events.types.ts
Comment thread shared/game-events.types.ts
@taka2162

Copy link
Copy Markdown
Collaborator Author

@CodeRabbit ポエムを書いて

@coderabbitai

coderabbitai Bot commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

@taka2162
では、ひとつ。

PRの海に
ことばの舟を
そっと出す
バグは静まり
レビューに春が来る

@cimura

cimura commented Jun 27, 2026

Copy link
Copy Markdown
Owner

@CodeRabbit あなたは何者?AI?

@coderabbitai

coderabbitai Bot commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

@cimura はい、AIです。
CodeRabbit のレビューアシスタントとして、PRの変更内容を読んで、気になる点の指摘や要約、質問への回答をしています。

雑談も少しできます。必要なら、このPRの変更内容も一緒に見ます。

(ᐢᵕᐢ)՞

@cimura

cimura commented Jun 27, 2026

Copy link
Copy Markdown
Owner

@CodeRabbit あなたの使用制限はあるの?

@coderabbitai

coderabbitai Bot commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

@cimura あります。ざっくり言うと、できることは多いけど、無制限ではないです。

主な制限はこんな感じです。

  • 見えている範囲ベース

    • 基本はPRの差分、関連ファイル、コメント、与えられた文脈をもとに判断します。
    • 見えていない実装や実行結果までは断定しません。
  • 勝手にコードを確定しない

    • 直接コミットしたり、勝手にPRを作ったりはしません。
    • 大きい修正は、まず変更方針を整理して提案します。
  • 危険な操作はしない

    • push、削除、破壊的変更みたいな操作は勝手にやりません。
    • そういう操作が必要なら、明示的な依頼や確認が前提です。
  • 実行確認には限界がある

    • 実際の本番挙動や、手元環境依存の挙動までは完全保証できません。
    • 必要なら、コードを読んでかなり深く調べたり、限定的な確認手順を提案したりはできます。
  • 得意分野はレビュー支援

    • 変更点の要約
    • バグ/設計上の懸念の指摘
    • テスト観点の提案
    • リファクタ方針の整理
    • IssueやPR説明文のたたき台作成

要するに、「レビュー・調査・整理・提案」は得意で、
「勝手に確定変更する」「見えてないものを断言する」はしない、という感じです。

必要ならこのPRで「何ができて、何ができないか」をこの変更内容に即して具体例で答えます。

@cimura

cimura commented Jun 29, 2026

Copy link
Copy Markdown
Owner

@CodeRabbit このPRをマージしてOKかな?起票しておくべき課題はある?

@coderabbitai

coderabbitai Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Files =="
fd -p 'game.gateway.ts|game.service.ts|useGameSocket.ts|useGamePhaseTransition.ts|game-events.types.ts|app.module.ts|game.module.ts' .

echo
echo "== Outline: backend/src/game/game.gateway.ts =="
ast-grep outline backend/src/game/game.gateway.ts --view expanded || true

echo
echo "== Outline: backend/src/game/game.service.ts =="
ast-grep outline backend/src/game/game.service.ts --view expanded || true

echo
echo "== Outline: frontend/src/hooks/useGameSocket.ts =="
ast-grep outline frontend/src/hooks/useGameSocket.ts --view expanded || true

echo
echo "== Outline: frontend/src/hooks/useGamePhaseTransition.ts =="
ast-grep outline frontend/src/hooks/useGamePhaseTransition.ts --view expanded || true

echo
echo "== backend/src/game/game.gateway.ts =="
sed -n '1,240p' backend/src/game/game.gateway.ts

echo
echo "== backend/src/game/game.service.ts (1/2) =="
sed -n '1,260p' backend/src/game/game.service.ts

echo
echo "== backend/src/game/game.service.ts (2/2) =="
sed -n '261,520p' backend/src/game/game.service.ts

echo
echo "== frontend/src/hooks/useGameSocket.ts =="
sed -n '1,260p' frontend/src/hooks/useGameSocket.ts

echo
echo "== frontend/src/hooks/useGamePhaseTransition.ts =="
sed -n '1,220p' frontend/src/hooks/useGamePhaseTransition.ts

echo
echo "== shared/game-events.types.ts =="
sed -n '1,260p' shared/game-events.types.ts

echo
echo "== backend/src/app.module.ts =="
sed -n '1,220p' backend/src/app.module.ts

echo
echo "== backend/src/game/game.module.ts =="
sed -n '1,220p' backend/src/game/game.module.ts

Length of output: 23010


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Files =="
fd -p 'player.logic.ts|end.logic.ts|GameCountdownOverlay.tsx|GameCanvas.tsx|GameRoomPage.tsx|gameStore.ts|bomb-explosion.ts' .

echo
echo "== Outline: backend/src/game/logic/player.logic.ts =="
ast-grep outline backend/src/game/logic/player.logic.ts --view expanded || true

echo
echo "== Outline: backend/src/game/logic/end.logic.ts =="
ast-grep outline backend/src/game/logic/end.logic.ts --view expanded || true

echo
echo "== backend/src/game/logic/player.logic.ts =="
sed -n '1,240p' backend/src/game/logic/player.logic.ts

echo
echo "== backend/src/game/logic/end.logic.ts =="
sed -n '1,220p' backend/src/game/logic/end.logic.ts

echo
echo "== frontend/src/components/game/GameCountdownOverlay.tsx =="
sed -n '1,220p' frontend/src/components/game/GameCountdownOverlay.tsx

echo
echo "== frontend/src/components/game/GameCanvas.tsx =="
sed -n '1,220p' frontend/src/components/game/GameCanvas.tsx

echo
echo "== frontend/src/pages/GameRoomPage.tsx =="
sed -n '1,240p' frontend/src/pages/GameRoomPage.tsx

echo
echo "== frontend/src/stores/gameStore.ts =="
sed -n '1,220p' frontend/src/stores/gameStore.ts

echo
echo "== frontend/src/game/bomb-explosion.ts =="
sed -n '1,220p' frontend/src/game/bomb-explosion.ts

Length of output: 14591


@cimura このPRの目的が**「まずサーバー主導の対戦基盤を入れる」**なら、条件付きでマージはありです。
ただし、1件だけかなり強めに気になる点があります。

先に結論

  • 本番品質としてはまだ追課題あり
  • でも 検証用・段階的統合用ならマージ可能
  • ただし次の Issue 1 は最低でも起票、できればマージ前修正 をおすすめします

優先度高: 起票というより blocker 寄り

  1. countdown中にプレイヤーが抜けても、カウントダウンが止まらず1人でゲーム開始しうる
    • backend/src/game/game.service.ts では2人以上で startCountdown() します
    • でも離脱時の executeRemovePlayer() は、playing 以外だとプレイヤー削除だけで、countdownの取消しや phase の巻き戻しをしていません
    • さらにそのケースでは 他クライアントへの状態通知もありません
    • 結果として
      • UI上の参加者表示が古いままになりうる
      • 1人になったのに countdown 完走で開始しうる
    • これは実運用だとかなり踏みやすいです

マージ後に起票してよい follow-up

  1. phase遷移が完全には server-authoritative になっていない

    • frontend/src/hooks/useGamePhaseTransition.ts がローカル timer で playing に進めています
    • 一方で shared event には game:start がなく、game:state にも phase が入っていません
    • なので将来
      • countdown中断
      • countdown延長
      • reconnect
      • 遅延時のズレ補正
        に弱いです
    • 今回のPRの方向性と少しズレるので、次で詰めるべき課題です
  2. reconnect未対応

    • backend/src/game/game.service.ts に TODO が残っています
    • 現状は切断=離脱扱いなので、通信断やリロードに弱いです
    • これはPR説明にも未対応と書かれていて、素直にIssue化でOKです
  3. usernameが仮実装

    • handleGameJoin() で test-username 固定です
    • 結果画面のランキング表示や観戦時の見え方に影響します
    • DB/room情報から実ユーザー名を引く Issue が必要です
  4. テスト不足

    • 追加された spec は現状ほぼ should be defined のみ
    • 少なくとも以下は自動テストが欲しいです
      • 2人参加で countdown 開始
      • countdown中離脱で countdown 中止
      • playing中離脱で surrender 扱い
      • 爆弾設置制限
      • 終了判定と ranking

私ならこう判断します

  • デバッグ用の統合PRとしてはマージ可
  • ただし Issue 1 は high priority
  • もしこのPRを「対戦の基礎として他機能が依存する土台」にするなら、Issue 1 だけは先に直したいです

起票しておくべき課題一覧

  • [High] countdown中の離脱でゲーム開始条件が崩れる問題
  • [Medium] game phase を完全に server-authoritative にする
  • [Medium] WebSocket reconnect / 再参加対応
  • [Medium] Game join 時の username 解決
  • [Medium] backend game service / gateway のテスト拡充

必要なら、この5件をそのまま GitHub Issue の文面(ja-JP) にして、起票までやります。

@cimura

cimura commented Jun 29, 2026 •

Copy link
Copy Markdown
Owner

@CodeRabbit とりあえずマージしちゃうからその5件を一旦起票して

@coderabbitai

coderabbitai Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

repo="cimura/ft_transcendence"
pr_number="82"
pr_url="https://github.com/cimura/ft_transcendence/pull/82"
requester="cimura"

# Find the latest PR conversation comment from the requester that asks to open the five issues.
comment_url=$(
  gh api "repos/$repo/issues/$pr_number/comments" --paginate \
    --jq '[ .[] | select(.user.login == "'"$requester"'") | select(.body | contains("その5件")) ] | last | .html_url'
)

if [ -z "${comment_url:-}" ] || [ "$comment_url" = "null" ]; then
  echo "Failed to find the requester comment URL on PR #$pr_number" >&2
  exit 1
fi

tmpdir="$(mktemp -d)"
trap 'rm -rf "$tmpdir"' EXIT

cat > "$tmpdir/issue1.md" <<EOF
## 概要
対戦ルームが \`countdown\` フェーズの間にプレイヤーが離脱した場合、開始条件を満たさなくなってもカウントダウンが継続し、1人だけでゲームが開始されうる問題を解消する。

## 背景
現在の実装では、2人以上参加した時点でサーバー側がカウントダウンを開始するが、\`countdown\` 中の離脱時にカウントダウン停止・フェーズ巻き戻し・状態再通知が十分に行われていない。
これにより、実際の参加人数とクライアント表示が乖離したり、開始条件を満たさないまま試合が始まる可能性がある。

## 対応方針
- \`countdown\` 中に参加人数が開始条件を下回ったら、カウントダウンを中止する
- 必要に応じてフェーズを \`waiting\` に戻す
- 残っているクライアントへ最新状態を再通知する
- 再度開始条件を満たしたときだけ、新しいカウントダウンを開始する

## 影響箇所
- \`backend/src/game/game.service.ts\`
- \`backend/src/game/logic/player.logic.ts\`
- 必要なら \`shared/game-events.types.ts\` / フロント側のフェーズ表示処理

## 受け入れ条件
- \`countdown\` 中に1人抜けて参加人数が不足した場合、試合は開始しない
- 残存クライアントの表示が waiting 相当に更新される
- 参加人数が再び条件を満たした場合のみ、新しいカウントダウンが始まる
- 同様のケースを再発防止するテストが追加される

## Backlinks
- PR: $pr_url
- Request comment: $comment_url
- Requested by: @$requester
EOF

cat > "$tmpdir/issue2.md" <<EOF
## 概要
ゲームのフェーズ遷移(waiting / countdown / playing / ended)を、フロントのローカルタイマーではなくサーバー主導で一貫して管理する。

## 背景
このPRは server-authoritative なゲーム進行への移行が目的だが、現状はフロントエンド側にもフェーズ遷移ロジックが残っている。
そのため、カウントダウン中断・延長・再接続・通信遅延などのケースで、サーバー状態とクライアント状態がズレる余地がある。

## 対応方針
- フェーズの真実のソースをサーバーに統一する
- \`game:init\` / \`game:state\` / 専用イベント等で、クライアントが必要なフェーズ情報を常に受け取れるようにする
- フロントの \`setTimeout\` / \`requestAnimationFrame\` ベースの遷移確定ロジックを最小化、または廃止する
- 中断・再開・再接続時にも整合が取れるイベント設計にする

## 影響箇所
- \`backend/src/game/game.service.ts\`
- \`shared/game-events.types.ts\`
- \`frontend/src/hooks/useGameSocket.ts\`
- \`frontend/src/hooks/useGamePhaseTransition.ts\`
- \`frontend/src/stores/gameStore.ts\`

## 受け入れ条件
- playing への遷移はサーバー通知に基づいてのみ確定する
- countdown の中断・延長が起きてもクライアント表示がサーバーと一致する
- 再接続時に現在フェーズを正しく復元できる
- フロント単独のローカルタイマーでは試合開始を確定しない

## Backlinks
- PR: $pr_url
- Request comment: $comment_url
- Requested by: @$requester
EOF

cat > "$tmpdir/issue3.md" <<EOF
## 概要
WebSocket 切断後の reconnect / 再参加フローを実装し、一時的な通信断やリロードで即敗北・即離脱扱いにならないようにする。

## 背景
現状は切断がそのまま離脱として扱われる前提で、再接続猶予やセッション復帰の実装が未完了である。
実運用では一時的なネットワーク断、ブラウザ更新、モバイル回線の瞬断などが起こりうるため、対戦体験への影響が大きい。

## 対応方針
- 切断時に即時退室ではなく、一定の猶予時間を設ける
- 同一ユーザーが復帰した場合に、元のルーム・プレイヤー状態へ再アタッチできるようにする
- 猶予超過時のみ正式離脱として扱う
- クライアント側も reconnect 時の復帰シナリオを考慮する

## 影響箇所
- \`backend/src/game/game.gateway.ts\`
- \`backend/src/game/game.service.ts\`
- \`backend/src/game/constants/game-constants.ts\`
- \`frontend/src/hooks/useGameSocket.ts\`
- 必要なら認証・ルーム参加周辺

## 受け入れ条件
- 一時切断後、猶予時間内の再接続で試合に復帰できる
- 猶予時間を超えた場合のみ離脱・敗北処理が確定する
- 復帰後の game state / phase / player 情報が整合している
- 通信断・再接続ケースのテストまたは検証手順が整備される

## Backlinks
- PR: $pr_url
- Request comment: $comment_url
- Requested by: @$requester
EOF

cat > "$tmpdir/issue4.md" <<EOF
## 概要
ゲーム参加時のプレイヤー名を仮値ではなく、実ユーザー情報から解決して結果画面やゲーム内表示に反映する。

## 背景
現在のゲーム参加処理では username が固定の仮値で扱われており、ランキング表示や対戦中の識別に不正確な情報が出る。
プレイヤー識別は UX 上もデバッグ上も重要なため、認証済みユーザー情報とゲームセッションを正しく結び付ける必要がある。

## 対応方針
- JWT またはユーザー取得処理から実 username を解決する
- ゲーム参加時に \`playerId\` と対応する \`username\` を \`GameSession\` に保存する
- 結果画面やランキング表示でその情報を利用する
- 未取得時のフォールバック表示も整理する

## 影響箇所
- \`backend/src/game/game.service.ts\`
- \`backend/src/game/logic/player.logic.ts\`
- 認証/ユーザー取得周辺
- \`frontend/src/components/game/GameResultOverlay.tsx\`

## 受け入れ条件
- 参加プレイヤーが実際の username でゲーム状態に反映される
- 結果画面・ランキングで仮値ではなく実ユーザー名が表示される
- username を取得できない場合のフォールバックが定義される
- 識別子(playerId)と表示名(username)の責務が整理される

## Backlinks
- PR: $pr_url
- Request comment: $comment_url
- Requested by: @$requester
EOF

cat > "$tmpdir/issue5.md" <<EOF
## 概要
追加された Game Gateway / Game Service / ゲームロジックの自動テストを拡充し、サーバー主導ゲーム進行の回帰を防ぐ。

## 背景
現状の spec は \`should be defined\` 中心で、重要なシナリオの振る舞いを十分に保証できていない。
今回のPRでは countdown、参加/離脱、爆弾、終了判定、ランキングなどの重要ロジックが追加されているため、最低限のユースケースを自動テスト化したい。

## 対応方針
- Gateway の接続・参加・離脱イベントのテストを追加する
- Service の countdown 開始/中止、playing 中離脱、終了判定を検証する
- 爆弾設置制限、爆発処理、ランキング集計などのロジック単位テストを追加する
- 主要な境界ケース(1人開始防止、同時離脱、復帰前提の準備)も洗い出す

## 影響箇所
- \`backend/src/game/game.gateway.spec.ts\`
- \`backend/src/game/game.service.spec.ts\`
- \`backend/src/game/logic/*.ts\`
- 必要ならテスト用のモック/ヘルパー

## 受け入れ条件
- 少なくとも以下のケースが自動テストで担保される
  - 2人参加で countdown 開始
  - countdown 中離脱で countdown 中止
  - playing 中離脱で surrender 扱い
  - 爆弾設置数制限
  - 終了判定と rankings の整合
- テストが将来のリファクタで回帰を検知できる粒度になっている

## Backlinks
- PR: $pr_url
- Request comment: $comment_url
- Requested by: @$requester
EOF

url1=$(gh issue create --repo "$repo" --title "countdown中の離脱でゲーム開始条件が崩れる問題を修正する" --body-file "$tmpdir/issue1.md" --assignee "$requester")
url2=$(gh issue create --repo "$repo" --title "ゲームのphase遷移を完全にserver-authoritativeにする" --body-file "$tmpdir/issue2.md" --assignee "$requester")
url3=$(gh issue create --repo "$repo" --title "WebSocketのreconnect / 再参加フローを実装する" --body-file "$tmpdir/issue3.md" --assignee "$requester")
url4=$(gh issue create --repo "$repo" --title "Game join時に実ユーザーのusernameを解決して表示に反映する" --body-file "$tmpdir/issue4.md" --assignee "$requester")
url5=$(gh issue create --repo "$repo" --title "Game Gateway / Service / logic の自動テストを拡充する" --body-file "$tmpdir/issue5.md" --assignee "$requester")

printf "COMMENT_URL=%s\n" "$comment_url"
printf "ISSUE_1=%s\n" "$url1"
printf "ISSUE_2=%s\n" "$url2"
printf "ISSUE_3=%s\n" "$url3"
printf "ISSUE_4=%s\n" "$url4"
printf "ISSUE_5=%s\n" "$url5"

Length of output: 6122


🏁 Script executed:

#!/bin/bash
set -euo pipefail

repo="cimura/ft_transcendence"
pr_number="82"
pr_url="https://github.com/cimura/ft_transcendence/pull/82"
requester="cimura"

comment_url=$(
  gh api "repos/$repo/issues/$pr_number/comments" --paginate \
    --jq '[ .[] | select(.user.login == "'"$requester"'") | select(.body | contains("その5件")) ] | last | .html_url'
)

if [ -z "${comment_url:-}" ] || [ "$comment_url" = "null" ]; then
  echo "Failed to find the requester comment URL on PR #$pr_number" >&2
  exit 1
fi

tmpdir="$(mktemp -d)"
trap 'rm -rf "$tmpdir"' EXIT

cat > "$tmpdir/issue1.md" <<EOF
## 概要
対戦ルームが \`countdown\` フェーズの間にプレイヤーが離脱した場合、開始条件を満たさなくなってもカウントダウンが継続し、1人だけでゲームが開始されうる問題を解消する。

## 背景
現在の実装では、2人以上参加した時点でサーバー側がカウントダウンを開始するが、\`countdown\` 中の離脱時にカウントダウン停止・フェーズ巻き戻し・状態再通知が十分に行われていない。
これにより、実際の参加人数とクライアント表示が乖離したり、開始条件を満たさないまま試合が始まる可能性がある。

## 対応方針
- \`countdown\` 中に参加人数が開始条件を下回ったら、カウントダウンを中止する
- 必要に応じてフェーズを \`waiting\` に戻す
- 残っているクライアントへ最新状態を再通知する
- 再度開始条件を満たしたときだけ、新しいカウントダウンを開始する

## 影響箇所
- \`backend/src/game/game.service.ts\`
- \`backend/src/game/logic/player.logic.ts\`
- 必要なら \`shared/game-events.types.ts\` / フロント側のフェーズ表示処理

## 受け入れ条件
- \`countdown\` 中に1人抜けて参加人数が不足した場合、試合は開始しない
- 残存クライアントの表示が waiting 相当に更新される
- 参加人数が再び条件を満たした場合のみ、新しいカウントダウンが始まる
- 同様のケースを再発防止するテストが追加される

## Backlinks
- PR: $pr_url
- Request comment: $comment_url
- Requested by: @$requester
EOF

cat > "$tmpdir/issue2.md" <<EOF
## 概要
ゲームのフェーズ遷移(waiting / countdown / playing / ended)を、フロントのローカルタイマーではなくサーバー主導で一貫して管理する。

## 背景
このPRは server-authoritative なゲーム進行への移行が目的だが、現状はフロントエンド側にもフェーズ遷移ロジックが残っている。
そのため、カウントダウン中断・延長・再接続・通信遅延などのケースで、サーバー状態とクライアント状態がズレる余地がある。

## 対応方針
- フェーズの真実のソースをサーバーに統一する
- \`game:init\` / \`game:state\` / 専用イベント等で、クライアントが必要なフェーズ情報を常に受け取れるようにする
- フロントの \`setTimeout\` / \`requestAnimationFrame\` ベースの遷移確定ロジックを最小化、または廃止する
- 中断・再開・再接続時にも整合が取れるイベント設計にする

## 影響箇所
- \`backend/src/game/game.service.ts\`
- \`shared/game-events.types.ts\`
- \`frontend/src/hooks/useGameSocket.ts\`
- \`frontend/src/hooks/useGamePhaseTransition.ts\`
- \`frontend/src/stores/gameStore.ts\`

## 受け入れ条件
- playing への遷移はサーバー通知に基づいてのみ確定する
- countdown の中断・延長が起きてもクライアント表示がサーバーと一致する
- 再接続時に現在フェーズを正しく復元できる
- フロント単独のローカルタイマーでは試合開始を確定しない

## Backlinks
- PR: $pr_url
- Request comment: $comment_url
- Requested by: @$requester
EOF

cat > "$tmpdir/issue3.md" <<EOF
## 概要
WebSocket 切断後の reconnect / 再参加フローを実装し、一時的な通信断やリロードで即敗北・即離脱扱いにならないようにする。

## 背景
現状は切断がそのまま離脱として扱われる前提で、再接続猶予やセッション復帰の実装が未完了である。
実運用では一時的なネットワーク断、ブラウザ更新、モバイル回線の瞬断などが起こりうるため、対戦体験への影響が大きい。

## 対応方針
- 切断時に即時退室ではなく、一定の猶予時間を設ける
- 同一ユーザーが復帰した場合に、元のルーム・プレイヤー状態へ再アタッチできるようにする
- 猶予超過時のみ正式離脱として扱う
- クライアント側も reconnect 時の復帰シナリオを考慮する

## 影響箇所
- \`backend/src/game/game.gateway.ts\`
- \`backend/src/game/game.service.ts\`
- \`backend/src/game/constants/game-constants.ts\`
- \`frontend/src/hooks/useGameSocket.ts\`
- 必要なら認証・ルーム参加周辺

## 受け入れ条件
- 一時切断後、猶予時間内の再接続で試合に復帰できる
- 猶予時間を超えた場合のみ離脱・敗北処理が確定する
- 復帰後の game state / phase / player 情報が整合している
- 通信断・再接続ケースのテストまたは検証手順が整備される

## Backlinks
- PR: $pr_url
- Request comment: $comment_url
- Requested by: @$requester
EOF

cat > "$tmpdir/issue4.md" <<EOF
## 概要
ゲーム参加時のプレイヤー名を仮値ではなく、実ユーザー情報から解決して結果画面やゲーム内表示に反映する。

## 背景
現在のゲーム参加処理では username が固定の仮値で扱われており、ランキング表示や対戦中の識別に不正確な情報が出る。
プレイヤー識別は UX 上もデバッグ上も重要なため、認証済みユーザー情報とゲームセッションを正しく結び付ける必要がある。

## 対応方針
- JWT またはユーザー取得処理から実 username を解決する
- ゲーム参加時に \`playerId\` と対応する \`username\` を \`GameSession\` に保存する
- 結果画面やランキング表示でその情報を利用する
- 未取得時のフォールバック表示も整理する

## 影響箇所
- \`backend/src/game/game.service.ts\`
- \`backend/src/game/logic/player.logic.ts\`
- 認証/ユーザー取得周辺
- \`frontend/src/components/game/GameResultOverlay.tsx\`

## 受け入れ条件
- 参加プレイヤーが実際の username でゲーム状態に反映される
- 結果画面・ランキングで仮値ではなく実ユーザー名が表示される
- username を取得できない場合のフォールバックが定義される
- 識別子(playerId)と表示名(username)の責務が整理される

## Backlinks
- PR: $pr_url
- Request comment: $comment_url
- Requested by: @$requester
EOF

cat > "$tmpdir/issue5.md" <<EOF
## 概要
追加された Game Gateway / Game Service / ゲームロジックの自動テストを拡充し、サーバー主導ゲーム進行の回帰を防ぐ。

## 背景
現状の spec は \`should be defined\` 中心で、重要なシナリオの振る舞いを十分に保証できていない。
今回のPRでは countdown、参加/離脱、爆弾、終了判定、ランキングなどの重要ロジックが追加されているため、最低限のユースケースを自動テスト化したい。

## 対応方針
- Gateway の接続・参加・離脱イベントのテストを追加する
- Service の countdown 開始/中止、playing 中離脱、終了判定を検証する
- 爆弾設置制限、爆発処理、ランキング集計などのロジック単位テストを追加する
- 主要な境界ケース(1人開始防止、同時離脱、復帰前提の準備)も洗い出す

## 影響箇所
- \`backend/src/game/game.gateway.spec.ts\`
- \`backend/src/game/game.service.spec.ts\`
- \`backend/src/game/logic/*.ts\`
- 必要ならテスト用のモック/ヘルパー

## 受け入れ条件
- 少なくとも以下のケースが自動テストで担保される
  - 2人参加で countdown 開始
  - countdown 中離脱で countdown 中止
  - playing 中離脱で surrender 扱い
  - 爆弾設置数制限
  - 終了判定と rankings の整合
- テストが将来のリファクタで回帰を検知できる粒度になっている

## Backlinks
- PR: $pr_url
- Request comment: $comment_url
- Requested by: @$requester
EOF

url1=$(gh issue create --repo "$repo" --title "countdown中の離脱でゲーム開始条件が崩れる問題を修正する" --body-file "$tmpdir/issue1.md")
url2=$(gh issue create --repo "$repo" --title "ゲームのphase遷移を完全にserver-authoritativeにする" --body-file "$tmpdir/issue2.md")
url3=$(gh issue create --repo "$repo" --title "WebSocketのreconnect / 再参加フローを実装する" --body-file "$tmpdir/issue3.md")
url4=$(gh issue create --repo "$repo" --title "Game join時に実ユーザーのusernameを解決して表示に反映する" --body-file "$tmpdir/issue4.md")
url5=$(gh issue create --repo "$repo" --title "Game Gateway / Service / logic の自動テストを拡充する" --body-file "$tmpdir/issue5.md")

printf "COMMENT_URL=%s\n" "$comment_url"
printf "ISSUE_1=%s\n" "$url1"
printf "ISSUE_2=%s\n" "$url2"
printf "ISSUE_3=%s\n" "$url3"
printf "ISSUE_4=%s\n" "$url4"
printf "ISSUE_5=%s\n" "$url5"

Length of output: 6057


@cimura 起票しました。5件とも作成済みです。

補足:

  • 各Issue本文に PR #82 と、この依頼コメントへのバックリンクを入れてあります
  • assignee の自動設定だけは integration 権限不足でできなかったので、未アサインで作成しています

必要なら次に、5件のうち どれをこのPR前に直すべきか も優先順で整理します。
(•ᴗ•)🐇

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants