dreamboard 0.1.15 → 0.1.17
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.
|
@@ -5509,7 +5509,7 @@ function renderCardPropertiesSchemaByCardSetId(cardSets) {
|
|
|
5509
5509
|
` ${quote(cardSet.id)}: ${toPascalCase(cardSet.id)}CardPropertiesSchema,`
|
|
5510
5510
|
];
|
|
5511
5511
|
});
|
|
5512
|
-
return `const cardPropertiesSchemaByCardSetId: Record<string, z.
|
|
5512
|
+
return `const cardPropertiesSchemaByCardSetId: Record<string, z.ZodType<unknown>> = {
|
|
5513
5513
|
${entries.join("\n")}
|
|
5514
5514
|
};`;
|
|
5515
5515
|
}
|
|
@@ -5715,7 +5715,7 @@ function renderCardStateSchemaById(analysis) {
|
|
|
5715
5715
|
return `z.object(
|
|
5716
5716
|
Object.fromEntries(
|
|
5717
5717
|
literals.cardIds.map((cardId) => [cardId, createCardStateSchema(cardId)]),
|
|
5718
|
-
) as Record<CardId, z.
|
|
5718
|
+
) as Record<CardId, z.ZodType<unknown>>,
|
|
5719
5719
|
)`;
|
|
5720
5720
|
}
|
|
5721
5721
|
function renderCardStateSchemaFactory(analysis) {
|
|
@@ -5793,8 +5793,17 @@ function renderGenericBoardStateSchema(board, runtimeBoardId) {
|
|
|
5793
5793
|
playerId: ${playerId ? `z.literal(${quote(playerId)})` : "ids.playerId.nullable().optional()"},
|
|
5794
5794
|
templateId: z.string().nullable().optional(),
|
|
5795
5795
|
fields: ${`${boardFieldsTypeName(board.board.id)}Schema`},
|
|
5796
|
+
// T220: per-board state.spaces is loose-keyed by string. The
|
|
5797
|
+
// canonical narrow id (\`ids.spaceId\`) is a Zod enum of EVERY
|
|
5798
|
+
// space id across every board, which makes a strict
|
|
5799
|
+
// \`z.record(enum, \u2026)\` reject any board whose spaces are a
|
|
5800
|
+
// proper subset of that enum. Loose keying matches the JSON wire
|
|
5801
|
+
// shape (\`additionalProperties\`); the inner \`id: ids.spaceId\`
|
|
5802
|
+
// narrows the value's spaceId at parse time. A future per-board
|
|
5803
|
+
// branded-id refactor (option B) can re-tighten this without a
|
|
5804
|
+
// wire change.
|
|
5796
5805
|
spaces: z.record(
|
|
5797
|
-
|
|
5806
|
+
z.string(),
|
|
5798
5807
|
z.object({
|
|
5799
5808
|
id: ids.spaceId,
|
|
5800
5809
|
name: z.string().nullable().optional(),
|
|
@@ -5840,8 +5849,9 @@ function renderHexBoardStateSchema(board, runtimeBoardId) {
|
|
|
5840
5849
|
playerId: ${playerId ? `z.literal(${quote(playerId)})` : "ids.playerId.nullable().optional()"},
|
|
5841
5850
|
templateId: z.string().nullable().optional(),
|
|
5842
5851
|
fields: ${`${boardFieldsTypeName(board.board.id)}Schema`},
|
|
5852
|
+
// T220: see generic-board comment on the loose-keying choice.
|
|
5843
5853
|
spaces: z.record(
|
|
5844
|
-
|
|
5854
|
+
z.string(),
|
|
5845
5855
|
z.object({
|
|
5846
5856
|
id: ids.spaceId,
|
|
5847
5857
|
name: z.string().nullable().optional(),
|
|
@@ -5897,8 +5907,9 @@ function renderSquareBoardStateSchema(board, runtimeBoardId) {
|
|
|
5897
5907
|
playerId: ${playerId ? `z.literal(${quote(playerId)})` : "ids.playerId.nullable().optional()"},
|
|
5898
5908
|
templateId: z.string().nullable().optional(),
|
|
5899
5909
|
fields: ${`${boardFieldsTypeName(board.board.id)}Schema`},
|
|
5910
|
+
// T220: see generic-board comment on the loose-keying choice.
|
|
5900
5911
|
spaces: z.record(
|
|
5901
|
-
|
|
5912
|
+
z.string(),
|
|
5902
5913
|
z.object({
|
|
5903
5914
|
id: ids.spaceId,
|
|
5904
5915
|
name: z.string().nullable().optional(),
|
|
@@ -7611,7 +7622,11 @@ const runtimeGenericBoardStateSchema = z.object({
|
|
|
7611
7622
|
playerId: ids.playerId.nullable().optional(),
|
|
7612
7623
|
templateId: z.string().nullable().optional(),
|
|
7613
7624
|
fields: unknownRecordSchema,
|
|
7614
|
-
|
|
7625
|
+
// T220: per-board state.spaces is loose-keyed by string. See the
|
|
7626
|
+
// codegen-template comment in renderGenericBoardStateSchema for
|
|
7627
|
+
// the rationale; the wire shape is unchanged (additionalProperties
|
|
7628
|
+
// JSON), and the inner id field narrows at parse time.
|
|
7629
|
+
spaces: z.record(z.string(), boardSpaceStateSchema),
|
|
7615
7630
|
relations: z.array(boardRelationStateSchema),
|
|
7616
7631
|
containers: z.record(ids.boardContainerId, boardContainerStateSchema),
|
|
7617
7632
|
});
|
|
@@ -7641,7 +7656,8 @@ const squareVertexStateSchema = z.object({
|
|
|
7641
7656
|
});
|
|
7642
7657
|
const runtimeHexBoardStateSchema = runtimeGenericBoardStateSchema.extend({
|
|
7643
7658
|
layout: z.literal("hex"),
|
|
7644
|
-
|
|
7659
|
+
// T220: loose-keyed by string \u2014 see comment above.
|
|
7660
|
+
spaces: z.record(z.string(), hexSpaceStateSchema),
|
|
7645
7661
|
relations: z.array(boardRelationStateSchema),
|
|
7646
7662
|
containers: z.object({}),
|
|
7647
7663
|
orientation: z.enum(["pointy-top", "flat-top"]),
|
|
@@ -7650,7 +7666,8 @@ const runtimeHexBoardStateSchema = runtimeGenericBoardStateSchema.extend({
|
|
|
7650
7666
|
});
|
|
7651
7667
|
const runtimeSquareBoardStateSchema = runtimeGenericBoardStateSchema.extend({
|
|
7652
7668
|
layout: z.literal("square"),
|
|
7653
|
-
|
|
7669
|
+
// T220: loose-keyed by string \u2014 see comment above.
|
|
7670
|
+
spaces: z.record(z.string(), squareSpaceStateSchema),
|
|
7654
7671
|
relations: z.array(boardRelationStateSchema),
|
|
7655
7672
|
containers: z.record(ids.boardContainerId, boardContainerStateSchema),
|
|
7656
7673
|
edges: z.array(hexEdgeStateSchema),
|
|
@@ -7862,11 +7879,11 @@ export const schemas = {
|
|
|
7862
7879
|
} as const;
|
|
7863
7880
|
|
|
7864
7881
|
export function createGameStateSchema<
|
|
7865
|
-
PhaseNameSchema extends z.
|
|
7866
|
-
PublicSchema extends z.
|
|
7867
|
-
PrivateSchema extends z.
|
|
7868
|
-
HiddenSchema extends z.
|
|
7869
|
-
PhasesSchema extends z.
|
|
7882
|
+
PhaseNameSchema extends z.ZodType<unknown>,
|
|
7883
|
+
PublicSchema extends z.ZodType<unknown>,
|
|
7884
|
+
PrivateSchema extends z.ZodType<unknown>,
|
|
7885
|
+
HiddenSchema extends z.ZodType<unknown>,
|
|
7886
|
+
PhasesSchema extends z.ZodType<unknown>,
|
|
7870
7887
|
>({
|
|
7871
7888
|
phaseNameSchema,
|
|
7872
7889
|
publicSchema,
|
|
@@ -8050,6 +8067,27 @@ import { literals } from "./manifest-literals";
|
|
|
8050
8067
|
import type { PlayerId as PublicPlayerId, TableState as PublicTableState } from "./manifest-types";
|
|
8051
8068
|
|
|
8052
8069
|
const unknownRecordSchema`
|
|
8070
|
+
).replaceAll(
|
|
8071
|
+
"literals.playerIds as unknown as readonly PlayerId[]",
|
|
8072
|
+
"literals.playerIds"
|
|
8073
|
+
).replaceAll(
|
|
8074
|
+
"cardId: cardIdSchema as unknown as z.ZodType<CardId>,",
|
|
8075
|
+
"cardId: assumeManifestSchema<CardId>(cardIdSchema),"
|
|
8076
|
+
).replaceAll(
|
|
8077
|
+
"deckId: deckIdSchema as unknown as z.ZodType<DeckId>,",
|
|
8078
|
+
"deckId: assumeManifestSchema<DeckId>(deckIdSchema),"
|
|
8079
|
+
).replaceAll(
|
|
8080
|
+
"handId: handIdSchema as unknown as z.ZodType<HandId>,",
|
|
8081
|
+
"handId: assumeManifestSchema<HandId>(handIdSchema),"
|
|
8082
|
+
).replace(
|
|
8083
|
+
/export const staticBoards = ([\s\S]*?) as const;\n\nconst baseInitialTable = /,
|
|
8084
|
+
"export const staticBoards = $1 as const satisfies StaticBoards<PublicTableState>;\n\nconst baseInitialTable = "
|
|
8085
|
+
).replace(
|
|
8086
|
+
/const baseInitialTable = ([\s\S]*?) as const as unknown as TableState;\nconst baseDeckCardsByZoneId:/,
|
|
8087
|
+
"const baseInitialTable = cloneManifestDefault<PublicTableState>($1);\nconst baseDeckCardsByZoneId:"
|
|
8088
|
+
).replace(
|
|
8089
|
+
"staticBoards: staticBoards as unknown as StaticBoards<TableState>,",
|
|
8090
|
+
"staticBoards,"
|
|
8053
8091
|
).replace(
|
|
8054
8092
|
`export const manifestContract: ReducerManifestContract<
|
|
8055
8093
|
RuntimeTableRecord,`,
|
|
@@ -8071,12 +8109,14 @@ const unknownRecordSchema`
|
|
|
8071
8109
|
.min(1)
|
|
8072
8110
|
.transform((value) => asPlayerId(value)),
|
|
8073
8111
|
);`,
|
|
8074
|
-
`const playerIdSchema =
|
|
8075
|
-
|
|
8076
|
-
|
|
8077
|
-
|
|
8078
|
-
|
|
8079
|
-
)
|
|
8112
|
+
`const playerIdSchema = assumeManifestSchema<PublicPlayerId>(
|
|
8113
|
+
markManifestScopedSchema(
|
|
8114
|
+
z
|
|
8115
|
+
.string()
|
|
8116
|
+
.min(1)
|
|
8117
|
+
.transform((value) => asPlayerId(value)),
|
|
8118
|
+
),
|
|
8119
|
+
);`
|
|
8080
8120
|
);
|
|
8081
8121
|
}
|
|
8082
8122
|
function renderCardSetTypeSections(analysis) {
|
|
@@ -9157,9 +9197,9 @@ import {
|
|
|
9157
9197
|
createClientParamSchemasByPhase,
|
|
9158
9198
|
} from "@dreamboard/app-sdk/reducer";
|
|
9159
9199
|
import type {
|
|
9160
|
-
|
|
9161
|
-
|
|
9162
|
-
|
|
9200
|
+
ClientParamsOfInteractionOfDefinition,
|
|
9201
|
+
DefaultedClientParamKeysOfInteractionOfDefinition,
|
|
9202
|
+
InteractionIdOfDefinition,
|
|
9163
9203
|
InteractionIdOfDefinitionPhase,
|
|
9164
9204
|
PhaseNamesOfDefinition,
|
|
9165
9205
|
StageNamesOfDefinitionPhase,
|
|
@@ -9167,35 +9207,38 @@ import type {
|
|
|
9167
9207
|
ViewOfDefinition,
|
|
9168
9208
|
} from "@dreamboard/app-sdk/reducer";
|
|
9169
9209
|
import {
|
|
9170
|
-
|
|
9171
|
-
|
|
9172
|
-
|
|
9173
|
-
|
|
9174
|
-
|
|
9175
|
-
|
|
9176
|
-
|
|
9177
|
-
|
|
9178
|
-
|
|
9179
|
-
|
|
9180
|
-
|
|
9181
|
-
|
|
9182
|
-
|
|
9183
|
-
|
|
9184
|
-
|
|
9185
|
-
|
|
9186
|
-
|
|
9187
|
-
|
|
9188
|
-
|
|
9189
|
-
|
|
9190
|
-
|
|
9191
|
-
} from "@dreamboard/ui-sdk";
|
|
9192
|
-
import { createElement,
|
|
9193
|
-
import {
|
|
9194
|
-
|
|
9195
|
-
|
|
9196
|
-
|
|
9197
|
-
|
|
9210
|
+
createDreamboardUI,
|
|
9211
|
+
createResourceCounter,
|
|
9212
|
+
type BoardHexGridProps as BoardHexGridPropsGeneric,
|
|
9213
|
+
type BoardHexViewProps as BoardHexViewPropsGeneric,
|
|
9214
|
+
type BoardSpaceIdOf,
|
|
9215
|
+
type ClientParamSchemaMap,
|
|
9216
|
+
type InteractionDescriptor,
|
|
9217
|
+
type InteractionHandle,
|
|
9218
|
+
type InteractionRouteMap as InteractionRouteMapGeneric,
|
|
9219
|
+
type InteractionSwitchProps as InteractionSwitchPropsGeneric,
|
|
9220
|
+
type InteractionSwitchRenderState,
|
|
9221
|
+
type DreamboardUI,
|
|
9222
|
+
type ResourceCounterComponents,
|
|
9223
|
+
type ResourceDisplayConfig,
|
|
9224
|
+
type TypedGame,
|
|
9225
|
+
type UIContract,
|
|
9226
|
+
type UIRootProps,
|
|
9227
|
+
type ZoneCardAtProps,
|
|
9228
|
+
type ZoneCardRenderItem,
|
|
9229
|
+
type ZoneListProps,
|
|
9230
|
+
type ZonePileCardsProps,
|
|
9231
|
+
} from "@dreamboard/ui-sdk";
|
|
9232
|
+
import { createElement, type ReactElement, type ReactNode } from "react";
|
|
9233
|
+
import {
|
|
9234
|
+
literals,
|
|
9235
|
+
staticBoards,
|
|
9236
|
+
type CardId,
|
|
9237
|
+
type CardProperties,
|
|
9238
|
+
type CardType,
|
|
9239
|
+
type EdgeId,
|
|
9198
9240
|
type PlayerId,
|
|
9241
|
+
type ResourceId,
|
|
9199
9242
|
type SpaceId,
|
|
9200
9243
|
type VertexId,
|
|
9201
9244
|
type ZoneId as ManifestZoneId,
|
|
@@ -9294,8 +9337,7 @@ export type InteractionDescriptorFor<Key extends InteractionKey> =
|
|
|
9294
9337
|
|
|
9295
9338
|
/**
|
|
9296
9339
|
* Params shape for a phase-qualified interaction key. Drives strong typing
|
|
9297
|
-
* for
|
|
9298
|
-
* \`submit\`, and \`setInput\`.
|
|
9340
|
+
* for component-first interaction state, forms, and submits.
|
|
9299
9341
|
*/
|
|
9300
9342
|
export type InteractionParamsOf<Key extends InteractionKey> =
|
|
9301
9343
|
InteractionParams<PhaseOfInteractionKey<Key>, IdOfInteractionKey<Key>>;
|
|
@@ -9318,6 +9360,50 @@ type InteractionHandleDefaultedKeys<Key extends InteractionKey> = Extract<
|
|
|
9318
9360
|
keyof InteractionParamsShape<Key> & string
|
|
9319
9361
|
>;
|
|
9320
9362
|
|
|
9363
|
+
type RequiredInteractionInputKeysOf<Key extends InteractionKey> = Exclude<
|
|
9364
|
+
InteractionInputKeysOf<Key>,
|
|
9365
|
+
InteractionHandleDefaultedKeys<Key>
|
|
9366
|
+
>;
|
|
9367
|
+
|
|
9368
|
+
export type RequiredInteractionInputKey<Key extends InteractionKey> =
|
|
9369
|
+
RequiredInteractionInputKeysOf<Key>;
|
|
9370
|
+
|
|
9371
|
+
export type ZeroInputInteractionKey = {
|
|
9372
|
+
[K in InteractionKey]: InteractionInputKeysOf<K> extends never
|
|
9373
|
+
? K
|
|
9374
|
+
: never;
|
|
9375
|
+
}[InteractionKey];
|
|
9376
|
+
|
|
9377
|
+
export type InputInteractionKey = Exclude<
|
|
9378
|
+
InteractionKey,
|
|
9379
|
+
ZeroInputInteractionKey
|
|
9380
|
+
>;
|
|
9381
|
+
|
|
9382
|
+
export type InteractionRouteRenderState<Key extends InteractionKey> =
|
|
9383
|
+
Omit<InteractionSwitchRenderState<Key>, "descriptor"> & {
|
|
9384
|
+
descriptor: InteractionDescriptorFor<Key>;
|
|
9385
|
+
};
|
|
9386
|
+
|
|
9387
|
+
export type InteractionRouteMap = {
|
|
9388
|
+
[K in InteractionKey]: (state: InteractionRouteRenderState<K>) => ReactNode;
|
|
9389
|
+
};
|
|
9390
|
+
|
|
9391
|
+
type ExactInteractionRoutes<Routes extends InteractionRouteMap> = Routes &
|
|
9392
|
+
Record<Exclude<keyof Routes, keyof InteractionRouteMap>, never>;
|
|
9393
|
+
|
|
9394
|
+
export function defineInteractionRoutes<const Routes extends InteractionRouteMap>(
|
|
9395
|
+
routes: ExactInteractionRoutes<Routes>,
|
|
9396
|
+
): InteractionRouteMap {
|
|
9397
|
+
return routes;
|
|
9398
|
+
}
|
|
9399
|
+
|
|
9400
|
+
type InteractionSwitchProps = Omit<
|
|
9401
|
+
InteractionSwitchPropsGeneric<InteractionKey>,
|
|
9402
|
+
"routes"
|
|
9403
|
+
> & {
|
|
9404
|
+
routes: InteractionRouteMap;
|
|
9405
|
+
};
|
|
9406
|
+
|
|
9321
9407
|
type InteractionInputKeyOf<Key extends InteractionKey> =
|
|
9322
9408
|
Key extends InteractionKey ? InteractionInputKeysOf<Key> : never;
|
|
9323
9409
|
|
|
@@ -9349,6 +9435,10 @@ type UIPromptOptionRegistry = {
|
|
|
9349
9435
|
[K in PromptOptionValue]: { value: K };
|
|
9350
9436
|
};
|
|
9351
9437
|
|
|
9438
|
+
type UIPlayerRegistry = {
|
|
9439
|
+
[K in PlayerId & string]: { player: K };
|
|
9440
|
+
};
|
|
9441
|
+
|
|
9352
9442
|
type UIZoneRegistry = {
|
|
9353
9443
|
[K in ZoneId & string]: { zone: K };
|
|
9354
9444
|
};
|
|
@@ -9370,6 +9460,7 @@ export const uiContract = {
|
|
|
9370
9460
|
inputs: {} as UIInputRegistry,
|
|
9371
9461
|
prompts: {} as UIPromptRegistry,
|
|
9372
9462
|
promptOptions: {} as UIPromptOptionRegistry,
|
|
9463
|
+
players: {} as UIPlayerRegistry,
|
|
9373
9464
|
zones: {} as UIZoneRegistry,
|
|
9374
9465
|
cards: {} as UICardRegistry,
|
|
9375
9466
|
phases: {} as UIPhaseRegistry,
|
|
@@ -9383,142 +9474,6 @@ declare module "@dreamboard/ui-sdk" {
|
|
|
9383
9474
|
}
|
|
9384
9475
|
}
|
|
9385
9476
|
|
|
9386
|
-
type WorkspaceUI = DreamboardUI<typeof uiContract>;
|
|
9387
|
-
|
|
9388
|
-
export const UI: WorkspaceUI = createDreamboardUI(uiContract);
|
|
9389
|
-
export const Interaction = UI.Interaction;
|
|
9390
|
-
export const Prompt = UI.Prompt;
|
|
9391
|
-
export const PromptInbox = UI.PromptInbox;
|
|
9392
|
-
export const PromptDialogHost = UI.PromptDialogHost;
|
|
9393
|
-
export const PlayerRoster: WorkspaceUI["PlayerRoster"] = UI.PlayerRoster;
|
|
9394
|
-
export const Phase = UI.Phase;
|
|
9395
|
-
export const Zone = UI.Zone;
|
|
9396
|
-
export const Board = UI.Board;
|
|
9397
|
-
|
|
9398
|
-
export type InteractionFieldRenderers<Key extends InteractionKey> =
|
|
9399
|
-
InteractionFieldRenderMap<InteractionParamsShape<Key>>;
|
|
9400
|
-
|
|
9401
|
-
export type InteractionFormProps<Key extends InteractionKey> = Omit<
|
|
9402
|
-
InteractionFormPropsGeneric<
|
|
9403
|
-
InteractionParamsShape<Key>,
|
|
9404
|
-
InteractionHandleDefaultedKeys<Key>
|
|
9405
|
-
>,
|
|
9406
|
-
"descriptor" | "handle"
|
|
9407
|
-
> & {
|
|
9408
|
-
descriptor: InteractionDescriptorFor<Key>;
|
|
9409
|
-
handle: InteractionHandle<
|
|
9410
|
-
InteractionParamsShape<Key>,
|
|
9411
|
-
InteractionHandleDefaultedKeys<Key>
|
|
9412
|
-
>;
|
|
9413
|
-
renderFields?: InteractionFieldRenderers<Key>;
|
|
9414
|
-
};
|
|
9415
|
-
|
|
9416
|
-
export type InteractionFieldProps<
|
|
9417
|
-
Key extends InteractionKey,
|
|
9418
|
-
InputKey extends keyof InteractionParamsShape<Key> & string,
|
|
9419
|
-
> = Omit<
|
|
9420
|
-
InteractionFieldPropsGeneric<InteractionParamsShape<Key>, InputKey>,
|
|
9421
|
-
"descriptor" | "handle"
|
|
9422
|
-
> & {
|
|
9423
|
-
descriptor: InteractionDescriptorFor<Key>;
|
|
9424
|
-
handle: InteractionHandle<
|
|
9425
|
-
InteractionParamsShape<Key>,
|
|
9426
|
-
InteractionHandleDefaultedKeys<Key>
|
|
9427
|
-
>;
|
|
9428
|
-
};
|
|
9429
|
-
|
|
9430
|
-
export const clientParamSchemasByPhase = createClientParamSchemasByPhase(
|
|
9431
|
-
game,
|
|
9432
|
-
) as ClientParamSchemaMap;
|
|
9433
|
-
|
|
9434
|
-
/**
|
|
9435
|
-
* Workspace-typed wrapper over \`@dreamboard/ui-sdk\`'s generic
|
|
9436
|
-
* \`useInteractionByKey\`. The \`key\` argument is constrained to the
|
|
9437
|
-
* generated {@link InteractionKey} union (typos are compile errors), and
|
|
9438
|
-
* the returned {@link InteractionHandle} is parameterised on
|
|
9439
|
-
* {@link InteractionParamsOf} so \`handle.draft\`, \`handle.submit\`, and
|
|
9440
|
-
* \`handle.setInput\` are statically typed against the interaction's
|
|
9441
|
-
* declared inputs.
|
|
9442
|
-
*
|
|
9443
|
-
* \`\`\`ts
|
|
9444
|
-
* const handle = useInteractionByKey("play.placeThingCard");
|
|
9445
|
-
* if (!handle) return null;
|
|
9446
|
-
* handle.setInput("cardId", card.id); // inferred as ThingsDeckCardId
|
|
9447
|
-
* await handle.submit(); // params typed from the reducer contract
|
|
9448
|
-
* \`\`\`
|
|
9449
|
-
*/
|
|
9450
|
-
export function useInteractionByKey<Key extends InteractionKey>(
|
|
9451
|
-
key: Key | null | undefined,
|
|
9452
|
-
): InteractionHandle<
|
|
9453
|
-
InteractionParamsShape<Key>,
|
|
9454
|
-
InteractionHandleDefaultedKeys<Key>
|
|
9455
|
-
> | null {
|
|
9456
|
-
return useInteractionByKeyGeneric<
|
|
9457
|
-
Key,
|
|
9458
|
-
InteractionParamsShape<Key>,
|
|
9459
|
-
InteractionHandleDefaultedKeys<Key>
|
|
9460
|
-
>(key);
|
|
9461
|
-
}
|
|
9462
|
-
|
|
9463
|
-
export function InteractionForm<Key extends InteractionKey>(
|
|
9464
|
-
props: InteractionFormProps<Key>,
|
|
9465
|
-
): ReactElement {
|
|
9466
|
-
return createElement(
|
|
9467
|
-
InteractionFormGeneric<
|
|
9468
|
-
InteractionParamsShape<Key>,
|
|
9469
|
-
InteractionHandleDefaultedKeys<Key>
|
|
9470
|
-
>,
|
|
9471
|
-
props,
|
|
9472
|
-
);
|
|
9473
|
-
}
|
|
9474
|
-
|
|
9475
|
-
export function InteractionField<
|
|
9476
|
-
Key extends InteractionKey,
|
|
9477
|
-
InputKey extends keyof InteractionParamsShape<Key> & string,
|
|
9478
|
-
>(props: InteractionFieldProps<Key, InputKey>): ReactElement | null {
|
|
9479
|
-
return createElement(
|
|
9480
|
-
InteractionFieldGeneric<InteractionParamsShape<Key>, InputKey>,
|
|
9481
|
-
props,
|
|
9482
|
-
);
|
|
9483
|
-
}
|
|
9484
|
-
|
|
9485
|
-
/**
|
|
9486
|
-
* Workspace-typed wrapper over \`@dreamboard/ui-sdk\`'s
|
|
9487
|
-
* \`useBoardInteractions\`. Returns a {@link BoardInteractionsContext}
|
|
9488
|
-
* narrowed to this workspace's board-interaction union for exhaustive
|
|
9489
|
-
* downstream logic.
|
|
9490
|
-
*
|
|
9491
|
-
* \`\`\`tsx
|
|
9492
|
-
* const board = useBoardInteractions();
|
|
9493
|
-
* <HexGrid interactiveVertices={board.targetLayers.vertex()} />
|
|
9494
|
-
* \`\`\`
|
|
9495
|
-
*
|
|
9496
|
-
* Reach for this whenever a screen keeps more than one board target
|
|
9497
|
-
* interaction live simultaneously and dispatch is target-driven instead of
|
|
9498
|
-
* armed-then-clicked. Ambiguous unarmed overlaps should be resolved in the UI
|
|
9499
|
-
* by arming an explicit interaction/input route.
|
|
9500
|
-
*/
|
|
9501
|
-
export function useBoardInteractions(
|
|
9502
|
-
options?: BoardInteractionsOptions,
|
|
9503
|
-
): BoardInteractionsContext<BoardInteractions> {
|
|
9504
|
-
return useBoardInteractionsGeneric<BoardInteractions>(options);
|
|
9505
|
-
}
|
|
9506
|
-
|
|
9507
|
-
/** Workspace-typed active-player hook. */
|
|
9508
|
-
export function useActivePlayers(): readonly PlayerId[] {
|
|
9509
|
-
return useActivePlayersGeneric() as readonly PlayerId[];
|
|
9510
|
-
}
|
|
9511
|
-
|
|
9512
|
-
/** Workspace-typed reducer-native player view hook. */
|
|
9513
|
-
export function useGameView(): GameView {
|
|
9514
|
-
return useGameViewGeneric() as GameView;
|
|
9515
|
-
}
|
|
9516
|
-
|
|
9517
|
-
/** Workspace-typed player turn order hook. */
|
|
9518
|
-
export function usePlayerTurnOrder(): readonly PlayerId[] {
|
|
9519
|
-
return usePlayerTurnOrderGeneric() as readonly PlayerId[];
|
|
9520
|
-
}
|
|
9521
|
-
|
|
9522
9477
|
// -------------------------------------------------------------------------
|
|
9523
9478
|
// Typed hex-board view adapter
|
|
9524
9479
|
// -------------------------------------------------------------------------
|
|
@@ -9537,49 +9492,176 @@ export type HexBoardSpaceId<Id extends HexBoardId> = BoardSpaceIdOf<
|
|
|
9537
9492
|
HexBoardTopology<Id>
|
|
9538
9493
|
>;
|
|
9539
9494
|
|
|
9540
|
-
|
|
9541
|
-
|
|
9542
|
-
|
|
9543
|
-
|
|
9544
|
-
|
|
9545
|
-
|
|
9546
|
-
|
|
9547
|
-
|
|
9548
|
-
|
|
9549
|
-
|
|
9550
|
-
|
|
9551
|
-
|
|
9552
|
-
|
|
9553
|
-
|
|
9554
|
-
|
|
9555
|
-
|
|
9556
|
-
|
|
9557
|
-
|
|
9558
|
-
|
|
9559
|
-
|
|
9560
|
-
|
|
9561
|
-
|
|
9562
|
-
|
|
9563
|
-
|
|
9564
|
-
|
|
9565
|
-
>
|
|
9566
|
-
|
|
9567
|
-
|
|
9568
|
-
|
|
9569
|
-
|
|
9570
|
-
|
|
9571
|
-
|
|
9572
|
-
|
|
9573
|
-
|
|
9574
|
-
|
|
9575
|
-
|
|
9495
|
+
export type HexBoardViewProps<
|
|
9496
|
+
Id extends HexBoardId,
|
|
9497
|
+
TSpaceView extends { id: HexBoardSpaceId<Id> },
|
|
9498
|
+
> = Omit<BoardHexViewPropsGeneric<HexBoardTopology<Id>, TSpaceView>, "board"> & {
|
|
9499
|
+
board: Id;
|
|
9500
|
+
};
|
|
9501
|
+
|
|
9502
|
+
export type HexBoardGridProps<
|
|
9503
|
+
Id extends HexBoardId,
|
|
9504
|
+
TSpaceView extends { id: HexBoardSpaceId<Id> },
|
|
9505
|
+
> = Omit<
|
|
9506
|
+
BoardHexGridPropsGeneric<HexBoardTopology<Id>, TSpaceView>,
|
|
9507
|
+
"board" | "interactions"
|
|
9508
|
+
> & {
|
|
9509
|
+
board: Id;
|
|
9510
|
+
interactions?:
|
|
9511
|
+
| "auto"
|
|
9512
|
+
| false
|
|
9513
|
+
| {
|
|
9514
|
+
edge?: readonly InteractionKey[];
|
|
9515
|
+
vertex?: readonly InteractionKey[];
|
|
9516
|
+
space?: readonly InteractionKey[];
|
|
9517
|
+
};
|
|
9518
|
+
};
|
|
9519
|
+
|
|
9520
|
+
type WorkspaceBoard = Omit<DreamboardUI<typeof uiContract>["Board"], "HexView" | "HexGrid"> & {
|
|
9521
|
+
HexView<
|
|
9522
|
+
const Id extends HexBoardId,
|
|
9523
|
+
const TSpaceView extends { id: HexBoardSpaceId<Id> },
|
|
9524
|
+
>(props: HexBoardViewProps<Id, TSpaceView>): ReactElement;
|
|
9525
|
+
HexGrid<
|
|
9526
|
+
const Id extends HexBoardId,
|
|
9527
|
+
const TSpaceView extends { id: HexBoardSpaceId<Id> },
|
|
9528
|
+
>(props: HexBoardGridProps<Id, TSpaceView>): ReactElement;
|
|
9529
|
+
};
|
|
9530
|
+
|
|
9531
|
+
type WorkspaceCardProperties = CardProperties extends Record<string, unknown>
|
|
9532
|
+
? CardProperties
|
|
9533
|
+
: Record<string, unknown>;
|
|
9534
|
+
type WorkspaceZoneId = [ZoneId] extends [never] ? string : ZoneId;
|
|
9535
|
+
type WorkspaceCardId = [CardId] extends [never] ? string : CardId;
|
|
9536
|
+
type WorkspaceCardType = [CardType] extends [never] ? string : CardType;
|
|
9537
|
+
|
|
9538
|
+
// ZoneCardRenderItem is a discriminated union (hidden: true | false).
|
|
9539
|
+
// A bare Omit<..., "zone"> would collapse the union to its common keys and
|
|
9540
|
+
// strip cardType / properties from the hydrated branch, defeating the
|
|
9541
|
+
// discriminated-union narrowing the SDK contract promises. Distribute Omit
|
|
9542
|
+
// across the union so each branch keeps its own shape.
|
|
9543
|
+
type WorkspaceZoneCard = ZoneCardRenderItem<
|
|
9544
|
+
WorkspaceCardId & string,
|
|
9545
|
+
WorkspaceCardType & string,
|
|
9546
|
+
WorkspaceCardProperties
|
|
9547
|
+
> extends infer Item
|
|
9548
|
+
? Item extends { zone: string }
|
|
9549
|
+
? Omit<Item, "zone"> & { zone: WorkspaceZoneId }
|
|
9550
|
+
: never
|
|
9551
|
+
: never;
|
|
9552
|
+
|
|
9553
|
+
type WorkspaceZone = Omit<
|
|
9554
|
+
DreamboardUI<typeof uiContract>["Zone"],
|
|
9555
|
+
"CardAt" | "TopCard" | "List" | "PileCards"
|
|
9556
|
+
> & {
|
|
9557
|
+
CardAt(
|
|
9558
|
+
props: Omit<ZoneCardAtProps<WorkspaceZoneId>, "zone" | "children"> & {
|
|
9559
|
+
zone?: WorkspaceZoneId;
|
|
9560
|
+
children?: ReactNode | ((card: WorkspaceZoneCard) => ReactNode);
|
|
9561
|
+
},
|
|
9562
|
+
): ReactElement | null;
|
|
9563
|
+
TopCard(
|
|
9564
|
+
props: Omit<
|
|
9565
|
+
ZoneCardAtProps<WorkspaceZoneId>,
|
|
9566
|
+
"zone" | "index" | "children"
|
|
9567
|
+
> & {
|
|
9568
|
+
zone?: WorkspaceZoneId;
|
|
9569
|
+
children?: ReactNode | ((card: WorkspaceZoneCard) => ReactNode);
|
|
9570
|
+
},
|
|
9571
|
+
): ReactElement | null;
|
|
9572
|
+
List(
|
|
9573
|
+
props: Omit<ZoneListProps, "children"> & {
|
|
9574
|
+
children?: ReactNode | ((card: WorkspaceZoneCard) => ReactNode);
|
|
9575
|
+
},
|
|
9576
|
+
): ReactElement;
|
|
9577
|
+
PileCards(
|
|
9578
|
+
props: Omit<ZonePileCardsProps, "renderCard"> & {
|
|
9579
|
+
renderCard: (card: WorkspaceZoneCard) => ReactNode;
|
|
9580
|
+
},
|
|
9581
|
+
): ReactElement | null;
|
|
9582
|
+
};
|
|
9583
|
+
|
|
9584
|
+
type WorkspaceUI = Omit<
|
|
9585
|
+
DreamboardUI<typeof uiContract>,
|
|
9586
|
+
"Root" | "Game" | "Interaction" | "Board" | "Zone"
|
|
9587
|
+
> & {
|
|
9588
|
+
Root(props: UIRootProps): ReactElement;
|
|
9589
|
+
readonly Game: TypedGame<typeof uiContract, GameView, PlayerId, PhaseName>;
|
|
9590
|
+
readonly Interaction: Omit<
|
|
9591
|
+
DreamboardUI<typeof uiContract>["Interaction"],
|
|
9592
|
+
"Switch"
|
|
9593
|
+
> & {
|
|
9594
|
+
Switch(props: InteractionSwitchProps): ReactElement;
|
|
9595
|
+
};
|
|
9596
|
+
readonly Board: WorkspaceBoard;
|
|
9597
|
+
readonly Zone: WorkspaceZone;
|
|
9598
|
+
readonly ResourceCounter: ResourceCounterComponents<ResourceId>;
|
|
9599
|
+
};
|
|
9600
|
+
|
|
9601
|
+
const baseUI = createDreamboardUI(uiContract);
|
|
9602
|
+
|
|
9603
|
+
const resourcePresentationById = literals.resourcePresentationById as Partial<
|
|
9604
|
+
Record<string, { label?: string; icon?: string }>
|
|
9605
|
+
>;
|
|
9606
|
+
|
|
9607
|
+
const resourceDisplayConfig = literals.resourceIds.map((resource) => {
|
|
9608
|
+
const resourceId = resource as ResourceId;
|
|
9609
|
+
const presentation = resourcePresentationById[resource as string];
|
|
9610
|
+
return {
|
|
9611
|
+
type: resourceId,
|
|
9612
|
+
label: presentation?.label ?? resource,
|
|
9613
|
+
icon: presentation?.icon ?? resource,
|
|
9614
|
+
};
|
|
9615
|
+
}) satisfies readonly ResourceDisplayConfig<ResourceId>[];
|
|
9616
|
+
|
|
9617
|
+
const resourceCounter = createResourceCounter<ResourceId>(resourceDisplayConfig);
|
|
9618
|
+
|
|
9619
|
+
export const Board: WorkspaceUI["Board"] = {
|
|
9620
|
+
...baseUI.Board,
|
|
9621
|
+
HexView<
|
|
9622
|
+
const Id extends HexBoardId,
|
|
9623
|
+
const TSpaceView extends { id: HexBoardSpaceId<Id> },
|
|
9624
|
+
>({ board: boardId, ...props }: HexBoardViewProps<Id, TSpaceView>) {
|
|
9625
|
+
return createElement(baseUI.Board.HexView<HexBoardTopology<Id>, TSpaceView>, {
|
|
9626
|
+
...props,
|
|
9627
|
+
board: hexStaticBoards[boardId],
|
|
9628
|
+
});
|
|
9629
|
+
},
|
|
9630
|
+
HexGrid<
|
|
9631
|
+
const Id extends HexBoardId,
|
|
9632
|
+
const TSpaceView extends { id: HexBoardSpaceId<Id> },
|
|
9633
|
+
>({ board: boardId, ...props }: HexBoardGridProps<Id, TSpaceView>) {
|
|
9634
|
+
return createElement(baseUI.Board.HexGrid<HexBoardTopology<Id>, TSpaceView>, {
|
|
9635
|
+
...props,
|
|
9636
|
+
board: hexStaticBoards[boardId],
|
|
9637
|
+
});
|
|
9638
|
+
},
|
|
9639
|
+
} as WorkspaceUI["Board"];
|
|
9640
|
+
|
|
9641
|
+
export const UI: WorkspaceUI = {
|
|
9642
|
+
...baseUI,
|
|
9643
|
+
Board,
|
|
9644
|
+
ResourceCounter: resourceCounter,
|
|
9645
|
+
};
|
|
9646
|
+
export const Game: WorkspaceUI["Game"] = UI.Game;
|
|
9647
|
+
export const Interaction = UI.Interaction;
|
|
9648
|
+
export const Prompt = UI.Prompt;
|
|
9649
|
+
export const PromptInbox = UI.PromptInbox;
|
|
9650
|
+
export const PlayerRoster: WorkspaceUI["PlayerRoster"] = UI.PlayerRoster;
|
|
9651
|
+
export const Dice: WorkspaceUI["Dice"] = UI.Dice;
|
|
9652
|
+
export const Phase = UI.Phase;
|
|
9653
|
+
export const Zone = UI.Zone;
|
|
9654
|
+
export const ResourceCounter: WorkspaceUI["ResourceCounter"] = UI.ResourceCounter;
|
|
9655
|
+
|
|
9656
|
+
export const clientParamSchemasByPhase = createClientParamSchemasByPhase(
|
|
9657
|
+
game,
|
|
9658
|
+
) as ClientParamSchemaMap;
|
|
9576
9659
|
`;
|
|
9577
9660
|
}
|
|
9578
9661
|
function generateReducerSupportSeed() {
|
|
9579
9662
|
return `import {
|
|
9580
|
-
|
|
9663
|
+
createReducerEdit,
|
|
9581
9664
|
createStateQueries,
|
|
9582
|
-
pipe,
|
|
9583
9665
|
} from "@dreamboard/app-sdk/reducer";
|
|
9584
9666
|
import type { GameState } from "./game-contract";
|
|
9585
9667
|
|
|
@@ -9598,16 +9680,12 @@ import type { GameState } from "./game-contract";
|
|
|
9598
9680
|
*
|
|
9599
9681
|
* Recommended authoring pattern inside a phase reducer:
|
|
9600
9682
|
*
|
|
9601
|
-
* const
|
|
9602
|
-
*
|
|
9603
|
-
*
|
|
9604
|
-
* );
|
|
9605
|
-
* return accept(next);
|
|
9683
|
+
* const tx = edit(state);
|
|
9684
|
+
* tx.setActivePlayers([q.players.order()[0]]);
|
|
9685
|
+
* return accept(tx.state);
|
|
9606
9686
|
*/
|
|
9607
9687
|
|
|
9608
|
-
export const
|
|
9609
|
-
|
|
9610
|
-
export { pipe };
|
|
9688
|
+
export const edit = createReducerEdit<GameState>();
|
|
9611
9689
|
|
|
9612
9690
|
export function stateQueries(state: GameState) {
|
|
9613
9691
|
return createStateQueries(state);
|
|
@@ -9688,7 +9766,7 @@ function generateReducerGameContractSeed() {
|
|
|
9688
9766
|
import { ids, manifestContract } from "../shared/manifest-contract";
|
|
9689
9767
|
import { defineGameContract, type GameStateOf } from "@dreamboard/app-sdk/reducer";
|
|
9690
9768
|
|
|
9691
|
-
// Contract files should stay focused on schemas,
|
|
9769
|
+
// Contract files should stay focused on schemas, phases, and exported
|
|
9692
9770
|
// state types. Put reducers in app/phases/* and pure computations in
|
|
9693
9771
|
// app/derived.ts or app/rules/*.
|
|
9694
9772
|
const publicStateSchema = z.object({
|
|
@@ -9700,15 +9778,14 @@ const hiddenStateSchema = z.object({});
|
|
|
9700
9778
|
|
|
9701
9779
|
export const gameContract = defineGameContract({
|
|
9702
9780
|
manifest: manifestContract,
|
|
9703
|
-
// Keep this list in sync with the keys of the \`phases\` record in ./phases.
|
|
9704
|
-
// Declaring phase names here narrows \`fx.transition(...)\`, \`phase.dispatch\`,
|
|
9705
|
-
// and the flow state's \`currentPhase\` to a literal union.
|
|
9706
|
-
phaseNames: ["setup"] as const,
|
|
9707
9781
|
state: {
|
|
9708
9782
|
public: publicStateSchema,
|
|
9709
9783
|
private: privateStateSchema,
|
|
9710
9784
|
hidden: hiddenStateSchema,
|
|
9711
9785
|
},
|
|
9786
|
+
phases: {
|
|
9787
|
+
setup: z.object({}),
|
|
9788
|
+
},
|
|
9712
9789
|
});
|
|
9713
9790
|
|
|
9714
9791
|
export type GameContract = typeof gameContract;
|
|
@@ -9809,8 +9886,10 @@ function generateAppFrameworkTsConfig() {
|
|
|
9809
9886
|
moduleResolution: "bundler",
|
|
9810
9887
|
strict: true,
|
|
9811
9888
|
esModuleInterop: true,
|
|
9812
|
-
skipLibCheck:
|
|
9889
|
+
skipLibCheck: false,
|
|
9890
|
+
types: [],
|
|
9813
9891
|
declaration: false,
|
|
9892
|
+
rootDir: "..",
|
|
9814
9893
|
outDir: "./dist",
|
|
9815
9894
|
paths: {
|
|
9816
9895
|
"@dreamboard/manifest-contract": ["../shared/manifest-contract.ts"],
|
|
@@ -9832,48 +9911,57 @@ function generateAppFrameworkTsConfig() {
|
|
|
9832
9911
|
`;
|
|
9833
9912
|
}
|
|
9834
9913
|
function generateUiFrameworkTsConfig() {
|
|
9835
|
-
return
|
|
9836
|
-
|
|
9837
|
-
|
|
9838
|
-
|
|
9839
|
-
|
|
9840
|
-
|
|
9841
|
-
|
|
9842
|
-
|
|
9843
|
-
|
|
9844
|
-
|
|
9845
|
-
|
|
9846
|
-
|
|
9847
|
-
|
|
9848
|
-
|
|
9849
|
-
|
|
9850
|
-
|
|
9851
|
-
|
|
9852
|
-
|
|
9853
|
-
]
|
|
9854
|
-
}
|
|
9855
|
-
|
|
9856
|
-
|
|
9857
|
-
|
|
9858
|
-
"./**/*.tsx",
|
|
9859
|
-
"../shared/**/*.ts"
|
|
9860
|
-
],
|
|
9861
|
-
"exclude": [
|
|
9862
|
-
"node_modules",
|
|
9863
|
-
"dist"
|
|
9864
|
-
]
|
|
9865
|
-
}
|
|
9914
|
+
return `${JSON.stringify(
|
|
9915
|
+
{
|
|
9916
|
+
compilerOptions: {
|
|
9917
|
+
target: "ES2020",
|
|
9918
|
+
module: "ESNext",
|
|
9919
|
+
moduleResolution: "bundler",
|
|
9920
|
+
jsx: "react-jsx",
|
|
9921
|
+
strict: true,
|
|
9922
|
+
esModuleInterop: true,
|
|
9923
|
+
skipLibCheck: false,
|
|
9924
|
+
types: [],
|
|
9925
|
+
paths: {
|
|
9926
|
+
"@dreamboard/manifest-contract": ["../shared/manifest-contract.ts"],
|
|
9927
|
+
"@dreamboard/ui-contract": ["../shared/generated/ui-contract.ts"],
|
|
9928
|
+
"@shared/*": ["../shared/*"]
|
|
9929
|
+
}
|
|
9930
|
+
},
|
|
9931
|
+
include: ["./**/*.ts", "./**/*.tsx", "../shared/**/*.ts"],
|
|
9932
|
+
exclude: ["node_modules", "dist"]
|
|
9933
|
+
},
|
|
9934
|
+
null,
|
|
9935
|
+
2
|
|
9936
|
+
)}
|
|
9866
9937
|
`;
|
|
9867
9938
|
}
|
|
9868
9939
|
function generateReducerUiAppContent() {
|
|
9869
|
-
return `import { Phase, PromptInbox } from "@dreamboard/ui-contract";
|
|
9940
|
+
return `import { Game, Phase, Prompt, PromptInbox } from "@dreamboard/ui-contract";
|
|
9870
9941
|
|
|
9871
9942
|
function SetupPhase() {
|
|
9872
9943
|
return (
|
|
9873
9944
|
<main>
|
|
9874
9945
|
<PromptInbox.Root>
|
|
9875
9946
|
<PromptInbox.Empty>No available prompts.</PromptInbox.Empty>
|
|
9876
|
-
<PromptInbox.Items
|
|
9947
|
+
<PromptInbox.Items>
|
|
9948
|
+
{(prompt) => (
|
|
9949
|
+
<Prompt.Root
|
|
9950
|
+
key={prompt.interactionKey}
|
|
9951
|
+
interaction={prompt.interactionKey}
|
|
9952
|
+
>
|
|
9953
|
+
<Prompt.Title />
|
|
9954
|
+
<Prompt.Message />
|
|
9955
|
+
<Prompt.Options>
|
|
9956
|
+
{(option) => (
|
|
9957
|
+
<Prompt.Option value={option.id}>
|
|
9958
|
+
{option.label ?? option.id}
|
|
9959
|
+
</Prompt.Option>
|
|
9960
|
+
)}
|
|
9961
|
+
</Prompt.Options>
|
|
9962
|
+
</Prompt.Root>
|
|
9963
|
+
)}
|
|
9964
|
+
</PromptInbox.Items>
|
|
9877
9965
|
</PromptInbox.Root>
|
|
9878
9966
|
</main>
|
|
9879
9967
|
);
|
|
@@ -9881,11 +9969,15 @@ function SetupPhase() {
|
|
|
9881
9969
|
|
|
9882
9970
|
export default function App() {
|
|
9883
9971
|
return (
|
|
9884
|
-
<
|
|
9885
|
-
|
|
9886
|
-
|
|
9887
|
-
|
|
9888
|
-
|
|
9972
|
+
<Game.Root>
|
|
9973
|
+
{() => (
|
|
9974
|
+
<Phase.Switch
|
|
9975
|
+
routes={{
|
|
9976
|
+
setup: () => <SetupPhase />,
|
|
9977
|
+
}}
|
|
9978
|
+
/>
|
|
9979
|
+
)}
|
|
9980
|
+
</Game.Root>
|
|
9889
9981
|
);
|
|
9890
9982
|
}
|
|
9891
9983
|
`;
|
|
@@ -14006,6 +14098,9 @@ var ProjectSeatsDynamicRequestSchema = external_exports.object({ "state": Reduce
|
|
|
14006
14098
|
var BoardStaticProjectionSchema = external_exports.object({ "view": JsonValueSchema, "hash": external_exports.string().min(1), "manifestVersion": external_exports.string() }).strict();
|
|
14007
14099
|
|
|
14008
14100
|
// ../../packages/app-sdk/src/reducer/per-player.ts
|
|
14101
|
+
function asPlayerId(raw) {
|
|
14102
|
+
return raw;
|
|
14103
|
+
}
|
|
14009
14104
|
function perPlayerGet(value, id) {
|
|
14010
14105
|
for (const [candidate, v] of value.entries) {
|
|
14011
14106
|
if (candidate === id) {
|
|
@@ -14115,6 +14210,45 @@ function resolveDomainChoices(choices, context) {
|
|
|
14115
14210
|
disabledReason: choice.disabledReason
|
|
14116
14211
|
}));
|
|
14117
14212
|
}
|
|
14213
|
+
function resolveDependentDomainChoices(choices, context) {
|
|
14214
|
+
const resolved = typeof choices === "function" ? choices(context) : choices;
|
|
14215
|
+
return resolved.map((choice) => ({
|
|
14216
|
+
value: choice.value,
|
|
14217
|
+
label: choice.label,
|
|
14218
|
+
icon: choice.icon,
|
|
14219
|
+
badge: choice.badge,
|
|
14220
|
+
description: choice.description,
|
|
14221
|
+
disabled: choice.disabled,
|
|
14222
|
+
disabledReason: choice.disabledReason
|
|
14223
|
+
}));
|
|
14224
|
+
}
|
|
14225
|
+
function choiceValuesInclude(choices, value) {
|
|
14226
|
+
return choices.some((choice) => Object.is(choice.value, value));
|
|
14227
|
+
}
|
|
14228
|
+
function assertChoiceDefaultInChoices(inputName, choices, defaultValue) {
|
|
14229
|
+
if (choiceValuesInclude(choices, defaultValue)) return;
|
|
14230
|
+
const printable = defaultValue === null ? "null" : `'${defaultValue}'`;
|
|
14231
|
+
throw new Error(
|
|
14232
|
+
`${inputName} defaultValue ${printable} must be one of its choices. If null is a valid value, add an explicit { value: null, label: ... } choice.`
|
|
14233
|
+
);
|
|
14234
|
+
}
|
|
14235
|
+
function choiceSchema(choices) {
|
|
14236
|
+
const values = choices.map((choice) => choice.value);
|
|
14237
|
+
const stringValues = values.filter(
|
|
14238
|
+
(value) => value !== null
|
|
14239
|
+
);
|
|
14240
|
+
const hasNull = values.some((value) => value === null);
|
|
14241
|
+
if (stringValues.length === 0) {
|
|
14242
|
+
return external_exports.null();
|
|
14243
|
+
}
|
|
14244
|
+
const stringSchema = external_exports.enum(
|
|
14245
|
+
stringValues
|
|
14246
|
+
);
|
|
14247
|
+
if (hasNull) {
|
|
14248
|
+
return external_exports.union([stringSchema, external_exports.null()]);
|
|
14249
|
+
}
|
|
14250
|
+
return stringSchema;
|
|
14251
|
+
}
|
|
14118
14252
|
function resolveResourceMapChoices(choices, context) {
|
|
14119
14253
|
const resources = context.state.table.resources;
|
|
14120
14254
|
const firstResourceMap = isPerPlayer(resources) && resources.entries.length > 0 ? resources.entries[0]?.[1] : resources;
|
|
@@ -14151,7 +14285,13 @@ function resourceMapInput(options) {
|
|
|
14151
14285
|
schema: external_exports.record(external_exports.string(), external_exports.number().int().nonnegative()),
|
|
14152
14286
|
..."defaultValue" in options ? { defaultValue: options.defaultValue } : {},
|
|
14153
14287
|
domain: (state, playerId, q, derived) => {
|
|
14154
|
-
const context = {
|
|
14288
|
+
const context = {
|
|
14289
|
+
state,
|
|
14290
|
+
playerId,
|
|
14291
|
+
q,
|
|
14292
|
+
derived,
|
|
14293
|
+
values: {}
|
|
14294
|
+
};
|
|
14155
14295
|
return {
|
|
14156
14296
|
type: "resourceMap",
|
|
14157
14297
|
resources: options.resources.map((resource) => ({
|
|
@@ -14171,7 +14311,13 @@ function numberInput(options) {
|
|
|
14171
14311
|
schema: external_exports.number(),
|
|
14172
14312
|
..."defaultValue" in options ? { defaultValue: options.defaultValue } : {},
|
|
14173
14313
|
domain: (state, playerId, q, derived) => {
|
|
14174
|
-
const context = {
|
|
14314
|
+
const context = {
|
|
14315
|
+
state,
|
|
14316
|
+
playerId,
|
|
14317
|
+
q,
|
|
14318
|
+
derived,
|
|
14319
|
+
values: {}
|
|
14320
|
+
};
|
|
14175
14321
|
return {
|
|
14176
14322
|
type: "boundedNumber",
|
|
14177
14323
|
min: resolveDomainNumber(options.min, context, 0),
|
|
@@ -14182,23 +14328,80 @@ function numberInput(options) {
|
|
|
14182
14328
|
};
|
|
14183
14329
|
}
|
|
14184
14330
|
function choiceInput(options) {
|
|
14331
|
+
const dependsOn = options.dependsOn?.map((dependency) => dependency.key);
|
|
14185
14332
|
if (Array.isArray(options.choices) && options.choices.length === 0) {
|
|
14186
14333
|
throw new Error("formInput.choice requires at least one choice.");
|
|
14187
14334
|
}
|
|
14188
|
-
const
|
|
14189
|
-
|
|
14190
|
-
|
|
14335
|
+
const staticChoices = Array.isArray(options.choices) ? options.choices : null;
|
|
14336
|
+
const hasStaticDefault = typeof options.defaultValue !== "function";
|
|
14337
|
+
const staticDefault = options.defaultValue;
|
|
14338
|
+
if (staticChoices && hasStaticDefault) {
|
|
14339
|
+
assertChoiceDefaultInChoices(
|
|
14340
|
+
"formInput.choice",
|
|
14341
|
+
staticChoices,
|
|
14342
|
+
staticDefault
|
|
14343
|
+
);
|
|
14344
|
+
}
|
|
14345
|
+
const schema = staticChoices ? choiceSchema(staticChoices) : external_exports.string().nullable();
|
|
14346
|
+
const dynamicDefault = typeof options.defaultValue === "function" ? options.defaultValue : void 0;
|
|
14191
14347
|
return {
|
|
14192
14348
|
kind: "form",
|
|
14193
14349
|
schema,
|
|
14194
|
-
...
|
|
14195
|
-
|
|
14196
|
-
|
|
14350
|
+
...hasStaticDefault ? { defaultValue: staticDefault } : {},
|
|
14351
|
+
...dependsOn ? { dependsOn } : {},
|
|
14352
|
+
domain: (state, playerId, q, derived, values) => {
|
|
14353
|
+
const context = {
|
|
14354
|
+
state,
|
|
14355
|
+
playerId,
|
|
14356
|
+
q,
|
|
14357
|
+
derived
|
|
14358
|
+
};
|
|
14359
|
+
const choices = dependsOn ? resolveDependentDomainChoices(
|
|
14360
|
+
options.choices,
|
|
14361
|
+
{
|
|
14362
|
+
...context,
|
|
14363
|
+
values: values ?? {}
|
|
14364
|
+
}
|
|
14365
|
+
) : resolveDomainChoices(options.choices, {
|
|
14366
|
+
...context,
|
|
14367
|
+
values: {}
|
|
14368
|
+
});
|
|
14369
|
+
if (hasStaticDefault) {
|
|
14370
|
+
assertChoiceDefaultInChoices(
|
|
14371
|
+
"formInput.choice",
|
|
14372
|
+
choices,
|
|
14373
|
+
staticDefault
|
|
14374
|
+
);
|
|
14375
|
+
}
|
|
14197
14376
|
return {
|
|
14198
14377
|
type: "choice",
|
|
14199
|
-
choices
|
|
14378
|
+
choices
|
|
14200
14379
|
};
|
|
14201
|
-
}
|
|
14380
|
+
},
|
|
14381
|
+
...dynamicDefault ? {
|
|
14382
|
+
resolveDefaultValue: (state, playerId, q, derived, domain) => {
|
|
14383
|
+
const choices = domain.type === "choice" ? domain.choices.map((choice) => ({
|
|
14384
|
+
value: choice.value,
|
|
14385
|
+
label: choice.label,
|
|
14386
|
+
icon: choice.icon,
|
|
14387
|
+
badge: choice.badge,
|
|
14388
|
+
description: choice.description,
|
|
14389
|
+
disabled: choice.disabled,
|
|
14390
|
+
disabledReason: choice.disabledReason
|
|
14391
|
+
})) : [];
|
|
14392
|
+
const resolved = dynamicDefault({
|
|
14393
|
+
state,
|
|
14394
|
+
playerId,
|
|
14395
|
+
q,
|
|
14396
|
+
derived,
|
|
14397
|
+
values: {},
|
|
14398
|
+
choices
|
|
14399
|
+
});
|
|
14400
|
+
if (resolved === void 0) return void 0;
|
|
14401
|
+
assertChoiceDefaultInChoices("formInput.choice", choices, resolved);
|
|
14402
|
+
return resolved;
|
|
14403
|
+
}
|
|
14404
|
+
} : {}
|
|
14202
14405
|
};
|
|
14203
14406
|
}
|
|
14204
14407
|
function choiceListInput(options) {
|
|
@@ -14210,10 +14413,21 @@ function choiceListInput(options) {
|
|
|
14210
14413
|
return {
|
|
14211
14414
|
kind: "form",
|
|
14212
14415
|
schema: external_exports.array(external_exports.string()),
|
|
14213
|
-
...staticDefaultValue ? { defaultValue: staticDefaultValue } : {},
|
|
14416
|
+
...staticDefaultValue !== void 0 ? { defaultValue: staticDefaultValue } : {},
|
|
14214
14417
|
domain: (state, playerId, q, derived) => {
|
|
14215
|
-
const context = {
|
|
14216
|
-
|
|
14418
|
+
const context = {
|
|
14419
|
+
state,
|
|
14420
|
+
playerId,
|
|
14421
|
+
q,
|
|
14422
|
+
derived,
|
|
14423
|
+
values: {}
|
|
14424
|
+
};
|
|
14425
|
+
const choices = resolveDomainChoices(options.choices, context).map(
|
|
14426
|
+
(choice) => ({
|
|
14427
|
+
...choice,
|
|
14428
|
+
value: choice.value
|
|
14429
|
+
})
|
|
14430
|
+
);
|
|
14217
14431
|
return {
|
|
14218
14432
|
type: "choiceList",
|
|
14219
14433
|
choices,
|
|
@@ -14240,12 +14454,25 @@ function choiceListInput(options) {
|
|
|
14240
14454
|
playerId,
|
|
14241
14455
|
q,
|
|
14242
14456
|
derived,
|
|
14457
|
+
values: {},
|
|
14243
14458
|
choices
|
|
14244
14459
|
});
|
|
14245
14460
|
}
|
|
14246
14461
|
} : {}
|
|
14247
14462
|
};
|
|
14248
14463
|
}
|
|
14464
|
+
function formInputForState() {
|
|
14465
|
+
return Object.assign(
|
|
14466
|
+
((schema, options) => baseFormInput(schema, options)),
|
|
14467
|
+
{
|
|
14468
|
+
resourceMap: (options) => resourceMapInput(options),
|
|
14469
|
+
resourceChoices: (options) => formInput.resourceChoices(options),
|
|
14470
|
+
number: (options) => numberInput(options),
|
|
14471
|
+
choice: (options) => choiceInput(options),
|
|
14472
|
+
choiceList: (options) => choiceListInput(options)
|
|
14473
|
+
}
|
|
14474
|
+
);
|
|
14475
|
+
}
|
|
14249
14476
|
var formInput = Object.assign(baseFormInput, {
|
|
14250
14477
|
resourceMap: resourceMapInput,
|
|
14251
14478
|
resourceChoices: (options) => ({
|
|
@@ -14254,32 +14481,49 @@ var formInput = Object.assign(baseFormInput, {
|
|
|
14254
14481
|
}),
|
|
14255
14482
|
number: numberInput,
|
|
14256
14483
|
choice: choiceInput,
|
|
14257
|
-
choiceList: choiceListInput
|
|
14484
|
+
choiceList: choiceListInput,
|
|
14485
|
+
forState: formInputForState
|
|
14258
14486
|
});
|
|
14259
14487
|
|
|
14260
14488
|
// ../../packages/app-sdk/src/reducer/inputs/boardInput.ts
|
|
14261
14489
|
function makeBoardCollector(kind) {
|
|
14262
14490
|
return function collector(options) {
|
|
14263
14491
|
const target = options.target;
|
|
14492
|
+
const dependsOn = options.dependsOn?.map((dependency) => dependency.key);
|
|
14264
14493
|
return {
|
|
14265
14494
|
kind,
|
|
14266
14495
|
schema: external_exports.string(),
|
|
14267
|
-
eligibleTargets: ((state, playerId, q) => target.eligible({
|
|
14496
|
+
eligibleTargets: ((state, playerId, q, values) => target.eligible({
|
|
14268
14497
|
state,
|
|
14269
14498
|
playerId,
|
|
14270
|
-
q
|
|
14499
|
+
q,
|
|
14500
|
+
values
|
|
14271
14501
|
})),
|
|
14272
|
-
validateTarget: ((state, playerId, q, targetId) => target.validate(
|
|
14502
|
+
validateTarget: ((state, playerId, q, targetId, values) => target.validate(
|
|
14273
14503
|
{
|
|
14274
14504
|
state,
|
|
14275
14505
|
playerId,
|
|
14276
|
-
q
|
|
14506
|
+
q,
|
|
14507
|
+
values
|
|
14277
14508
|
},
|
|
14278
14509
|
targetId
|
|
14279
14510
|
)),
|
|
14511
|
+
...dependsOn ? { dependsOn } : {},
|
|
14512
|
+
domain: dependsOn ? (state, playerId, q, _derived, values) => ({
|
|
14513
|
+
type: "target",
|
|
14514
|
+
targetKind: target.targetKind,
|
|
14515
|
+
boardId: target.boardId,
|
|
14516
|
+
eligibleTargets: target.eligible({
|
|
14517
|
+
state,
|
|
14518
|
+
playerId,
|
|
14519
|
+
q,
|
|
14520
|
+
values
|
|
14521
|
+
}).map(String)
|
|
14522
|
+
}) : void 0,
|
|
14280
14523
|
meta: {
|
|
14281
14524
|
targetKind: target.targetKind,
|
|
14282
|
-
boardId: target.boardId
|
|
14525
|
+
boardId: target.boardId,
|
|
14526
|
+
valueKind: target.valueKind
|
|
14283
14527
|
}
|
|
14284
14528
|
};
|
|
14285
14529
|
};
|
|
@@ -14296,12 +14540,13 @@ var DEFAULT_MISSING_CANDIDATE_ISSUE = {
|
|
|
14296
14540
|
};
|
|
14297
14541
|
function createTargetRule(candidates, predicates, options = {}) {
|
|
14298
14542
|
const missingCandidateIssue = options.missingCandidateIssue ?? DEFAULT_MISSING_CANDIDATE_ISSUE;
|
|
14299
|
-
const
|
|
14300
|
-
|
|
14543
|
+
const equals = options.equals ?? Object.is;
|
|
14544
|
+
const validate2 = (ctx, target) => {
|
|
14545
|
+
if (!candidates(ctx).some((candidate) => equals(candidate, target))) {
|
|
14301
14546
|
return missingCandidateIssue;
|
|
14302
14547
|
}
|
|
14303
14548
|
for (const predicate of predicates) {
|
|
14304
|
-
if (!predicate.test({ ...ctx, targetId:
|
|
14549
|
+
if (!predicate.test({ ...ctx, targetId: target, target })) {
|
|
14305
14550
|
return {
|
|
14306
14551
|
errorCode: predicate.errorCode,
|
|
14307
14552
|
message: predicate.message
|
|
@@ -14313,7 +14558,7 @@ function createTargetRule(candidates, predicates, options = {}) {
|
|
|
14313
14558
|
const rule = {
|
|
14314
14559
|
eligible: (ctx) => candidates(ctx).filter((targetId) => validate2(ctx, targetId) == null),
|
|
14315
14560
|
validate: validate2,
|
|
14316
|
-
isEligible: (ctx,
|
|
14561
|
+
isEligible: (ctx, target) => validate2(ctx, target) == null,
|
|
14317
14562
|
bind: (ctx) => ({
|
|
14318
14563
|
eligible: () => rule.eligible(ctx),
|
|
14319
14564
|
validate: (id) => rule.validate(ctx, id),
|
|
@@ -14337,7 +14582,7 @@ function candidateIdsForKind(q, boardId, targetKind) {
|
|
|
14337
14582
|
if (targetKind === "vertex") {
|
|
14338
14583
|
return idsFromCollection(q.board.tiled(boardId).vertices);
|
|
14339
14584
|
}
|
|
14340
|
-
return idsFromCollection(q.board.get(boardId)
|
|
14585
|
+
return idsFromCollection(q.board.get(boardId)?.spaces);
|
|
14341
14586
|
}
|
|
14342
14587
|
function idsFromCollection(collection) {
|
|
14343
14588
|
if (!collection) return [];
|
|
@@ -14364,10 +14609,47 @@ function createBoardTargetBuilder(targetKind, boardId) {
|
|
|
14364
14609
|
}
|
|
14365
14610
|
),
|
|
14366
14611
|
boardId,
|
|
14367
|
-
targetKind
|
|
14612
|
+
targetKind,
|
|
14613
|
+
valueKind: "board-id"
|
|
14614
|
+
})
|
|
14615
|
+
);
|
|
14616
|
+
}
|
|
14617
|
+
function createPlayerSpaceTargetBuilder(boardId) {
|
|
14618
|
+
return createTargetRuleBuilder(
|
|
14619
|
+
(predicates) => ({
|
|
14620
|
+
...createTargetRule(
|
|
14621
|
+
({ state, q }) => {
|
|
14622
|
+
const spacesForPlayer = (playerId) => candidateIdsForKind(
|
|
14623
|
+
q,
|
|
14624
|
+
`${boardId}:${playerId}`,
|
|
14625
|
+
"space"
|
|
14626
|
+
);
|
|
14627
|
+
return state.table.playerOrder.flatMap(
|
|
14628
|
+
(playerId) => spacesForPlayer(playerId).map((spaceId) => ({
|
|
14629
|
+
boardId,
|
|
14630
|
+
playerId,
|
|
14631
|
+
spaceId
|
|
14632
|
+
}))
|
|
14633
|
+
);
|
|
14634
|
+
},
|
|
14635
|
+
predicates,
|
|
14636
|
+
{
|
|
14637
|
+
missingCandidateIssue: {
|
|
14638
|
+
errorCode: "BOARD_TARGET_NOT_ELIGIBLE",
|
|
14639
|
+
message: "Board target is not eligible."
|
|
14640
|
+
},
|
|
14641
|
+
equals: (left, right) => isPlayerBoardSpaceTarget(left) && isPlayerBoardSpaceTarget(right) && left.boardId === right.boardId && left.playerId === right.playerId && left.spaceId === right.spaceId
|
|
14642
|
+
}
|
|
14643
|
+
),
|
|
14644
|
+
boardId,
|
|
14645
|
+
targetKind: "space",
|
|
14646
|
+
valueKind: "player-board-space"
|
|
14368
14647
|
})
|
|
14369
14648
|
);
|
|
14370
14649
|
}
|
|
14650
|
+
function isPlayerBoardSpaceTarget(value) {
|
|
14651
|
+
return typeof value === "object" && value !== null && "boardId" in value && "playerId" in value && "spaceId" in value;
|
|
14652
|
+
}
|
|
14371
14653
|
function makeBoardTargetFactory(targetKind) {
|
|
14372
14654
|
return function target(boardId) {
|
|
14373
14655
|
return createBoardTargetBuilder(targetKind, boardId);
|
|
@@ -14377,7 +14659,10 @@ var boardTarget = {
|
|
|
14377
14659
|
edge: makeBoardTargetFactory("edge"),
|
|
14378
14660
|
vertex: makeBoardTargetFactory("vertex"),
|
|
14379
14661
|
space: makeBoardTargetFactory("space"),
|
|
14380
|
-
tile: makeBoardTargetFactory("tile")
|
|
14662
|
+
tile: makeBoardTargetFactory("tile"),
|
|
14663
|
+
playerSpace(boardId) {
|
|
14664
|
+
return createPlayerSpaceTargetBuilder(boardId);
|
|
14665
|
+
}
|
|
14381
14666
|
};
|
|
14382
14667
|
|
|
14383
14668
|
// ../../packages/app-sdk/src/reducer/inputs/cardTarget.ts
|
|
@@ -14424,22 +14709,38 @@ var cardTarget = {
|
|
|
14424
14709
|
// ../../packages/app-sdk/src/reducer/inputs/cardInput.ts
|
|
14425
14710
|
function cardInput(options) {
|
|
14426
14711
|
const target = options.target;
|
|
14712
|
+
const dependsOn = options.dependsOn?.map((dependency) => dependency.key);
|
|
14427
14713
|
return {
|
|
14428
14714
|
kind: "card",
|
|
14429
14715
|
schema: external_exports.string(),
|
|
14430
|
-
eligibleTargets: ((state, playerId, q) => target.eligible({
|
|
14716
|
+
eligibleTargets: ((state, playerId, q, values) => target.eligible({
|
|
14431
14717
|
state,
|
|
14432
14718
|
playerId,
|
|
14433
|
-
q
|
|
14719
|
+
q,
|
|
14720
|
+
values
|
|
14434
14721
|
})),
|
|
14435
|
-
validateTarget: ((state, playerId, q, targetId) => target.validate(
|
|
14722
|
+
validateTarget: ((state, playerId, q, targetId, values) => target.validate(
|
|
14436
14723
|
{
|
|
14437
14724
|
state,
|
|
14438
14725
|
playerId,
|
|
14439
|
-
q
|
|
14726
|
+
q,
|
|
14727
|
+
values
|
|
14440
14728
|
},
|
|
14441
14729
|
targetId
|
|
14442
14730
|
)),
|
|
14731
|
+
...dependsOn ? { dependsOn } : {},
|
|
14732
|
+
domain: dependsOn ? (state, playerId, q, _derived, values) => ({
|
|
14733
|
+
type: "target",
|
|
14734
|
+
targetKind: target.targetKind,
|
|
14735
|
+
zoneId: target.zoneId,
|
|
14736
|
+
zoneIds: target.zoneIds,
|
|
14737
|
+
eligibleTargets: target.eligible({
|
|
14738
|
+
state,
|
|
14739
|
+
playerId,
|
|
14740
|
+
q,
|
|
14741
|
+
values
|
|
14742
|
+
}).map(String)
|
|
14743
|
+
}) : void 0,
|
|
14443
14744
|
meta: {
|
|
14444
14745
|
zoneId: target.zoneId,
|
|
14445
14746
|
zoneIds: target.zoneIds,
|
|
@@ -16131,6 +16432,35 @@ function shuffleWithRng(values, rng, operation = "shuffleSharedZone") {
|
|
|
16131
16432
|
}
|
|
16132
16433
|
return { orderedValues, nextRng, consumptions };
|
|
16133
16434
|
}
|
|
16435
|
+
function subsetWithRng(values, count, rng) {
|
|
16436
|
+
if (!Number.isInteger(count) || count < 0) {
|
|
16437
|
+
throw new Error("random.subset count must be a non-negative integer.");
|
|
16438
|
+
}
|
|
16439
|
+
if (count > values.length) {
|
|
16440
|
+
throw new Error(
|
|
16441
|
+
`random.subset count ${count} exceeds source length ${values.length}.`
|
|
16442
|
+
);
|
|
16443
|
+
}
|
|
16444
|
+
const shuffled = shuffleWithRng(values, rng, "randomSubset");
|
|
16445
|
+
return {
|
|
16446
|
+
values: shuffled.orderedValues.slice(0, count),
|
|
16447
|
+
nextRng: shuffled.nextRng,
|
|
16448
|
+
consumptions: shuffled.consumptions
|
|
16449
|
+
};
|
|
16450
|
+
}
|
|
16451
|
+
function createMutableRandomHelpers(rng) {
|
|
16452
|
+
let current = rng;
|
|
16453
|
+
return {
|
|
16454
|
+
random: {
|
|
16455
|
+
subset(options) {
|
|
16456
|
+
const sampled = subsetWithRng(options.from, options.count, current);
|
|
16457
|
+
current = sampled.nextRng;
|
|
16458
|
+
return sampled.values;
|
|
16459
|
+
}
|
|
16460
|
+
},
|
|
16461
|
+
currentRng: () => current
|
|
16462
|
+
};
|
|
16463
|
+
}
|
|
16134
16464
|
function sampleRngCollectorValue(collector, rng) {
|
|
16135
16465
|
const meta = collector.meta;
|
|
16136
16466
|
switch (meta.rng) {
|
|
@@ -16579,6 +16909,126 @@ function createReducerFx(_state) {
|
|
|
16579
16909
|
function updateTable(state, nextTable) {
|
|
16580
16910
|
return { ...state, table: nextTable };
|
|
16581
16911
|
}
|
|
16912
|
+
function computePlayerZoneVisibility(table, zoneId, playerId) {
|
|
16913
|
+
const mode = table.handVisibility[zoneId];
|
|
16914
|
+
if (mode === "all" || mode === "public") {
|
|
16915
|
+
return { faceUp: true };
|
|
16916
|
+
}
|
|
16917
|
+
return { faceUp: false, visibleTo: [playerId] };
|
|
16918
|
+
}
|
|
16919
|
+
function readPlayerZoneCards(table, zoneId, playerId) {
|
|
16920
|
+
const zone = table.zones.perPlayer[zoneId] ?? table.hands[zoneId];
|
|
16921
|
+
if (!zone) {
|
|
16922
|
+
throw new Error(`Player zone '${zoneId}' does not exist.`);
|
|
16923
|
+
}
|
|
16924
|
+
return perPlayerGet(zone, asPlayerId(playerId)) ?? [];
|
|
16925
|
+
}
|
|
16926
|
+
function writePlayerZoneCards(table, zoneId, playerId, cards) {
|
|
16927
|
+
const currentZone = table.zones.perPlayer[zoneId];
|
|
16928
|
+
const currentHand = table.hands[zoneId];
|
|
16929
|
+
const player = asPlayerId(playerId);
|
|
16930
|
+
if (currentZone) {
|
|
16931
|
+
table.zones.perPlayer[zoneId] = perPlayerSet(
|
|
16932
|
+
currentZone,
|
|
16933
|
+
player,
|
|
16934
|
+
[...cards]
|
|
16935
|
+
);
|
|
16936
|
+
}
|
|
16937
|
+
if (currentHand) {
|
|
16938
|
+
table.hands[zoneId] = perPlayerSet(
|
|
16939
|
+
currentHand,
|
|
16940
|
+
player,
|
|
16941
|
+
[...cards]
|
|
16942
|
+
);
|
|
16943
|
+
}
|
|
16944
|
+
}
|
|
16945
|
+
function assertCardAllowedInPlayerZone(table, zoneId, cardId) {
|
|
16946
|
+
const allowedCardSetIds = table.zones.cardSetIdsByZoneId?.[zoneId];
|
|
16947
|
+
if (!allowedCardSetIds || allowedCardSetIds.length === 0) {
|
|
16948
|
+
return;
|
|
16949
|
+
}
|
|
16950
|
+
const card = table.cards[cardId];
|
|
16951
|
+
if (!card) {
|
|
16952
|
+
throw new Error(`Card '${cardId}' does not exist.`);
|
|
16953
|
+
}
|
|
16954
|
+
if (!allowedCardSetIds.includes(card.cardSetId)) {
|
|
16955
|
+
throw new Error(
|
|
16956
|
+
`Card '${cardId}' from set '${card.cardSetId}' is not allowed in player zone '${zoneId}'.`
|
|
16957
|
+
);
|
|
16958
|
+
}
|
|
16959
|
+
}
|
|
16960
|
+
function rotatePlayerZoneTable(options) {
|
|
16961
|
+
const nextTable = cloneRuntimeTable(options.table);
|
|
16962
|
+
const zoneId = options.zoneId;
|
|
16963
|
+
if (!nextTable.zones.perPlayer[zoneId] && !nextTable.hands[zoneId]) {
|
|
16964
|
+
throw new Error(`Player zone '${zoneId}' does not exist.`);
|
|
16965
|
+
}
|
|
16966
|
+
const players = [...options.players ?? nextTable.playerOrder];
|
|
16967
|
+
if (players.length === 0) {
|
|
16968
|
+
return nextTable;
|
|
16969
|
+
}
|
|
16970
|
+
const playerSet = new Set(nextTable.playerOrder);
|
|
16971
|
+
for (const playerId of players) {
|
|
16972
|
+
if (!playerSet.has(playerId)) {
|
|
16973
|
+
throw new Error(
|
|
16974
|
+
`Cannot rotate player zone '${zoneId}': player '${playerId}' is not in player order.`
|
|
16975
|
+
);
|
|
16976
|
+
}
|
|
16977
|
+
}
|
|
16978
|
+
const selectedByPlayer = /* @__PURE__ */ new Map();
|
|
16979
|
+
for (const playerId of players) {
|
|
16980
|
+
const sourceCards = readPlayerZoneCards(nextTable, zoneId, playerId);
|
|
16981
|
+
const selected = options.cardIdsByPlayer?.[playerId] ?? sourceCards;
|
|
16982
|
+
for (const cardId of selected) {
|
|
16983
|
+
if (!sourceCards.includes(cardId)) {
|
|
16984
|
+
throw new Error(
|
|
16985
|
+
`Cannot rotate player zone '${zoneId}': card '${cardId}' is not in zone for player '${playerId}'.`
|
|
16986
|
+
);
|
|
16987
|
+
}
|
|
16988
|
+
assertCardAllowedInPlayerZone(nextTable, zoneId, cardId);
|
|
16989
|
+
}
|
|
16990
|
+
selectedByPlayer.set(playerId, [...selected]);
|
|
16991
|
+
}
|
|
16992
|
+
const removeByPlayer = /* @__PURE__ */ new Map();
|
|
16993
|
+
for (const playerId of players) {
|
|
16994
|
+
const selected = new Set(selectedByPlayer.get(playerId) ?? []);
|
|
16995
|
+
removeByPlayer.set(
|
|
16996
|
+
playerId,
|
|
16997
|
+
readPlayerZoneCards(nextTable, zoneId, playerId).filter(
|
|
16998
|
+
(cardId) => !selected.has(cardId)
|
|
16999
|
+
)
|
|
17000
|
+
);
|
|
17001
|
+
}
|
|
17002
|
+
const additionsByPlayer = new Map(
|
|
17003
|
+
players.map((playerId) => [playerId, []])
|
|
17004
|
+
);
|
|
17005
|
+
for (const [index, fromPlayerId] of players.entries()) {
|
|
17006
|
+
const offset = options.direction === "left" ? 1 : -1;
|
|
17007
|
+
const recipient = players[(index + offset + players.length) % players.length];
|
|
17008
|
+
additionsByPlayer.get(recipient).push(...selectedByPlayer.get(fromPlayerId) ?? []);
|
|
17009
|
+
}
|
|
17010
|
+
for (const playerId of players) {
|
|
17011
|
+
const remaining = removeByPlayer.get(playerId) ?? [];
|
|
17012
|
+
const additions = additionsByPlayer.get(playerId) ?? [];
|
|
17013
|
+
const nextCards = options.position === "top" ? [...additions, ...remaining] : [...remaining, ...additions];
|
|
17014
|
+
writePlayerZoneCards(nextTable, zoneId, playerId, nextCards);
|
|
17015
|
+
for (const [position, cardId] of nextCards.entries()) {
|
|
17016
|
+
nextTable.componentLocations[cardId] = {
|
|
17017
|
+
type: "InHand",
|
|
17018
|
+
handId: zoneId,
|
|
17019
|
+
playerId,
|
|
17020
|
+
position
|
|
17021
|
+
};
|
|
17022
|
+
nextTable.ownerOfCard[cardId] = playerId;
|
|
17023
|
+
nextTable.visibility[cardId] = computePlayerZoneVisibility(
|
|
17024
|
+
nextTable,
|
|
17025
|
+
zoneId,
|
|
17026
|
+
playerId
|
|
17027
|
+
);
|
|
17028
|
+
}
|
|
17029
|
+
}
|
|
17030
|
+
return nextTable;
|
|
17031
|
+
}
|
|
16582
17032
|
var moveComponentToEdgeInternal = moveComponentToEdge;
|
|
16583
17033
|
var moveComponentToVertexInternal = moveComponentToVertex;
|
|
16584
17034
|
var dealCardsFromDeckToHandInternal = dealCardsFromDeckToHand;
|
|
@@ -16762,6 +17212,19 @@ function createReducerOps() {
|
|
|
16762
17212
|
return updateTable(state, nextTable);
|
|
16763
17213
|
};
|
|
16764
17214
|
},
|
|
17215
|
+
rotatePlayerZone(args) {
|
|
17216
|
+
return (state) => {
|
|
17217
|
+
const nextTable = rotatePlayerZoneTable({
|
|
17218
|
+
table: state.table,
|
|
17219
|
+
zoneId: args.zoneId,
|
|
17220
|
+
direction: args.direction,
|
|
17221
|
+
players: args.players,
|
|
17222
|
+
cardIdsByPlayer: args.cardIdsByPlayer,
|
|
17223
|
+
position: args.position ?? "bottom"
|
|
17224
|
+
});
|
|
17225
|
+
return updateTable(state, nextTable);
|
|
17226
|
+
};
|
|
17227
|
+
},
|
|
16765
17228
|
moveComponentToSpace(args) {
|
|
16766
17229
|
return (state) => {
|
|
16767
17230
|
const nextTable = moveComponentToSpace(
|
|
@@ -16861,6 +17324,47 @@ function createReducerOps() {
|
|
|
16861
17324
|
return impl;
|
|
16862
17325
|
}
|
|
16863
17326
|
|
|
17327
|
+
// ../../packages/app-sdk/src/reducer/transaction.ts
|
|
17328
|
+
function createReducerTransaction(initialState, ops = createReducerOps()) {
|
|
17329
|
+
let currentState = initialState;
|
|
17330
|
+
let currentQueries = createStateQueries(currentState);
|
|
17331
|
+
const refresh = (nextState) => {
|
|
17332
|
+
currentState = nextState;
|
|
17333
|
+
currentQueries = createStateQueries(currentState);
|
|
17334
|
+
return currentState;
|
|
17335
|
+
};
|
|
17336
|
+
const apply = (op) => refresh(op(currentState));
|
|
17337
|
+
const base = {
|
|
17338
|
+
get state() {
|
|
17339
|
+
return currentState;
|
|
17340
|
+
},
|
|
17341
|
+
get q() {
|
|
17342
|
+
return currentQueries;
|
|
17343
|
+
},
|
|
17344
|
+
apply
|
|
17345
|
+
};
|
|
17346
|
+
return new Proxy(base, {
|
|
17347
|
+
get(target, property, receiver) {
|
|
17348
|
+
if (property in target) {
|
|
17349
|
+
return Reflect.get(target, property, receiver);
|
|
17350
|
+
}
|
|
17351
|
+
const opFactory = ops[property];
|
|
17352
|
+
if (typeof opFactory !== "function") {
|
|
17353
|
+
return void 0;
|
|
17354
|
+
}
|
|
17355
|
+
return (...args) => {
|
|
17356
|
+
const op = opFactory(
|
|
17357
|
+
...args
|
|
17358
|
+
);
|
|
17359
|
+
return apply(op);
|
|
17360
|
+
};
|
|
17361
|
+
}
|
|
17362
|
+
});
|
|
17363
|
+
}
|
|
17364
|
+
function createReducerEdit(ops = createReducerOps()) {
|
|
17365
|
+
return (state) => createReducerTransaction(state, ops);
|
|
17366
|
+
}
|
|
17367
|
+
|
|
16864
17368
|
// ../../packages/app-sdk/src/reducer/definition-index.ts
|
|
16865
17369
|
function phaseEntriesOf(definition) {
|
|
16866
17370
|
return Object.entries(definition.phases);
|
|
@@ -16909,6 +17413,7 @@ function collectReducerDefinitionIndex(definition) {
|
|
|
16909
17413
|
cardActionId,
|
|
16910
17414
|
{
|
|
16911
17415
|
...cardAction,
|
|
17416
|
+
__steps: cardAction.__steps,
|
|
16912
17417
|
inputs: {
|
|
16913
17418
|
cardId: cardInput({
|
|
16914
17419
|
target: cardTarget.zones([cardAction.playFrom]).where({
|
|
@@ -16986,7 +17491,7 @@ function buildContext(state, manifest) {
|
|
|
16986
17491
|
manifest,
|
|
16987
17492
|
playerOrder: [...state.table.playerOrder],
|
|
16988
17493
|
activePlayers: [...state.flow.activePlayers],
|
|
16989
|
-
runtime: state.runtime,
|
|
17494
|
+
runtime: publicRuntime(state.runtime),
|
|
16990
17495
|
setup: state.runtime.setup ? {
|
|
16991
17496
|
profileId: state.runtime.setup.profileId,
|
|
16992
17497
|
optionValues: {
|
|
@@ -16995,6 +17500,17 @@ function buildContext(state, manifest) {
|
|
|
16995
17500
|
} : null
|
|
16996
17501
|
};
|
|
16997
17502
|
}
|
|
17503
|
+
function publicRuntime(runtime) {
|
|
17504
|
+
const { rng: _rng, ...rest } = runtime;
|
|
17505
|
+
return rest;
|
|
17506
|
+
}
|
|
17507
|
+
var DISABLED_RANDOM_HELPERS = {
|
|
17508
|
+
subset() {
|
|
17509
|
+
throw new Error(
|
|
17510
|
+
"random helpers are only available in reducer mutation callbacks."
|
|
17511
|
+
);
|
|
17512
|
+
}
|
|
17513
|
+
};
|
|
16998
17514
|
function buildRuntimeArgs(state, manifest, helpers, toDomainState2, extra, options = {}) {
|
|
16999
17515
|
const domainState = toDomainState2(state);
|
|
17000
17516
|
const q = options.q ?? createStateQueries(domainState);
|
|
@@ -17004,7 +17520,8 @@ function buildRuntimeArgs(state, manifest, helpers, toDomainState2, extra, optio
|
|
|
17004
17520
|
fx: options.fx ?? fxForState(state),
|
|
17005
17521
|
q,
|
|
17006
17522
|
derived: options.derived ?? createDerivedResolver(domainState, { q }),
|
|
17007
|
-
runtime: state.runtime,
|
|
17523
|
+
runtime: publicRuntime(state.runtime),
|
|
17524
|
+
random: options.random ?? DISABLED_RANDOM_HELPERS,
|
|
17008
17525
|
...extra
|
|
17009
17526
|
};
|
|
17010
17527
|
}
|
|
@@ -17038,13 +17555,16 @@ var runtimeResultHelpers = {
|
|
|
17038
17555
|
// ../../packages/app-sdk/src/reducer/bundle/trusted/trusted-state-codec.ts
|
|
17039
17556
|
function toDomainState(state) {
|
|
17040
17557
|
const { runtime: _runtime, ...domain } = state;
|
|
17558
|
+
attachPhaseAccessor(domain);
|
|
17041
17559
|
return domain;
|
|
17042
17560
|
}
|
|
17043
17561
|
function toCombinedState(session) {
|
|
17044
|
-
|
|
17562
|
+
const combined = {
|
|
17045
17563
|
...session.domain,
|
|
17046
17564
|
runtime: session.runtime
|
|
17047
17565
|
};
|
|
17566
|
+
attachPhaseAccessor(combined);
|
|
17567
|
+
return combined;
|
|
17048
17568
|
}
|
|
17049
17569
|
function toSessionState(state, toDomain) {
|
|
17050
17570
|
return {
|
|
@@ -17052,6 +17572,19 @@ function toSessionState(state, toDomain) {
|
|
|
17052
17572
|
runtime: state.runtime
|
|
17053
17573
|
};
|
|
17054
17574
|
}
|
|
17575
|
+
function attachPhaseAccessor(state) {
|
|
17576
|
+
if (!state || typeof state !== "object") return;
|
|
17577
|
+
const candidate = state;
|
|
17578
|
+
const phase = candidate.phase;
|
|
17579
|
+
if (!phase || typeof phase !== "object") return;
|
|
17580
|
+
const descriptor = Object.getOwnPropertyDescriptor(phase, "get");
|
|
17581
|
+
if (descriptor && typeof descriptor.value === "function") return;
|
|
17582
|
+
Object.defineProperty(phase, "get", {
|
|
17583
|
+
enumerable: false,
|
|
17584
|
+
configurable: true,
|
|
17585
|
+
value: (phaseName) => candidate.flow?.currentPhase === phaseName ? phase : null
|
|
17586
|
+
});
|
|
17587
|
+
}
|
|
17055
17588
|
|
|
17056
17589
|
// ../../packages/app-sdk/src/reducer/bundle/trusted/trusted-setup-profiles.ts
|
|
17057
17590
|
function resolveTrustedSetupProfiles(definition) {
|
|
@@ -17133,7 +17666,8 @@ function createTrustedRuntimeScope(definition) {
|
|
|
17133
17666
|
}
|
|
17134
17667
|
const helpers = {
|
|
17135
17668
|
...runtimeResultHelpers,
|
|
17136
|
-
ops: createReducerOps()
|
|
17669
|
+
ops: createReducerOps(),
|
|
17670
|
+
edit: createReducerEdit()
|
|
17137
17671
|
};
|
|
17138
17672
|
function fxForState2(state) {
|
|
17139
17673
|
return fxForState(state);
|
|
@@ -17196,24 +17730,31 @@ function createTrustedInstructionRunner(scope, interactions, lifecycle) {
|
|
|
17196
17730
|
}
|
|
17197
17731
|
const parsed = interactions.parseInteractionParams(
|
|
17198
17732
|
interaction,
|
|
17199
|
-
input.params
|
|
17733
|
+
input.params,
|
|
17734
|
+
{ playerId: input.playerId }
|
|
17200
17735
|
);
|
|
17201
17736
|
if (!parsed.ok) {
|
|
17202
17737
|
return rejectResult("invalid-action-params", parsed.message);
|
|
17203
17738
|
}
|
|
17204
|
-
|
|
17739
|
+
const random = createMutableRandomHelpers(state.runtime.rng);
|
|
17740
|
+
const result = normalizeResult(
|
|
17205
17741
|
interaction.reduce(
|
|
17206
|
-
scope.buildRuntimeArgs(
|
|
17207
|
-
|
|
17208
|
-
|
|
17209
|
-
|
|
17210
|
-
|
|
17211
|
-
|
|
17212
|
-
|
|
17213
|
-
|
|
17742
|
+
scope.buildRuntimeArgs(
|
|
17743
|
+
state,
|
|
17744
|
+
{
|
|
17745
|
+
...ctx,
|
|
17746
|
+
state: scope.toDomainState(state),
|
|
17747
|
+
input: {
|
|
17748
|
+
playerId: input.playerId,
|
|
17749
|
+
params: parsed.params
|
|
17750
|
+
}
|
|
17751
|
+
},
|
|
17752
|
+
{ random: random.random }
|
|
17753
|
+
)
|
|
17214
17754
|
),
|
|
17215
17755
|
scope.toDomainState(state)
|
|
17216
17756
|
);
|
|
17757
|
+
return result.type === "accept" ? { ...result, runtimeRng: random.currentRng() } : result;
|
|
17217
17758
|
}
|
|
17218
17759
|
if (input.kind === "continuation") {
|
|
17219
17760
|
const continuation = scope.continuationById(input.continuationId);
|
|
@@ -17223,21 +17764,27 @@ function createTrustedInstructionRunner(scope, interactions, lifecycle) {
|
|
|
17223
17764
|
`Continuation '${input.continuationId}' was not registered.`
|
|
17224
17765
|
);
|
|
17225
17766
|
}
|
|
17226
|
-
|
|
17767
|
+
const random = createMutableRandomHelpers(state.runtime.rng);
|
|
17768
|
+
const result = normalizeResult(
|
|
17227
17769
|
continuation.reduce(
|
|
17228
|
-
scope.buildRuntimeArgs(
|
|
17229
|
-
|
|
17230
|
-
|
|
17231
|
-
|
|
17232
|
-
|
|
17233
|
-
|
|
17234
|
-
|
|
17235
|
-
|
|
17236
|
-
|
|
17237
|
-
|
|
17770
|
+
scope.buildRuntimeArgs(
|
|
17771
|
+
state,
|
|
17772
|
+
{
|
|
17773
|
+
...ctx,
|
|
17774
|
+
state: scope.toDomainState(state),
|
|
17775
|
+
input: {
|
|
17776
|
+
source: "effect",
|
|
17777
|
+
effectKind: input.effectKind,
|
|
17778
|
+
data: input.resumeData,
|
|
17779
|
+
response: input.response
|
|
17780
|
+
}
|
|
17781
|
+
},
|
|
17782
|
+
{ random: random.random }
|
|
17783
|
+
)
|
|
17238
17784
|
),
|
|
17239
17785
|
scope.toDomainState(state)
|
|
17240
17786
|
);
|
|
17787
|
+
return result.type === "accept" ? { ...result, runtimeRng: random.currentRng() } : result;
|
|
17241
17788
|
}
|
|
17242
17789
|
return scope.runtimeHelpers.accept(scope.toDomainState(state));
|
|
17243
17790
|
}
|
|
@@ -17369,14 +17916,19 @@ function createTrustedInstructionRunner(scope, interactions, lifecycle) {
|
|
|
17369
17916
|
}
|
|
17370
17917
|
])
|
|
17371
17918
|
);
|
|
17919
|
+
const random = createMutableRandomHelpers(stateWithSubmission.runtime.rng);
|
|
17372
17920
|
const resolved = normalizeResult(
|
|
17373
17921
|
resolve(
|
|
17374
|
-
scope.buildRuntimeArgs(
|
|
17375
|
-
|
|
17376
|
-
|
|
17377
|
-
|
|
17378
|
-
|
|
17379
|
-
|
|
17922
|
+
scope.buildRuntimeArgs(
|
|
17923
|
+
stateWithSubmission,
|
|
17924
|
+
{
|
|
17925
|
+
state: scope.toDomainState(stateWithSubmission),
|
|
17926
|
+
submissions: resolvedSubmissions,
|
|
17927
|
+
submittedPlayerIds: [...actors],
|
|
17928
|
+
waitingPlayerIds: []
|
|
17929
|
+
},
|
|
17930
|
+
{ random: random.random }
|
|
17931
|
+
)
|
|
17380
17932
|
),
|
|
17381
17933
|
scope.toDomainState(stateWithSubmission)
|
|
17382
17934
|
);
|
|
@@ -17387,7 +17939,7 @@ function createTrustedInstructionRunner(scope, interactions, lifecycle) {
|
|
|
17387
17939
|
type: "accept",
|
|
17388
17940
|
state: clearSimultaneousCurrent({
|
|
17389
17941
|
...resolved.state,
|
|
17390
|
-
runtime: stateWithSubmission.runtime
|
|
17942
|
+
runtime: { ...stateWithSubmission.runtime, rng: random.currentRng() }
|
|
17391
17943
|
}),
|
|
17392
17944
|
instructions: resolved.instructions ?? []
|
|
17393
17945
|
};
|
|
@@ -17409,7 +17961,10 @@ function createTrustedInstructionRunner(scope, interactions, lifecycle) {
|
|
|
17409
17961
|
type: "accept",
|
|
17410
17962
|
state: {
|
|
17411
17963
|
...result.state,
|
|
17412
|
-
runtime:
|
|
17964
|
+
runtime: {
|
|
17965
|
+
...sampled.state.runtime,
|
|
17966
|
+
rng: result.runtimeRng ?? sampled.state.runtime.rng
|
|
17967
|
+
}
|
|
17413
17968
|
},
|
|
17414
17969
|
instructions: result.instructions ?? []
|
|
17415
17970
|
};
|
|
@@ -17504,6 +18059,48 @@ function withSelection(domain, collector) {
|
|
|
17504
18059
|
if (!collector.selection) return domain;
|
|
17505
18060
|
return { ...domain, selection: collector.selection };
|
|
17506
18061
|
}
|
|
18062
|
+
function finiteValuesForDependency(key, domain) {
|
|
18063
|
+
if (!domain) {
|
|
18064
|
+
throw new Error(
|
|
18065
|
+
`Interaction input '${key}' is declared as a dependency before it has a projected domain.`
|
|
18066
|
+
);
|
|
18067
|
+
}
|
|
18068
|
+
if (domain.type === "target") {
|
|
18069
|
+
if (!domain.eligibleTargets) {
|
|
18070
|
+
throw new Error(
|
|
18071
|
+
`Interaction input '${key}' cannot be used as a dependency because its target domain is not finite.`
|
|
18072
|
+
);
|
|
18073
|
+
}
|
|
18074
|
+
return [...domain.eligibleTargets];
|
|
18075
|
+
}
|
|
18076
|
+
if (domain.type === "choice") {
|
|
18077
|
+
return domain.choices.flatMap(
|
|
18078
|
+
(choice) => choice.value === null ? [] : [choice.value]
|
|
18079
|
+
);
|
|
18080
|
+
}
|
|
18081
|
+
throw new Error(
|
|
18082
|
+
`Interaction input '${key}' cannot be used as a dependency. V1 supports finite target and choice dependencies only.`
|
|
18083
|
+
);
|
|
18084
|
+
}
|
|
18085
|
+
function cartesianDependencyTuples(dependencies, domainsByKey) {
|
|
18086
|
+
return dependencies.reduce(
|
|
18087
|
+
(tuples, key) => {
|
|
18088
|
+
const values = finiteValuesForDependency(key, domainsByKey[key]);
|
|
18089
|
+
return tuples.flatMap(
|
|
18090
|
+
(tuple) => values.map((value) => ({ ...tuple, [key]: value }))
|
|
18091
|
+
);
|
|
18092
|
+
},
|
|
18093
|
+
[{}]
|
|
18094
|
+
);
|
|
18095
|
+
}
|
|
18096
|
+
function withoutDependentProjection(domain) {
|
|
18097
|
+
const {
|
|
18098
|
+
dependsOn: _dependsOn,
|
|
18099
|
+
dependentCases: _dependentCases,
|
|
18100
|
+
...rest
|
|
18101
|
+
} = domain;
|
|
18102
|
+
return rest;
|
|
18103
|
+
}
|
|
17507
18104
|
function unsupportedDefaultInputError(key, collector) {
|
|
17508
18105
|
return new Error(
|
|
17509
18106
|
`Interaction input '${key}' uses a '${collector.kind}' collector without a default-renderable domain or target metadata. Use formInput.choice(...), formInput.choiceList(...), formInput.number(...), formInput.resourceMap(...), cardInput(...), or boardInput(...). For custom payloads, use a custom interaction surface with paramsSchema instead of the default InteractionForm.`
|
|
@@ -17552,19 +18149,74 @@ function collectInputDomains(interaction, domainState, playerId, eligibleTargets
|
|
|
17552
18149
|
const derived = () => derivedLazy ??= createDerivedResolver(domainState, { q: queries() });
|
|
17553
18150
|
const result = {};
|
|
17554
18151
|
for (const [key, collector] of Object.entries(collectors)) {
|
|
17555
|
-
if (collector.kind === "rng"
|
|
18152
|
+
if (collector.kind === "rng") {
|
|
18153
|
+
continue;
|
|
18154
|
+
}
|
|
18155
|
+
if (collector.kind === "prompt") {
|
|
18156
|
+
const optionFactory = collector.meta?.options;
|
|
18157
|
+
if (!optionFactory) continue;
|
|
18158
|
+
result[key] = {
|
|
18159
|
+
type: "choice",
|
|
18160
|
+
choices: optionFactory(domainState, playerId, queries()).map(
|
|
18161
|
+
(option) => ({
|
|
18162
|
+
value: String(option.id),
|
|
18163
|
+
label: option.label ?? String(option.id),
|
|
18164
|
+
...(() => {
|
|
18165
|
+
const issue = collector.validateTarget?.(
|
|
18166
|
+
domainState,
|
|
18167
|
+
playerId,
|
|
18168
|
+
queries(),
|
|
18169
|
+
String(option.id)
|
|
18170
|
+
);
|
|
18171
|
+
return issue ? {
|
|
18172
|
+
disabled: true,
|
|
18173
|
+
disabledReason: issue.message ?? issue.errorCode
|
|
18174
|
+
} : {};
|
|
18175
|
+
})()
|
|
18176
|
+
})
|
|
18177
|
+
)
|
|
18178
|
+
};
|
|
17556
18179
|
continue;
|
|
17557
18180
|
}
|
|
17558
18181
|
if (collector.domain) {
|
|
17559
|
-
|
|
18182
|
+
const dependencies = collector.dependsOn ?? [];
|
|
18183
|
+
const baseDomain = withSelection(
|
|
17560
18184
|
collector.domain(
|
|
17561
18185
|
domainState,
|
|
17562
18186
|
playerId,
|
|
17563
18187
|
queries(),
|
|
17564
|
-
derived()
|
|
18188
|
+
derived(),
|
|
18189
|
+
{}
|
|
17565
18190
|
),
|
|
17566
18191
|
collector
|
|
17567
18192
|
);
|
|
18193
|
+
if (dependencies.length === 0) {
|
|
18194
|
+
result[key] = baseDomain;
|
|
18195
|
+
continue;
|
|
18196
|
+
}
|
|
18197
|
+
const dependentCases = cartesianDependencyTuples(
|
|
18198
|
+
dependencies,
|
|
18199
|
+
result
|
|
18200
|
+
).map((values) => ({
|
|
18201
|
+
when: values,
|
|
18202
|
+
domain: withoutDependentProjection(
|
|
18203
|
+
withSelection(
|
|
18204
|
+
collector.domain?.(
|
|
18205
|
+
domainState,
|
|
18206
|
+
playerId,
|
|
18207
|
+
queries(),
|
|
18208
|
+
derived(),
|
|
18209
|
+
values
|
|
18210
|
+
),
|
|
18211
|
+
collector
|
|
18212
|
+
)
|
|
18213
|
+
)
|
|
18214
|
+
}));
|
|
18215
|
+
result[key] = {
|
|
18216
|
+
...baseDomain,
|
|
18217
|
+
dependsOn: dependencies,
|
|
18218
|
+
dependentCases
|
|
18219
|
+
};
|
|
17568
18220
|
continue;
|
|
17569
18221
|
}
|
|
17570
18222
|
const targets = eligibleTargets[key];
|
|
@@ -17586,7 +18238,17 @@ function collectInputDomains(interaction, domainState, playerId, eligibleTargets
|
|
|
17586
18238
|
}
|
|
17587
18239
|
function collectInteractionInputs(interaction, domainState, playerId, options = {}) {
|
|
17588
18240
|
const collectors = interactionInputsOf(interaction);
|
|
17589
|
-
const
|
|
18241
|
+
const dependencyKeys = new Set(
|
|
18242
|
+
Object.values(collectors).flatMap((collector) => [
|
|
18243
|
+
...collector.dependsOn ?? []
|
|
18244
|
+
])
|
|
18245
|
+
);
|
|
18246
|
+
const collectedEligibleTargets = options.includeEligibleTargets === false && dependencyKeys.size === 0 ? {} : collectEligibleTargets(interaction, domainState, playerId, options);
|
|
18247
|
+
const eligibleTargets = options.includeEligibleTargets === false ? Object.fromEntries(
|
|
18248
|
+
Object.entries(collectedEligibleTargets).filter(
|
|
18249
|
+
([key]) => dependencyKeys.has(key)
|
|
18250
|
+
)
|
|
18251
|
+
) : collectedEligibleTargets;
|
|
17590
18252
|
const domainsByKey = collectInputDomains(
|
|
17591
18253
|
interaction,
|
|
17592
18254
|
domainState,
|
|
@@ -17601,10 +18263,13 @@ function collectInteractionInputs(interaction, domainState, playerId, options =
|
|
|
17601
18263
|
let derivedLazy = options.derived ?? null;
|
|
17602
18264
|
const derived = () => derivedLazy ??= createDerivedResolver(domainState, { q: queries() });
|
|
17603
18265
|
return Object.entries(collectors).flatMap(([key, collector]) => {
|
|
17604
|
-
if (collector.kind === "rng"
|
|
18266
|
+
if (collector.kind === "rng") {
|
|
17605
18267
|
return [];
|
|
17606
18268
|
}
|
|
17607
18269
|
const domain = domainsByKey[key];
|
|
18270
|
+
if (!domain && collector.kind === "prompt") {
|
|
18271
|
+
return [];
|
|
18272
|
+
}
|
|
17608
18273
|
if (!domain) {
|
|
17609
18274
|
throw unsupportedDefaultInputError(key, collector);
|
|
17610
18275
|
}
|
|
@@ -17651,7 +18316,7 @@ function collectCardZoneIds(interaction) {
|
|
|
17651
18316
|
function collectPromptOptions(interaction, domainState, playerId, queries) {
|
|
17652
18317
|
for (const collector of Object.values(interaction.inputs)) {
|
|
17653
18318
|
if (collector.kind !== "prompt") continue;
|
|
17654
|
-
const factory = collector.meta?.
|
|
18319
|
+
const factory = collector.meta?.options;
|
|
17655
18320
|
if (!factory) continue;
|
|
17656
18321
|
return factory(domainState, playerId, queries).map((option) => ({
|
|
17657
18322
|
id: String(option.id),
|
|
@@ -17677,7 +18342,12 @@ function parseInteractionParams(interaction, rawParams, options = {}) {
|
|
|
17677
18342
|
const issues = [];
|
|
17678
18343
|
for (const [key, collector] of Object.entries(collectors)) {
|
|
17679
18344
|
if (collector.kind === "rng" && options.skipRng) continue;
|
|
17680
|
-
const
|
|
18345
|
+
const rawValueBase = record[key] === void 0 && "defaultValue" in collector ? collector.defaultValue : record[key];
|
|
18346
|
+
const rawValue = collector.kind === "board-space" && collector.meta?.valueKind === "player-board-space" && typeof rawValueBase === "string" && options.playerId ? {
|
|
18347
|
+
boardId: collector.meta.boardId,
|
|
18348
|
+
playerId: options.playerId,
|
|
18349
|
+
spaceId: rawValueBase
|
|
18350
|
+
} : rawValueBase;
|
|
17681
18351
|
const result = collector.schema.safeParse(rawValue);
|
|
17682
18352
|
if (!result.success) {
|
|
17683
18353
|
for (const issue of result.error.issues) {
|
|
@@ -17739,7 +18409,7 @@ function validateCollectorTargets(interaction, domainState, playerId, params) {
|
|
|
17739
18409
|
domainState,
|
|
17740
18410
|
playerId,
|
|
17741
18411
|
queries(),
|
|
17742
|
-
|
|
18412
|
+
value
|
|
17743
18413
|
);
|
|
17744
18414
|
if (issue) {
|
|
17745
18415
|
return makeValidationError(issue.errorCode, issue.message);
|
|
@@ -17951,11 +18621,14 @@ function deriveCommitPolicy(inputs, explicit) {
|
|
|
17951
18621
|
if (hasManyCollector) {
|
|
17952
18622
|
return { mode: "manual" };
|
|
17953
18623
|
}
|
|
18624
|
+
if (collectors.some(isDefaultRenderableFormCollector)) {
|
|
18625
|
+
return { mode: "manual" };
|
|
18626
|
+
}
|
|
17954
18627
|
if (collectors.length === 0 || !collectors.some(isTargetCollector2)) {
|
|
17955
18628
|
return { mode: "manual" };
|
|
17956
18629
|
}
|
|
17957
18630
|
return collectors.every(
|
|
17958
|
-
(collector) => isTargetCollector2(collector) ||
|
|
18631
|
+
(collector) => isTargetCollector2(collector) || collector.kind === "rng"
|
|
17959
18632
|
) ? { mode: "autoWhenReady" } : { mode: "manual" };
|
|
17960
18633
|
}
|
|
17961
18634
|
function projectInteractionMetadata(interaction) {
|
|
@@ -17971,7 +18644,7 @@ function enrichResourceInputPresentation(inputs, manifest) {
|
|
|
17971
18644
|
}
|
|
17972
18645
|
const resources = presentationById;
|
|
17973
18646
|
const enrichChoice = (choice) => {
|
|
17974
|
-
const presentation = resources[choice.value];
|
|
18647
|
+
const presentation = choice.value === null ? void 0 : resources[choice.value];
|
|
17975
18648
|
return {
|
|
17976
18649
|
...choice,
|
|
17977
18650
|
label: typeof presentation?.label === "string" && (!choice.label || choice.label === choice.value) ? presentation.label : choice.label || (typeof presentation?.label === "string" ? presentation.label : ""),
|
|
@@ -17979,7 +18652,16 @@ function enrichResourceInputPresentation(inputs, manifest) {
|
|
|
17979
18652
|
};
|
|
17980
18653
|
};
|
|
17981
18654
|
return inputs.map((input) => {
|
|
17982
|
-
if (input.domain.type === "choice"
|
|
18655
|
+
if (input.domain.type === "choice") {
|
|
18656
|
+
return {
|
|
18657
|
+
...input,
|
|
18658
|
+
domain: {
|
|
18659
|
+
...input.domain,
|
|
18660
|
+
choices: input.domain.choices.map(enrichChoice)
|
|
18661
|
+
}
|
|
18662
|
+
};
|
|
18663
|
+
}
|
|
18664
|
+
if (input.domain.type === "choiceList") {
|
|
17983
18665
|
return {
|
|
17984
18666
|
...input,
|
|
17985
18667
|
domain: {
|
|
@@ -18099,7 +18781,10 @@ function createInteractionDecisionResolver(scope, stages, authorization) {
|
|
|
18099
18781
|
}
|
|
18100
18782
|
const trustedInteractionId = interactionId;
|
|
18101
18783
|
const parseForSubmit = mode === "submit";
|
|
18102
|
-
const parsed = parseForSubmit ? parseInteractionParams(interaction, params, {
|
|
18784
|
+
const parsed = parseForSubmit ? parseInteractionParams(interaction, params, {
|
|
18785
|
+
skipRng: true,
|
|
18786
|
+
playerId
|
|
18787
|
+
}) : {
|
|
18103
18788
|
ok: true,
|
|
18104
18789
|
params: prepareInteractionProjectionParams(interaction, params)
|
|
18105
18790
|
};
|
|
@@ -18359,10 +19044,7 @@ function createStageResolver(scope) {
|
|
|
18359
19044
|
return allowlist;
|
|
18360
19045
|
}
|
|
18361
19046
|
function isInteractionAllowedInStep(state, interaction, projection) {
|
|
18362
|
-
const allowedSteps = [
|
|
18363
|
-
...interaction.step !== void 0 ? [interaction.step] : [],
|
|
18364
|
-
...interaction.steps ?? []
|
|
18365
|
-
];
|
|
19047
|
+
const allowedSteps = interaction.__steps ?? [];
|
|
18366
19048
|
if (allowedSteps.length === 0) {
|
|
18367
19049
|
return true;
|
|
18368
19050
|
}
|
|
@@ -18491,16 +19173,15 @@ function resolveContainerRef(table, ref) {
|
|
|
18491
19173
|
throw new Error(`Unknown board '${ref.boardId}'.`);
|
|
18492
19174
|
}
|
|
18493
19175
|
const space2 = board2?.spaces[ref.spaceId];
|
|
18494
|
-
if (!space2
|
|
19176
|
+
if (!space2) {
|
|
18495
19177
|
throw new Error(
|
|
18496
|
-
`
|
|
19178
|
+
`Unknown board space '${ref.spaceId}' on board '${ref.boardId}'.`
|
|
18497
19179
|
);
|
|
18498
19180
|
}
|
|
18499
19181
|
return {
|
|
18500
19182
|
kind: "space",
|
|
18501
19183
|
boardId: board2.id,
|
|
18502
|
-
spaceId: ref.spaceId
|
|
18503
|
-
zoneId: space2.zoneId
|
|
19184
|
+
spaceId: ref.spaceId
|
|
18504
19185
|
};
|
|
18505
19186
|
}
|
|
18506
19187
|
const board = table.boards.byId[resolveRuntimeBoardId(table, ref.boardId, ref.playerId)];
|
|
@@ -18510,16 +19191,15 @@ function resolveContainerRef(table, ref) {
|
|
|
18510
19191
|
);
|
|
18511
19192
|
}
|
|
18512
19193
|
const space = board?.spaces[ref.spaceId];
|
|
18513
|
-
if (!space
|
|
19194
|
+
if (!space) {
|
|
18514
19195
|
throw new Error(
|
|
18515
|
-
`
|
|
19196
|
+
`Unknown board space '${ref.spaceId}' on board '${ref.boardId}' for '${ref.playerId}'.`
|
|
18516
19197
|
);
|
|
18517
19198
|
}
|
|
18518
19199
|
return {
|
|
18519
19200
|
kind: "space",
|
|
18520
19201
|
boardId: board.id,
|
|
18521
|
-
spaceId: ref.spaceId
|
|
18522
|
-
zoneId: space.zoneId
|
|
19202
|
+
spaceId: ref.spaceId
|
|
18523
19203
|
};
|
|
18524
19204
|
}
|
|
18525
19205
|
function readContainerComponents(table, ref) {
|
|
@@ -18830,7 +19510,11 @@ function createLifecycleRunner(scope, interactions) {
|
|
|
18830
19510
|
}) : safeParseOrThrow(phase.state, {}, `phase:${phaseName}:initialState`);
|
|
18831
19511
|
return {
|
|
18832
19512
|
...state,
|
|
18833
|
-
phase: safeParseOrThrow(
|
|
19513
|
+
phase: safeParseOrThrow(
|
|
19514
|
+
phase.state,
|
|
19515
|
+
phaseState,
|
|
19516
|
+
`phase:${phaseName}`
|
|
19517
|
+
),
|
|
18834
19518
|
flow: {
|
|
18835
19519
|
...state.flow,
|
|
18836
19520
|
currentPhase: phaseName
|
|
@@ -18848,12 +19532,17 @@ function createLifecycleRunner(scope, interactions) {
|
|
|
18848
19532
|
let nextState = workingState;
|
|
18849
19533
|
const instructions = [];
|
|
18850
19534
|
if (phase.enter) {
|
|
19535
|
+
const random = createMutableRandomHelpers(workingState.runtime.rng);
|
|
18851
19536
|
const entered = normalizeResult(
|
|
18852
19537
|
phase.enter(
|
|
18853
|
-
scope.buildRuntimeArgs(
|
|
18854
|
-
|
|
18855
|
-
|
|
18856
|
-
|
|
19538
|
+
scope.buildRuntimeArgs(
|
|
19539
|
+
workingState,
|
|
19540
|
+
{
|
|
19541
|
+
event,
|
|
19542
|
+
state: scope.toDomainState(workingState)
|
|
19543
|
+
},
|
|
19544
|
+
{ random: random.random }
|
|
19545
|
+
)
|
|
18857
19546
|
),
|
|
18858
19547
|
scope.toDomainState(workingState)
|
|
18859
19548
|
);
|
|
@@ -18864,18 +19553,23 @@ function createLifecycleRunner(scope, interactions) {
|
|
|
18864
19553
|
}
|
|
18865
19554
|
nextState = {
|
|
18866
19555
|
...entered.state,
|
|
18867
|
-
runtime: workingState.runtime
|
|
19556
|
+
runtime: { ...workingState.runtime, rng: random.currentRng() }
|
|
18868
19557
|
};
|
|
18869
19558
|
if (entered.instructions) instructions.push(...entered.instructions);
|
|
18870
19559
|
}
|
|
18871
19560
|
const activeStage = interactions.resolveActiveStage(nextState, phaseName);
|
|
18872
19561
|
if (activeStage?.stage.onEnter) {
|
|
19562
|
+
const random = createMutableRandomHelpers(nextState.runtime.rng);
|
|
18873
19563
|
const stageEntered = normalizeResult(
|
|
18874
19564
|
activeStage.stage.onEnter(
|
|
18875
|
-
scope.buildRuntimeArgs(
|
|
18876
|
-
|
|
18877
|
-
|
|
18878
|
-
|
|
19565
|
+
scope.buildRuntimeArgs(
|
|
19566
|
+
nextState,
|
|
19567
|
+
{
|
|
19568
|
+
event,
|
|
19569
|
+
state: scope.toDomainState(nextState)
|
|
19570
|
+
},
|
|
19571
|
+
{ random: random.random }
|
|
19572
|
+
)
|
|
18879
19573
|
),
|
|
18880
19574
|
scope.toDomainState(nextState)
|
|
18881
19575
|
);
|
|
@@ -18886,7 +19580,7 @@ function createLifecycleRunner(scope, interactions) {
|
|
|
18886
19580
|
}
|
|
18887
19581
|
nextState = {
|
|
18888
19582
|
...stageEntered.state,
|
|
18889
|
-
runtime: nextState.runtime
|
|
19583
|
+
runtime: { ...nextState.runtime, rng: random.currentRng() }
|
|
18890
19584
|
};
|
|
18891
19585
|
if (stageEntered.instructions) {
|
|
18892
19586
|
instructions.push(...stageEntered.instructions);
|
|
@@ -19939,6 +20633,11 @@ function toWireDispatchResult(result, serializeState) {
|
|
|
19939
20633
|
function createReducerBundle(definition) {
|
|
19940
20634
|
const trustedBundle = createTrustedReducerBundle(definition);
|
|
19941
20635
|
const codec = createIngressRuntimeCodec(definition);
|
|
20636
|
+
function parseTrustedState(state) {
|
|
20637
|
+
return codec.parseState(
|
|
20638
|
+
state
|
|
20639
|
+
);
|
|
20640
|
+
}
|
|
19942
20641
|
function parseRuntimePlayerId(playerId) {
|
|
19943
20642
|
if (typeof playerId !== "string") {
|
|
19944
20643
|
throw new Error("Expected a string playerId.");
|
|
@@ -19971,7 +20670,7 @@ function createReducerBundle(definition) {
|
|
|
19971
20670
|
);
|
|
19972
20671
|
},
|
|
19973
20672
|
async initializePhase({ state, to }) {
|
|
19974
|
-
const decodedState =
|
|
20673
|
+
const decodedState = parseTrustedState(state);
|
|
19975
20674
|
return codec.serializeState(
|
|
19976
20675
|
await trustedBundle.initializePhase({
|
|
19977
20676
|
state: decodedState,
|
|
@@ -19983,7 +20682,7 @@ function createReducerBundle(definition) {
|
|
|
19983
20682
|
const validatedWire = codec.parseInput(input);
|
|
19984
20683
|
const routed = routeInteraction(validatedWire);
|
|
19985
20684
|
return trustedBundle.validateInput({
|
|
19986
|
-
state:
|
|
20685
|
+
state: parseTrustedState(state),
|
|
19987
20686
|
input: routed
|
|
19988
20687
|
});
|
|
19989
20688
|
},
|
|
@@ -19994,7 +20693,7 @@ function createReducerBundle(definition) {
|
|
|
19994
20693
|
const validatedWire = codec.parseInput(input);
|
|
19995
20694
|
const routed = routeInteraction(validatedWire);
|
|
19996
20695
|
const result = await trustedBundle.reduce({
|
|
19997
|
-
state:
|
|
20696
|
+
state: parseTrustedState(state),
|
|
19998
20697
|
input: routed
|
|
19999
20698
|
});
|
|
20000
20699
|
return toWireReduceResult(
|
|
@@ -20009,7 +20708,7 @@ function createReducerBundle(definition) {
|
|
|
20009
20708
|
const validatedWire = codec.parseInput(input);
|
|
20010
20709
|
const routed = routeInteraction(validatedWire);
|
|
20011
20710
|
const result = await trustedBundle.dispatch({
|
|
20012
|
-
state:
|
|
20711
|
+
state: parseTrustedState(state),
|
|
20013
20712
|
input: routed
|
|
20014
20713
|
});
|
|
20015
20714
|
return toWireDispatchResult(
|
|
@@ -20036,7 +20735,7 @@ function createReducerBundle(definition) {
|
|
|
20036
20735
|
playerIds,
|
|
20037
20736
|
viewId = "player"
|
|
20038
20737
|
}) {
|
|
20039
|
-
const parsedState =
|
|
20738
|
+
const parsedState = parseTrustedState(state);
|
|
20040
20739
|
const parsedPlayerIds = playerIds.map((pid) => codec.parsePlayerId(pid));
|
|
20041
20740
|
return trustedBundle.projectSeatsDynamic({
|
|
20042
20741
|
state: parsedState,
|
|
@@ -20045,9 +20744,7 @@ function createReducerBundle(definition) {
|
|
|
20045
20744
|
});
|
|
20046
20745
|
},
|
|
20047
20746
|
projectSeatViewDynamic({ state, playerId, viewId = "player" }) {
|
|
20048
|
-
const parsedState =
|
|
20049
|
-
state
|
|
20050
|
-
);
|
|
20747
|
+
const parsedState = parseTrustedState(state);
|
|
20051
20748
|
return trustedBundle.projectSeatViewDynamic({
|
|
20052
20749
|
state: parsedState,
|
|
20053
20750
|
playerId: parseRuntimePlayerId(playerId),
|
|
@@ -20076,7 +20773,7 @@ function createReducerBundle(definition) {
|
|
|
20076
20773
|
});
|
|
20077
20774
|
},
|
|
20078
20775
|
hydrate({ state: snapshot }) {
|
|
20079
|
-
state =
|
|
20776
|
+
state = parseTrustedState(snapshot);
|
|
20080
20777
|
},
|
|
20081
20778
|
async dispatch({ input }) {
|
|
20082
20779
|
const validatedWire = codec.parseInput(
|
|
@@ -21316,6 +22013,11 @@ var ShadowReducerRuntime = class {
|
|
|
21316
22013
|
this.version = version;
|
|
21317
22014
|
this.started = true;
|
|
21318
22015
|
}
|
|
22016
|
+
patchState(mutator) {
|
|
22017
|
+
const next = structuredClone(this.rawState());
|
|
22018
|
+
mutator(next);
|
|
22019
|
+
this.hydrate(next, this.version + 1);
|
|
22020
|
+
}
|
|
21319
22021
|
projectAllSeats() {
|
|
21320
22022
|
const projection = this.runtime.projectSeatsDynamic({
|
|
21321
22023
|
playerIds: this.playerIds
|
|
@@ -21616,6 +22318,15 @@ async function createScenarioContext(options) {
|
|
|
21616
22318
|
await assertLiveMatchesShadow("browser", options.shadow, live);
|
|
21617
22319
|
}
|
|
21618
22320
|
},
|
|
22321
|
+
patchState: async (mutator) => {
|
|
22322
|
+
await api.start();
|
|
22323
|
+
if (options.live || options.embedded || options.browser || options.actionPlan) {
|
|
22324
|
+
throw new Error(
|
|
22325
|
+
"game.patchState is only supported for reducer snapshot scenarios. Use it to materialize a state before --from-scenario or reducer tests, not inside live replay/browser runners."
|
|
22326
|
+
);
|
|
22327
|
+
}
|
|
22328
|
+
options.shadow.patchState(mutator);
|
|
22329
|
+
},
|
|
21619
22330
|
submit: async (playerId, interactionId, params) => {
|
|
21620
22331
|
await api.start();
|
|
21621
22332
|
const interactionParams = params ?? {};
|
|
@@ -26119,4 +26830,4 @@ export {
|
|
|
26119
26830
|
test_default,
|
|
26120
26831
|
runDreamboardCli
|
|
26121
26832
|
};
|
|
26122
|
-
//# sourceMappingURL=chunk-
|
|
26833
|
+
//# sourceMappingURL=chunk-ZLYS5DGK.js.map
|