Explain typed writes at runtime and the typed List node (#271)
- Structs: new section A typed List node, In the running game split into lists and struct variables, and Under the hood for the check. - Architecture: typedValues and what lookup tells a port. - Development: e2e total 1606. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent
0b54e14387
commit
5952fa0bd0
3 files changed
+41
-9
No files matched your search
+2
-1
@@ -89,7 +89,8 @@ src/core/graph/ graph model, NodeRegistry/NodeContext/values (a travellin
|
||||
portTypes (#207: ports of one node that carry the same value, and the type their inputs agree on),
|
||||
savedValues (#166: the SaveArea a run reads persistent Variables assets from and writes them to, and restoring a save through today's declaration),
|
||||
stateMachine (the State node, a machine's states, the ports they become), variablePorts, propertyPorts,
|
||||
lookup (what a node may look up: behaviors, state machines), keyRepeat; nodes/{events,flow,data,action,variable}/<Name>.ts
|
||||
typedValues (#271: what fits a struct type, and a written variable held to its declaration),
|
||||
lookup (what a node may look up: behaviors, state machines, struct types, what a variable declares), keyRepeat; nodes/{events,flow,data,action,variable}/<Name>.ts
|
||||
src/core/particles/ nodes (the catalogue), compile (a graph → one function per output),
|
||||
emission (which particles are alive at a second — a pure rule, no state)
|
||||
src/core/store/ serialize (untrusted JSON → Project), projectPlugins (which plugins a project switches on, read off the raw
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@ php tests/php/accounts.test.php # the API's accoun
|
||||
# has and the web server's container has not (SKIP there)
|
||||
php tests/php/snapshots.test.php # the snapshot store (#231), the same way
|
||||
php tests/php/releases.test.php # the release store (#266), the same way
|
||||
node tools/seed-e2e.mjs && node tools/e2e.mjs # 1603 editor checks, screenshots in /tmp/gm-e2e-*.png
|
||||
node tools/seed-e2e.mjs && node tools/e2e.mjs # 1606 editor checks, screenshots in /tmp/gm-e2e-*.png
|
||||
GM_STEPS=20 node tools/e2e.mjs # or 1-12, or 6,20 — a subset while working on one step
|
||||
./e2e.sh start [GM_STEPS] # the same run detached, see below
|
||||
./e2e.sh status # live progress, or the last run's result
|
||||
|
||||
+38
-7
@@ -116,6 +116,16 @@ In a **mixed** list, every struct item has a **Type** row of its own, as does a
|
||||
such an item. Pick a struct asset there, and that one item takes on its fields and follows it, while
|
||||
the other items stay as they are. **Own fields** turns it back.
|
||||
|
||||
### A typed List node
|
||||
|
||||
The `List` node, a constant list, has a **Type** setting too. Pick a struct asset there, and its
|
||||
items take on the type exactly as a typed list variable's do: what they hold under the same name
|
||||
stays, every other field starts at the default, **+ Item** adds one of the type, and the field
|
||||
names are fixed. A list holding anything but structs refuses the type, with a line in the console.
|
||||
**None** makes it a mixed list again: the items keep their values but no longer follow the asset,
|
||||
since a node's list has no Type row per item. A `For each` over a typed `List` offers **Split into
|
||||
Loot fields** for its `item`, like one over a typed list variable.
|
||||
|
||||
### When the asset changes
|
||||
|
||||
Typed items follow their asset like every other place of that type — the table above applies to
|
||||
@@ -125,7 +135,7 @@ the overrides of placed objects and in lists nested inside other items, in one u
|
||||
## Deleting a struct asset
|
||||
|
||||
The delete dialog counts the structs, the typed lists and the nodes that use it (`Pack`/`Expand`
|
||||
with the type, and every split output).
|
||||
and `List` with the type, and every split output).
|
||||
After deleting, each of them **keeps the fields it last had**, now as its own fields — no value is
|
||||
lost, only the link. A Type row reads **Own fields** again, an Items row **Mixed**.
|
||||
|
||||
@@ -135,11 +145,25 @@ A struct value is the same plain bundle of fields, with or without a type: the t
|
||||
with the value, so `Equals`, `Index of`, saving and loading treat it as before. Edges do not check
|
||||
the type either — any struct fits any struct port.
|
||||
|
||||
The places that check are **Add item** and **Set item**, each with its **Type** setting. With a
|
||||
type they take a value only if it is a struct with **exactly** the type's field names — none
|
||||
missing, none more. Anything else is not added or set: the list comes out as it went in, and the
|
||||
console names the value and the type. An item taken out of a typed list, and a `Pack` with the same
|
||||
type, always fit. Without a type (or with one that was deleted) both take anything, as before.
|
||||
The places that check are **Add item** and **Set item** with their **Type** setting, and every
|
||||
**variable with a type** that a graph writes:
|
||||
|
||||
- **Add item** and **Set item** with a type take a value only if it is a struct with **exactly**
|
||||
the type's field names — none missing, none more. Anything else is not added or set: the list
|
||||
comes out as it went in, and the console names the value and the type. An item taken out of a
|
||||
typed list, and a `Pack` with the same type, always fit. Without a type (or with one that was
|
||||
deleted) both take anything, as before.
|
||||
- **A typed list** keeps, of what is written into it, only the items that fit its type by the same
|
||||
rule. Every other item is left out and named in the console, one line each; the rest of the list
|
||||
is written. This holds for a list variable, for a typed list field inside a struct variable, and
|
||||
for the lists inside typed items, at any depth.
|
||||
- **A struct variable with a type** takes a struct whose fields are all fields of the type. It may
|
||||
leave some out: those keep their value, as in any struct variable, so a `Pack` of one field still
|
||||
sets just that field. A struct bringing a field the type does not have, or a value that is no
|
||||
struct at all, is not written, and the console says so.
|
||||
|
||||
Writing means the `Variables` node, on a behavior's own variables and on a Variables asset's alike,
|
||||
and the `Properties` node setting a behavior variable of the object it is handed.
|
||||
|
||||
## Under the hood
|
||||
|
||||
@@ -158,7 +182,14 @@ struct item with a type of its own in a mixed list holds the same key. No field
|
||||
since field names never start with `$`. The same sync brings every marked item into shape, wherever
|
||||
it sits. A run never sees the key: it is taken out where values enter the game
|
||||
(`withoutItemTypes` in `src/core/model/Properties.ts`), which is why `Add item` and `Set item` can
|
||||
compare field names exactly.
|
||||
compare field names exactly. A typed `List` node keeps the marks in its setting, and its output
|
||||
drops them the same way.
|
||||
|
||||
What a written variable is held to comes from its declaration, not from the value. When a
|
||||
`Variables` or `Properties` node is resolved, `GraphLookup.variableTyping` hands each port that
|
||||
writes a variable its item type, its struct type and the typed fields inside it (`typingOf` in
|
||||
`structTypes.ts`); `writeDeclared` in `src/core/graph/typedValues.ts` holds the written value to
|
||||
that. A run resolves each node once, so this costs nothing per frame beyond the check itself.
|
||||
|
||||
A typed item keeps a field's value as plain JSON, the way a declared struct does: an asset id or a
|
||||
texture id is a text, a color a number. What kind a field is comes from the type, so the item rows
|
||||
|
||||
Reference in new issue
Block a user