@typeonce/ritmo 0.6.0 → 0.8.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/README.md +2 -0
- package/dist/Brand.d.ts +9 -4
- package/dist/Brand.d.ts.map +1 -1
- package/dist/Brand.js +9 -4
- package/dist/Brand.js.map +1 -1
- package/dist/Clock.d.ts +186 -0
- package/dist/Clock.d.ts.map +1 -0
- package/dist/Clock.js +111 -0
- package/dist/Clock.js.map +1 -0
- package/dist/Command.d.ts +250 -41
- package/dist/Command.d.ts.map +1 -1
- package/dist/Command.js +59 -23
- package/dist/Command.js.map +1 -1
- package/dist/Condition.d.ts +12 -1
- package/dist/Condition.d.ts.map +1 -1
- package/dist/Condition.js.map +1 -1
- package/dist/Debug.d.ts +163 -15
- package/dist/Debug.d.ts.map +1 -1
- package/dist/Debug.js.map +1 -1
- package/dist/Decode.d.ts +1 -1
- package/dist/Decode.js +1 -1
- package/dist/Descriptor.d.ts +67 -24
- package/dist/Descriptor.d.ts.map +1 -1
- package/dist/Descriptor.js +32 -15
- package/dist/Descriptor.js.map +1 -1
- package/dist/Entity.d.ts +22 -5
- package/dist/Entity.d.ts.map +1 -1
- package/dist/Entity.js +2 -2
- package/dist/Entity.js.map +1 -1
- package/dist/EntityScope.d.ts +26 -1
- package/dist/EntityScope.d.ts.map +1 -1
- package/dist/EntityScope.js +14 -2
- package/dist/EntityScope.js.map +1 -1
- package/dist/HostClock.d.ts +49 -0
- package/dist/HostClock.d.ts.map +1 -0
- package/dist/HostClock.js +46 -0
- package/dist/HostClock.js.map +1 -0
- package/dist/Inspector.d.ts +7 -1
- package/dist/Inspector.d.ts.map +1 -1
- package/dist/Inspector.js.map +1 -1
- package/dist/Machine.d.ts +67 -36
- package/dist/Machine.d.ts.map +1 -1
- package/dist/Machine.js +10 -3
- package/dist/Machine.js.map +1 -1
- package/dist/Query.d.ts +74 -26
- package/dist/Query.d.ts.map +1 -1
- package/dist/Query.js +32 -28
- package/dist/Query.js.map +1 -1
- package/dist/Runtime.d.ts +39 -16
- package/dist/Runtime.d.ts.map +1 -1
- package/dist/Runtime.js +556 -87
- package/dist/Runtime.js.map +1 -1
- package/dist/Schedule.d.ts +217 -10
- package/dist/Schedule.d.ts.map +1 -1
- package/dist/Schedule.js +5 -0
- package/dist/Schedule.js.map +1 -1
- package/dist/Schema.d.ts +196 -44
- package/dist/Schema.d.ts.map +1 -1
- package/dist/Schema.js +29 -11
- package/dist/Schema.js.map +1 -1
- package/dist/Snapshot.d.ts +14 -0
- package/dist/Snapshot.d.ts.map +1 -1
- package/dist/Snapshot.js.map +1 -1
- package/dist/System.d.ts +212 -58
- package/dist/System.d.ts.map +1 -1
- package/dist/System.js +84 -6
- package/dist/System.js.map +1 -1
- package/dist/index.d.ts +8 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -7
- package/dist/index.js.map +1 -1
- package/dist/internal/cells.d.ts +3 -3
- package/dist/internal/cells.d.ts.map +1 -1
- package/dist/internal/cells.js +9 -11
- package/dist/internal/cells.js.map +1 -1
- package/dist/internal/debug.d.ts +13 -0
- package/dist/internal/debug.d.ts.map +1 -1
- package/dist/internal/debug.js +192 -7
- package/dist/internal/debug.js.map +1 -1
- package/dist/internal/equal.d.ts +8 -0
- package/dist/internal/equal.d.ts.map +1 -0
- package/dist/internal/equal.js +38 -0
- package/dist/internal/equal.js.map +1 -0
- package/dist/internal/fragments.d.ts.map +1 -1
- package/dist/internal/fragments.js +11 -1
- package/dist/internal/fragments.js.map +1 -1
- package/dist/internal/game.d.ts.map +1 -1
- package/dist/internal/game.js +41 -6
- package/dist/internal/game.js.map +1 -1
- package/dist/internal/order.d.ts +10 -0
- package/dist/internal/order.d.ts.map +1 -0
- package/dist/internal/order.js +122 -0
- package/dist/internal/order.js.map +1 -0
- package/dist/internal/queries.d.ts.map +1 -1
- package/dist/internal/queries.js +32 -10
- package/dist/internal/queries.js.map +1 -1
- package/dist/internal/requirements.d.ts +26 -0
- package/dist/internal/requirements.d.ts.map +1 -0
- package/dist/internal/requirements.js +46 -0
- package/dist/internal/requirements.js.map +1 -0
- package/package.json +1 -1
- package/src/Brand.ts +9 -4
- package/src/Clock.ts +311 -0
- package/src/Command.ts +407 -89
- package/src/Condition.ts +17 -1
- package/src/Debug.ts +172 -14
- package/src/Decode.ts +1 -1
- package/src/Descriptor.ts +92 -37
- package/src/Entity.ts +24 -5
- package/src/EntityScope.ts +27 -2
- package/src/HostClock.ts +64 -0
- package/src/Inspector.ts +7 -2
- package/src/Machine.ts +81 -37
- package/src/Query.ts +110 -38
- package/src/Runtime.ts +607 -111
- package/src/Schedule.ts +380 -13
- package/src/Schema.ts +249 -63
- package/src/Snapshot.ts +4 -0
- package/src/System.ts +248 -93
- package/src/index.ts +8 -7
- package/src/internal/cells.ts +10 -12
- package/src/internal/debug.ts +208 -12
- package/src/internal/equal.ts +31 -0
- package/src/internal/fragments.ts +12 -2
- package/src/internal/game.ts +61 -7
- package/src/internal/order.ts +144 -0
- package/src/internal/queries.ts +37 -13
- package/src/internal/requirements.ts +71 -0
- package/dist/Definition.d.ts +0 -99
- package/dist/Definition.d.ts.map +0 -1
- package/dist/Definition.js +0 -68
- package/dist/Definition.js.map +0 -1
- package/dist/Feature.d.ts +0 -106
- package/dist/Feature.d.ts.map +0 -1
- package/dist/Feature.js +0 -87
- package/dist/Feature.js.map +0 -1
- package/dist/Fx.d.ts +0 -128
- package/dist/Fx.d.ts.map +0 -1
- package/dist/Fx.js +0 -112
- package/dist/Fx.js.map +0 -1
- package/dist/internal/definition.d.ts +0 -17
- package/dist/internal/definition.d.ts.map +0 -1
- package/dist/internal/definition.js +0 -25
- package/dist/internal/definition.js.map +0 -1
- package/src/Definition.ts +0 -106
- package/src/Feature.ts +0 -241
- package/src/Fx.ts +0 -176
- package/src/internal/definition.ts +0 -56
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The runtime form of the `Game.System.thisTick` check, for erased schedules
|
|
3
|
+
* (`tryTick`) and the `this-tick-order` lint. The compile-time form lives in
|
|
4
|
+
* `Schedule.ts` (`TickOrderErrors`) and produces the same messages.
|
|
5
|
+
*/
|
|
6
|
+
import type { Descriptor } from "../Descriptor.ts"
|
|
7
|
+
import type * as Query from "../Query.ts"
|
|
8
|
+
import * as Schedule from "../Schedule.ts"
|
|
9
|
+
import type { SystemDefinition } from "../System.ts"
|
|
10
|
+
|
|
11
|
+
type AnySystem = SystemDefinition<any, any, any, any, any>
|
|
12
|
+
type OrderIssue = Schedule.OrderIssue
|
|
13
|
+
type Access = { readonly mode: "read" | "changed" | "write"; readonly descriptor: Descriptor.Any; readonly thisTick?: true }
|
|
14
|
+
type QueryAccess = {
|
|
15
|
+
readonly thisTick?: true
|
|
16
|
+
readonly selection: Record<string, { readonly mode?: string; readonly descriptor?: Descriptor.Any }>
|
|
17
|
+
readonly with: ReadonlyArray<Descriptor.Any>
|
|
18
|
+
readonly without: ReadonlyArray<Descriptor.Any>
|
|
19
|
+
readonly filters: ReadonlyArray<Query.Filter<any>>
|
|
20
|
+
}
|
|
21
|
+
/** Every component a filter names: the one of `added` / `changed`, or each member of `anyOf`. */
|
|
22
|
+
const filterNames = (filter: Query.Filter<any>): ReadonlyArray<string> =>
|
|
23
|
+
filter.kind === "anyOf" ? filter.filters.map((member) => member.descriptor.name) : [filter.descriptor.name]
|
|
24
|
+
type Permission = { readonly permission: string; readonly values: ReadonlyArray<{ readonly name: string }> }
|
|
25
|
+
|
|
26
|
+
/** One position of a tick: a system, or a point where queued commands are applied. */
|
|
27
|
+
type Item = { readonly kind: "system"; readonly system: AnySystem } | { readonly kind: "flush" }
|
|
28
|
+
|
|
29
|
+
const accesses = (system: AnySystem): ReadonlyArray<Access> => [
|
|
30
|
+
...Object.values(system.spec.events as Record<string, Access>),
|
|
31
|
+
...Object.values(system.spec.resources as Record<string, Access>)
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
const sameData = (left: Descriptor.Any, right: Descriptor.Any): boolean =>
|
|
35
|
+
left.kind === right.kind && left.name === right.name
|
|
36
|
+
|
|
37
|
+
const sameSystem = (left: AnySystem, right: AnySystem): boolean => (left.base ?? left) === (right.base ?? right)
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* The positions of a tick, flattened: an `applyStateTransitions(...)` step
|
|
41
|
+
* applies queued commands, then runs every schedule of its bundle (as if
|
|
42
|
+
* each may run), markers inside them included.
|
|
43
|
+
*/
|
|
44
|
+
const flatten = (steps: ReadonlyArray<Schedule.ScheduleStep>): Array<Item> =>
|
|
45
|
+
steps.flatMap((step): Array<Item> => {
|
|
46
|
+
if (Schedule.isSystemStep(step)) return [{ kind: "system", system: step as AnySystem }]
|
|
47
|
+
if (step.kind === "applyDeferred") return [{ kind: "flush" }]
|
|
48
|
+
const bundle = step.bundle as { readonly entries: ReadonlyArray<{ readonly steps: ReadonlyArray<Schedule.ScheduleStep> }> } | undefined
|
|
49
|
+
return [{ kind: "flush" }, ...(bundle?.entries ?? []).flatMap((entry) => flatten(entry.steps))]
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
const permissionNames = (system: AnySystem, kind: string): Set<string> => {
|
|
53
|
+
const commands = system.spec.commands as { readonly permissions: ReadonlyArray<Permission> } | undefined
|
|
54
|
+
return new Set((commands?.permissions ?? []).filter((p) => p.permission === kind).flatMap((p) => p.values.map((value) => value.name)))
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Whether a system's declared commands can change what a query sees: spawns
|
|
59
|
+
* covering every component it requires, or inserts / removes of any
|
|
60
|
+
* component it names. Despawns never count.
|
|
61
|
+
*/
|
|
62
|
+
const changesQuery = (system: AnySystem, query: QueryAccess): boolean => {
|
|
63
|
+
const slots = Object.values(query.selection)
|
|
64
|
+
const required = [
|
|
65
|
+
...slots.filter((slot) => slot.mode === "read" || slot.mode === "write").flatMap((slot) => slot.descriptor ? [slot.descriptor.name] : []),
|
|
66
|
+
...query.with.map((d) => d.name)
|
|
67
|
+
]
|
|
68
|
+
const named = new Set([
|
|
69
|
+
...slots.flatMap((slot) => slot.descriptor ? [slot.descriptor.name] : []),
|
|
70
|
+
...query.with.map((d) => d.name),
|
|
71
|
+
...query.without.map((d) => d.name),
|
|
72
|
+
...query.filters.flatMap((filter) => filterNames(filter))
|
|
73
|
+
])
|
|
74
|
+
const changes = [...permissionNames(system, "inserts"), ...permissionNames(system, "removes")]
|
|
75
|
+
if (changes.some((name) => named.has(name))) return true
|
|
76
|
+
const spawns = permissionNames(system, "spawns")
|
|
77
|
+
return spawns.size > 0 && required.every((name) => spawns.has(name))
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Checks the systems of one tick, in the order they run. A read with no
|
|
82
|
+
* writer in the tick is fine (a reused reader); `event-never-written` covers
|
|
83
|
+
* a writer missing everywhere.
|
|
84
|
+
*/
|
|
85
|
+
export const tickOrderIssues = (steps: ReadonlyArray<Schedule.ScheduleStep>): ReadonlyArray<OrderIssue> => {
|
|
86
|
+
// A schedule's steps never change, so `tryTick` checks each schedule once.
|
|
87
|
+
const cached = checked.get(steps)
|
|
88
|
+
if (cached !== undefined) return cached
|
|
89
|
+
const issues = computeIssues(steps)
|
|
90
|
+
checked.set(steps, issues)
|
|
91
|
+
return issues
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const checked = new WeakMap<ReadonlyArray<Schedule.ScheduleStep>, ReadonlyArray<OrderIssue>>()
|
|
95
|
+
|
|
96
|
+
const computeIssues = (steps: ReadonlyArray<Schedule.ScheduleStep>): ReadonlyArray<OrderIssue> => {
|
|
97
|
+
const items = flatten(steps)
|
|
98
|
+
const issues: Array<OrderIssue> = []
|
|
99
|
+
const systemsAt = items.flatMap((item, at) => item.kind === "system" ? [{ system: item.system, at }] : [])
|
|
100
|
+
for (const { system: reader, at: index } of systemsAt) {
|
|
101
|
+
for (const read of accesses(reader)) {
|
|
102
|
+
if ((read.mode !== "read" && read.mode !== "changed") || read.thisTick !== true) continue
|
|
103
|
+
const data = read.descriptor.name
|
|
104
|
+
for (const { system, at } of systemsAt) {
|
|
105
|
+
if (at <= index || sameSystem(system, reader)) continue
|
|
106
|
+
if (!accesses(system).some((access) => access.mode === "write" && sameData(access.descriptor, read.descriptor))) continue
|
|
107
|
+
issues.push({
|
|
108
|
+
kind: "lateWriter",
|
|
109
|
+
reader: reader.name,
|
|
110
|
+
data,
|
|
111
|
+
writer: system.name,
|
|
112
|
+
message: `${reader.name} needs ${data} from this tick, but its writer ${system.name} runs after it: move ${system.name} before ${reader.name}, or read ${data} without thisTick`
|
|
113
|
+
})
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
for (const [slot, query] of Object.entries(reader.spec.queries as Record<string, QueryAccess>)) {
|
|
117
|
+
if (query.thisTick !== true) continue
|
|
118
|
+
const data = `queries.${slot}`
|
|
119
|
+
let lastFlush = -1
|
|
120
|
+
for (let at = 0; at < index; at++) if (items[at]!.kind === "flush") lastFlush = at
|
|
121
|
+
for (const { system, at } of systemsAt) {
|
|
122
|
+
if (sameSystem(system, reader) || !changesQuery(system, query)) continue
|
|
123
|
+
if (at > index) {
|
|
124
|
+
issues.push({
|
|
125
|
+
kind: "lateWriter",
|
|
126
|
+
reader: reader.name,
|
|
127
|
+
data,
|
|
128
|
+
writer: system.name,
|
|
129
|
+
message: `${system.name} queues commands that ${reader.name} needs this tick (${data}), but it runs after ${reader.name}: move ${system.name} before the applyDeferred() that precedes ${reader.name}, or read ${data} without thisTick`
|
|
130
|
+
})
|
|
131
|
+
} else if (at > lastFlush && at < index) {
|
|
132
|
+
issues.push({
|
|
133
|
+
kind: "unflushedWriter",
|
|
134
|
+
reader: reader.name,
|
|
135
|
+
data,
|
|
136
|
+
writer: system.name,
|
|
137
|
+
message: `${reader.name} needs this tick's commands for ${data}, but ${system.name} queues them with no applyDeferred() in between: add Game.Schedule.applyDeferred() after ${system.name}`
|
|
138
|
+
})
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return issues
|
|
144
|
+
}
|
package/src/internal/queries.ts
CHANGED
|
@@ -33,7 +33,7 @@ type SlotPlan =
|
|
|
33
33
|
readonly mode: "write"
|
|
34
34
|
readonly ordinal: number
|
|
35
35
|
readonly constructor: DescriptorModule.ResultConstructor<unknown, unknown, unknown> | undefined
|
|
36
|
-
readonly
|
|
36
|
+
readonly entityState: string | undefined
|
|
37
37
|
}
|
|
38
38
|
| {
|
|
39
39
|
readonly slot: string
|
|
@@ -46,6 +46,9 @@ interface LifecycleFilterPlan {
|
|
|
46
46
|
readonly ordinal: number
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
+
/** A query filter: one lifecycle filter, or `anyOf` several (passes when one does). */
|
|
50
|
+
type FilterPlan = ReadonlyArray<LifecycleFilterPlan>
|
|
51
|
+
|
|
49
52
|
interface QueryState {
|
|
50
53
|
readonly ordinal: number
|
|
51
54
|
readonly required: ReadonlyArray<number>
|
|
@@ -54,7 +57,7 @@ interface QueryState {
|
|
|
54
57
|
readonly withoutRelations: ReadonlyArray<Relation.Relation.Any>
|
|
55
58
|
readonly withRelated: ReadonlyArray<Relation.Relation.Any>
|
|
56
59
|
readonly withoutRelated: ReadonlyArray<Relation.Relation.Any>
|
|
57
|
-
readonly filters: ReadonlyArray<
|
|
60
|
+
readonly filters: ReadonlyArray<FilterPlan>
|
|
58
61
|
readonly slots: ReadonlyArray<SlotPlan>
|
|
59
62
|
readonly proofSlots: ReadonlyArray<readonly [string, number]>
|
|
60
63
|
readonly writeSlots: ReadonlyArray<readonly [string, number]>
|
|
@@ -143,7 +146,7 @@ export const makeQueryEngine = (world: World) => {
|
|
|
143
146
|
mode: "write",
|
|
144
147
|
ordinal,
|
|
145
148
|
constructor: DescriptorModule.constructorOf(access.descriptor),
|
|
146
|
-
|
|
149
|
+
entityState: DescriptorModule.isEntityState(access.descriptor) ? access.descriptor.name : undefined
|
|
147
150
|
})
|
|
148
151
|
} else {
|
|
149
152
|
slots.push({ slot, mode: "read", ordinal })
|
|
@@ -185,11 +188,13 @@ export const makeQueryEngine = (world: World) => {
|
|
|
185
188
|
withoutRelations: query.withoutRelations,
|
|
186
189
|
withRelated: unique(withRelated),
|
|
187
190
|
withoutRelated: query.withoutRelated,
|
|
188
|
-
filters: query.filters.map((filter) =>
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
191
|
+
filters: query.filters.map((filter) =>
|
|
192
|
+
(filter.kind === "anyOf" ? filter.filters : [filter]).map((member) => {
|
|
193
|
+
const ordinal = world.ordinalOf(member.descriptor)
|
|
194
|
+
world.trackChanges(ordinal)
|
|
195
|
+
return { kind: member.kind, ordinal }
|
|
196
|
+
})
|
|
197
|
+
),
|
|
193
198
|
slots,
|
|
194
199
|
proofSlots,
|
|
195
200
|
writeSlots,
|
|
@@ -239,14 +244,33 @@ export const makeQueryEngine = (world: World) => {
|
|
|
239
244
|
|
|
240
245
|
const matchesFilters = (state: QueryState, record: EntityRecord, since: number): boolean => {
|
|
241
246
|
for (const filter of state.filters) {
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
247
|
+
let matched = false
|
|
248
|
+
for (const member of filter) {
|
|
249
|
+
matched = member.kind === "added"
|
|
250
|
+
? world.addedSince(record, member.ordinal, since)
|
|
251
|
+
: world.changedSince(record, member.ordinal, since)
|
|
252
|
+
if (matched) break
|
|
253
|
+
}
|
|
245
254
|
if (!matched) return false
|
|
246
255
|
}
|
|
247
256
|
return true
|
|
248
257
|
}
|
|
249
258
|
|
|
259
|
+
/**
|
|
260
|
+
* Ids that may pass one filter (may repeat), or `undefined` when a change
|
|
261
|
+
* log no longer covers `since`. An `anyOf` is the union of its members' logs.
|
|
262
|
+
*/
|
|
263
|
+
const filterCandidates = (filter: FilterPlan, since: number): ReadonlyArray<number> | undefined => {
|
|
264
|
+
if (filter.length === 1) return world.changedCandidates(filter[0]!.ordinal, since)
|
|
265
|
+
const union: Array<number> = []
|
|
266
|
+
for (const member of filter) {
|
|
267
|
+
const logged = world.changedCandidates(member.ordinal, since)
|
|
268
|
+
if (logged === undefined) return undefined
|
|
269
|
+
for (const id of logged) union.push(id)
|
|
270
|
+
}
|
|
271
|
+
return union
|
|
272
|
+
}
|
|
273
|
+
|
|
250
274
|
const relatedIds = (relation: Relation.Relation.Any, id: number): ReadonlyArray<Entity.EntityId<any, any>> =>
|
|
251
275
|
world.relatedSourceIds(relation, id).map(world.entityIdOf)
|
|
252
276
|
|
|
@@ -255,7 +279,7 @@ export const makeQueryEngine = (world: World) => {
|
|
|
255
279
|
case "read":
|
|
256
280
|
return Cells.componentRead(record, plan.ordinal)
|
|
257
281
|
case "write":
|
|
258
|
-
return Cells.componentWrite(record, plan.ordinal, world, plan.constructor, plan.
|
|
282
|
+
return Cells.componentWrite(record, plan.ordinal, world, plan.constructor, plan.entityState)
|
|
259
283
|
case "optional":
|
|
260
284
|
return Cells.componentOptional(record, plan.ordinal)
|
|
261
285
|
case "readRelation":
|
|
@@ -426,7 +450,7 @@ export const makeQueryEngine = (world: World) => {
|
|
|
426
450
|
// bounds the candidates for either filter.
|
|
427
451
|
let candidates: ReadonlyArray<number> | undefined
|
|
428
452
|
for (const filter of state.filters) {
|
|
429
|
-
const logged =
|
|
453
|
+
const logged = filterCandidates(filter, since)
|
|
430
454
|
if (logged === undefined) continue
|
|
431
455
|
if (logged.length === 0) return []
|
|
432
456
|
if (candidates === undefined || logged.length < candidates.length) candidates = logged
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime side of `Schema.requires`: the requirement index built once per
|
|
3
|
+
* bound schema, used to expand `Game.System.spawns(...)`, to check commands
|
|
4
|
+
* when they are applied, and to check restored entities.
|
|
5
|
+
*
|
|
6
|
+
* The compile-time counterpart lives in `Command.ts` (spawn, insert, remove)
|
|
7
|
+
* and `Schema.ts` (`ValidateRequires`).
|
|
8
|
+
*/
|
|
9
|
+
import type { Descriptor } from "../Descriptor.ts"
|
|
10
|
+
import type { Schema } from "../Schema.ts"
|
|
11
|
+
|
|
12
|
+
type ComponentDescriptor = Descriptor<"component", string, any>
|
|
13
|
+
|
|
14
|
+
export interface RequirementIndex {
|
|
15
|
+
/** Whether the schema declares any requirement. */
|
|
16
|
+
readonly empty: boolean
|
|
17
|
+
/** Component name to the components it directly requires. */
|
|
18
|
+
readonly requires: ReadonlyMap<string, ReadonlyArray<ComponentDescriptor>>
|
|
19
|
+
/** Component name to the components that directly require it. */
|
|
20
|
+
readonly requiredBy: ReadonlyMap<string, ReadonlyArray<ComponentDescriptor>>
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const push = (map: Map<string, Array<ComponentDescriptor>>, key: string, value: ComponentDescriptor): void => {
|
|
24
|
+
const list = map.get(key)
|
|
25
|
+
if (list === undefined) map.set(key, [value])
|
|
26
|
+
else if (!list.some((entry) => entry.name === value.name)) list.push(value)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export const requirementIndex = (schema: Schema.Any): RequirementIndex => {
|
|
30
|
+
const requires = new Map<string, Array<ComponentDescriptor>>()
|
|
31
|
+
const requiredBy = new Map<string, Array<ComponentDescriptor>>()
|
|
32
|
+
for (const requirement of schema.requires) {
|
|
33
|
+
for (const required of requirement.required) {
|
|
34
|
+
push(requires, requirement.component.name, required)
|
|
35
|
+
push(requiredBy, required.name, requirement.component)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return { empty: requires.size === 0, requires, requiredBy }
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** `components` and everything they require, transitively, without duplicates. */
|
|
42
|
+
export const withRequired = (
|
|
43
|
+
index: RequirementIndex,
|
|
44
|
+
components: ReadonlyArray<ComponentDescriptor>
|
|
45
|
+
): ReadonlyArray<ComponentDescriptor> => {
|
|
46
|
+
if (index.empty) return components
|
|
47
|
+
const result: Array<ComponentDescriptor> = []
|
|
48
|
+
const seen = new Set<string>()
|
|
49
|
+
const visit = (descriptor: ComponentDescriptor): void => {
|
|
50
|
+
if (seen.has(descriptor.name)) return
|
|
51
|
+
seen.add(descriptor.name)
|
|
52
|
+
result.push(descriptor)
|
|
53
|
+
for (const required of index.requires.get(descriptor.name) ?? []) visit(required)
|
|
54
|
+
}
|
|
55
|
+
components.forEach(visit)
|
|
56
|
+
return result
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** The first requirement `held` breaks, as `[requirer, missing]`, or `undefined`. */
|
|
60
|
+
export const firstMissing = (
|
|
61
|
+
index: RequirementIndex,
|
|
62
|
+
held: (name: string) => boolean,
|
|
63
|
+
names: Iterable<string>
|
|
64
|
+
): readonly [string, string] | undefined => {
|
|
65
|
+
for (const name of names) {
|
|
66
|
+
for (const required of index.requires.get(name) ?? []) {
|
|
67
|
+
if (!held(required.name)) return [name, required.name]
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return undefined
|
|
71
|
+
}
|
package/dist/Definition.d.ts
DELETED
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Helpers for validating reusable authored values once and reusing them later.
|
|
3
|
-
*
|
|
4
|
-
* `Definition` is intended for static or rarely changing authored data such as
|
|
5
|
-
* spawn points, collider sizes, arena bounds, or other constants that should
|
|
6
|
-
* cross the validation boundary once and then remain branded afterward.
|
|
7
|
-
*
|
|
8
|
-
* In game code this is the "content setup" companion to runtime/world setup:
|
|
9
|
-
* validate authored constants early, keep them in carried form, and then reuse
|
|
10
|
-
* them from setup systems, reset systems, or content modules without
|
|
11
|
-
* revalidating on every frame.
|
|
12
|
-
*
|
|
13
|
-
* @example
|
|
14
|
-
* ```ts
|
|
15
|
-
* // Validate authored constants once when defining the content bundle.
|
|
16
|
-
* const player = Definition.all({
|
|
17
|
-
* spawn: Definition.entry(Vector2, { x: 32, y: 48 }),
|
|
18
|
-
* size: Definition.entry(Size2, { width: 16, height: 16 })
|
|
19
|
-
* })
|
|
20
|
-
* ```
|
|
21
|
-
*
|
|
22
|
-
* @module Definition
|
|
23
|
-
* @docGroup core
|
|
24
|
-
*
|
|
25
|
-
* @categoryDescription Definition Types
|
|
26
|
-
* Named reusable shapes used to validate and retain authored values.
|
|
27
|
-
*
|
|
28
|
-
* @categoryDescription Definition Builders
|
|
29
|
-
* Helpers that validate one or several authored values through existing constructors.
|
|
30
|
-
*/
|
|
31
|
-
import * as internal from "./internal/definition.ts";
|
|
32
|
-
import type * as Result from "./Result.ts";
|
|
33
|
-
/**
|
|
34
|
-
* One reusable validated definition entry.
|
|
35
|
-
*
|
|
36
|
-
* @category Definition Types
|
|
37
|
-
*/
|
|
38
|
-
export type Entry<Value, Error> = internal.Entry<Value, Error>;
|
|
39
|
-
/**
|
|
40
|
-
* Record of named definition entries accepted by {@link all}.
|
|
41
|
-
*
|
|
42
|
-
* @category Definition Types
|
|
43
|
-
*/
|
|
44
|
-
export type Entries = internal.Entries;
|
|
45
|
-
/**
|
|
46
|
-
* Minimal constructor contract accepted by {@link entry}.
|
|
47
|
-
*
|
|
48
|
-
* @category Definition Types
|
|
49
|
-
*/
|
|
50
|
-
export type ResultConstructor<Value, Raw, Error> = internal.ResultConstructor<Value, Raw, Error>;
|
|
51
|
-
/**
|
|
52
|
-
* Success shape produced by {@link all}.
|
|
53
|
-
*
|
|
54
|
-
* @category Definition Types
|
|
55
|
-
*/
|
|
56
|
-
export type SuccessOf<Input extends Entries> = internal.SuccessOf<Input>;
|
|
57
|
-
/**
|
|
58
|
-
* Error shape produced by {@link all}.
|
|
59
|
-
*
|
|
60
|
-
* @category Definition Types
|
|
61
|
-
*/
|
|
62
|
-
export type ErrorOf<Input extends Entries> = internal.ErrorOf<Input>;
|
|
63
|
-
/**
|
|
64
|
-
* Validates one reusable authored value through an existing constructor.
|
|
65
|
-
*
|
|
66
|
-
* Use this for one named authored constant that should cross a constructor
|
|
67
|
-
* boundary now and remain in carried form afterward.
|
|
68
|
-
*
|
|
69
|
-
* @example
|
|
70
|
-
* ```ts
|
|
71
|
-
* // Validate a single authored position once during content setup.
|
|
72
|
-
* const playerSpawn = Definition.entry(Vector2, { x: 32, y: 48 })
|
|
73
|
-
* ```
|
|
74
|
-
*
|
|
75
|
-
* @category Definition Builders
|
|
76
|
-
*/
|
|
77
|
-
export declare const entry: <Value, Raw, Error>(constructor: ResultConstructor<Value, Raw, Error>, raw: Raw) => Entry<Value, Error>;
|
|
78
|
-
/**
|
|
79
|
-
* Validates a named record of reusable authored values at once.
|
|
80
|
-
*
|
|
81
|
-
* Successful entries are returned under the same keys. Failed entries remain
|
|
82
|
-
* keyed so authored-data setup can report exactly which constant was invalid.
|
|
83
|
-
*
|
|
84
|
-
* Use this when one content bundle or level definition should either validate
|
|
85
|
-
* as a whole or report a structured set of authoring failures.
|
|
86
|
-
*
|
|
87
|
-
* @example
|
|
88
|
-
* ```ts
|
|
89
|
-
* // Validate one authored content bundle and keep failures keyed by field.
|
|
90
|
-
* const definitions = Definition.all({
|
|
91
|
-
* spawn: Definition.entry(Vector2, { x: 32, y: 48 }),
|
|
92
|
-
* collider: Definition.entry(Size2, { width: 16, height: 16 })
|
|
93
|
-
* })
|
|
94
|
-
* ```
|
|
95
|
-
*
|
|
96
|
-
* @category Definition Builders
|
|
97
|
-
*/
|
|
98
|
-
export declare const all: <Input extends Entries>(input: Input) => Result.Result<SuccessOf<Input>, ErrorOf<Input>>;
|
|
99
|
-
//# sourceMappingURL=Definition.d.ts.map
|
package/dist/Definition.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Definition.d.ts","sourceRoot":"","sources":["../src/Definition.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,OAAO,KAAK,QAAQ,MAAM,0BAA0B,CAAA;AACpD,OAAO,KAAK,KAAK,MAAM,MAAM,aAAa,CAAA;AAE1C;;;;GAIG;AACH,MAAM,MAAM,KAAK,CAAC,KAAK,EAAE,KAAK,IAAI,QAAQ,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,CAAA;AAC9D;;;;GAIG;AACH,MAAM,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAA;AACtC;;;;GAIG;AACH,MAAM,MAAM,iBAAiB,CAAC,KAAK,EAAE,GAAG,EAAE,KAAK,IAAI,QAAQ,CAAC,iBAAiB,CAAC,KAAK,EAAE,GAAG,EAAE,KAAK,CAAC,CAAA;AAChG;;;;GAIG;AACH,MAAM,MAAM,SAAS,CAAC,KAAK,SAAS,OAAO,IAAI,QAAQ,CAAC,SAAS,CAAC,KAAK,CAAC,CAAA;AACxE;;;;GAIG;AACH,MAAM,MAAM,OAAO,CAAC,KAAK,SAAS,OAAO,IAAI,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;AAEpE;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,KAAK,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,KAAK,EACpC,WAAW,EAAE,iBAAiB,CAAC,KAAK,EAAE,GAAG,EAAE,KAAK,CAAC,EACjD,GAAG,EAAE,GAAG,KACL,KAAK,CAAC,KAAK,EAAE,KAAK,CAAkB,CAAA;AAEzC;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,GAAG,EAAE,CAAC,KAAK,SAAS,OAAO,EACtC,KAAK,EAAE,KAAK,KACT,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC,KAAK,CAAC,CAAgB,CAAA"}
|
package/dist/Definition.js
DELETED
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Helpers for validating reusable authored values once and reusing them later.
|
|
3
|
-
*
|
|
4
|
-
* `Definition` is intended for static or rarely changing authored data such as
|
|
5
|
-
* spawn points, collider sizes, arena bounds, or other constants that should
|
|
6
|
-
* cross the validation boundary once and then remain branded afterward.
|
|
7
|
-
*
|
|
8
|
-
* In game code this is the "content setup" companion to runtime/world setup:
|
|
9
|
-
* validate authored constants early, keep them in carried form, and then reuse
|
|
10
|
-
* them from setup systems, reset systems, or content modules without
|
|
11
|
-
* revalidating on every frame.
|
|
12
|
-
*
|
|
13
|
-
* @example
|
|
14
|
-
* ```ts
|
|
15
|
-
* // Validate authored constants once when defining the content bundle.
|
|
16
|
-
* const player = Definition.all({
|
|
17
|
-
* spawn: Definition.entry(Vector2, { x: 32, y: 48 }),
|
|
18
|
-
* size: Definition.entry(Size2, { width: 16, height: 16 })
|
|
19
|
-
* })
|
|
20
|
-
* ```
|
|
21
|
-
*
|
|
22
|
-
* @module Definition
|
|
23
|
-
* @docGroup core
|
|
24
|
-
*
|
|
25
|
-
* @categoryDescription Definition Types
|
|
26
|
-
* Named reusable shapes used to validate and retain authored values.
|
|
27
|
-
*
|
|
28
|
-
* @categoryDescription Definition Builders
|
|
29
|
-
* Helpers that validate one or several authored values through existing constructors.
|
|
30
|
-
*/
|
|
31
|
-
import * as internal from "./internal/definition.js";
|
|
32
|
-
/**
|
|
33
|
-
* Validates one reusable authored value through an existing constructor.
|
|
34
|
-
*
|
|
35
|
-
* Use this for one named authored constant that should cross a constructor
|
|
36
|
-
* boundary now and remain in carried form afterward.
|
|
37
|
-
*
|
|
38
|
-
* @example
|
|
39
|
-
* ```ts
|
|
40
|
-
* // Validate a single authored position once during content setup.
|
|
41
|
-
* const playerSpawn = Definition.entry(Vector2, { x: 32, y: 48 })
|
|
42
|
-
* ```
|
|
43
|
-
*
|
|
44
|
-
* @category Definition Builders
|
|
45
|
-
*/
|
|
46
|
-
export const entry = internal.entry;
|
|
47
|
-
/**
|
|
48
|
-
* Validates a named record of reusable authored values at once.
|
|
49
|
-
*
|
|
50
|
-
* Successful entries are returned under the same keys. Failed entries remain
|
|
51
|
-
* keyed so authored-data setup can report exactly which constant was invalid.
|
|
52
|
-
*
|
|
53
|
-
* Use this when one content bundle or level definition should either validate
|
|
54
|
-
* as a whole or report a structured set of authoring failures.
|
|
55
|
-
*
|
|
56
|
-
* @example
|
|
57
|
-
* ```ts
|
|
58
|
-
* // Validate one authored content bundle and keep failures keyed by field.
|
|
59
|
-
* const definitions = Definition.all({
|
|
60
|
-
* spawn: Definition.entry(Vector2, { x: 32, y: 48 }),
|
|
61
|
-
* collider: Definition.entry(Size2, { width: 16, height: 16 })
|
|
62
|
-
* })
|
|
63
|
-
* ```
|
|
64
|
-
*
|
|
65
|
-
* @category Definition Builders
|
|
66
|
-
*/
|
|
67
|
-
export const all = internal.all;
|
|
68
|
-
//# sourceMappingURL=Definition.js.map
|
package/dist/Definition.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Definition.js","sourceRoot":"","sources":["../src/Definition.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,OAAO,KAAK,QAAQ,MAAM,0BAA0B,CAAA;AAkCpD;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,KAAK,GAGS,QAAQ,CAAC,KAAK,CAAA;AAEzC;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,CAAC,MAAM,GAAG,GAEuC,QAAQ,CAAC,GAAG,CAAA"}
|
package/dist/Feature.d.ts
DELETED
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
import type * as Schedule from "./Schedule.ts";
|
|
2
|
-
import type { MergeSchemaDefinitions, Schema, SchemaDefinition, ValidateFragments } from "./Schema.ts";
|
|
3
|
-
type EmptySchema = SchemaDefinition<{}, {}, {}, {}>;
|
|
4
|
-
type AnyFeature = {
|
|
5
|
-
readonly kind: "feature";
|
|
6
|
-
readonly name: string;
|
|
7
|
-
readonly schema: Schema.Any;
|
|
8
|
-
readonly requires: ReadonlyArray<AnyFeature>;
|
|
9
|
-
readonly build: unknown;
|
|
10
|
-
readonly output: FeatureBuildOutput;
|
|
11
|
-
};
|
|
12
|
-
type AnySchedule = Schedule.ScheduleDefinition<any, any, any, any, any>;
|
|
13
|
-
/**
|
|
14
|
-
* What a feature builder returns: bootstrap and update schedules, plus any
|
|
15
|
-
* other values the feature wants to expose on the composed project.
|
|
16
|
-
*/
|
|
17
|
-
export type FeatureBuildOutput = {
|
|
18
|
-
readonly bootstrap?: ReadonlyArray<AnySchedule>;
|
|
19
|
-
readonly update?: ReadonlyArray<AnySchedule>;
|
|
20
|
-
};
|
|
21
|
-
/**
|
|
22
|
-
* The bound authoring surface a feature builder receives. It is the normal
|
|
23
|
-
* `Game` API restricted to the descriptors the feature can see; runtimes are
|
|
24
|
-
* built from the composed project instead.
|
|
25
|
-
*/
|
|
26
|
-
export type FeatureBuildGame<Accessible extends Schema.Any, Root = unknown> = Omit<Schema.Game<Accessible, Root>, "Runtime">;
|
|
27
|
-
type FeatureBuildFunction<Accessible extends Schema.Any, Output extends FeatureBuildOutput = FeatureBuildOutput> = (Game: FeatureBuildGame<Accessible>) => Output;
|
|
28
|
-
export interface FeatureDefinition<Name extends string = string, FeatureSchema extends Schema.Any = Schema.Any, Requires extends ReadonlyArray<AnyFeature> = ReadonlyArray<AnyFeature>, Output extends FeatureBuildOutput = FeatureBuildOutput> {
|
|
29
|
-
readonly kind: "feature";
|
|
30
|
-
readonly name: Name;
|
|
31
|
-
readonly schema: FeatureSchema;
|
|
32
|
-
readonly requires: Requires;
|
|
33
|
-
readonly build: FeatureBuildFunction<MergeSchemaDefinitions<FeatureSchema, MergeFeatureSchemas<Requires>>, Output>;
|
|
34
|
-
readonly output: Output;
|
|
35
|
-
}
|
|
36
|
-
type MergeFeatureSchemas<Features extends ReadonlyArray<AnyFeature>> = Features extends readonly [infer Head extends AnyFeature, ...infer Tail extends Array<AnyFeature>] ? MergeSchemaDefinitions<FeatureClosureSchema<Head>, MergeFeatureSchemas<Tail>> : EmptySchema;
|
|
37
|
-
type FeatureClosureSchema<F extends AnyFeature> = F extends FeatureDefinition<any, infer FeatureSchema extends Schema.Any, infer Requires extends ReadonlyArray<AnyFeature>, any> ? MergeSchemaDefinitions<FeatureSchema, MergeFeatureSchemas<Requires>> : EmptySchema;
|
|
38
|
-
type FeatureNames<Features extends ReadonlyArray<AnyFeature>> = Features[number]["name"];
|
|
39
|
-
type DuplicateFeatureNames<Features extends ReadonlyArray<AnyFeature>, Seen extends string = never> = Features extends readonly [infer Head extends AnyFeature, ...infer Tail extends Array<AnyFeature>] ? Head["name"] extends Seen ? Head["name"] | DuplicateFeatureNames<Tail, Seen> : DuplicateFeatureNames<Tail, Seen | Head["name"]> : never;
|
|
40
|
-
type MissingFeatureDependencies<Features extends ReadonlyArray<AnyFeature>> = Exclude<Features[number]["requires"][number]["name"], FeatureNames<Features>>;
|
|
41
|
-
type FeatureSchemas<Features extends ReadonlyArray<AnyFeature>> = {
|
|
42
|
-
readonly [K in keyof Features]: Features[K]["schema"];
|
|
43
|
-
};
|
|
44
|
-
/**
|
|
45
|
-
* Rejects duplicate feature names, missing required features, and schema
|
|
46
|
-
* fragments whose keys or descriptor names collide.
|
|
47
|
-
*/
|
|
48
|
-
type ValidateFeatureSelection<Features extends ReadonlyArray<AnyFeature>> = [
|
|
49
|
-
DuplicateFeatureNames<Features>
|
|
50
|
-
] extends [never] ? [MissingFeatureDependencies<Features>] extends [never] ? ValidateFragments<FeatureSchemas<Features>> : {
|
|
51
|
-
readonly __fixFeatureDependencies__: MissingFeatureDependencies<Features>;
|
|
52
|
-
} : {
|
|
53
|
-
readonly __fixFeatureSelection__: DuplicateFeatureNames<Features>;
|
|
54
|
-
};
|
|
55
|
-
type RebindFeatureSchedule<ScheduleValue, S extends Schema.Any, Root> = ScheduleValue extends Schedule.ScheduleDefinition<any, infer Requirements, any, infer Carried, infer Failure> ? Schedule.ScheduleDefinition<S, Requirements, Root, Carried, Failure> : never;
|
|
56
|
-
type FeatureScheduleArray<Output, Key extends "bootstrap" | "update"> = Key extends keyof Output ? Extract<Output[Key], ReadonlyArray<AnySchedule>> : readonly [];
|
|
57
|
-
type NormalizeFeatureOutput<Output extends object, S extends Schema.Any, Root> = {
|
|
58
|
-
readonly [K in Exclude<keyof Output, "bootstrap" | "update">]: Output[K];
|
|
59
|
-
} & {
|
|
60
|
-
readonly bootstrap: ReadonlyArray<RebindFeatureSchedule<FeatureScheduleArray<Output, "bootstrap">[number], S, Root>>;
|
|
61
|
-
readonly update: ReadonlyArray<RebindFeatureSchedule<FeatureScheduleArray<Output, "update">[number], S, Root>>;
|
|
62
|
-
};
|
|
63
|
-
type FeatureOutputRecord<Features extends ReadonlyArray<AnyFeature>, S extends Schema.Any, Root> = {
|
|
64
|
-
readonly [K in FeatureNames<Features>]: NormalizeFeatureOutput<Extract<Features[number], {
|
|
65
|
-
readonly name: K;
|
|
66
|
-
}>["output"], S, Root>;
|
|
67
|
-
};
|
|
68
|
-
/**
|
|
69
|
-
* The result of composing features: the merged schema, the bound `Game`,
|
|
70
|
-
* each feature's normalized output, and the aggregated schedules in feature
|
|
71
|
-
* order.
|
|
72
|
-
*/
|
|
73
|
-
export interface ComposedFeatureProject<Features extends ReadonlyArray<AnyFeature>, Root = unknown, S extends Schema.Any = MergeFeatureSchemas<Features>> {
|
|
74
|
-
readonly schema: S;
|
|
75
|
-
readonly Game: Schema.Game<S, Root>;
|
|
76
|
-
readonly features: FeatureOutputRecord<Features, S, Root>;
|
|
77
|
-
readonly schedules: {
|
|
78
|
-
readonly bootstrap: ReadonlyArray<FeatureOutputRecord<Features, S, Root>[FeatureNames<Features>]["bootstrap"][number]>;
|
|
79
|
-
readonly update: ReadonlyArray<FeatureOutputRecord<Features, S, Root>[FeatureNames<Features>]["update"][number]>;
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
/**
|
|
83
|
-
* Defines one pre-bind feature.
|
|
84
|
-
*/
|
|
85
|
-
export declare const define: <const Name extends string, FeatureSchema extends Schema.Any, const Requires extends ReadonlyArray<AnyFeature> = [], Output extends FeatureBuildOutput = FeatureBuildOutput>(name: Name, options: {
|
|
86
|
-
readonly schema: FeatureSchema;
|
|
87
|
-
readonly requires?: Requires;
|
|
88
|
-
readonly build: FeatureBuildFunction<MergeSchemaDefinitions<FeatureSchema, MergeFeatureSchemas<Requires>>, Output>;
|
|
89
|
-
}) => FeatureDefinition<Name, FeatureSchema, Requires, Output>;
|
|
90
|
-
/**
|
|
91
|
-
* Composes features into one merged schema and one bound `Game`, then builds
|
|
92
|
-
* every feature against it.
|
|
93
|
-
*
|
|
94
|
-
* Aggregated schedule order is the selected feature order, not dependency
|
|
95
|
-
* order. Run them with `runtime.tick(...project.schedules.update)`.
|
|
96
|
-
*/
|
|
97
|
-
export declare const compose: <Root, const Features extends readonly [AnyFeature, ...Array<AnyFeature>]>(options: {
|
|
98
|
-
readonly root: Root;
|
|
99
|
-
readonly features: Features;
|
|
100
|
-
} & ValidateFeatureSelection<Features>) => ComposedFeatureProject<Features, Root>;
|
|
101
|
-
export declare const Feature: {
|
|
102
|
-
define: typeof define;
|
|
103
|
-
compose: typeof compose;
|
|
104
|
-
};
|
|
105
|
-
export {};
|
|
106
|
-
//# sourceMappingURL=Feature.d.ts.map
|
package/dist/Feature.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Feature.d.ts","sourceRoot":"","sources":["../src/Feature.ts"],"names":[],"mappings":"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"}
|