@neocompose/cli 0.75.2 → 0.76.1
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/CHANGELOG.md +42 -0
- package/dist/neo.mjs +8310 -8741
- package/dist/test-worker.mjs +1292 -915
- package/package.json +1 -1
- package/skills/neocompose-cli/SKILL.md +7 -3
- package/skills/neocompose-cli/references/animation-and-world-authoring.md +3 -2
- package/skills/neocompose-cli/references/cli-development.md +1 -1
- package/skills/neocompose-cli/references/declarations-and-construction.md +42 -3
- package/skills/neocompose-cli/references/neoscript.md +4 -3
- package/skills/neocompose-cli/references/values-identities-and-references.md +39 -0
package/package.json
CHANGED
|
@@ -9,7 +9,7 @@ description: >-
|
|
|
9
9
|
`@neocompose/cli` or `node cli/bin/neo.mjs` in the neo-compose repository.
|
|
10
10
|
---
|
|
11
11
|
|
|
12
|
-
<!-- reviewed-through-cli: 0.
|
|
12
|
+
<!-- reviewed-through-cli: 0.76.1 -->
|
|
13
13
|
|
|
14
14
|
# Neo Compose CLI
|
|
15
15
|
|
|
@@ -211,8 +211,12 @@ copies, use the editor's duplicate action or copy the initializer without IDs.
|
|
|
211
211
|
Scalars may have several owners. If those values diverge in web, pull keeps
|
|
212
212
|
the different server values by inlining the differing uses. Initializer
|
|
213
213
|
aliases are local source organization, not runtime globals or server records.
|
|
214
|
-
|
|
215
|
-
|
|
214
|
+
Complete member and collection entries compose owned values, including inside
|
|
215
|
+
constructor-backed initializers. A class local used as a constructor argument or
|
|
216
|
+
executable operand refers to its single stored instance. Nested targets need an
|
|
217
|
+
existing `@id` or an authored UUID-v4; a direct static owner supports pending IDs.
|
|
218
|
+
Scalar executable expressions such as `BASE + 1` still require inlining the
|
|
219
|
+
scalar expression. Locals are unavailable inside executable closures.
|
|
216
220
|
The shared editor offers extract-to-file on a selected complete initializer,
|
|
217
221
|
inline on its sole use, and duplicate at a use. Move the created file freely.
|
|
218
222
|
|
|
@@ -66,8 +66,9 @@ new GlassFloorTile { Cell = new(9, -4) }
|
|
|
66
66
|
|
|
67
67
|
Layer-link `Tiles` lists contain these values directly. `NeoTileInstance` and
|
|
68
68
|
`@tile(...)` are removed. A tile's `Name`, `Sprite`, and `SmartTile` are
|
|
69
|
-
`readonly`
|
|
70
|
-
|
|
69
|
+
class-level `readonly` members: tiles render per class, so override them on a
|
|
70
|
+
subclass. Push rejects a placement that sets them. `Cell` is the placement's
|
|
71
|
+
writable field.
|
|
71
72
|
|
|
72
73
|
Object `PlacementTiles` is a `List<NeoPlacementTile>`. Each entry marks a
|
|
73
74
|
footprint cell with its own `Cell` member. It is independent of `NeoTile`. Rendered
|
|
@@ -129,7 +129,7 @@ wrappers.
|
|
|
129
129
|
The marker near the top of `SKILL.md` must exactly match the package version:
|
|
130
130
|
|
|
131
131
|
```html
|
|
132
|
-
<!-- reviewed-through-cli: 0.
|
|
132
|
+
<!-- reviewed-through-cli: 0.76.1 -->
|
|
133
133
|
```
|
|
134
134
|
|
|
135
135
|
The quoted version above is checked too, so this instruction cannot go stale
|
|
@@ -166,6 +166,30 @@ a User class reads only `root.User`. Other code reads `root.User` but can't
|
|
|
166
166
|
assign, mutate, construct, or invoke User data. Lookups and listeners don't
|
|
167
167
|
cross between User and Save data; Session lookups may target `root.User`.
|
|
168
168
|
|
|
169
|
+
`readonly` is init-only, as in C#, and independent of storage. A field
|
|
170
|
+
initializer, a constructor body, an object initializer block, or an authored
|
|
171
|
+
value sets it; nothing writes it after construction. It is valid on Save,
|
|
172
|
+
Session, Immutable, and User classes, but not with Writable storage. It may
|
|
173
|
+
read a header parameter:
|
|
174
|
+
|
|
175
|
+
```neo
|
|
176
|
+
class MixerGroup(string name) {
|
|
177
|
+
public readonly string Name = name;
|
|
178
|
+
public readonly List<MixerChannel> Children = [];
|
|
179
|
+
public float Volume = 1;
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
Readonly is shallow. A readonly collection's membership is fixed, while its
|
|
184
|
+
entries' members follow their own storage and mutability. User class members
|
|
185
|
+
still declare no storage.
|
|
186
|
+
|
|
187
|
+
A readonly member declared as a literal (no initializer or constructor call)
|
|
188
|
+
that reads neither `this` nor a constructor argument and holds nothing
|
|
189
|
+
writable is a constant. Instances share its declared value and store nothing
|
|
190
|
+
until a constructor or initializer block writes it. A readonly collection or
|
|
191
|
+
initializer is still built per instance.
|
|
192
|
+
|
|
169
193
|
`@index(member: Field, kind: .Unique)` and
|
|
170
194
|
`@column(member: Field, width: ..., visibility: ..., pin: ..., overflow: ...)`
|
|
171
195
|
are repeatable List annotations. `member:` is a bare field name on the entry
|
|
@@ -369,8 +393,8 @@ Accept settlement only from:
|
|
|
369
393
|
|
|
370
394
|
1. The member's own initializer expression.
|
|
371
395
|
2. Assignment on every reachable path in `init` or a constructor body.
|
|
372
|
-
3. A call-site initializer entry
|
|
373
|
-
path.
|
|
396
|
+
3. A call-site initializer entry, in value source and NeoScript bodies alike,
|
|
397
|
+
when using an otherwise valid construction path.
|
|
374
398
|
|
|
375
399
|
Do not infer settlement from a side effect inside another function. Require
|
|
376
400
|
full `if`/`else` coverage when an assignment is conditional.
|
|
@@ -434,7 +458,22 @@ class PlacedItem<
|
|
|
434
458
|
}
|
|
435
459
|
```
|
|
436
460
|
|
|
437
|
-
|
|
461
|
+
Object initializer blocks can set `readonly` members of the newly constructed
|
|
462
|
+
instance, including nested `new` expressions. Ordinary assignments after
|
|
463
|
+
construction remain subject to storage and `readonly` restrictions.
|
|
464
|
+
|
|
465
|
+
Runtime construction never supplies an Immutable member: an initializer block,
|
|
466
|
+
constructor body, base-clause argument, or generated C# factory cannot set one.
|
|
467
|
+
The value is never stored with the instance. When the declaration, including
|
|
468
|
+
every row it owns, reads neither `this` nor a constructor argument, and no
|
|
469
|
+
value of its type holds a writable member, the member is a constant and every
|
|
470
|
+
instance shares one value. Otherwise each instance evaluates the declared
|
|
471
|
+
initializer with its own `this` and constructor arguments, again after a
|
|
472
|
+
reload. A method group such as `selector: SelectTorso` binds `this`.
|
|
473
|
+
`Clone()` shares an authored Immutable value or a constant and re-evaluates a
|
|
474
|
+
per-instance one. A class with a required Immutable member and
|
|
475
|
+
no initializer cannot be constructed at runtime; only authored values construct
|
|
476
|
+
it.
|
|
438
477
|
|
|
439
478
|
Populated unordered member defaults, such as `@settings(kind: .Unordered)` with
|
|
440
479
|
`List<Entry> Entries = [new Entry()]`, are constructed by an initializer for
|
|
@@ -154,9 +154,10 @@ Object initializers are available in method bodies and `.spec.neo` tests:
|
|
|
154
154
|
var tile = new DirtWetTile { Cell = Vector2Int(3, -2) };
|
|
155
155
|
```
|
|
156
156
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
157
|
+
An entry that settles a required member is evaluated with construction, as the
|
|
158
|
+
constructor argument it stands in for. The remaining entries then use ordinary
|
|
159
|
+
assignment rules in source order, including property setters, access checks,
|
|
160
|
+
and readonly restrictions. Initializer expressions read the caller's scope.
|
|
160
161
|
|
|
161
162
|
## Nullability and ownership
|
|
162
163
|
|
|
@@ -90,6 +90,45 @@ formatting moves its ID above the declaration. Do not put an ID in both places.
|
|
|
90
90
|
A local initializer such as `Delivery DeliveryRow = new()` retains `Delivery`
|
|
91
91
|
when consumed by a base-class member. Aliases retain that same concrete type.
|
|
92
92
|
|
|
93
|
+
Complete local member and collection initializers also work inside constructions
|
|
94
|
+
that execute a constructor. Each local composes its owned subtree and preserves
|
|
95
|
+
its concrete class:
|
|
96
|
+
|
|
97
|
+
```neo
|
|
98
|
+
AudioFolder SFX_FOLDER = new("Sound effects") {
|
|
99
|
+
Children = [UI_VOLUME, GAMEPLAY_VOLUME]
|
|
100
|
+
};
|
|
101
|
+
AudioSettings AUDIO_SETTINGS = new() { Main = SFX_FOLDER };
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
In constructor arguments and executable operands, a class local names its one
|
|
105
|
+
stored instance instead of constructing a copy:
|
|
106
|
+
|
|
107
|
+
```neo
|
|
108
|
+
@id("86ac7c7d-8d3b-4642-9def-cdf32643bdc5")
|
|
109
|
+
DeliveryQuest HARD_AS_STONE = new();
|
|
110
|
+
// The core quest list owns HARD_AS_STONE.
|
|
111
|
+
WorkflowStep UNLOCK = new QuestUnlockStep(HARD_AS_STONE);
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
The referenced local must have exactly one owning placement. A nested target
|
|
115
|
+
needs its existing `@id`. A structurally owned list entry can also use an unused
|
|
116
|
+
UUID-v4 in the same push. For a local nested inside an evaluated constructor,
|
|
117
|
+
leave it idless on the first push; push assigns its actual identity before it can
|
|
118
|
+
be referenced. Do not assign a fresh UUID to that nested construction. A direct static owning member can supply an idless local's pending identity.
|
|
119
|
+
Aliases of that static local work too. A member default is a construction template,
|
|
120
|
+
so its local does not identify a single stored instance. Unowned locals, ambiguous
|
|
121
|
+
placements, and cycles are errors at source. Constructor argument type checking
|
|
122
|
+
still applies. Canonical construction arguments may use `Reference<Type>(id: "…")`.
|
|
123
|
+
|
|
124
|
+
Owned locals inside evaluated initializers need directly addressable fields, list
|
|
125
|
+
entries, or literal dictionary keys; inline the construction when a computed key
|
|
126
|
+
or other executable expression prevents tracking its owning path.
|
|
127
|
+
|
|
128
|
+
Scalar locals remain complete-initializer bindings; inline their expressions when
|
|
129
|
+
using them in arithmetic or constructor arguments. Closure bodies cannot capture
|
|
130
|
+
project authoring locals.
|
|
131
|
+
|
|
93
132
|
Nested class/list rows remain independently addressable and keep inline IDs:
|
|
94
133
|
|
|
95
134
|
```neo
|