diff --git a/apps/client/src/network/handlers/GameHandler.ts b/apps/client/src/network/handlers/GameHandler.ts index 3d0bd9c..eff8959 100644 --- a/apps/client/src/network/handlers/GameHandler.ts +++ b/apps/client/src/network/handlers/GameHandler.ts @@ -12,6 +12,7 @@ ClientToServerEventPayloadMap, ServerToClientEventPayloadMap, CurrentPlayersPayload, + CurrentHurricanesPayload, GameResultPayload, GameStartPayload, HurricaneHitPayload, @@ -46,6 +47,12 @@ offUpdateMapCells: ( callback: (updates: UpdateMapCellsPayload) => void, ) => void; + onCurrentHurricanes: ( + callback: (payload: CurrentHurricanesPayload) => void, + ) => void; + offCurrentHurricanes: ( + callback: (payload: CurrentHurricanesPayload) => void, + ) => void; onUpdateHurricanes: ( callback: (payload: UpdateHurricanesPayload) => void, ) => void; @@ -124,6 +131,9 @@ const updateMapCellsSubscription = createSubscriptionPair( protocol.SocketEvents.UPDATE_MAP_CELLS, ); + const currentHurricanesSubscription = createSubscriptionPair( + protocol.SocketEvents.CURRENT_HURRICANES, + ); const updateHurricanesSubscription = createSubscriptionPair( protocol.SocketEvents.UPDATE_HURRICANES, ); @@ -187,6 +197,12 @@ offUpdateMapCells: (callback) => { updateMapCellsSubscription.off(callback); }, + onCurrentHurricanes: (callback) => { + currentHurricanesSubscription.on(callback); + }, + offCurrentHurricanes: (callback) => { + currentHurricanesSubscription.off(callback); + }, onUpdateHurricanes: (callback) => { updateHurricanesSubscription.on(callback); }, diff --git a/apps/client/src/scenes/game/application/network/NetworkSubscriptions.ts b/apps/client/src/scenes/game/application/network/NetworkSubscriptions.ts index 5334686..47fe065 100644 --- a/apps/client/src/scenes/game/application/network/NetworkSubscriptions.ts +++ b/apps/client/src/scenes/game/application/network/NetworkSubscriptions.ts @@ -8,6 +8,7 @@ BombPlacedAckPayload, BombPlacedPayload, CurrentPlayersPayload, + CurrentHurricanesPayload, GameStartPayload, HurricaneHitPayload, NewPlayerPayload, @@ -33,6 +34,7 @@ updatePlayers: SocketSubscription; removePlayer: SocketSubscription; updateMapCells: SocketSubscription; + currentHurricanes: SocketSubscription; updateHurricanes: SocketSubscription; gameEnd: SocketSubscription; bombPlaced: SocketSubscription; @@ -50,6 +52,7 @@ onUpdatePlayers: (payload: UpdatePlayersPayload) => void; onRemovePlayer: (payload: RemovePlayerPayload) => void; onUpdateMapCells: (payload: UpdateMapCellsPayload) => void; + onCurrentHurricanes: (payload: CurrentHurricanesPayload) => void; onUpdateHurricanes: (payload: UpdateHurricanesPayload) => void; onGameEnd: () => void; onBombPlaced: (payload: BombPlacedPayload) => void; @@ -113,6 +116,15 @@ }), }, { + key: "currentHurricanes", + create: (handlers) => ({ + bind: () => + socketManager.game.onCurrentHurricanes(handlers.onCurrentHurricanes), + unbind: () => + socketManager.game.offCurrentHurricanes(handlers.onCurrentHurricanes), + }), + }, + { key: "updateHurricanes", create: (handlers) => ({ bind: () => diff --git a/apps/client/src/scenes/game/application/network/handlers/GameNetworkStateApplier.ts b/apps/client/src/scenes/game/application/network/handlers/GameNetworkStateApplier.ts index 908e72c..17b2e50 100644 --- a/apps/client/src/scenes/game/application/network/handlers/GameNetworkStateApplier.ts +++ b/apps/client/src/scenes/game/application/network/handlers/GameNetworkStateApplier.ts @@ -159,6 +159,9 @@ const updates = domain.game.gridMap.ungroupCellUpdates(payload); this.mapSyncHandler.handleUpdateMapCells(updates); }, + onReceivedCurrentHurricanes: (payload) => { + this.hurricaneSyncHandler.handleUpdateHurricanes(payload); + }, onReceivedUpdateHurricanes: (payload) => { this.hurricaneSyncHandler.handleUpdateHurricanes(payload); }, diff --git a/apps/client/src/scenes/game/application/network/receivers/GameNetworkEventReceiver.ts b/apps/client/src/scenes/game/application/network/receivers/GameNetworkEventReceiver.ts index 8f4d080..563560b 100644 --- a/apps/client/src/scenes/game/application/network/receivers/GameNetworkEventReceiver.ts +++ b/apps/client/src/scenes/game/application/network/receivers/GameNetworkEventReceiver.ts @@ -7,6 +7,7 @@ BombPlacedAckPayload, BombPlacedPayload, CurrentPlayersPayload, + CurrentHurricanesPayload, GameStartPayload, HurricaneHitPayload, NewPlayerPayload, @@ -30,6 +31,7 @@ onReceivedUpdatePlayers: (payload: UpdatePlayersPayload) => void; onReceivedRemovePlayer: (payload: RemovePlayerPayload) => void; onReceivedUpdateMapCells: (payload: UpdateMapCellsPayload) => void; + onReceivedCurrentHurricanes: (payload: CurrentHurricanesPayload) => void; onReceivedUpdateHurricanes: (payload: UpdateHurricanesPayload) => void; onReceivedGameEnd: () => void; onReceivedBombPlaced: (payload: BombPlacedPayload) => void; @@ -52,6 +54,7 @@ onUpdatePlayers: handlers.onReceivedUpdatePlayers, onRemovePlayer: handlers.onReceivedRemovePlayer, onUpdateMapCells: handlers.onReceivedUpdateMapCells, + onCurrentHurricanes: handlers.onReceivedCurrentHurricanes, onUpdateHurricanes: handlers.onReceivedUpdateHurricanes, onGameEnd: handlers.onReceivedGameEnd, onBombPlaced: handlers.onReceivedBombPlaced, diff --git a/apps/server/src/domains/game/application/ports/gameUseCasePorts.ts b/apps/server/src/domains/game/application/ports/gameUseCasePorts.ts index f5c90b3..9b04c4f 100644 --- a/apps/server/src/domains/game/application/ports/gameUseCasePorts.ts +++ b/apps/server/src/domains/game/application/ports/gameUseCasePorts.ts @@ -69,11 +69,11 @@ roomId: domain.room.Room["roomId"], cellUpdates: domain.game.gridMap.CellUpdate[], ): void; - publishUpdateHurricanesToRoom( + publishCurrentHurricanesToRoom( roomId: domain.room.Room["roomId"], hurricanes: UpdateHurricanesPayload, ): void; - publishReliableHurricanesToRoom( + publishUpdateHurricanesToRoom( roomId: domain.room.Room["roomId"], hurricanes: UpdateHurricanesPayload, ): void; @@ -129,7 +129,7 @@ GameOutputPort, | "publishUpdatePlayersToRoom" | "publishMapCellUpdatesToRoom" - | "publishReliableHurricanesToRoom" + | "publishCurrentHurricanesToRoom" | "publishUpdateHurricanesToRoom" | "publishGameEndToRoom" | "publishGameResultToRoom" diff --git a/apps/server/src/domains/game/application/useCases/startGameUseCase.ts b/apps/server/src/domains/game/application/useCases/startGameUseCase.ts index 3cd14ea..733ba8d 100644 --- a/apps/server/src/domains/game/application/useCases/startGameUseCase.ts +++ b/apps/server/src/domains/game/application/useCases/startGameUseCase.ts @@ -37,36 +37,74 @@ : never; }; +type TickPublishStep = { + key: "hurricaneSnapshot" | "hurricaneDelta" | "player" | "map"; + run: (params: TickUpdatePublishParams) => void; +}; + +const TICK_PUBLISH_STEPS: TickPublishStep[] = [ + { + key: "hurricaneSnapshot", + run: ({ roomId, output, tickData }) => { + if (tickData.hurricaneSync.snapshotUpdates.length === 0) { + return; + } + + output.publishCurrentHurricanesToRoom( + roomId, + tickData.hurricaneSync.snapshotUpdates, + ); + }, + }, + { + key: "hurricaneDelta", + run: ({ roomId, output, tickData }) => { + if (tickData.hurricaneSync.deltaUpdates.length === 0) { + return; + } + + output.publishUpdateHurricanesToRoom( + roomId, + tickData.hurricaneSync.deltaUpdates, + ); + }, + }, + { + key: "player", + run: ({ roomId, output, tickData }) => { + if (tickData.playerUpdates.length === 0) { + return; + } + + output.publishUpdatePlayersToRoom(roomId, tickData.playerUpdates); + }, + }, + { + key: "map", + run: ({ roomId, output, tickData }) => { + if (tickData.cellUpdates.length === 0) { + return; + } + + output.publishMapCellUpdatesToRoom(roomId, tickData.cellUpdates); + }, + }, +]; + const publishTickUpdates = ({ roomId, output, tickData, }: TickUpdatePublishParams): void => { - if (tickData.hurricaneInitialSnapshot.length > 0) { - output.publishReliableHurricanesToRoom( - roomId, - tickData.hurricaneInitialSnapshot, - ); - } + const params: TickUpdatePublishParams = { + roomId, + output, + tickData, + }; - if (tickData.hurricaneReliableSnapshot.length > 0) { - output.publishReliableHurricanesToRoom( - roomId, - tickData.hurricaneReliableSnapshot, - ); - } - - if (tickData.hurricaneUpdates.length > 0) { - output.publishUpdateHurricanesToRoom(roomId, tickData.hurricaneUpdates); - } - - if (tickData.playerUpdates.length > 0) { - output.publishUpdatePlayersToRoom(roomId, tickData.playerUpdates); - } - - if (tickData.cellUpdates.length > 0) { - output.publishMapCellUpdatesToRoom(roomId, tickData.cellUpdates); - } + TICK_PUBLISH_STEPS.forEach((step) => { + step.run(params); + }); }; /** ゲームセッション開始とティック通知,終了通知を実行する */ diff --git a/apps/server/src/domains/game/loop/GameLoop.ts b/apps/server/src/domains/game/loop/GameLoop.ts index 7df18ce..d052cb9 100644 --- a/apps/server/src/domains/game/loop/GameLoop.ts +++ b/apps/server/src/domains/game/loop/GameLoop.ts @@ -263,17 +263,12 @@ const activePlayerIds = new Set(); const playerUpdates = this.collectChangedPlayerUpdates(activePlayerIds); this.cleanupInactivePlayerSnapshots(activePlayerIds); - const hurricaneInitialSnapshot = - this.hurricaneSystem.consumeInitialSyncPayload(elapsedMs); - const hurricaneReliableSnapshot = - this.hurricaneSystem.consumePeriodicReliableSyncPayload(elapsedMs); + const hurricaneSync = this.hurricaneSystem.consumeSyncOutputs(elapsedMs); return { playerUpdates, cellUpdates: this.mapStore.getAndClearUpdates(), - hurricaneInitialSnapshot, - hurricaneReliableSnapshot, - hurricaneUpdates: this.hurricaneSystem.getUpdatePayload(), + hurricaneSync, }; } diff --git a/apps/server/src/domains/game/loop/HurricaneSystem.ts b/apps/server/src/domains/game/loop/HurricaneSystem.ts index 99fd5ef..8d78a13 100644 --- a/apps/server/src/domains/game/loop/HurricaneSystem.ts +++ b/apps/server/src/domains/game/loop/HurricaneSystem.ts @@ -9,7 +9,14 @@ import { Player } from "../entities/player/Player.js"; const { checkBombHit } = domain.game.bombHit; -const HURRICANE_RELIABLE_RESYNC_INTERVAL_MS = 200; +const HURRICANE_RELIABLE_RESYNC_INTERVAL_MS = + config.GAME_CONFIG.NETWORK_SYNC.HURRICANE_RELIABLE_RESYNC_INTERVAL_MS; + +/** 1ティック分のハリケーン同期出力 */ +export type HurricaneSyncOutputs = { + snapshotUpdates: HurricaneStatePayload[]; + deltaUpdates: HurricaneStatePayload[]; +}; type HurricaneState = { id: string; @@ -109,40 +116,15 @@ ); } - /** 出現直後に1回だけ配信用の初期同期スナップショットを返す */ - public consumeInitialSyncPayload(elapsedMs: number): HurricaneStatePayload[] { - if (!this.hasInitialSyncPending) { - return []; - } + /** 1ティック分のハリケーン同期出力をまとめて返す */ + public consumeSyncOutputs(elapsedMs: number): HurricaneSyncOutputs { + const snapshotUpdates = this.consumeSnapshotUpdates(elapsedMs); + const deltaUpdates = this.consumeDeltaUpdates(); - this.hasInitialSyncPending = false; - this.lastReliableSyncElapsedMs = elapsedMs; - - return this.buildSnapshotPayload(true); - } - - /** 欠損復旧のため一定間隔で再同期スナップショットを返す */ - public consumePeriodicReliableSyncPayload( - elapsedMs: number, - ): HurricaneStatePayload[] { - if (this.hurricanes.length === 0 || this.hasInitialSyncPending) { - return []; - } - - if (this.lastReliableSyncElapsedMs < 0) { - this.lastReliableSyncElapsedMs = elapsedMs; - return []; - } - - if ( - elapsedMs - this.lastReliableSyncElapsedMs - < HURRICANE_RELIABLE_RESYNC_INTERVAL_MS - ) { - return []; - } - - this.lastReliableSyncElapsedMs = elapsedMs; - return this.buildSnapshotPayload(true); + return { + snapshotUpdates, + deltaUpdates, + }; } /** ハリケーンを直線移動させ,境界で反射させる */ @@ -178,8 +160,8 @@ }); } - /** 同期配信用のハリケーン状態配列を返す */ - public getUpdatePayload(): HurricaneStatePayload[] { + /** 差分同期配信用のハリケーン状態配列を返す */ + private consumeDeltaUpdates(): HurricaneStatePayload[] { return collectSyncDeltaEntries( this.hurricanes, this.lastSentSnapshotByHurricaneId, @@ -282,13 +264,39 @@ return min + Math.random() * Math.max(0, max - min); } - /** 現在状態を量子化スナップショットへ変換する */ - private buildSnapshotPayload(rememberAsLastSent: boolean): HurricaneStatePayload[] { + /** スナップショット同期が必要なら全量ペイロードを返す */ + private consumeSnapshotUpdates(elapsedMs: number): HurricaneStatePayload[] { + if (this.hurricanes.length === 0) { + return []; + } + + if (this.hasInitialSyncPending) { + this.hasInitialSyncPending = false; + this.lastReliableSyncElapsedMs = elapsedMs; + return this.buildSnapshotPayloadAndCommit(); + } + + if (this.lastReliableSyncElapsedMs < 0) { + this.lastReliableSyncElapsedMs = elapsedMs; + return []; + } + + if ( + elapsedMs - this.lastReliableSyncElapsedMs + < HURRICANE_RELIABLE_RESYNC_INTERVAL_MS + ) { + return []; + } + + this.lastReliableSyncElapsedMs = elapsedMs; + return this.buildSnapshotPayloadAndCommit(); + } + + /** 現在状態を量子化スナップショットへ変換して送信済み状態へ反映する */ + private buildSnapshotPayloadAndCommit(): HurricaneStatePayload[] { return this.hurricanes.map((hurricane) => { const snapshot = toHurricaneSyncSnapshot(hurricane); - if (rememberAsLastSent) { - this.lastSentSnapshotByHurricaneId.set(hurricane.id, snapshot); - } + this.lastSentSnapshotByHurricaneId.set(hurricane.id, snapshot); return { id: hurricane.id, diff --git a/apps/server/src/network/handlers/game/createGameOutputAdapter.ts b/apps/server/src/network/handlers/game/createGameOutputAdapter.ts index ea9c04e..d25cf3c 100644 --- a/apps/server/src/network/handlers/game/createGameOutputAdapter.ts +++ b/apps/server/src/network/handlers/game/createGameOutputAdapter.ts @@ -34,6 +34,16 @@ type RoomId = domain.room.Room["roomId"]; +type ReliableRoomEvent = + | typeof protocol.SocketEvents.UPDATE_PLAYERS + | typeof protocol.SocketEvents.UPDATE_MAP_CELLS + | typeof protocol.SocketEvents.CURRENT_HURRICANES + | typeof protocol.SocketEvents.UPDATE_HURRICANES + | typeof protocol.SocketEvents.GAME_END + | typeof protocol.SocketEvents.GAME_RESULT + | typeof protocol.SocketEvents.GAME_START + | typeof protocol.SocketEvents.HURRICANE_HIT; + /** ゲーム出力アダプターのインターフェース */ export type GameOutputAdapter = Omit< GameOutputPort, @@ -55,6 +65,19 @@ const { reliable } = common; const realtimeRoomSyncState = createRealtimeRoomSyncStateStore(); + const emitReliableToRoom = ( + roomId: RoomId, + event: ReliableRoomEvent, + payload?: unknown, + ): void => { + if (payload === undefined) { + reliable.emitToRoom(roomId, event); + return; + } + + reliable.emitToRoom(roomId, event, payload as never); + }; + return { publishPongToSocket: (payload: PongPayload) => { reliable.emitToSocket(protocol.SocketEvents.PONG, payload); @@ -73,49 +96,37 @@ return; } - reliable.emitToRoom( - roomId, - protocol.SocketEvents.UPDATE_PLAYERS, - changedPlayers, - ); + emitReliableToRoom(roomId, protocol.SocketEvents.UPDATE_PLAYERS, changedPlayers); }, publishMapCellUpdatesToRoom: ( roomId: RoomId, cellUpdates: domainNs.game.gridMap.CellUpdate[], ) => { const grouped = domainNs.game.gridMap.groupCellUpdates(cellUpdates); - reliable.emitToRoom( - roomId, - protocol.SocketEvents.UPDATE_MAP_CELLS, - grouped, - ); + emitReliableToRoom(roomId, protocol.SocketEvents.UPDATE_MAP_CELLS, grouped); + }, + publishCurrentHurricanesToRoom: ( + roomId: RoomId, + hurricanes: UpdateHurricanesPayload, + ) => { + emitReliableToRoom(roomId, protocol.SocketEvents.CURRENT_HURRICANES, hurricanes); }, publishUpdateHurricanesToRoom: ( roomId: RoomId, hurricanes: UpdateHurricanesPayload, ) => { - reliable.emitToRoom(roomId, protocol.SocketEvents.UPDATE_HURRICANES, hurricanes); - }, - publishReliableHurricanesToRoom: ( - roomId: RoomId, - hurricanes: UpdateHurricanesPayload, - ) => { - reliable.emitToRoom( - roomId, - protocol.SocketEvents.UPDATE_HURRICANES, - hurricanes, - ); + emitReliableToRoom(roomId, protocol.SocketEvents.UPDATE_HURRICANES, hurricanes); }, publishGameEndToRoom: (roomId: RoomId) => { realtimeRoomSyncState.resetRoom(roomId); - reliable.emitToRoom(roomId, protocol.SocketEvents.GAME_END); + emitReliableToRoom(roomId, protocol.SocketEvents.GAME_END); }, publishGameResultToRoom: (roomId: RoomId, payload: GameResultPayload) => { - reliable.emitToRoom(roomId, protocol.SocketEvents.GAME_RESULT, payload); + emitReliableToRoom(roomId, protocol.SocketEvents.GAME_RESULT, payload); }, publishGameStartToRoom: (roomId: RoomId, payload: GameStartPayload) => { realtimeRoomSyncState.resetRoom(roomId); - reliable.emitToRoom(roomId, protocol.SocketEvents.GAME_START, payload); + emitReliableToRoom(roomId, protocol.SocketEvents.GAME_START, payload); }, publishCurrentPlayersToSocket: (players: CurrentPlayersPayload) => { reliable.emitToSocket(protocol.SocketEvents.CURRENT_PLAYERS, players); @@ -169,7 +180,7 @@ roomId: RoomId, payload: HurricaneHitPayload, ) => { - reliable.emitToRoom(roomId, protocol.SocketEvents.HURRICANE_HIT, payload); + emitReliableToRoom(roomId, protocol.SocketEvents.HURRICANE_HIT, payload); }, }; }; diff --git a/packages/shared/src/config/gameConfig.ts b/packages/shared/src/config/gameConfig.ts index f3670ce..b1f5d2c 100644 --- a/packages/shared/src/config/gameConfig.ts +++ b/packages/shared/src/config/gameConfig.ts @@ -9,6 +9,7 @@ POSITION_QUANTIZE_SCALE: 100, HURRICANE_POSITION_QUANTIZE_SCALE: 10, HURRICANE_ROTATION_QUANTIZE_SCALE: 4, + HURRICANE_RELIABLE_RESYNC_INTERVAL_MS: 200, } as const; /** AOI同期で利用する1セルのグリッド幅 */ @@ -67,6 +68,7 @@ POSITION_QUANTIZE_SCALE: NETWORK_SYNC_CONFIG.POSITION_QUANTIZE_SCALE, // 後方互換のため維持 HURRICANE_POSITION_QUANTIZE_SCALE: NETWORK_SYNC_CONFIG.HURRICANE_POSITION_QUANTIZE_SCALE, // 後方互換のため維持 HURRICANE_ROTATION_QUANTIZE_SCALE: NETWORK_SYNC_CONFIG.HURRICANE_ROTATION_QUANTIZE_SCALE, // 後方互換のため維持 + HURRICANE_RELIABLE_RESYNC_INTERVAL_MS: NETWORK_SYNC_CONFIG.HURRICANE_RELIABLE_RESYNC_INTERVAL_MS, // 後方互換のため維持 // AOI設定(クライアント/サーバー契約) AOI_CELL_SIZE, diff --git a/packages/shared/src/domains/game/tick/index.ts b/packages/shared/src/domains/game/tick/index.ts index 2b0417e..8da92c2 100644 --- a/packages/shared/src/domains/game/tick/index.ts +++ b/packages/shared/src/domains/game/tick/index.ts @@ -5,4 +5,4 @@ */ /** tick同期関連の型を再公開する */ -export type { PlayerPositionUpdate, TickData } from "./tick.type"; +export type { HurricaneSyncData, PlayerPositionUpdate, TickData } from "./tick.type"; diff --git a/packages/shared/src/domains/game/tick/tick.type.ts b/packages/shared/src/domains/game/tick/tick.type.ts index e5d42f1..ff7bd8f 100644 --- a/packages/shared/src/domains/game/tick/tick.type.ts +++ b/packages/shared/src/domains/game/tick/tick.type.ts @@ -9,13 +9,17 @@ /** 1ティックで配信するプレイヤー座標差分 */ export type PlayerPositionUpdate = Pick; +/** 1ティック分のハリケーン同期データ */ +export type HurricaneSyncData = { + /** 初回同期や定期再同期で配信する全量スナップショット */ + snapshotUpdates: HurricaneStatePayload[]; + /** スナップショット間で配信する差分更新 */ + deltaUpdates: HurricaneStatePayload[]; +}; + /** 1ティック分のプレイヤー差分更新とマップ差分を表す共有データ */ export interface TickData { playerUpdates: PlayerPositionUpdate[]; cellUpdates: CellUpdate[]; - /** 出現直後に1回だけ配信するハリケーン初期同期スナップショット */ - hurricaneInitialSnapshot: HurricaneStatePayload[]; - /** 欠損復旧のため定期配信するハリケーン再同期スナップショット */ - hurricaneReliableSnapshot: HurricaneStatePayload[]; - hurricaneUpdates: HurricaneStatePayload[]; + hurricaneSync: HurricaneSyncData; } diff --git a/packages/shared/src/protocol/eventPayloads.ts b/packages/shared/src/protocol/eventPayloads.ts index dca324e..e74b3d3 100644 --- a/packages/shared/src/protocol/eventPayloads.ts +++ b/packages/shared/src/protocol/eventPayloads.ts @@ -26,6 +26,7 @@ HurricaneStatePayload, HurricaneSnapshotPayload, HurricaneDeltaPayload, + CurrentHurricanesPayload, UpdateHurricanesPayload, NewPlayerPayload, RemovePlayerPayload, diff --git a/packages/shared/src/protocol/maps/gameEventPayloadMap.ts b/packages/shared/src/protocol/maps/gameEventPayloadMap.ts index 41e7e2d..ed21e8b 100644 --- a/packages/shared/src/protocol/maps/gameEventPayloadMap.ts +++ b/packages/shared/src/protocol/maps/gameEventPayloadMap.ts @@ -10,6 +10,7 @@ BombPlacedAckPayload, BombPlacedPayload, CurrentPlayersPayload, + CurrentHurricanesPayload, GameResultPayload, GameStartPayload, HurricaneHitPayload, @@ -42,6 +43,7 @@ [SocketEvents.UPDATE_PLAYERS_SYNC]: UpdatePlayersPayload; [SocketEvents.REMOVE_PLAYER_SYNC]: RemovePlayerPayload; [SocketEvents.UPDATE_MAP_CELLS_SYNC]: UpdateMapCellsPayload; + [SocketEvents.CURRENT_HURRICANES_SYNC]: CurrentHurricanesPayload; [SocketEvents.UPDATE_HURRICANES_SYNC]: UpdateHurricanesPayload; [SocketEvents.BOMB_PLACED]: BombPlacedPayload; [SocketEvents.BOMB_PLACED_ACK]: BombPlacedAckPayload; diff --git a/packages/shared/src/protocol/payloads/gamePayloads.ts b/packages/shared/src/protocol/payloads/gamePayloads.ts index 76a60ee..a7f2cc9 100644 --- a/packages/shared/src/protocol/payloads/gamePayloads.ts +++ b/packages/shared/src/protocol/payloads/gamePayloads.ts @@ -87,6 +87,9 @@ /** update-hurricanes イベントで送受信するハリケーン差分配列 */ export type HurricaneDeltaPayload = HurricaneStatePayload[]; +/** current-hurricanes イベントで送受信するハリケーン全量配列 */ +export type CurrentHurricanesPayload = HurricaneSnapshotPayload; + /** update-hurricanes イベントで送受信するハリケーン差分配列(互換名) */ export type UpdateHurricanesPayload = HurricaneDeltaPayload; diff --git a/packages/shared/src/protocol/socketEvents.ts b/packages/shared/src/protocol/socketEvents.ts index 0648621..242ae61 100644 --- a/packages/shared/src/protocol/socketEvents.ts +++ b/packages/shared/src/protocol/socketEvents.ts @@ -24,6 +24,7 @@ UPDATE_PLAYERS_SYNC: "update-players", REMOVE_PLAYER_SYNC: "remove-player", UPDATE_MAP_CELLS_SYNC: "update-map-cells", + CURRENT_HURRICANES_SYNC: "current-hurricanes", UPDATE_HURRICANES_SYNC: "update-hurricanes", // 互換維持のため残す旧キー名 @@ -35,6 +36,7 @@ PLACE_BOMB: "place-bomb", BOMB_HIT_REPORT: "bomb-hit-report", UPDATE_MAP_CELLS: "update-map-cells", + CURRENT_HURRICANES: "current-hurricanes", UPDATE_HURRICANES: "update-hurricanes", BOMB_PLACED: "bomb-placed", BOMB_PLACED_ACK: "bomb-placed-ack",