@game-infra/game-state-schemas 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +103 -0
- package/dist/contracts.d.ts +220 -0
- package/dist/contracts.d.ts.map +1 -0
- package/dist/contracts.js +147 -0
- package/dist/contracts.js.map +1 -0
- package/dist/freeformPayloads.d.ts +368 -0
- package/dist/freeformPayloads.d.ts.map +1 -0
- package/dist/freeformPayloads.js +318 -0
- package/dist/freeformPayloads.js.map +1 -0
- package/dist/index.d.ts +39 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +45 -0
- package/dist/index.js.map +1 -0
- package/dist/sessionState.d.ts +252 -0
- package/dist/sessionState.d.ts.map +1 -0
- package/dist/sessionState.js +191 -0
- package/dist/sessionState.js.map +1 -0
- package/package.json +51 -0
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
import { ActivationDTOSchema } from "@game-infra/event-schemas";
|
|
2
|
+
import { array, looseObject, number, object, optional, picklist, string, } from "valibot";
|
|
3
|
+
/**
|
|
4
|
+
* What goes inside a session's `data` and its journal entries' for **freeform
|
|
5
|
+
* mode**: play that follows the player's own words instead of authored
|
|
6
|
+
* branches.
|
|
7
|
+
*
|
|
8
|
+
* Where story mode stores a tree of beats addressed by the choices taken to
|
|
9
|
+
* reach them, freeform mode stores a linear journal of **turns**. Each turn
|
|
10
|
+
* records what the player wrote, what the narrator answered, the skill check
|
|
11
|
+
* that was rolled (if the attempt warranted one), the state effects that
|
|
12
|
+
* followed — the same `ActivationDTO` vocabulary a story branch carries — and
|
|
13
|
+
* the **memories** the turn left behind. Replaying the journal from the start
|
|
14
|
+
* rebuilds the whole session state, so nothing beyond the journal is stored.
|
|
15
|
+
*
|
|
16
|
+
* Memories are organised as a *synapse graph*: every remembered fact connects
|
|
17
|
+
* to one or more **neurons** — a character, a faction, a location, or a domain
|
|
18
|
+
* such as war or romance — and recall walks those connections rather than the
|
|
19
|
+
* whole journal. Old memories are **consolidated**: several small entries
|
|
20
|
+
* connected to the same neuron collapse into one summary, the way five small
|
|
21
|
+
* grievances become "many past grievances". A consolidation is recorded on the
|
|
22
|
+
* turn that performed it, so replay compresses exactly as play did.
|
|
23
|
+
*
|
|
24
|
+
* None of this is attached to any endpoint — `game-state-service` stores `data`
|
|
25
|
+
* as an opaque string, the same way `game-content-service` stores authored
|
|
26
|
+
* design content — but two clients reading the same session must agree on the
|
|
27
|
+
* shapes, so they live here.
|
|
28
|
+
*
|
|
29
|
+
* They live in *this* package rather than `@game-infra/story-schemas` because a
|
|
30
|
+
* journal is not design. A world and its cast are authored once and read by
|
|
31
|
+
* every player; a session's turns belong to one player, change every turn, and
|
|
32
|
+
* are deleted with the run.
|
|
33
|
+
*/
|
|
34
|
+
/** Separator inside a neuron id, between its kind and the entity it names. */
|
|
35
|
+
export const NEURON_KEY_SEPARATOR = ":";
|
|
36
|
+
/**
|
|
37
|
+
* The id of a neuron: its kind, then the id it wraps.
|
|
38
|
+
*
|
|
39
|
+
* Entity neurons wrap a design id (`character:tallow`, `faction:ash-wardens`);
|
|
40
|
+
* domain neurons wrap a domain name (`domain:war`). Keeping the kind in the id
|
|
41
|
+
* is what lets a memory's `neuronIds` list mix people and themes freely.
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```ts
|
|
45
|
+
* import { neuronKey } from '@game-infra/game-state-schemas'
|
|
46
|
+
*
|
|
47
|
+
* neuronKey('character', 'tallow') // 'character:tallow'
|
|
48
|
+
* neuronKey('domain', 'war') // 'domain:war'
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
export function neuronKey(kind, id) {
|
|
52
|
+
return `${kind}${NEURON_KEY_SEPARATOR}${id}`;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* The kind and wrapped id a neuron key encodes. The inverse of
|
|
56
|
+
* {@link neuronKey}; a key with no separator reads as a bare domain.
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```ts
|
|
60
|
+
* import { parseNeuronKey } from '@game-infra/game-state-schemas'
|
|
61
|
+
*
|
|
62
|
+
* parseNeuronKey('character:tallow') // { kind: 'character', id: 'tallow' }
|
|
63
|
+
* parseNeuronKey('war') // { kind: 'domain', id: 'war' }
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
export function parseNeuronKey(key) {
|
|
67
|
+
const at = key.indexOf(NEURON_KEY_SEPARATOR);
|
|
68
|
+
if (at === -1)
|
|
69
|
+
return { kind: "domain", id: key };
|
|
70
|
+
return { kind: key.slice(0, at), id: key.slice(at + 1) };
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* The suggested domain neurons: the recurring subject matters of play that are
|
|
74
|
+
* nobody in particular. A game may extend the list — a domain neuron is just a
|
|
75
|
+
* key — but sharing a default set means two clients file "the war got worse"
|
|
76
|
+
* under the same neuron.
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* ```ts
|
|
80
|
+
* import { FREEFORM_DOMAINS, neuronKey } from '@game-infra/game-state-schemas'
|
|
81
|
+
*
|
|
82
|
+
* FREEFORM_DOMAINS.includes('romance') // true
|
|
83
|
+
* neuronKey('domain', 'romance') // 'domain:romance'
|
|
84
|
+
* ```
|
|
85
|
+
*/
|
|
86
|
+
export const FREEFORM_DOMAINS = [
|
|
87
|
+
"war",
|
|
88
|
+
"politics",
|
|
89
|
+
"economy",
|
|
90
|
+
"business",
|
|
91
|
+
"crime",
|
|
92
|
+
"romance",
|
|
93
|
+
"faith",
|
|
94
|
+
"health",
|
|
95
|
+
"knowledge",
|
|
96
|
+
"travel",
|
|
97
|
+
];
|
|
98
|
+
/**
|
|
99
|
+
* One remembered fact — an engram.
|
|
100
|
+
*
|
|
101
|
+
* `neuronIds` are the {@link neuronKey} connections recall walks; `turn` is
|
|
102
|
+
* when it was formed, which is what lets recent memory outrank old memory; and
|
|
103
|
+
* `weight` (1–5) is how much it mattered, which is what lets a betrayal outrank
|
|
104
|
+
* a purchase. A memory produced by consolidation looks like any other — its
|
|
105
|
+
* sources are named by the {@link ConsolidationDTOSchema} that replaced them.
|
|
106
|
+
*
|
|
107
|
+
* @example
|
|
108
|
+
* ```ts
|
|
109
|
+
* import type { MemoryDTO } from '@game-infra/game-state-schemas'
|
|
110
|
+
*
|
|
111
|
+
* const memory: MemoryDTO = {
|
|
112
|
+
* id: 'm4-1',
|
|
113
|
+
* text: 'Ilse saw you pocket the ledger and said nothing.',
|
|
114
|
+
* neuronIds: ['character:warden-ilse', 'domain:crime'],
|
|
115
|
+
* turn: 4,
|
|
116
|
+
* weight: 4,
|
|
117
|
+
* }
|
|
118
|
+
* ```
|
|
119
|
+
*/
|
|
120
|
+
export const MemoryDTOSchema = object({
|
|
121
|
+
id: string(),
|
|
122
|
+
/** One sentence, written to be read back to a narrator later. */
|
|
123
|
+
text: string(),
|
|
124
|
+
/** The {@link neuronKey} connections recall walks. */
|
|
125
|
+
neuronIds: array(string()),
|
|
126
|
+
/** The turn index the memory was formed on. */
|
|
127
|
+
turn: number(),
|
|
128
|
+
/** Salience, 1 (incidental) to 5 (unforgettable). */
|
|
129
|
+
weight: number(),
|
|
130
|
+
});
|
|
131
|
+
/**
|
|
132
|
+
* One act of forgetting-by-summary: the memories consolidated away, and the
|
|
133
|
+
* single summary memory that stands for them from this turn on.
|
|
134
|
+
*
|
|
135
|
+
* Recorded on the turn that performed it so replaying the journal compresses
|
|
136
|
+
* exactly as play did — the superseded ids stop being recalled, the summary
|
|
137
|
+
* starts.
|
|
138
|
+
*
|
|
139
|
+
* @example
|
|
140
|
+
* ```ts
|
|
141
|
+
* import type { ConsolidationDTO } from '@game-infra/game-state-schemas'
|
|
142
|
+
*
|
|
143
|
+
* const consolidation: ConsolidationDTO = {
|
|
144
|
+
* memoryIds: ['m2-1', 'm3-2', 'm5-1'],
|
|
145
|
+
* memory: {
|
|
146
|
+
* id: 'c9-1',
|
|
147
|
+
* text: 'The wardens hold many small grievances against you.',
|
|
148
|
+
* neuronIds: ['faction:ash-wardens'],
|
|
149
|
+
* turn: 9,
|
|
150
|
+
* weight: 4,
|
|
151
|
+
* },
|
|
152
|
+
* }
|
|
153
|
+
* ```
|
|
154
|
+
*/
|
|
155
|
+
export const ConsolidationDTOSchema = object({
|
|
156
|
+
/** The memories the summary supersedes. */
|
|
157
|
+
memoryIds: array(string()),
|
|
158
|
+
/** The summary that stands for them. */
|
|
159
|
+
memory: MemoryDTOSchema,
|
|
160
|
+
});
|
|
161
|
+
/**
|
|
162
|
+
* One situational bonus or malus on a check, with the reason it applies —
|
|
163
|
+
* `{ label: 'the wardens distrust you', amount: -2 }` — so a roll readout can
|
|
164
|
+
* say why the odds were what they were.
|
|
165
|
+
*/
|
|
166
|
+
export const CheckModifierDTOSchema = object({
|
|
167
|
+
label: string(),
|
|
168
|
+
amount: number(),
|
|
169
|
+
});
|
|
170
|
+
/** How hard an attempt was judged. `trivial` attempts are not rolled at all. */
|
|
171
|
+
export const FREEFORM_COMPLEXITIES = ["trivial", "easy", "moderate", "hard", "formidable"];
|
|
172
|
+
export const FreeformComplexitySchema = picklist(FREEFORM_COMPLEXITIES);
|
|
173
|
+
/** How a rolled check landed. */
|
|
174
|
+
export const FREEFORM_OUTCOMES = [
|
|
175
|
+
"critical-success",
|
|
176
|
+
"success",
|
|
177
|
+
"failure",
|
|
178
|
+
"critical-failure",
|
|
179
|
+
];
|
|
180
|
+
export const FreeformOutcomeSchema = picklist(FREEFORM_OUTCOMES);
|
|
181
|
+
/**
|
|
182
|
+
* A skill check, rolled once and recorded forever.
|
|
183
|
+
*
|
|
184
|
+
* The roll happens when the turn is resolved and its result is stored, never
|
|
185
|
+
* re-rolled: replaying the journal must rebuild the same session, and dice do
|
|
186
|
+
* not replay. Everything a reader needs to see the roll was fair is here — the
|
|
187
|
+
* skill and stat it leaned on, the difficulty the complexity mapped to, the
|
|
188
|
+
* die, every modifier with its reason, and the total that met or missed it.
|
|
189
|
+
*
|
|
190
|
+
* @example
|
|
191
|
+
* ```ts
|
|
192
|
+
* import type { ResolvedCheckDTO } from '@game-infra/game-state-schemas'
|
|
193
|
+
*
|
|
194
|
+
* const check: ResolvedCheckDTO = {
|
|
195
|
+
* skillId: 'skulking',
|
|
196
|
+
* statId: 'grace',
|
|
197
|
+
* complexity: 'hard',
|
|
198
|
+
* difficulty: 16,
|
|
199
|
+
* roll: 13,
|
|
200
|
+
* modifiers: [
|
|
201
|
+
* { label: 'Skulking rank', amount: 2 },
|
|
202
|
+
* { label: 'moonless night', amount: 1 },
|
|
203
|
+
* ],
|
|
204
|
+
* total: 16,
|
|
205
|
+
* outcome: 'success',
|
|
206
|
+
* }
|
|
207
|
+
* ```
|
|
208
|
+
*/
|
|
209
|
+
export const ResolvedCheckDTOSchema = object({
|
|
210
|
+
/** The skill rolled, when one applied. */
|
|
211
|
+
skillId: optional(string()),
|
|
212
|
+
/** The stat behind it, when one applied. */
|
|
213
|
+
statId: optional(string()),
|
|
214
|
+
complexity: FreeformComplexitySchema,
|
|
215
|
+
/** The target number the complexity mapped to. */
|
|
216
|
+
difficulty: number(),
|
|
217
|
+
/** The die, unmodified. */
|
|
218
|
+
roll: number(),
|
|
219
|
+
/** Every bonus and malus that applied, each with its reason. */
|
|
220
|
+
modifiers: array(CheckModifierDTOSchema),
|
|
221
|
+
/** `roll` plus every modifier. */
|
|
222
|
+
total: number(),
|
|
223
|
+
outcome: FreeformOutcomeSchema,
|
|
224
|
+
});
|
|
225
|
+
/**
|
|
226
|
+
* A character first met during freeform play, persisted so the world remembers
|
|
227
|
+
* them.
|
|
228
|
+
*
|
|
229
|
+
* The definition is whatever design-document character shape the game uses —
|
|
230
|
+
* this contract guarantees only the id and name and passes the rest through,
|
|
231
|
+
* the same stance `sessionState.ts` takes on `data`.
|
|
232
|
+
*/
|
|
233
|
+
export const IntroducedEntityDTOSchema = looseObject({
|
|
234
|
+
id: string(),
|
|
235
|
+
name: string(),
|
|
236
|
+
});
|
|
237
|
+
/**
|
|
238
|
+
* One turn of freeform play — the payload of one journal entry, stored at the
|
|
239
|
+
* entry's `sequence`.
|
|
240
|
+
*
|
|
241
|
+
* Everything downstream of the player's words is recorded: the neurons the
|
|
242
|
+
* adjudicator judged relevant (`focus`), the check it rolled (absent when the
|
|
243
|
+
* attempt was trivial or purely conversational), the effects in the same
|
|
244
|
+
* `ActivationDTO` vocabulary a story branch carries, the characters the turn
|
|
245
|
+
* introduced, the memories it formed and the consolidations it performed.
|
|
246
|
+
* Folding turns in order rebuilds the play state, the cast and the memory
|
|
247
|
+
* graph; nothing else is stored.
|
|
248
|
+
*
|
|
249
|
+
* @example
|
|
250
|
+
* ```ts
|
|
251
|
+
* import type { FreeformTurnPayload } from '@game-infra/game-state-schemas'
|
|
252
|
+
*
|
|
253
|
+
* const turn: FreeformTurnPayload = {
|
|
254
|
+
* index: 4,
|
|
255
|
+
* input: 'I slip the ledger under my coat and walk out.',
|
|
256
|
+
* title: 'The ledger walks out',
|
|
257
|
+
* narration: 'The clasp catches once, then gives…',
|
|
258
|
+
* focus: ['character:warden-ilse', 'domain:crime'],
|
|
259
|
+
* check: {
|
|
260
|
+
* skillId: 'skulking', statId: 'grace', complexity: 'moderate', difficulty: 12,
|
|
261
|
+
* roll: 11, modifiers: [{ label: 'Skulking rank', amount: 2 }], total: 13,
|
|
262
|
+
* outcome: 'success',
|
|
263
|
+
* },
|
|
264
|
+
* effects: [{ type: 'GrantItem', params: { itemId: 'ilses-ledger', quantity: 1 } }],
|
|
265
|
+
* introduced: [],
|
|
266
|
+
* memories: [{
|
|
267
|
+
* id: 'm4-1', text: 'You stole the ledger from under Ilse\'s eyes.',
|
|
268
|
+
* neuronIds: ['character:warden-ilse', 'domain:crime'], turn: 4, weight: 4,
|
|
269
|
+
* }],
|
|
270
|
+
* consolidations: [],
|
|
271
|
+
* model: 'aion',
|
|
272
|
+
* }
|
|
273
|
+
* ```
|
|
274
|
+
*/
|
|
275
|
+
export const FreeformTurnPayloadSchema = object({
|
|
276
|
+
index: number(),
|
|
277
|
+
/** What the player wrote. Empty on the opening turn. */
|
|
278
|
+
input: string(),
|
|
279
|
+
/** A few words naming the moment, for the journal listing. */
|
|
280
|
+
title: string(),
|
|
281
|
+
/** The narrator's answer — what actually happened. */
|
|
282
|
+
narration: string(),
|
|
283
|
+
/** The {@link neuronKey}s the adjudicator judged relevant to this turn. */
|
|
284
|
+
focus: array(string()),
|
|
285
|
+
/** The check that was rolled, when the attempt warranted one. */
|
|
286
|
+
check: optional(ResolvedCheckDTOSchema),
|
|
287
|
+
/** State changes, in the same vocabulary a story branch's effects use. */
|
|
288
|
+
effects: array(ActivationDTOSchema),
|
|
289
|
+
/** Characters first met this turn, persisted with their definitions. */
|
|
290
|
+
introduced: array(IntroducedEntityDTOSchema),
|
|
291
|
+
/** The memories this turn formed. */
|
|
292
|
+
memories: array(MemoryDTOSchema),
|
|
293
|
+
/** The memory summaries this turn performed. */
|
|
294
|
+
consolidations: array(ConsolidationDTOSchema),
|
|
295
|
+
/** The model that resolved the turn, so a re-read can say what produced it. */
|
|
296
|
+
model: string(),
|
|
297
|
+
});
|
|
298
|
+
/**
|
|
299
|
+
* A freeform session's header payload — what goes inside a
|
|
300
|
+
* {@link GameSessionRecord}'s `data`. The session is scoped to the world it
|
|
301
|
+
* plays in; its turns are the journal entries under it.
|
|
302
|
+
*
|
|
303
|
+
* @example
|
|
304
|
+
* ```ts
|
|
305
|
+
* import type { FreeformSessionPayload } from '@game-infra/game-state-schemas'
|
|
306
|
+
*
|
|
307
|
+
* const session: FreeformSessionPayload = {
|
|
308
|
+
* title: 'A thief in Cinderhold',
|
|
309
|
+
* premise: 'Arrive with nothing and see what the city lets you take.',
|
|
310
|
+
* }
|
|
311
|
+
* ```
|
|
312
|
+
*/
|
|
313
|
+
export const FreeformSessionPayloadSchema = object({
|
|
314
|
+
title: string(),
|
|
315
|
+
/** The player's opening intent — what this playthrough is about. May be empty. */
|
|
316
|
+
premise: string(),
|
|
317
|
+
});
|
|
318
|
+
//# sourceMappingURL=freeformPayloads.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"freeformPayloads.js","sourceRoot":"","sources":["../src/freeformPayloads.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @game-infra/game-state-schemas
|
|
3
|
+
*
|
|
4
|
+
* The API contract for **play state**: the sessions a player has in progress,
|
|
5
|
+
* the journal each one is rebuilt from, and the payload shapes freeform mode
|
|
6
|
+
* puts inside them.
|
|
7
|
+
*
|
|
8
|
+
* The line this package draws is the point of it. `@game-infra/story-schemas`
|
|
9
|
+
* carries what an author writes — one world, read by every player, the same
|
|
10
|
+
* tomorrow as today. This package carries what a *player* produces — one run,
|
|
11
|
+
* belonging to them alone, rewritten every turn and deleted when they abandon
|
|
12
|
+
* it. `game-state-service` implements these contracts; `game-content-service`
|
|
13
|
+
* implements the design-content ones and holds no session state at all.
|
|
14
|
+
*
|
|
15
|
+
* Savegames — slot snapshots — are the same service's other half, but their
|
|
16
|
+
* contracts predate this package and stay in `@game-infra/api-schemas-core`
|
|
17
|
+
* (`savegameSaveContract`, `savegameLoadContract`, `savegameListSlotsContract`).
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```ts
|
|
21
|
+
* import {
|
|
22
|
+
* gameSessionListContract,
|
|
23
|
+
* gameJournalAppendContract,
|
|
24
|
+
* type FreeformTurnPayload,
|
|
25
|
+
* } from '@game-infra/game-state-schemas'
|
|
26
|
+
* import { sendByApiContract } from '@toad-contracts/frontend-http-client'
|
|
27
|
+
*
|
|
28
|
+
* const { result } = await sendByApiContract(http, gameSessionListContract, {
|
|
29
|
+
* pathParams: { gameId: 'fluid-emerald' },
|
|
30
|
+
* queryParams: { scopeId: 'the-ash-reckoning' },
|
|
31
|
+
* })
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export { GameJournalAppendRequestSchema, GameJournalAppendResponseSchema, GameJournalEntryRecordSchema, GameJournalListResponseSchema, GameJournalTruncateResponseSchema, GameSessionDeleteResponseSchema, GameSessionListResponseSchema, GameSessionLoadResponseSchema, GameSessionRecordSchema, GameSessionSaveRequestSchema, GameSessionSaveResponseSchema, JOURNAL_TRUNCATIONS, JournalTruncationSchema, ROOT_SESSION_SCOPE, SequenceParamSchema, } from "./sessionState.js";
|
|
35
|
+
export type { GameJournalAppendRequest, GameJournalAppendResponse, GameJournalEntryRecord, GameJournalListResponse, GameJournalTruncateResponse, GameSessionDeleteResponse, GameSessionListResponse, GameSessionLoadResponse, GameSessionRecord, GameSessionSaveRequest, GameSessionSaveResponse, JournalTruncation, } from "./sessionState.js";
|
|
36
|
+
export { CheckModifierDTOSchema, ConsolidationDTOSchema, FREEFORM_COMPLEXITIES, FREEFORM_DOMAINS, FREEFORM_OUTCOMES, FreeformComplexitySchema, FreeformOutcomeSchema, FreeformSessionPayloadSchema, FreeformTurnPayloadSchema, IntroducedEntityDTOSchema, MemoryDTOSchema, NEURON_KEY_SEPARATOR, ResolvedCheckDTOSchema, neuronKey, parseNeuronKey, } from "./freeformPayloads.js";
|
|
37
|
+
export type { CheckModifierDTO, ConsolidationDTO, FreeformComplexity, FreeformOutcome, FreeformSessionPayload, FreeformTurnPayload, IntroducedEntityDTO, MemoryDTO, ResolvedCheckDTO, } from "./freeformPayloads.js";
|
|
38
|
+
export { gameJournalAppendContract, gameJournalListContract, gameJournalTruncateContract, gameSessionDeleteContract, gameSessionListContract, gameSessionLoadContract, gameSessionSaveContract, } from "./contracts.js";
|
|
39
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAIH,OAAO,EACL,8BAA8B,EAC9B,+BAA+B,EAC/B,4BAA4B,EAC5B,6BAA6B,EAC7B,iCAAiC,EACjC,+BAA+B,EAC/B,6BAA6B,EAC7B,6BAA6B,EAC7B,uBAAuB,EACvB,4BAA4B,EAC5B,6BAA6B,EAC7B,mBAAmB,EACnB,uBAAuB,EACvB,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACV,wBAAwB,EACxB,yBAAyB,EACzB,sBAAsB,EACtB,uBAAuB,EACvB,2BAA2B,EAC3B,yBAAyB,EACzB,uBAAuB,EACvB,uBAAuB,EACvB,iBAAiB,EACjB,sBAAsB,EACtB,uBAAuB,EACvB,iBAAiB,GAClB,MAAM,mBAAmB,CAAC;AAK3B,OAAO,EACL,sBAAsB,EACtB,sBAAsB,EACtB,qBAAqB,EACrB,gBAAgB,EAChB,iBAAiB,EACjB,wBAAwB,EACxB,qBAAqB,EACrB,4BAA4B,EAC5B,yBAAyB,EACzB,yBAAyB,EACzB,eAAe,EACf,oBAAoB,EACpB,sBAAsB,EACtB,SAAS,EACT,cAAc,GACf,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EACV,gBAAgB,EAChB,gBAAgB,EAChB,kBAAkB,EAClB,eAAe,EACf,sBAAsB,EACtB,mBAAmB,EACnB,mBAAmB,EACnB,SAAS,EACT,gBAAgB,GACjB,MAAM,uBAAuB,CAAC;AAK/B,OAAO,EACL,yBAAyB,EACzB,uBAAuB,EACvB,2BAA2B,EAC3B,yBAAyB,EACzB,uBAAuB,EACvB,uBAAuB,EACvB,uBAAuB,GACxB,MAAM,gBAAgB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @game-infra/game-state-schemas
|
|
3
|
+
*
|
|
4
|
+
* The API contract for **play state**: the sessions a player has in progress,
|
|
5
|
+
* the journal each one is rebuilt from, and the payload shapes freeform mode
|
|
6
|
+
* puts inside them.
|
|
7
|
+
*
|
|
8
|
+
* The line this package draws is the point of it. `@game-infra/story-schemas`
|
|
9
|
+
* carries what an author writes — one world, read by every player, the same
|
|
10
|
+
* tomorrow as today. This package carries what a *player* produces — one run,
|
|
11
|
+
* belonging to them alone, rewritten every turn and deleted when they abandon
|
|
12
|
+
* it. `game-state-service` implements these contracts; `game-content-service`
|
|
13
|
+
* implements the design-content ones and holds no session state at all.
|
|
14
|
+
*
|
|
15
|
+
* Savegames — slot snapshots — are the same service's other half, but their
|
|
16
|
+
* contracts predate this package and stay in `@game-infra/api-schemas-core`
|
|
17
|
+
* (`savegameSaveContract`, `savegameLoadContract`, `savegameListSlotsContract`).
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```ts
|
|
21
|
+
* import {
|
|
22
|
+
* gameSessionListContract,
|
|
23
|
+
* gameJournalAppendContract,
|
|
24
|
+
* type FreeformTurnPayload,
|
|
25
|
+
* } from '@game-infra/game-state-schemas'
|
|
26
|
+
* import { sendByApiContract } from '@toad-contracts/frontend-http-client'
|
|
27
|
+
*
|
|
28
|
+
* const { result } = await sendByApiContract(http, gameSessionListContract, {
|
|
29
|
+
* pathParams: { gameId: 'fluid-emerald' },
|
|
30
|
+
* queryParams: { scopeId: 'the-ash-reckoning' },
|
|
31
|
+
* })
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
// Sessions and journals: the records the service stores, the requests that
|
|
35
|
+
// write them, and the responses that carry them back.
|
|
36
|
+
export { GameJournalAppendRequestSchema, GameJournalAppendResponseSchema, GameJournalEntryRecordSchema, GameJournalListResponseSchema, GameJournalTruncateResponseSchema, GameSessionDeleteResponseSchema, GameSessionListResponseSchema, GameSessionLoadResponseSchema, GameSessionRecordSchema, GameSessionSaveRequestSchema, GameSessionSaveResponseSchema, JOURNAL_TRUNCATIONS, JournalTruncationSchema, ROOT_SESSION_SCOPE, SequenceParamSchema, } from "./sessionState.js";
|
|
37
|
+
// Freeform mode: the journal of turns a session is replayed from, and the
|
|
38
|
+
// synapse memory graph — memories connected to neurons, consolidated over time
|
|
39
|
+
// — that decides what a narrator is reminded of.
|
|
40
|
+
export { CheckModifierDTOSchema, ConsolidationDTOSchema, FREEFORM_COMPLEXITIES, FREEFORM_DOMAINS, FREEFORM_OUTCOMES, FreeformComplexitySchema, FreeformOutcomeSchema, FreeformSessionPayloadSchema, FreeformTurnPayloadSchema, IntroducedEntityDTOSchema, MemoryDTOSchema, NEURON_KEY_SEPARATOR, ResolvedCheckDTOSchema, neuronKey, parseNeuronKey, } from "./freeformPayloads.js";
|
|
41
|
+
// Typed endpoint contracts (toad-contracts). Each contract carries its own
|
|
42
|
+
// `pathResolver`; wire them into a client via @toad-contracts/frontend-http-client
|
|
43
|
+
// and into a Hono service via @toad-contracts/hono.
|
|
44
|
+
export { gameJournalAppendContract, gameJournalListContract, gameJournalTruncateContract, gameSessionDeleteContract, gameSessionListContract, gameSessionLoadContract, gameSessionSaveContract, } from "./contracts.js";
|
|
45
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,2EAA2E;AAC3E,sDAAsD;AACtD,OAAO,EACL,8BAA8B,EAC9B,+BAA+B,EAC/B,4BAA4B,EAC5B,6BAA6B,EAC7B,iCAAiC,EACjC,+BAA+B,EAC/B,6BAA6B,EAC7B,6BAA6B,EAC7B,uBAAuB,EACvB,4BAA4B,EAC5B,6BAA6B,EAC7B,mBAAmB,EACnB,uBAAuB,EACvB,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,mBAAmB,CAAC;AAgB3B,0EAA0E;AAC1E,+EAA+E;AAC/E,iDAAiD;AACjD,OAAO,EACL,sBAAsB,EACtB,sBAAsB,EACtB,qBAAqB,EACrB,gBAAgB,EAChB,iBAAiB,EACjB,wBAAwB,EACxB,qBAAqB,EACrB,4BAA4B,EAC5B,yBAAyB,EACzB,yBAAyB,EACzB,eAAe,EACf,oBAAoB,EACpB,sBAAsB,EACtB,SAAS,EACT,cAAc,GACf,MAAM,uBAAuB,CAAC;AAa/B,2EAA2E;AAC3E,mFAAmF;AACnF,oDAAoD;AACpD,OAAO,EACL,yBAAyB,EACzB,uBAAuB,EACvB,2BAA2B,EAC3B,yBAAyB,EACzB,uBAAuB,EACvB,uBAAuB,EACvB,uBAAuB,GACxB,MAAM,gBAAgB,CAAC"}
|