/**
* NetworkSubscriptions
* ゲーム中のソケット購読定義を辞書形式で生成する
* bind と unbind の対応関係を一元管理する
*/
import { socketManager } from "@client/network/SocketManager";
import type {
BombPlacedAckPayload,
BombPlacedPayload,
CurrentPlayersPayload,
GameStartPayload,
NewPlayerPayload,
PlayerDeadPayload,
RemovePlayerPayload,
UpdateMapCellsPayload,
UpdatePlayersPayload,
} from "@repo/shared";
/** ソケット購読の bind と unbind を保持する型 */
export type SocketSubscription = {
bind: () => void;
unbind: () => void;
};
/** ゲーム中に利用する購読辞書の型 */
export type SocketSubscriptionDictionary = {
currentPlayers: SocketSubscription;
newPlayer: SocketSubscription;
gameStart: SocketSubscription;
updatePlayers: SocketSubscription;
removePlayer: SocketSubscription;
updateMapCells: SocketSubscription;
gameEnd: SocketSubscription;
bombPlaced: SocketSubscription;
bombPlacedAck: SocketSubscription;
playerDead: SocketSubscription;
};
/** 購読辞書生成に必要なハンドラ群 */
export type NetworkSubscriptionHandlers = {
onCurrentPlayers: (payload: CurrentPlayersPayload) => void;
onNewPlayer: (payload: NewPlayerPayload) => void;
onGameStart: (payload: GameStartPayload) => void;
onUpdatePlayers: (payload: UpdatePlayersPayload) => void;
onRemovePlayer: (payload: RemovePlayerPayload) => void;
onUpdateMapCells: (payload: UpdateMapCellsPayload) => void;
onGameEnd: () => void;
onBombPlaced: (payload: BombPlacedPayload) => void;
onBombPlacedAck: (payload: BombPlacedAckPayload) => void;
onPlayerDead: (payload: PlayerDeadPayload) => void;
};
type SubscriptionDefinition = {
key: keyof SocketSubscriptionDictionary;
create: (handlers: NetworkSubscriptionHandlers) => SocketSubscription;
};
const SUBSCRIPTION_DEFINITIONS: SubscriptionDefinition[] = [
{
key: "currentPlayers",
create: (handlers) => ({
bind: () => socketManager.game.onCurrentPlayers(handlers.onCurrentPlayers),
unbind: () => socketManager.game.offCurrentPlayers(handlers.onCurrentPlayers),
}),
},
{
key: "newPlayer",
create: (handlers) => ({
bind: () => socketManager.game.onNewPlayer(handlers.onNewPlayer),
unbind: () => socketManager.game.offNewPlayer(handlers.onNewPlayer),
}),
},
{
key: "gameStart",
create: (handlers) => ({
bind: () => socketManager.game.onGameStart(handlers.onGameStart),
unbind: () => socketManager.game.offGameStart(handlers.onGameStart),
}),
},
{
key: "updatePlayers",
create: (handlers) => ({
bind: () => socketManager.game.onUpdatePlayers(handlers.onUpdatePlayers),
unbind: () => socketManager.game.offUpdatePlayers(handlers.onUpdatePlayers),
}),
},
{
key: "removePlayer",
create: (handlers) => ({
bind: () => socketManager.game.onRemovePlayer(handlers.onRemovePlayer),
unbind: () => socketManager.game.offRemovePlayer(handlers.onRemovePlayer),
}),
},
{
key: "updateMapCells",
create: (handlers) => ({
bind: () => socketManager.game.onUpdateMapCells(handlers.onUpdateMapCells),
unbind: () => socketManager.game.offUpdateMapCells(handlers.onUpdateMapCells),
}),
},
{
key: "gameEnd",
create: (handlers) => ({
bind: () => socketManager.game.onGameEnd(handlers.onGameEnd),
unbind: () => socketManager.game.offGameEnd(handlers.onGameEnd),
}),
},
{
key: "bombPlaced",
create: (handlers) => ({
bind: () => socketManager.game.onBombPlaced(handlers.onBombPlaced),
unbind: () => socketManager.game.offBombPlaced(handlers.onBombPlaced),
}),
},
{
key: "bombPlacedAck",
create: (handlers) => ({
bind: () => socketManager.game.onBombPlacedAck(handlers.onBombPlacedAck),
unbind: () => socketManager.game.offBombPlacedAck(handlers.onBombPlacedAck),
}),
},
{
key: "playerDead",
create: (handlers) => ({
bind: () => socketManager.game.onPlayerDead(handlers.onPlayerDead),
unbind: () => socketManager.game.offPlayerDead(handlers.onPlayerDead),
}),
},
];
/** ソケット購読辞書を生成する */
export const createNetworkSubscriptions = (
handlers: NetworkSubscriptionHandlers,
): SocketSubscriptionDictionary => {
return SUBSCRIPTION_DEFINITIONS.reduce<SocketSubscriptionDictionary>((dictionary, definition) => {
dictionary[definition.key] = definition.create(handlers);
return dictionary;
}, {} as SocketSubscriptionDictionary);
};