Files
feuerwerk/tools/lib/builders.mjs
T
rootandClaude Opus 5 f60358c951 Let a list hold structs, and read or write variables in bundles
A list item may now be a struct. The depth is bounded in the declaration
rather than by a comment: FieldKind (number|text|boolean|color) says what a
struct field holds, ListItemKind adds struct on top and says what a list
holds, so list -> struct -> primitive is the deepest storable shape and
sameValue stays finite. A struct item renders inline in the List tab, which
is why it needs no path in the slot address.

Four paths silently assumed a list item was a primitive: sameValue compared
items with ===, textOf would have printed [object Object], asListItem turned
a struct into text on Set item and Fill, and Index of used indexOf, which is
reference equality and could never have found a struct.

Tetris now runs on bundles. shapes is 112 {x, y} structs instead of 224 loose
numbers, piece and the candidate are structs, so Next move hands back a whole
candidate and each strand packs only the field it changes, since mergeStruct
leaves the rest standing. Declared behavior ports drop 49 -> 35, the master's
variables 18 -> 13, its graph 84/94 -> 69/76 nodes/edges.

Get variables and Set variables declare their ports from a list of variable
names, the way Pack and Expand already do, so one node can read or write
several at once. Renaming a variable rewires them, because there the port key
is the variable name.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-10 14:01:56 +02:00

64 lines
2.0 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* Small factories for writing project documents by hand (the seed scripts). They produce the
* exact shape `src/core/store/serialize.ts` reads; optional fields get their defaults.
*/
/** A scene object (also a container template entry). Position defaults to the origin. */
export const sceneObject = (
id,
assetId,
{ name = '', x = 0, y = 0, z = 0, overrides = {}, parentId = '', instanceEdits, editorOffset } = {},
) => ({
id,
assetId,
name,
position: { x, y, z },
overrides,
parentId,
...(instanceEdits ? { instanceEdits } : {}),
...(editorOffset ? { editorOffset } : {}),
});
/**
* The id an object of a placed container resolves to: `<instance>~<template ids>`. A placed
* container stores nothing but itself, so this is how its content is addressed – in the editor,
* in a running game and in the check scripts alike (see `src/core/model/instance.ts`).
*/
export const instanceChild = (instanceId, ...templatePath) => `${instanceId}~${templatePath.join('/')}`;
/** A graph edge from `from.fromPort` to `to.toPort`. */
export const edge = (id, from, fromPort, to, toPort) => ({
id,
from: { node: from, port: fromPort },
to: { node: to, port: toPort },
});
/** A graph node; `params` holds settings and inline input values alike. `ports` only on the types that declare them. */
export const node = (id, type, x, y, params = {}, ports) => ({
id,
type,
x,
y,
params,
...(ports ? { ports } : {}),
});
/** A port a behavior's start or end node declares. */
export const port = (key, kind) => ({ key, kind });
/**
* A behavior variable declaration. `items` is the item kind of a `list`, `fields` the shape of a
* `struct` – or of the items of a `list` whose items are structs.
*/
export const variable = (key, kind, value, items, fields) => ({
key,
label: key,
kind,
default: value,
...(items ? { items } : {}),
...(fields ? { fields } : {}),
});
/** A struct field declaration, and the same shape a list of structs declares for its items. */
export const field = (key, kind = 'number') => ({ key, kind });