@aprovan/patchwork-image-boardgameio 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/index.d.ts +559 -0
- package/dist/index.js +1392 -0
- package/dist/index.js.map +1 -0
- package/package.json +79 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2022 zolvery
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,559 @@
|
|
|
1
|
+
import { Game, StorageAPI, State, LogEntry, Server, CredentialedActionShape, ChatMessage } from 'boardgame.io';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @aprovan/patchwork-image-boardgameio
|
|
5
|
+
*
|
|
6
|
+
* Setup function for the Boardgame.io image.
|
|
7
|
+
* Uses Tailwind Play CDN for runtime CSS generation.
|
|
8
|
+
*/
|
|
9
|
+
interface SetupOptions {
|
|
10
|
+
darkMode?: boolean | 'system';
|
|
11
|
+
cssRuntime?: boolean;
|
|
12
|
+
multiplayer?: boolean;
|
|
13
|
+
}
|
|
14
|
+
declare global {
|
|
15
|
+
interface Window {
|
|
16
|
+
tailwind?: {
|
|
17
|
+
config?: Record<string, unknown>;
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
declare function setup(container: HTMLElement, options?: SetupOptions): Promise<void>;
|
|
22
|
+
declare function cleanup(container: HTMLElement): void;
|
|
23
|
+
/**
|
|
24
|
+
* Ensures PeerJS is loaded (can be called directly by mount if needed)
|
|
25
|
+
*/
|
|
26
|
+
declare function ensurePeerJS(): Promise<void>;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Settings Context for boardgame.io widgets
|
|
30
|
+
*
|
|
31
|
+
* Provides game settings to board components via React context.
|
|
32
|
+
* Uses window.React at runtime (preloaded by the compiler).
|
|
33
|
+
*/
|
|
34
|
+
type GameSettings = Record<string, unknown>;
|
|
35
|
+
interface SettingsProviderProps {
|
|
36
|
+
settings: GameSettings;
|
|
37
|
+
children: unknown;
|
|
38
|
+
}
|
|
39
|
+
declare function SettingsProvider({ settings, children, }: SettingsProviderProps): unknown;
|
|
40
|
+
/**
|
|
41
|
+
* Hook to access game settings from within a board component.
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```tsx
|
|
45
|
+
* function MyBoard({ G, ctx, moves }: BoardProps) {
|
|
46
|
+
* const settings = useSettings<{ difficulty: string }>();
|
|
47
|
+
* // ...
|
|
48
|
+
* }
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
declare function useSettings<T extends GameSettings = GameSettings>(): T;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Bot Manager for boardgame.io widgets
|
|
55
|
+
*
|
|
56
|
+
* Centralizes bot execution with support for:
|
|
57
|
+
* - Multiple strategies (Random, MCTS, Custom)
|
|
58
|
+
* - Configurable delays with variable timing
|
|
59
|
+
* - Difficulty presets with mistake rates
|
|
60
|
+
* - Observable thinking state
|
|
61
|
+
*/
|
|
62
|
+
|
|
63
|
+
interface BoardgameState {
|
|
64
|
+
G: unknown;
|
|
65
|
+
ctx: {
|
|
66
|
+
currentPlayer: string;
|
|
67
|
+
gameover?: unknown;
|
|
68
|
+
turn?: number;
|
|
69
|
+
phase?: string;
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
type BotStrategy = 'random' | 'mcts' | 'custom';
|
|
73
|
+
type BotDifficulty = 'easy' | 'medium' | 'hard' | 'custom';
|
|
74
|
+
interface DifficultyPreset {
|
|
75
|
+
strategy: BotStrategy;
|
|
76
|
+
mctsIterations: number;
|
|
77
|
+
delay: number;
|
|
78
|
+
minDelay: number;
|
|
79
|
+
mistakeRate: number;
|
|
80
|
+
}
|
|
81
|
+
declare const DIFFICULTY_PRESETS: Record<BotDifficulty, DifficultyPreset>;
|
|
82
|
+
interface BotConfig {
|
|
83
|
+
/** Difficulty preset: 'easy', 'medium', 'hard', or 'custom' */
|
|
84
|
+
difficulty?: BotDifficulty;
|
|
85
|
+
/** Bot strategy: 'random' or 'mcts' (overrides difficulty preset) */
|
|
86
|
+
strategy?: BotStrategy;
|
|
87
|
+
/** Delay before bot makes move (ms). Default from difficulty. */
|
|
88
|
+
delay?: number;
|
|
89
|
+
/** Min delay for variable timing (ms). If set, delay becomes max. */
|
|
90
|
+
minDelay?: number;
|
|
91
|
+
/** MCTS iterations (only for strategy: 'mcts'). Default from difficulty. */
|
|
92
|
+
mctsIterations?: number;
|
|
93
|
+
/** Chance bot picks suboptimal move (0-1). Default from difficulty. */
|
|
94
|
+
mistakeRate?: number;
|
|
95
|
+
/** Custom bot factory (only for strategy: 'custom') */
|
|
96
|
+
customBot?: () => BotInstance;
|
|
97
|
+
}
|
|
98
|
+
interface ResolvedBotConfig {
|
|
99
|
+
strategy: BotStrategy;
|
|
100
|
+
delay: number;
|
|
101
|
+
minDelay: number;
|
|
102
|
+
mctsIterations: number;
|
|
103
|
+
mistakeRate: number;
|
|
104
|
+
customBot?: () => BotInstance;
|
|
105
|
+
}
|
|
106
|
+
interface BotState {
|
|
107
|
+
/** Whether a bot is currently "thinking" */
|
|
108
|
+
isThinking: boolean;
|
|
109
|
+
/** Which player ID is thinking (null if none) */
|
|
110
|
+
thinkingPlayer: string | null;
|
|
111
|
+
/** Estimated time remaining for bot move (ms, if calculable) */
|
|
112
|
+
estimatedTime?: number;
|
|
113
|
+
}
|
|
114
|
+
interface BotInstance {
|
|
115
|
+
play(state: BoardgameState, playerID: string): Promise<BotAction | null> | BotAction | null;
|
|
116
|
+
}
|
|
117
|
+
interface BotAction {
|
|
118
|
+
action?: {
|
|
119
|
+
payload: {
|
|
120
|
+
type: string;
|
|
121
|
+
args: unknown[];
|
|
122
|
+
};
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
interface EnumeratedMove {
|
|
126
|
+
move: string;
|
|
127
|
+
args: unknown[];
|
|
128
|
+
}
|
|
129
|
+
declare global {
|
|
130
|
+
interface Window {
|
|
131
|
+
BoardgameAI?: {
|
|
132
|
+
RandomBot?: new (opts: {
|
|
133
|
+
game: BoardgameGame;
|
|
134
|
+
enumerate: (G: unknown, ctx: unknown) => EnumeratedMove[];
|
|
135
|
+
}) => BotInstance;
|
|
136
|
+
MCTSBot?: new (opts: {
|
|
137
|
+
game: BoardgameGame;
|
|
138
|
+
enumerate: (G: unknown, ctx: unknown) => EnumeratedMove[];
|
|
139
|
+
iterations?: number;
|
|
140
|
+
playoutDepth?: number;
|
|
141
|
+
}) => BotInstance;
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Resolves bot configuration from inputs, game-specific overrides, and defaults.
|
|
147
|
+
*
|
|
148
|
+
* Resolution order:
|
|
149
|
+
* 1. Explicit input values (e.g., inputs.mctsIterations)
|
|
150
|
+
* 2. Game-specific difficulty preset (game.ai.difficulty[level])
|
|
151
|
+
* 3. Global difficulty preset (DIFFICULTY_PRESETS[level])
|
|
152
|
+
*/
|
|
153
|
+
declare function resolveBotConfig(inputs: Record<string, unknown>, gameAiDifficulty?: Partial<Record<BotDifficulty, Partial<DifficultyPreset>>>): ResolvedBotConfig;
|
|
154
|
+
/**
|
|
155
|
+
* Computes which player IDs should be controlled by bots.
|
|
156
|
+
*
|
|
157
|
+
* Bots fill all slots except the human player's slot.
|
|
158
|
+
*/
|
|
159
|
+
declare function computeBotPlayerIDs(numPlayers: number, botCount: number, humanPlayerID: string): string[];
|
|
160
|
+
declare class BotManager {
|
|
161
|
+
private game;
|
|
162
|
+
private config;
|
|
163
|
+
private bot;
|
|
164
|
+
private pendingMove;
|
|
165
|
+
private stateListeners;
|
|
166
|
+
private currentState;
|
|
167
|
+
private moveInProgress;
|
|
168
|
+
constructor(game: BoardgameGame, config: ResolvedBotConfig);
|
|
169
|
+
private initializeBot;
|
|
170
|
+
/**
|
|
171
|
+
* Select a move, potentially with mistakes for easier difficulties.
|
|
172
|
+
*/
|
|
173
|
+
private selectMove;
|
|
174
|
+
/**
|
|
175
|
+
* Check if it's a bot's turn and schedule a move if so.
|
|
176
|
+
* Call this after every state update.
|
|
177
|
+
*/
|
|
178
|
+
maybePlayBot(state: BoardgameState, botPlayerIDs: string[], makeMove: (type: string, ...args: unknown[]) => void): Promise<void>;
|
|
179
|
+
/** Subscribe to bot state changes */
|
|
180
|
+
subscribe(listener: (state: BotState) => void): () => void;
|
|
181
|
+
/** Get current bot state */
|
|
182
|
+
getState(): BotState;
|
|
183
|
+
private notifyState;
|
|
184
|
+
private cancelPendingMove;
|
|
185
|
+
dispose(): void;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Mount helper for boardgame.io widgets
|
|
190
|
+
*
|
|
191
|
+
* Handles mounting automatically when widgets export `game` and `app` (or default).
|
|
192
|
+
* The image detects these exports and creates the mount - widgets don't need to
|
|
193
|
+
* reference image internals.
|
|
194
|
+
*
|
|
195
|
+
* Uses window.React at runtime (preloaded by the compiler).
|
|
196
|
+
*/
|
|
197
|
+
|
|
198
|
+
/** Multiplayer configuration passed via inputs */
|
|
199
|
+
interface MultiplayerInput {
|
|
200
|
+
matchID: string;
|
|
201
|
+
playerID: string;
|
|
202
|
+
credentials?: string;
|
|
203
|
+
isHost?: boolean;
|
|
204
|
+
}
|
|
205
|
+
interface GameMountOptions {
|
|
206
|
+
/** Number of players for the game */
|
|
207
|
+
numPlayers?: number;
|
|
208
|
+
/** Default player ID */
|
|
209
|
+
defaultPlayerID?: string;
|
|
210
|
+
}
|
|
211
|
+
interface BoardgameGame {
|
|
212
|
+
name?: string;
|
|
213
|
+
minPlayers?: number;
|
|
214
|
+
maxPlayers?: number;
|
|
215
|
+
setup: (context: unknown) => unknown;
|
|
216
|
+
ai?: {
|
|
217
|
+
/** Enumerate legal moves for bot players */
|
|
218
|
+
enumerate: (G: unknown, ctx: unknown) => Array<{
|
|
219
|
+
move: string;
|
|
220
|
+
args: unknown[];
|
|
221
|
+
}>;
|
|
222
|
+
/** Optional game-specific difficulty presets */
|
|
223
|
+
difficulty?: Partial<Record<BotDifficulty, Partial<DifficultyPreset>>>;
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
/** Manifest structure for player count */
|
|
227
|
+
interface WidgetManifest {
|
|
228
|
+
players?: {
|
|
229
|
+
min?: number;
|
|
230
|
+
max?: number;
|
|
231
|
+
};
|
|
232
|
+
[key: string]: unknown;
|
|
233
|
+
}
|
|
234
|
+
type BoardComponent = (props: any) => unknown;
|
|
235
|
+
declare global {
|
|
236
|
+
interface Window {
|
|
237
|
+
BoardgameReact?: {
|
|
238
|
+
Client: (opts: {
|
|
239
|
+
game: BoardgameGame;
|
|
240
|
+
board: BoardComponent;
|
|
241
|
+
numPlayers?: number;
|
|
242
|
+
multiplayer?: unknown;
|
|
243
|
+
}) => any;
|
|
244
|
+
};
|
|
245
|
+
BoardgameMultiplayer?: {
|
|
246
|
+
Local?: () => unknown;
|
|
247
|
+
};
|
|
248
|
+
React?: any;
|
|
249
|
+
ReactDOM?: {
|
|
250
|
+
createRoot: (el: HTMLElement) => {
|
|
251
|
+
render: (el: unknown) => void;
|
|
252
|
+
unmount: () => void;
|
|
253
|
+
};
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Creates a mount function for a boardgame.io widget.
|
|
259
|
+
*
|
|
260
|
+
* @param game - The boardgame.io game definition
|
|
261
|
+
* @param Board - The React board component
|
|
262
|
+
* @param options - Mount options (numPlayers, defaultPlayerID)
|
|
263
|
+
* @returns A mount function compatible with the patchwork runtime
|
|
264
|
+
*
|
|
265
|
+
* @example
|
|
266
|
+
* ```tsx
|
|
267
|
+
* export const game = { name: 'my-game', setup: () => ({}) };
|
|
268
|
+
* export default function MyBoard({ G, ctx, moves }) { ... }
|
|
269
|
+
* export const mount = createGameMount(game, MyBoard, { numPlayers: 2 });
|
|
270
|
+
* ```
|
|
271
|
+
*/
|
|
272
|
+
declare function createGameMount(game: BoardgameGame, Board: BoardComponent, options?: GameMountOptions): (container: HTMLElement, inputs?: GameSettings) => () => void;
|
|
273
|
+
/**
|
|
274
|
+
* Widget module structure expected by the boardgameio image.
|
|
275
|
+
* Widgets should export `game` and either `app` or `default`.
|
|
276
|
+
*/
|
|
277
|
+
interface BoardgameWidgetModule {
|
|
278
|
+
game: BoardgameGame;
|
|
279
|
+
app?: BoardComponent;
|
|
280
|
+
default?: BoardComponent;
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Creates a mount function from a widget module's exports.
|
|
284
|
+
* Called automatically by the runtime when it detects a boardgameio widget.
|
|
285
|
+
*
|
|
286
|
+
* @param module - The widget module with game and app/default exports
|
|
287
|
+
* @param manifest - The widget manifest (for player count settings)
|
|
288
|
+
* @returns A mount function or null if not a valid boardgameio widget
|
|
289
|
+
*/
|
|
290
|
+
declare function createMountFromExports(module: BoardgameWidgetModule, manifest?: WidgetManifest): ((container: HTMLElement, inputs?: GameSettings) => () => void) | null;
|
|
291
|
+
/**
|
|
292
|
+
* Injects the mount helpers onto the window for runtime access.
|
|
293
|
+
* Called during image setup.
|
|
294
|
+
*/
|
|
295
|
+
declare function injectMountHelper(): void;
|
|
296
|
+
/**
|
|
297
|
+
* Image mount function - handles mounting widgets for the boardgameio image.
|
|
298
|
+
*
|
|
299
|
+
* Supports three patterns:
|
|
300
|
+
* 1. BoardGame.io widgets: exports `game` and `app`/`default`
|
|
301
|
+
* 2. Custom mount: exports a `mount` function
|
|
302
|
+
* 3. React component: exports `default` as a React component
|
|
303
|
+
*
|
|
304
|
+
* @param module - The widget module exports
|
|
305
|
+
* @param container - The DOM element to mount into
|
|
306
|
+
* @param inputs - Props/settings to pass to the widget
|
|
307
|
+
* @returns A cleanup function to unmount, or void
|
|
308
|
+
*/
|
|
309
|
+
declare function mount(module: Record<string, unknown>, container: HTMLElement, inputs: Record<string, unknown>): Promise<void | (() => void)>;
|
|
310
|
+
|
|
311
|
+
interface MultiplayerConfig {
|
|
312
|
+
isMultiplayer: boolean;
|
|
313
|
+
isHost?: boolean;
|
|
314
|
+
appId: string;
|
|
315
|
+
matchID?: string;
|
|
316
|
+
botCount?: number;
|
|
317
|
+
}
|
|
318
|
+
declare function getMultiplayer(config: MultiplayerConfig, game?: Game): unknown;
|
|
319
|
+
declare function generateMatchID(): string;
|
|
320
|
+
|
|
321
|
+
declare class P2PDB {
|
|
322
|
+
private initialState;
|
|
323
|
+
private state;
|
|
324
|
+
private log;
|
|
325
|
+
private metadata;
|
|
326
|
+
connect(): void;
|
|
327
|
+
createMatch(matchID: string, opts: StorageAPI.CreateMatchOpts): void;
|
|
328
|
+
setState(matchID: string, state: State, deltalog?: LogEntry[]): void;
|
|
329
|
+
setMetadata(matchID: string, metadata: Server.MatchData): void;
|
|
330
|
+
fetch<O extends StorageAPI.FetchOpts>(matchID: string): StorageAPI.FetchResult<O>;
|
|
331
|
+
wipe(matchID: string): void;
|
|
332
|
+
listMatches(): string[];
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
interface ClientMetadata {
|
|
336
|
+
playerID: string | null;
|
|
337
|
+
credentials?: string;
|
|
338
|
+
message?: string;
|
|
339
|
+
}
|
|
340
|
+
interface Client {
|
|
341
|
+
metadata: ClientMetadata;
|
|
342
|
+
send: (data: unknown) => void;
|
|
343
|
+
}
|
|
344
|
+
type ClientAction = {
|
|
345
|
+
type: 'sync';
|
|
346
|
+
} | {
|
|
347
|
+
type: 'update';
|
|
348
|
+
args: [string, State, CredentialedActionShape.Any];
|
|
349
|
+
} | {
|
|
350
|
+
type: 'chat';
|
|
351
|
+
args: [string, ChatMessage, string | undefined];
|
|
352
|
+
};
|
|
353
|
+
|
|
354
|
+
declare function generateCredentials(): string;
|
|
355
|
+
declare function generateKeyPair(): {
|
|
356
|
+
publicKey: string;
|
|
357
|
+
privateKey: string;
|
|
358
|
+
};
|
|
359
|
+
|
|
360
|
+
declare class P2PHost {
|
|
361
|
+
private clients;
|
|
362
|
+
private hostClient;
|
|
363
|
+
private matchID;
|
|
364
|
+
private db;
|
|
365
|
+
private game;
|
|
366
|
+
private numPlayers;
|
|
367
|
+
private state;
|
|
368
|
+
constructor({ game, numPlayers, matchID, }: {
|
|
369
|
+
game: Game;
|
|
370
|
+
numPlayers?: number;
|
|
371
|
+
matchID: string;
|
|
372
|
+
});
|
|
373
|
+
private persistSession;
|
|
374
|
+
private createInitialState;
|
|
375
|
+
registerClient(client: Client): void;
|
|
376
|
+
registerHostClient(client: Client): void;
|
|
377
|
+
unregisterClient(client: Client): void;
|
|
378
|
+
processAction(client: Client, data: ClientAction): void;
|
|
379
|
+
private syncClient;
|
|
380
|
+
private filterStateForPlayer;
|
|
381
|
+
private handleUpdate;
|
|
382
|
+
private broadcastState;
|
|
383
|
+
private broadcastChat;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
declare global {
|
|
387
|
+
interface Window {
|
|
388
|
+
Peer?: new (id?: string, options?: object) => PeerInstance;
|
|
389
|
+
__peerConfig?: {
|
|
390
|
+
host?: string;
|
|
391
|
+
port?: number;
|
|
392
|
+
path?: string;
|
|
393
|
+
secure?: boolean;
|
|
394
|
+
iceServers?: RTCIceServer[];
|
|
395
|
+
};
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
interface DataConnection {
|
|
399
|
+
on(event: 'data' | 'open' | 'close' | 'error', handler: (data?: unknown) => void): void;
|
|
400
|
+
send(data: unknown): void;
|
|
401
|
+
close(): void;
|
|
402
|
+
}
|
|
403
|
+
interface PeerInstance {
|
|
404
|
+
on(event: 'open' | 'connection' | 'error' | 'close', handler: (data?: unknown) => void): void;
|
|
405
|
+
connect(peerId: string, options?: {
|
|
406
|
+
reliable?: boolean;
|
|
407
|
+
serialization?: string;
|
|
408
|
+
}): DataConnection;
|
|
409
|
+
destroy(): void;
|
|
410
|
+
id: string;
|
|
411
|
+
}
|
|
412
|
+
type TransportData = {
|
|
413
|
+
type: 'sync' | 'update' | 'chat';
|
|
414
|
+
args: unknown[];
|
|
415
|
+
};
|
|
416
|
+
interface P2PTransportOpts {
|
|
417
|
+
isHost?: boolean;
|
|
418
|
+
peerOptions?: object;
|
|
419
|
+
onError?: (error: Error) => void;
|
|
420
|
+
}
|
|
421
|
+
interface TransportConfig {
|
|
422
|
+
gameName: string;
|
|
423
|
+
playerID: string | null;
|
|
424
|
+
matchID: string;
|
|
425
|
+
credentials?: string;
|
|
426
|
+
numPlayers: number;
|
|
427
|
+
game: Game;
|
|
428
|
+
transportDataCallback: (data: TransportData) => void;
|
|
429
|
+
}
|
|
430
|
+
declare class P2PTransport {
|
|
431
|
+
private peer;
|
|
432
|
+
private connection;
|
|
433
|
+
private host;
|
|
434
|
+
private isHost;
|
|
435
|
+
private game;
|
|
436
|
+
private gameName;
|
|
437
|
+
private playerID;
|
|
438
|
+
private matchID;
|
|
439
|
+
private credentials?;
|
|
440
|
+
private numPlayers;
|
|
441
|
+
private privateKey?;
|
|
442
|
+
private transportDataCallback;
|
|
443
|
+
private peerOptions?;
|
|
444
|
+
private onError?;
|
|
445
|
+
private connected;
|
|
446
|
+
private connectionStatusCallbacks;
|
|
447
|
+
private hostRetryCount;
|
|
448
|
+
private maxHostRetries;
|
|
449
|
+
private lastPeerConfig;
|
|
450
|
+
constructor(config: TransportConfig, opts?: P2PTransportOpts);
|
|
451
|
+
private get hostID();
|
|
452
|
+
private setCredentials;
|
|
453
|
+
private get metadata();
|
|
454
|
+
connect(): void;
|
|
455
|
+
private createPeer;
|
|
456
|
+
private retryCount;
|
|
457
|
+
private maxRetries;
|
|
458
|
+
private retryDelayMs;
|
|
459
|
+
private connectToHost;
|
|
460
|
+
private onConnect;
|
|
461
|
+
private notifyConnectionStatus;
|
|
462
|
+
private notifyClient;
|
|
463
|
+
disconnect(): void;
|
|
464
|
+
requestSync(): void;
|
|
465
|
+
sendAction(state: State, action: CredentialedActionShape.Any): void;
|
|
466
|
+
sendChatMessage(matchID: string, chatMessage: ChatMessage): void;
|
|
467
|
+
updateMatchID(id: string): void;
|
|
468
|
+
updatePlayerID(id: string): void;
|
|
469
|
+
updateCredentials(credentials?: string): void;
|
|
470
|
+
isConnected(): boolean;
|
|
471
|
+
subscribeToConnectionStatus(callback: (connected: boolean) => void): () => void;
|
|
472
|
+
}
|
|
473
|
+
declare function createP2PTransport(opts?: P2PTransportOpts): (config: TransportConfig) => P2PTransport;
|
|
474
|
+
|
|
475
|
+
/**
|
|
476
|
+
* Type definitions for boardgame.io widgets with bot support.
|
|
477
|
+
*/
|
|
478
|
+
|
|
479
|
+
/**
|
|
480
|
+
* BoardGame.io context object
|
|
481
|
+
*/
|
|
482
|
+
interface Ctx {
|
|
483
|
+
currentPlayer: string;
|
|
484
|
+
numPlayers: number;
|
|
485
|
+
turn: number;
|
|
486
|
+
phase: string | null;
|
|
487
|
+
gameover?: unknown;
|
|
488
|
+
playOrder: string[];
|
|
489
|
+
playOrderPos: number;
|
|
490
|
+
activePlayers: Record<string, string> | null;
|
|
491
|
+
}
|
|
492
|
+
/**
|
|
493
|
+
* Extended board props with bot-related information.
|
|
494
|
+
*
|
|
495
|
+
* All board components receive these props when mounted via createGameMount.
|
|
496
|
+
*/
|
|
497
|
+
interface BoardPropsWithBots<G = unknown> {
|
|
498
|
+
/** Game state */
|
|
499
|
+
G: G;
|
|
500
|
+
/** BoardGame.io context */
|
|
501
|
+
ctx: Ctx;
|
|
502
|
+
/** Available moves */
|
|
503
|
+
moves: Record<string, (...args: unknown[]) => void>;
|
|
504
|
+
/** BoardGame.io events (endTurn, setActivePlayers, etc) */
|
|
505
|
+
events: Record<string, (...args: unknown[]) => void>;
|
|
506
|
+
/** The player ID for this client */
|
|
507
|
+
playerID: string;
|
|
508
|
+
/** Whether it's this player's turn */
|
|
509
|
+
isActive: boolean;
|
|
510
|
+
/** Bot thinking state (injected by mount) */
|
|
511
|
+
botState: BotState;
|
|
512
|
+
/** List of player IDs controlled by bots */
|
|
513
|
+
botPlayerIDs: string[];
|
|
514
|
+
/** Total number of bots in the game */
|
|
515
|
+
botCount: number;
|
|
516
|
+
/** Current difficulty setting */
|
|
517
|
+
botDifficulty: BotDifficulty;
|
|
518
|
+
/** Whether this is a multiplayer game */
|
|
519
|
+
isMultiplayer: boolean;
|
|
520
|
+
}
|
|
521
|
+
/**
|
|
522
|
+
* Props for boards that don't use bots.
|
|
523
|
+
* Maintains backward compatibility with existing games.
|
|
524
|
+
*/
|
|
525
|
+
interface BoardProps<G = unknown> {
|
|
526
|
+
G: G;
|
|
527
|
+
ctx: Ctx;
|
|
528
|
+
moves: Record<string, (...args: unknown[]) => void>;
|
|
529
|
+
events: Record<string, (...args: unknown[]) => void>;
|
|
530
|
+
playerID: string;
|
|
531
|
+
isActive: boolean;
|
|
532
|
+
isMultiplayer?: boolean;
|
|
533
|
+
botCount?: number;
|
|
534
|
+
}
|
|
535
|
+
/**
|
|
536
|
+
* Game settings that can be passed via inputs.
|
|
537
|
+
*/
|
|
538
|
+
interface BotGameSettings {
|
|
539
|
+
/** Total player count */
|
|
540
|
+
numPlayers?: number;
|
|
541
|
+
/** Number of bot players */
|
|
542
|
+
botCount?: number;
|
|
543
|
+
/** Bot difficulty preset */
|
|
544
|
+
botDifficulty?: BotDifficulty;
|
|
545
|
+
/** Bot strategy override */
|
|
546
|
+
botStrategy?: 'random' | 'mcts' | 'custom';
|
|
547
|
+
/** Delay before bot move (ms) */
|
|
548
|
+
botDelay?: number;
|
|
549
|
+
/** Minimum delay for variable timing (ms) */
|
|
550
|
+
botMinDelay?: number;
|
|
551
|
+
/** MCTS iterations (for mcts strategy) */
|
|
552
|
+
mctsIterations?: number;
|
|
553
|
+
/** Chance of suboptimal move (0-1) */
|
|
554
|
+
botMistakeRate?: number;
|
|
555
|
+
/** Player ID for this client */
|
|
556
|
+
playerID?: string;
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
export { type BoardProps, type BoardPropsWithBots, type BoardgameGame, type BoardgameState, type BoardgameWidgetModule, type BotConfig, type BotDifficulty, type BotGameSettings, BotManager, type BotState, type BotStrategy, type Ctx, DIFFICULTY_PRESETS, type DifficultyPreset, type GameMountOptions, type GameSettings, type MultiplayerConfig, type MultiplayerInput, P2PDB, P2PHost, P2PTransport, type P2PTransportOpts, type ResolvedBotConfig, SettingsProvider, type SettingsProviderProps, type SetupOptions, type TransportConfig, type WidgetManifest, cleanup, computeBotPlayerIDs, createGameMount, createMountFromExports, createP2PTransport, ensurePeerJS, generateCredentials, generateKeyPair, generateMatchID, getMultiplayer, injectMountHelper, mount, resolveBotConfig, setup, useSettings };
|