refactor: separate Nakama provider concerns into context, refs, and state modules
- Extracted context contract to `contexts.ts` (NakamaContextType) - Added strongly typed internal provider refs in `refs.ts` - socketRef: React.RefObject<Socket | null> - gameMetadataRef: React.RefObject<GameMetadata | null> - Added `NakamaProviderState` in `states.ts` for React-managed provider state - session, socket, matchId, matchmakerTicket - Refactored NakamaProvider to use new modular structure - Replaced scattered useState/useRef with structured internal state + refs - Updated onMatchData to use MatchDataMessage model - Replaced deprecated MutableRefObject typing with RefObject - Cleaned update patterns using `updateState` helper - Updated imports to use new models and context structure - Improved separation of responsibilities: - models = pure domain types - context = exposed provider API - refs = internal mutable runtime refs - state = provider-managed reactive state - Ensured all Nakama provider functions fully typed and consistent with TS This refactor improves clarity, type safety, and maintainability for the Nakama real-time multiplayer provider.
This commit is contained in:
38
src/interfaces/contexts.ts
Normal file
38
src/interfaces/contexts.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
import {
|
||||
Client,
|
||||
Session,
|
||||
Socket,
|
||||
} from "@heroiclabs/nakama-js";
|
||||
|
||||
import {
|
||||
ApiMatch,
|
||||
ApiLeaderboardRecordList,
|
||||
// @ts-ignore
|
||||
} from "@heroiclabs/nakama-js/dist/api.gen"
|
||||
|
||||
import {
|
||||
GameMetadata,
|
||||
MatchDataMessage,
|
||||
} from './models'
|
||||
|
||||
|
||||
export interface NakamaContextType {
|
||||
client: Client;
|
||||
socket: Socket | null;
|
||||
session: Session | null;
|
||||
matchId: string | null;
|
||||
|
||||
loginOrRegister(username?: string): Promise<void>;
|
||||
logout(): Promise<void>;
|
||||
|
||||
joinMatchmaker(gameMetadata: GameMetadata): Promise<string>;
|
||||
exitMatchmaker(gameMetadata: GameMetadata): Promise<void>;
|
||||
joinMatch(matchId: string): Promise<void>;
|
||||
|
||||
sendMatchData(matchId: string, op: number, data: object): void;
|
||||
|
||||
onMatchData(cb: (msg: MatchDataMessage) => void): void;
|
||||
|
||||
getLeaderboardTop(): Promise<ApiLeaderboardRecordList>;
|
||||
listOpenMatches(): Promise<ApiMatch[]>;
|
||||
}
|
||||
36
src/interfaces/models.ts
Normal file
36
src/interfaces/models.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
export interface PlayerModel {
|
||||
user_id: string;
|
||||
username: string;
|
||||
index: number;
|
||||
metadata: Record<string, string>; // e.g. { symbol: "X" }
|
||||
}
|
||||
|
||||
export interface MatchDataMessage<T = any> {
|
||||
opCode: number;
|
||||
data: T;
|
||||
userId: string | null;
|
||||
}
|
||||
|
||||
export interface Board {
|
||||
grid: string[][];
|
||||
}
|
||||
|
||||
export interface GameState {
|
||||
boards: Record<string, Board>;
|
||||
turn: number;
|
||||
winner: string | null;
|
||||
gameOver: boolean;
|
||||
players: PlayerModel[];
|
||||
metadata: Record<string, any>;
|
||||
}
|
||||
|
||||
export interface GameMetadata {
|
||||
game: string;
|
||||
mode: string;
|
||||
}
|
||||
|
||||
export interface MatchDataMessage<T = any> {
|
||||
opCode: number;
|
||||
data: T;
|
||||
userId: string | null;
|
||||
}
|
||||
7
src/interfaces/props.ts
Normal file
7
src/interfaces/props.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import {
|
||||
MatchDataMessage,
|
||||
} from './models'
|
||||
|
||||
export interface PlayerProps {
|
||||
onMatchDataCallback: (msg:MatchDataMessage) => void;
|
||||
}
|
||||
15
src/interfaces/refs.ts
Normal file
15
src/interfaces/refs.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import React from "react";
|
||||
|
||||
import {
|
||||
Socket
|
||||
} from "@heroiclabs/nakama-js";
|
||||
|
||||
import {
|
||||
GameMetadata,
|
||||
} from './models'
|
||||
|
||||
|
||||
export interface NakamaRefs {
|
||||
socketRef: React.RefObject<Socket | null>;
|
||||
gameMetadataRef: React.RefObject<GameMetadata | null>;
|
||||
}
|
||||
11
src/interfaces/states.ts
Normal file
11
src/interfaces/states.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import {
|
||||
Session,
|
||||
Socket
|
||||
} from "@heroiclabs/nakama-js";
|
||||
|
||||
export interface NakamaProviderState {
|
||||
session: Session | null;
|
||||
socket: Socket | null;
|
||||
matchId: string | null;
|
||||
matchmakerTicket: string | null;
|
||||
}
|
||||
Reference in New Issue
Block a user