@neocompose/cli 0.79.1 → 0.81.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neocompose/cli",
3
- "version": "0.79.1",
3
+ "version": "0.81.0",
4
4
  "description": "Neo Compose native project-source CLI with bidirectional sync.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -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.79.1 -->
12
+ <!-- reviewed-through-cli: 0.81.0 -->
13
13
 
14
14
  # Neo Compose CLI
15
15
 
@@ -57,7 +57,9 @@ On a placed `NeoObject`, `this.Cell` returns its grid cell.
57
57
  same grid, filtered to `Plant` and subclasses. `this.GetTile(neighbors)`
58
58
  returns the first tile found in pattern order, or null.
59
59
  `this.GetTiles(neighbors)` returns the tile at each occupied cell in pattern
60
- order and skips empty cells. Each query takes an optional `offset` that shifts
60
+ order and skips empty cells. A type argument filters each cell's top tile:
61
+ `this.GetTiles<DirtDryTile>(neighbors)` returns `List<DirtDryTile>` and skips
62
+ a cell whose top tile is something else, even when a dry tile sits under it. Each query takes an optional `offset` that shifts
61
63
  the whole pattern, so `this.GetTiles(neighbors, new(0, 2))` queries around the
62
64
  cell two rows up without building a translated pattern. These queries track
63
65
  empty cells as well as hits, so a getter updates when a new neighbor appears.
@@ -93,7 +95,12 @@ Object `PlacementTiles` is a `List<NeoPlacementTile>`. Each entry marks a
93
95
  footprint cell with its own `Cell` member. It is independent of `NeoTile`. Rendered
94
96
  tile classes do not belong in this list. An object with no placement tiles
95
97
  occupies no cells. It doesn't block other placements, and cell queries don't
96
- return it.
98
+ return it. A placed object with no tiles still has a `Cell`.
99
+
100
+ `NeoSpriteObject` extends `NeoObject`. Place a sprite class like any object,
101
+ give it `Children`, and override `OnObjectSpawned`/`OnObjectDespawned` on it.
102
+ Hooks fire on every object in a placed hierarchy, parent first; despawn runs
103
+ children first. `NeoObjectBehaviour.IsRoot` is true only on the placed root.
97
104
 
98
105
  Convert a writable placement without changing its row identity or cell:
99
106
 
@@ -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.79.1 -->
132
+ <!-- reviewed-through-cli: 0.81.0 -->
133
133
  ```
134
134
 
135
135
  The quoted version above is checked too, so this instruction cannot go stale
@@ -102,6 +102,23 @@ A generic receiver may call methods from its class or interface constraint,
102
102
  including void calls used as statements. Generic arguments substitute through
103
103
  the constraint; nullable receivers still require narrowing or null handling.
104
104
 
105
+ Functions, natives and interface functions can declare their own type
106
+ parameters after the name, each with an optional constraint and default:
107
+
108
+ ```neo
109
+ public static T? FirstOf<T extends Item = Item>(List<Item> items) {
110
+ foreach (Item item in items) {
111
+ if (item is T match) return match;
112
+ }
113
+ return null;
114
+ }
115
+ ```
116
+
117
+ A call writes every type argument or omits the defaulted tail
118
+ (`FirstOf<Seed>(items)`, `FirstOf(items)`); nothing is inferred. Function type
119
+ parameters take no `@id`, and an override declares the same count, constraints
120
+ and defaults, though it may rename them.
121
+
105
122
  Prefer `--json` for automation.
106
123
 
107
124
  `neo script check --all` reconstructs the prospective project entirely from
@@ -146,6 +163,10 @@ A static field that names another static copies a value, as in
146
163
  `public static int B = Holder.A;`. A class, List, Set, or Dictionary static
147
164
  already owns its value, so call `Clone()` or use `Reference`. A static delegate cannot copy another Class's delegate field,
148
165
  because its closure compiles in its own Class; wrap it as `() => Other.Call()`.
166
+ Omitted constructor fields use their authored defaults, including optional fields.
167
+ Writable collection defaults belong to each instance; mutations persist on later
168
+ reads without changing another instance's default. Fields without defaults remain
169
+ absent, and `null` arguments in generated member-wise constructors mean omission.
149
170
  Collection type arguments in constructions, such as `new Box<List<int>>([1, 2])`,
150
171
  work even when no field declares that collection type. Preparation includes the
151
172
  needed type descriptors; spec-only types remain in the test candidate.
@@ -157,6 +178,12 @@ Explicit lambda parameter annotations accept the same type grammar as
157
178
  declarations, including `decimal`, generic parameters, collections, arrays, and
158
179
  nullable types.
159
180
 
181
+ Instance reads in collection-entry initializers must be deferred. A default such
182
+ as `List<int> Values = [this.Number + 1]` (or `[Number + 1]`) is a compile error:
183
+ the instance does not exist while the entry initializer runs. Delegate lambdas
184
+ such as `() => this.Number` and method groups such as `Read` or `this.Read`
185
+ remain valid, including inside `new Callback { Read = Read }` entries.
186
+
160
187
  A lambda may use an expression body too: `(x) => x * 2` is the block body
161
188
  `(x) => { return x * 2; }`. In a void delegate the expression is a statement,
162
189
  so it must call or assign. A dictionary-literal body needs parentheses,
@@ -330,6 +357,8 @@ return this.Beds
330
357
  Use `items.IndexOf(value)` to return the zero-based index of the first equal
331
358
  list entry, or `-1` when the value is absent. `IndexOf` is list-only and uses
332
359
  the same equality as `Contains`.
360
+ `Remove(value)` removes the first equal entry using that same equality, including
361
+ scalar entries supplied by instance field defaults. Removing a missing value is a no-op.
333
362
 
334
363
  Use `items.Insert(index, value)` to insert an entry into a writable ordered
335
364
  list. The index may range from zero through `items.Count`; the count appends
@@ -300,6 +300,11 @@ linked source record.
300
300
 
301
301
  ## Managed files
302
302
 
303
+ Managed images support PNG, JPEG, GIF, and SVG. SVG files use `image/svg+xml`
304
+ and retain their original bytes through pull, push, and Unity export; the CLI
305
+ does not rasterize them. The same byte-length, MIME-type, and SHA-256 checks
306
+ apply to SVG transfers as to other managed files.
307
+
303
308
  Declare files in typed registries:
304
309
 
305
310
  ```neo