@neocompose/cli 0.64.1 → 0.65.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 +13 -0
- package/dist/neo.mjs +111 -70
- package/dist/test-worker.mjs +37 -33
- package/package.json +1 -1
- package/skills/neocompose-cli/SKILL.md +1 -1
- package/skills/neocompose-cli/references/animation-and-world-authoring.md +31 -0
- package/skills/neocompose-cli/references/cli-development.md +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.65.1] - 2026-10-03
|
|
4
|
+
|
|
5
|
+
- Pull and push reconciliation emit a stored `new NeoAnimationSegmentFrame<NeoCollider?>(value: null)`. A null constructor argument typed by a class's generic parameter now checks nullability against the row's type argument. Previously, a pushed segment holding a null frame committed, but source reconciliation failed with "Required constructor argument stores null".
|
|
6
|
+
- Pulled type arguments keep a nullable binding's `?`, in constructions, references, and declared member types. Previously `FrameBox<NeoCollider?> Box` pulled as `FrameBox<NeoCollider> Box`, and the next push made the binding required.
|
|
7
|
+
- Code compiled from stored records keeps a nullable binding's `?`. A member declared `NeoAnimationSegmentFrame<NeoCollider?>` keeps that type, so passing it where that type is expected compiles, and reading its value as a required `NeoCollider` reports an error. Previously, every bound type argument was typed as required.
|
|
8
|
+
|
|
9
|
+
## [0.65.0] - 2026-10-03
|
|
10
|
+
|
|
11
|
+
- Move `Collider` from `NeoObject` to `NeoObjectBase`, so sprite objects and layer groups can carry a box collider too. Unity codegen implements `INeoColliderSource` on `NeoObjectBase`.
|
|
12
|
+
- Segment tracks may target a Class member, such as `NeoObjectBase.Collider`. Each frame plays a whole value or `null`. A segment whose class does not fit the target member reports which class it plays. A segment of nullable values cannot target a required member.
|
|
13
|
+
- Constructor arguments and object initializers typed by a class's generic parameter take the site's type argument. `new NeoAnimationSegmentFrame<NeoCollider?>(value: null)` and `{ Value = null }` now compile.
|
|
14
|
+
- Authoring `null` over a member that held a class instance drops the instance's class and constructor metadata. Previously the row kept them, and push rejected it as an invalid value record.
|
|
15
|
+
|
|
3
16
|
## [0.64.1] - 2026-10-02
|
|
4
17
|
|
|
5
18
|
- Reserve `OnChanged` as a member name. Every generated Unity class declares the SDK's `OnChanged` change subscription, so a member by that name now reports `reserved-project-name` instead of pushing the SDK method aside as `OnChanged_2`.
|
package/dist/neo.mjs
CHANGED
|
@@ -14192,11 +14192,18 @@ function validateExpression(expression, expected, scope, environment, uri, range
|
|
|
14192
14192
|
siteArgumentNames,
|
|
14193
14193
|
siteInitializerNames
|
|
14194
14194
|
);
|
|
14195
|
+
const siteTypeArguments = expression.typeArguments?.map(semanticAstType) ?? (expression.className === null ? expected?.arguments : void 0) ?? [];
|
|
14196
|
+
const siteBindings = new Map(
|
|
14197
|
+
declaration.genericParameters.flatMap((parameter4, index) => {
|
|
14198
|
+
const argument2 = siteTypeArguments[index];
|
|
14199
|
+
return argument2 ? [[parameter4.name, argument2]] : [];
|
|
14200
|
+
})
|
|
14201
|
+
);
|
|
14195
14202
|
for (const diagnostic of validateNeoConstructionSite(
|
|
14196
14203
|
environment.construction,
|
|
14197
14204
|
{
|
|
14198
14205
|
className: declaration.name,
|
|
14199
|
-
typeArguments:
|
|
14206
|
+
typeArguments: siteTypeArguments,
|
|
14200
14207
|
argumentNames: variantSite?.argumentNames ?? siteArgumentNames,
|
|
14201
14208
|
initializerNames: variantSite?.initializerNames ?? siteInitializerNames
|
|
14202
14209
|
}
|
|
@@ -14232,7 +14239,7 @@ function validateExpression(expression, expected, scope, environment, uri, range
|
|
|
14232
14239
|
(candidate) => candidate.name === (variantMember ?? named)
|
|
14233
14240
|
) : fields[index];
|
|
14234
14241
|
const expectedType = parameter4?.type ?? field?.type;
|
|
14235
|
-
const expectedSemanticType = declaration.name === NEO_LOOKUP_VARIANT_FOLDER_TYPE_NAME && named === "collectionValue" ? { name: "string" } : expectedType ? semanticType(expectedType) : void 0;
|
|
14242
|
+
const expectedSemanticType = declaration.name === NEO_LOOKUP_VARIANT_FOLDER_TYPE_NAME && named === "collectionValue" ? { name: "string" } : expectedType ? substituteSemanticType(semanticType(expectedType), siteBindings) : void 0;
|
|
14236
14243
|
validateExpression(
|
|
14237
14244
|
argument2,
|
|
14238
14245
|
expectedSemanticType,
|
|
@@ -14253,8 +14260,11 @@ function validateExpression(expression, expected, scope, environment, uri, range
|
|
|
14253
14260
|
validateExpression(
|
|
14254
14261
|
entry.value,
|
|
14255
14262
|
field ? substituteSemanticType(
|
|
14256
|
-
|
|
14257
|
-
|
|
14263
|
+
substituteSemanticType(
|
|
14264
|
+
semanticType(field.member.type),
|
|
14265
|
+
field.bindings
|
|
14266
|
+
),
|
|
14267
|
+
siteBindings
|
|
14258
14268
|
) : void 0,
|
|
14259
14269
|
scope,
|
|
14260
14270
|
environment,
|
|
@@ -14469,7 +14479,7 @@ function sourceClassMemberByName(declaration, name, environment, initialBindings
|
|
|
14469
14479
|
function substituteSemanticType(type, bindings) {
|
|
14470
14480
|
const bound = bindings.get(type.name);
|
|
14471
14481
|
if (bound !== void 0 && (type.arguments ?? []).length === 0) {
|
|
14472
|
-
return type.nullable ===
|
|
14482
|
+
return type.nullable === true ? { ...bound, nullable: true } : bound;
|
|
14473
14483
|
}
|
|
14474
14484
|
const argumentsList2 = (type.arguments ?? []).map(
|
|
14475
14485
|
(argument2) => substituteSemanticType(argument2, bindings)
|
|
@@ -22778,7 +22788,12 @@ var init_strict_resolver = __esm({
|
|
|
22778
22788
|
};
|
|
22779
22789
|
});
|
|
22780
22790
|
fields.push(
|
|
22781
|
-
...this.resolveCallSiteInitializerFields(
|
|
22791
|
+
...this.resolveCallSiteInitializerFields(
|
|
22792
|
+
schemaClass2,
|
|
22793
|
+
targetType,
|
|
22794
|
+
expression,
|
|
22795
|
+
scope
|
|
22796
|
+
)
|
|
22782
22797
|
);
|
|
22783
22798
|
const schemaClassInfo = toWireType(targetType, this.project);
|
|
22784
22799
|
if (schemaClassInfo.type !== 7 /* Class */) {
|
|
@@ -22904,6 +22919,7 @@ var init_strict_resolver = __esm({
|
|
|
22904
22919
|
) : [];
|
|
22905
22920
|
const fields = this.resolveCallSiteInitializerFields(
|
|
22906
22921
|
schemaClass2,
|
|
22922
|
+
targetType,
|
|
22907
22923
|
expression,
|
|
22908
22924
|
scope
|
|
22909
22925
|
);
|
|
@@ -23018,7 +23034,7 @@ var init_strict_resolver = __esm({
|
|
|
23018
23034
|
* the class's own schema exactly as a `classConstructor` field is, and
|
|
23019
23035
|
* applied after the body so an explicit assignment always wins.
|
|
23020
23036
|
*/
|
|
23021
|
-
resolveCallSiteInitializerFields(schemaClass2, expression, scope) {
|
|
23037
|
+
resolveCallSiteInitializerFields(schemaClass2, targetType, expression, scope) {
|
|
23022
23038
|
const entries = expression.initializer ?? [];
|
|
23023
23039
|
const seen = /* @__PURE__ */ new Set();
|
|
23024
23040
|
return entries.map((entry) => {
|
|
@@ -23063,10 +23079,15 @@ var init_strict_resolver = __esm({
|
|
|
23063
23079
|
entry.pos
|
|
23064
23080
|
);
|
|
23065
23081
|
}
|
|
23066
|
-
const
|
|
23067
|
-
|
|
23082
|
+
const memberType2 = substituteTypeParameters(
|
|
23083
|
+
member.type,
|
|
23084
|
+
targetType,
|
|
23085
|
+
schemaClass2
|
|
23086
|
+
);
|
|
23087
|
+
const value = this.resolveExpression(entry.value, scope, memberType2);
|
|
23088
|
+
if (!isNeoScriptTypeAssignable(value.type, memberType2, this.project)) {
|
|
23068
23089
|
throw new CompileError(
|
|
23069
|
-
`Object initializer '${member.name}' expected ${this.describe(
|
|
23090
|
+
`Object initializer '${member.name}' expected ${this.describe(memberType2)} but got ${this.describe(value.type)}.`,
|
|
23070
23091
|
entry.pos
|
|
23071
23092
|
);
|
|
23072
23093
|
}
|
|
@@ -29934,7 +29955,7 @@ var init_registry = __esm({
|
|
|
29934
29955
|
"../packages/manifest/schema-contract/registry.mjs"() {
|
|
29935
29956
|
"use strict";
|
|
29936
29957
|
PROJECT_SCHEMA_CONTRACT = Object.freeze({
|
|
29937
|
-
cliVersion: "0.
|
|
29958
|
+
cliVersion: "0.65.1",
|
|
29938
29959
|
projectFileUploadBatchSize: 32,
|
|
29939
29960
|
documentRecords: {
|
|
29940
29961
|
member: {
|
|
@@ -43302,6 +43323,9 @@ function createMergeMemo() {
|
|
|
43302
43323
|
function resolveInheritanceChain(classId, classes, draft) {
|
|
43303
43324
|
return [...indexClasses(classes).inheritanceChain(classId, draft)];
|
|
43304
43325
|
}
|
|
43326
|
+
function resolveInheritanceChainFromIndex(classId, classIndex, draft) {
|
|
43327
|
+
return resolveChainFromIndex(classId, classIndex, draft);
|
|
43328
|
+
}
|
|
43305
43329
|
function resolveChainFromIndex(classId, index, draft) {
|
|
43306
43330
|
const chain = [];
|
|
43307
43331
|
const visited = /* @__PURE__ */ new Set();
|
|
@@ -44374,6 +44398,14 @@ var init_world_system_classes_generated = __esm({
|
|
|
44374
44398
|
docsText: "When false, this object and its children are neither rendered nor collided with. The value stays live: member writes still apply and a running animation clip keeps playing. Disabling an object hides its whole subtree regardless of each child's own value, and re-enabling it restores exactly what was there.",
|
|
44375
44399
|
requirement: 1 /* Required */,
|
|
44376
44400
|
schemaKey: "Enabled"
|
|
44401
|
+
},
|
|
44402
|
+
{
|
|
44403
|
+
memberId: "system_a0083c92-72f7-405f-8863-ff86f995d36d",
|
|
44404
|
+
memberKind: "class",
|
|
44405
|
+
defaultValue: null,
|
|
44406
|
+
docsText: "The object's box collider, or null for none. Any world object can carry one: placed objects, nested children, and sprites alike.",
|
|
44407
|
+
schemaClassWorldKind: "objectCollider",
|
|
44408
|
+
schemaKey: "Collider"
|
|
44377
44409
|
}
|
|
44378
44410
|
],
|
|
44379
44411
|
worldKind: "objectBase"
|
|
@@ -44583,13 +44615,6 @@ var init_world_system_classes_generated = __esm({
|
|
|
44583
44615
|
requirement: 1 /* Required */,
|
|
44584
44616
|
schemaKey: "Children"
|
|
44585
44617
|
},
|
|
44586
|
-
{
|
|
44587
|
-
memberId: "system_a0083c92-72f7-405f-8863-ff86f995d36d",
|
|
44588
|
-
memberKind: "class",
|
|
44589
|
-
defaultValue: null,
|
|
44590
|
-
schemaClassWorldKind: "objectCollider",
|
|
44591
|
-
schemaKey: "Collider"
|
|
44592
|
-
},
|
|
44593
44618
|
{
|
|
44594
44619
|
memberId: "system_c609fed3-53e4-5147-b493-e4aa23031d79",
|
|
44595
44620
|
memberKind: "computed",
|
|
@@ -52500,7 +52525,7 @@ function renderMemberType(context, member, enclosingClassId, elementSettings = f
|
|
|
52500
52525
|
context,
|
|
52501
52526
|
required(context.members, boundMemberId, "generic binding"),
|
|
52502
52527
|
enclosingClassId
|
|
52503
|
-
)
|
|
52528
|
+
);
|
|
52504
52529
|
});
|
|
52505
52530
|
value = `${schemaClass2.name}${args.length ? `<${args.join(", ")}>` : ""}`;
|
|
52506
52531
|
}
|
|
@@ -61100,7 +61125,7 @@ function resolveMemberDeclaredTypeInfoInternal(member, members, seen) {
|
|
|
61100
61125
|
members,
|
|
61101
61126
|
nextSeen
|
|
61102
61127
|
);
|
|
61103
|
-
return argumentType === null ? [] : [[genericParamId,
|
|
61128
|
+
return argumentType === null ? [] : [[genericParamId, argumentType]];
|
|
61104
61129
|
}
|
|
61105
61130
|
)
|
|
61106
61131
|
);
|
|
@@ -65443,13 +65468,11 @@ function classArguments(member, context, seen, genericEnvironment) {
|
|
|
65443
65468
|
if (environmentEntry?.kind === "member") {
|
|
65444
65469
|
const argument3 = analyzerMemberById(context, environmentEntry.memberId);
|
|
65445
65470
|
return argument3 ? [
|
|
65446
|
-
|
|
65447
|
-
|
|
65448
|
-
|
|
65449
|
-
|
|
65450
|
-
|
|
65451
|
-
genericEnvironment
|
|
65452
|
-
)
|
|
65471
|
+
memberRuntimeType(
|
|
65472
|
+
argument3,
|
|
65473
|
+
context,
|
|
65474
|
+
new Set(seen),
|
|
65475
|
+
genericEnvironment
|
|
65453
65476
|
)
|
|
65454
65477
|
] : [];
|
|
65455
65478
|
}
|
|
@@ -65464,13 +65487,11 @@ function classArguments(member, context, seen, genericEnvironment) {
|
|
|
65464
65487
|
}
|
|
65465
65488
|
const argument2 = analyzerMemberById(context, binding.memberId);
|
|
65466
65489
|
return argument2 ? [
|
|
65467
|
-
|
|
65468
|
-
|
|
65469
|
-
|
|
65470
|
-
|
|
65471
|
-
|
|
65472
|
-
genericEnvironment
|
|
65473
|
-
)
|
|
65490
|
+
memberRuntimeType(
|
|
65491
|
+
argument2,
|
|
65492
|
+
context,
|
|
65493
|
+
new Set(seen),
|
|
65494
|
+
genericEnvironment
|
|
65474
65495
|
)
|
|
65475
65496
|
] : [];
|
|
65476
65497
|
});
|
|
@@ -65657,11 +65678,7 @@ function genericConstraintLanguageType(constraint, context, genericEnvironment,
|
|
|
65657
65678
|
];
|
|
65658
65679
|
}
|
|
65659
65680
|
const member = analyzerMemberById(context, binding.memberId);
|
|
65660
|
-
return member ? [
|
|
65661
|
-
requiredType(
|
|
65662
|
-
memberRuntimeType(member, context, /* @__PURE__ */ new Set(), genericEnvironment)
|
|
65663
|
-
)
|
|
65664
|
-
] : [];
|
|
65681
|
+
return member ? [memberRuntimeType(member, context, /* @__PURE__ */ new Set(), genericEnvironment)] : [];
|
|
65665
65682
|
});
|
|
65666
65683
|
return {
|
|
65667
65684
|
kind: "named",
|
|
@@ -73507,7 +73524,7 @@ function runtimeTypeCheck(value, checkType, ctx, seenCollections = /* @__PURE__
|
|
|
73507
73524
|
function runtimeValueMatchesType(value, typeInfo, ctx, seenCollections = /* @__PURE__ */ new Set()) {
|
|
73508
73525
|
if (typeInfo.type === NS_TYPE_UNKNOWN) return true;
|
|
73509
73526
|
if (value === null || value === void 0) {
|
|
73510
|
-
return typeInfo.type === 0 /* Null */ || !typeInfo.required;
|
|
73527
|
+
return typeInfo.type === 0 /* Null */ || typeInfo.type === 21 /* Generic */ || !typeInfo.required;
|
|
73511
73528
|
}
|
|
73512
73529
|
return runtimeTypeCheck(value, typeInfo, ctx, seenCollections);
|
|
73513
73530
|
}
|
|
@@ -103116,11 +103133,26 @@ var init_animation_clips = __esm({
|
|
|
103116
103133
|
`${args.label} targets "${boundChildName}.${targetEntry.schemaKey}" of kind ${MemberKind[targetMember.kind]}, but its segment plays ${MemberKind[valueBindingMember.kind]} values.`
|
|
103117
103134
|
);
|
|
103118
103135
|
}
|
|
103119
|
-
if (!
|
|
103120
|
-
|
|
103136
|
+
if (isMemberClass(targetMember) && isMemberClass(valueBindingMember) && !resolveInheritanceChainFromIndex(
|
|
103137
|
+
valueBindingMember.classId,
|
|
103138
|
+
this.classById
|
|
103139
|
+
).some((current) => current.id === targetMember.classId)) {
|
|
103140
|
+
const targetClassName = this.classById.get(targetMember.classId)?.name ?? targetMember.classId;
|
|
103141
|
+
const valueClassName2 = this.classById.get(valueBindingMember.classId)?.name ?? valueBindingMember.classId;
|
|
103142
|
+
throw new Error(
|
|
103143
|
+
`${args.label} targets "${boundChildName}.${targetEntry.schemaKey}" of class ${targetClassName}, but its segment plays ${valueClassName2} values.`
|
|
103144
|
+
);
|
|
103145
|
+
}
|
|
103146
|
+
if (isRequiredMember2(targetMember) && !isRequiredMember2(valueBindingMember)) {
|
|
103147
|
+
throw new Error(
|
|
103148
|
+
`${args.label} targets "${boundChildName}.${targetEntry.schemaKey}", which is required, but its segment plays nullable values.`
|
|
103149
|
+
);
|
|
103150
|
+
}
|
|
103151
|
+
if (animationTrackStorage(
|
|
103121
103152
|
[targetMember.id],
|
|
103153
|
+
this.memberById,
|
|
103122
103154
|
args.childStoragePath
|
|
103123
|
-
)) {
|
|
103155
|
+
) === null) {
|
|
103124
103156
|
throw new Error(
|
|
103125
103157
|
`${args.label} targets "${boundChildName}.${targetEntry.schemaKey}", which is not a writable Save, Session, or Writable override leaf.`
|
|
103126
103158
|
);
|
|
@@ -124540,7 +124572,7 @@ function lowerValueBody(context, member, expression, base, source, environment,
|
|
|
124540
124572
|
if (member.required) {
|
|
124541
124573
|
throw new Error(`Required member ${member.name} cannot store null.`);
|
|
124542
124574
|
}
|
|
124543
|
-
return
|
|
124575
|
+
return overlayLiteralValueContent(next, { value: null });
|
|
124544
124576
|
}
|
|
124545
124577
|
switch (member.kind) {
|
|
124546
124578
|
case "null":
|
|
@@ -127700,7 +127732,7 @@ function recordedStoredConstructorId(value, schemaClass2) {
|
|
|
127700
127732
|
}
|
|
127701
127733
|
function storedConstructorArgumentSource(context, type, value, environment, visited, cloneAggregateArguments = false, partial = false, constructorOwnsGraph = false) {
|
|
127702
127734
|
if (value === null) {
|
|
127703
|
-
if (!type.nullable) {
|
|
127735
|
+
if (!type.nullable && (type.kind !== "generic" || !storedGenericArgumentType(context, type, environment).nullable)) {
|
|
127704
127736
|
throw new Error("Required constructor argument stores null.");
|
|
127705
127737
|
}
|
|
127706
127738
|
return "null";
|
|
@@ -127790,26 +127822,10 @@ function storedConstructorArgumentSource(context, type, value, environment, visi
|
|
|
127790
127822
|
constructorOwnsGraph
|
|
127791
127823
|
);
|
|
127792
127824
|
}
|
|
127793
|
-
case "generic":
|
|
127794
|
-
const bindingId = environment.get(type.genericParamId);
|
|
127795
|
-
const inferredClassId = inferredGenericClassId(bindingId);
|
|
127796
|
-
const resolvedType = inferredClassId === null ? bindingId === void 0 ? null : schemaTypeForBindingMember(context, bindingId, environment) : {
|
|
127797
|
-
kind: "class",
|
|
127798
|
-
nullable: type.nullable,
|
|
127799
|
-
classId: inferredClassId,
|
|
127800
|
-
classArguments: {}
|
|
127801
|
-
};
|
|
127802
|
-
if (resolvedType === null) {
|
|
127803
|
-
throw new Error(
|
|
127804
|
-
`Stored Generic constructor argument cannot resolve parameter ${type.genericParamId}.`
|
|
127805
|
-
);
|
|
127806
|
-
}
|
|
127825
|
+
case "generic":
|
|
127807
127826
|
return storedConstructorArgumentSource(
|
|
127808
127827
|
context,
|
|
127809
|
-
|
|
127810
|
-
resolvedType,
|
|
127811
|
-
type.nullable || resolvedType.nullable
|
|
127812
|
-
),
|
|
127828
|
+
storedGenericArgumentType(context, type, environment),
|
|
127813
127829
|
value,
|
|
127814
127830
|
environment,
|
|
127815
127831
|
visited,
|
|
@@ -127817,7 +127833,6 @@ function storedConstructorArgumentSource(context, type, value, environment, visi
|
|
|
127817
127833
|
partial,
|
|
127818
127834
|
constructorOwnsGraph
|
|
127819
127835
|
);
|
|
127820
|
-
}
|
|
127821
127836
|
case "interface":
|
|
127822
127837
|
case "list":
|
|
127823
127838
|
case "dictionary":
|
|
@@ -127868,6 +127883,25 @@ function storedConstructorArgumentSource(context, type, value, environment, visi
|
|
|
127868
127883
|
);
|
|
127869
127884
|
}
|
|
127870
127885
|
}
|
|
127886
|
+
function storedGenericArgumentType(context, type, environment) {
|
|
127887
|
+
const bindingId = environment.get(type.genericParamId);
|
|
127888
|
+
const inferredClassId = inferredGenericClassId(bindingId);
|
|
127889
|
+
const resolvedType = inferredClassId === null ? bindingId === void 0 ? null : schemaTypeForBindingMember(context, bindingId, environment) : {
|
|
127890
|
+
kind: "class",
|
|
127891
|
+
nullable: type.nullable,
|
|
127892
|
+
classId: inferredClassId,
|
|
127893
|
+
classArguments: {}
|
|
127894
|
+
};
|
|
127895
|
+
if (resolvedType === null) {
|
|
127896
|
+
throw new Error(
|
|
127897
|
+
`Stored Generic constructor argument cannot resolve parameter ${type.genericParamId}.`
|
|
127898
|
+
);
|
|
127899
|
+
}
|
|
127900
|
+
return withSchemaTypeNullability(
|
|
127901
|
+
resolvedType,
|
|
127902
|
+
type.nullable || resolvedType.nullable
|
|
127903
|
+
);
|
|
127904
|
+
}
|
|
127871
127905
|
function schemaTypeForBindingMember(context, memberId, environment, visited = /* @__PURE__ */ new Set()) {
|
|
127872
127906
|
if (visited.has(memberId)) {
|
|
127873
127907
|
throw new Error(
|
|
@@ -128033,6 +128067,10 @@ function storedAggregateReplaySource(context, type, valueId, environment, constr
|
|
|
128033
128067
|
function isSharedConstructorArgument(context, valueId, constructorOwnsGraph) {
|
|
128034
128068
|
return !constructorOwnsGraph && context.readMaterializedGraph().independentlyOwnedValueIds.has(valueId);
|
|
128035
128069
|
}
|
|
128070
|
+
function storedTypeArgumentName(context, type, environment) {
|
|
128071
|
+
const settled = type.kind === "generic" ? storedGenericArgumentType(context, type, environment) : type;
|
|
128072
|
+
return `${storedSchemaTypeName(context, settled, environment)}${settled.nullable ? "?" : ""}`;
|
|
128073
|
+
}
|
|
128036
128074
|
function storedSchemaTypeName(context, type, environment, valueId) {
|
|
128037
128075
|
switch (type.kind) {
|
|
128038
128076
|
case "unknown":
|
|
@@ -128045,7 +128083,7 @@ function storedSchemaTypeName(context, type, environment, valueId) {
|
|
|
128045
128083
|
const argumentsValue = schemaClass2.genericParameters.flatMap(
|
|
128046
128084
|
(parameter4) => {
|
|
128047
128085
|
const argument2 = type.classArguments[parameter4.id];
|
|
128048
|
-
return argument2 === void 0 ? [] : [
|
|
128086
|
+
return argument2 === void 0 ? [] : [storedTypeArgumentName(context, argument2, environment)];
|
|
128049
128087
|
}
|
|
128050
128088
|
);
|
|
128051
128089
|
return `${schemaClass2.name}${argumentsValue.length === 0 ? "" : `<${argumentsValue.join(", ")}>`}`;
|
|
@@ -128073,10 +128111,10 @@ function storedSchemaTypeName(context, type, environment, valueId) {
|
|
|
128073
128111
|
return manifestMemberTypeName(context, member);
|
|
128074
128112
|
}
|
|
128075
128113
|
case "list":
|
|
128076
|
-
return `List<${
|
|
128114
|
+
return `List<${storedTypeArgumentName(context, type.entryType, environment)}>`;
|
|
128077
128115
|
case "dictionary": {
|
|
128078
128116
|
const keyType = type.keyEnumId === null ? "string" : stringField3(context.enums.get(type.keyEnumId) ?? {}, "name");
|
|
128079
|
-
return `Dictionary<${keyType}, ${
|
|
128117
|
+
return `Dictionary<${keyType}, ${storedTypeArgumentName(context, type.entryType, environment)}>`;
|
|
128080
128118
|
}
|
|
128081
128119
|
case "bool":
|
|
128082
128120
|
case "int":
|
|
@@ -128293,10 +128331,13 @@ function classValueTypeName(context, classId, member, environment) {
|
|
|
128293
128331
|
`Stored Class member ${String(member.name ?? member.id)} has no concrete ${parameter4.name} binding.`
|
|
128294
128332
|
);
|
|
128295
128333
|
}
|
|
128296
|
-
return
|
|
128334
|
+
return typeArgumentName(context, bindingMember);
|
|
128297
128335
|
});
|
|
128298
128336
|
return `${name}<${argumentsValue.join(", ")}>`;
|
|
128299
128337
|
}
|
|
128338
|
+
function typeArgumentName(context, member) {
|
|
128339
|
+
return `${manifestMemberTypeName(context, member)}${member.required ? "" : "?"}`;
|
|
128340
|
+
}
|
|
128300
128341
|
function manifestMemberTypeName(context, member) {
|
|
128301
128342
|
if (member.kind === "class") {
|
|
128302
128343
|
const schemaClass2 = context.manifestClasses.get(member.classId);
|
|
@@ -128317,7 +128358,7 @@ function manifestMemberTypeName(context, member) {
|
|
|
128317
128358
|
`Stored generic binding ${binding.memberId} was not pulled.`
|
|
128318
128359
|
);
|
|
128319
128360
|
}
|
|
128320
|
-
return
|
|
128361
|
+
return typeArgumentName(context, argument2);
|
|
128321
128362
|
});
|
|
128322
128363
|
return `${schemaClass2.name}<${argumentsValue.join(", ")}>`;
|
|
128323
128364
|
}
|
|
@@ -156165,7 +156206,7 @@ There is no --keep-current: preserving current semantic state defines flatten.
|
|
|
156165
156206
|
async function main() {
|
|
156166
156207
|
const args = parseArgs(process.argv.slice(2));
|
|
156167
156208
|
if (args.command === "--version") {
|
|
156168
|
-
console.log("0.
|
|
156209
|
+
console.log("0.65.1");
|
|
156169
156210
|
return;
|
|
156170
156211
|
}
|
|
156171
156212
|
if (args.command === null || args.command === "help" || args.command === "--help" || args.command === "-h") {
|
package/dist/test-worker.mjs
CHANGED
|
@@ -6058,6 +6058,14 @@ var WORLD_SYSTEM_CLASS_DEFINITIONS = [
|
|
|
6058
6058
|
docsText: "When false, this object and its children are neither rendered nor collided with. The value stays live: member writes still apply and a running animation clip keeps playing. Disabling an object hides its whole subtree regardless of each child's own value, and re-enabling it restores exactly what was there.",
|
|
6059
6059
|
requirement: 1 /* Required */,
|
|
6060
6060
|
schemaKey: "Enabled"
|
|
6061
|
+
},
|
|
6062
|
+
{
|
|
6063
|
+
memberId: "system_a0083c92-72f7-405f-8863-ff86f995d36d",
|
|
6064
|
+
memberKind: "class",
|
|
6065
|
+
defaultValue: null,
|
|
6066
|
+
docsText: "The object's box collider, or null for none. Any world object can carry one: placed objects, nested children, and sprites alike.",
|
|
6067
|
+
schemaClassWorldKind: "objectCollider",
|
|
6068
|
+
schemaKey: "Collider"
|
|
6061
6069
|
}
|
|
6062
6070
|
],
|
|
6063
6071
|
worldKind: "objectBase"
|
|
@@ -6267,13 +6275,6 @@ var WORLD_SYSTEM_CLASS_DEFINITIONS = [
|
|
|
6267
6275
|
requirement: 1 /* Required */,
|
|
6268
6276
|
schemaKey: "Children"
|
|
6269
6277
|
},
|
|
6270
|
-
{
|
|
6271
|
-
memberId: "system_a0083c92-72f7-405f-8863-ff86f995d36d",
|
|
6272
|
-
memberKind: "class",
|
|
6273
|
-
defaultValue: null,
|
|
6274
|
-
schemaClassWorldKind: "objectCollider",
|
|
6275
|
-
schemaKey: "Collider"
|
|
6276
|
-
},
|
|
6277
6278
|
{
|
|
6278
6279
|
memberId: "system_c609fed3-53e4-5147-b493-e4aa23031d79",
|
|
6279
6280
|
memberKind: "computed",
|
|
@@ -18651,7 +18652,7 @@ function runtimeTypeCheck(value, checkType, ctx, seenCollections = /* @__PURE__
|
|
|
18651
18652
|
function runtimeValueMatchesType(value, typeInfo, ctx, seenCollections = /* @__PURE__ */ new Set()) {
|
|
18652
18653
|
if (typeInfo.type === NS_TYPE_UNKNOWN) return true;
|
|
18653
18654
|
if (value === null || value === void 0) {
|
|
18654
|
-
return typeInfo.type === 0 /* Null */ || !typeInfo.required;
|
|
18655
|
+
return typeInfo.type === 0 /* Null */ || typeInfo.type === 21 /* Generic */ || !typeInfo.required;
|
|
18655
18656
|
}
|
|
18656
18657
|
return runtimeTypeCheck(value, typeInfo, ctx, seenCollections);
|
|
18657
18658
|
}
|
|
@@ -24779,7 +24780,7 @@ function resolveMemberDeclaredTypeInfoInternal(member, members, seen) {
|
|
|
24779
24780
|
members,
|
|
24780
24781
|
nextSeen
|
|
24781
24782
|
);
|
|
24782
|
-
return argumentType === null ? [] : [[genericParamId,
|
|
24783
|
+
return argumentType === null ? [] : [[genericParamId, argumentType]];
|
|
24783
24784
|
}
|
|
24784
24785
|
)
|
|
24785
24786
|
);
|
|
@@ -35277,7 +35278,12 @@ var StrictNeoScriptResolver = class {
|
|
|
35277
35278
|
};
|
|
35278
35279
|
});
|
|
35279
35280
|
fields.push(
|
|
35280
|
-
...this.resolveCallSiteInitializerFields(
|
|
35281
|
+
...this.resolveCallSiteInitializerFields(
|
|
35282
|
+
schemaClass,
|
|
35283
|
+
targetType,
|
|
35284
|
+
expression,
|
|
35285
|
+
scope
|
|
35286
|
+
)
|
|
35281
35287
|
);
|
|
35282
35288
|
const schemaClassInfo = toWireType(targetType, this.project);
|
|
35283
35289
|
if (schemaClassInfo.type !== 7 /* Class */) {
|
|
@@ -35403,6 +35409,7 @@ var StrictNeoScriptResolver = class {
|
|
|
35403
35409
|
) : [];
|
|
35404
35410
|
const fields = this.resolveCallSiteInitializerFields(
|
|
35405
35411
|
schemaClass,
|
|
35412
|
+
targetType,
|
|
35406
35413
|
expression,
|
|
35407
35414
|
scope
|
|
35408
35415
|
);
|
|
@@ -35517,7 +35524,7 @@ var StrictNeoScriptResolver = class {
|
|
|
35517
35524
|
* the class's own schema exactly as a `classConstructor` field is, and
|
|
35518
35525
|
* applied after the body so an explicit assignment always wins.
|
|
35519
35526
|
*/
|
|
35520
|
-
resolveCallSiteInitializerFields(schemaClass, expression, scope) {
|
|
35527
|
+
resolveCallSiteInitializerFields(schemaClass, targetType, expression, scope) {
|
|
35521
35528
|
const entries = expression.initializer ?? [];
|
|
35522
35529
|
const seen = /* @__PURE__ */ new Set();
|
|
35523
35530
|
return entries.map((entry) => {
|
|
@@ -35562,10 +35569,15 @@ var StrictNeoScriptResolver = class {
|
|
|
35562
35569
|
entry.pos
|
|
35563
35570
|
);
|
|
35564
35571
|
}
|
|
35565
|
-
const
|
|
35566
|
-
|
|
35572
|
+
const memberType = substituteTypeParameters(
|
|
35573
|
+
member.type,
|
|
35574
|
+
targetType,
|
|
35575
|
+
schemaClass
|
|
35576
|
+
);
|
|
35577
|
+
const value = this.resolveExpression(entry.value, scope, memberType);
|
|
35578
|
+
if (!isNeoScriptTypeAssignable(value.type, memberType, this.project)) {
|
|
35567
35579
|
throw new CompileError(
|
|
35568
|
-
`Object initializer '${member.name}' expected ${this.describe(
|
|
35580
|
+
`Object initializer '${member.name}' expected ${this.describe(memberType)} but got ${this.describe(value.type)}.`,
|
|
35569
35581
|
entry.pos
|
|
35570
35582
|
);
|
|
35571
35583
|
}
|
|
@@ -40627,13 +40639,11 @@ function classArguments(member, context, seen, genericEnvironment) {
|
|
|
40627
40639
|
if (environmentEntry?.kind === "member") {
|
|
40628
40640
|
const argument3 = analyzerMemberById(context, environmentEntry.memberId);
|
|
40629
40641
|
return argument3 ? [
|
|
40630
|
-
|
|
40631
|
-
|
|
40632
|
-
|
|
40633
|
-
|
|
40634
|
-
|
|
40635
|
-
genericEnvironment
|
|
40636
|
-
)
|
|
40642
|
+
memberRuntimeType(
|
|
40643
|
+
argument3,
|
|
40644
|
+
context,
|
|
40645
|
+
new Set(seen),
|
|
40646
|
+
genericEnvironment
|
|
40637
40647
|
)
|
|
40638
40648
|
] : [];
|
|
40639
40649
|
}
|
|
@@ -40648,13 +40658,11 @@ function classArguments(member, context, seen, genericEnvironment) {
|
|
|
40648
40658
|
}
|
|
40649
40659
|
const argument2 = analyzerMemberById(context, binding.memberId);
|
|
40650
40660
|
return argument2 ? [
|
|
40651
|
-
|
|
40652
|
-
|
|
40653
|
-
|
|
40654
|
-
|
|
40655
|
-
|
|
40656
|
-
genericEnvironment
|
|
40657
|
-
)
|
|
40661
|
+
memberRuntimeType(
|
|
40662
|
+
argument2,
|
|
40663
|
+
context,
|
|
40664
|
+
new Set(seen),
|
|
40665
|
+
genericEnvironment
|
|
40658
40666
|
)
|
|
40659
40667
|
] : [];
|
|
40660
40668
|
});
|
|
@@ -40841,11 +40849,7 @@ function genericConstraintLanguageType(constraint, context, genericEnvironment,
|
|
|
40841
40849
|
];
|
|
40842
40850
|
}
|
|
40843
40851
|
const member = analyzerMemberById(context, binding.memberId);
|
|
40844
|
-
return member ? [
|
|
40845
|
-
requiredType(
|
|
40846
|
-
memberRuntimeType(member, context, /* @__PURE__ */ new Set(), genericEnvironment)
|
|
40847
|
-
)
|
|
40848
|
-
] : [];
|
|
40852
|
+
return member ? [memberRuntimeType(member, context, /* @__PURE__ */ new Set(), genericEnvironment)] : [];
|
|
40849
40853
|
});
|
|
40850
40854
|
return {
|
|
40851
40855
|
kind: "named",
|
package/package.json
CHANGED
|
@@ -388,6 +388,37 @@ frame after a watched dependency changes.
|
|
|
388
388
|
When multiple tracks write the same member in one frame, apply list order and
|
|
389
389
|
let the last write win.
|
|
390
390
|
|
|
391
|
+
A track can target a Class member. Each frame writes its whole value, and a
|
|
392
|
+
`null` frame clears the member. Every `NeoObjectBase`, sprites included,
|
|
393
|
+
declares `Collider`, so a per-frame trigger such as an attack hit box is a
|
|
394
|
+
Session `Collider` override on the child plus a track of `NeoCollider?`
|
|
395
|
+
frames:
|
|
396
|
+
|
|
397
|
+
```neo
|
|
398
|
+
class ColliderAnimationSegment : NeoAnimationSegment<NeoCollider?> {
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
@settings(target: NeoObjectBase.Collider)
|
|
402
|
+
class SwingColliderTrack(NeoDelegate<SwordSprite> selector)
|
|
403
|
+
: NeoAnimationSegmentTrack<SwordSprite, NeoCollider?>(selector: selector) {
|
|
404
|
+
public override ColliderAnimationSegment Segment = new ColliderAnimationSegment() {
|
|
405
|
+
Duration = 3,
|
|
406
|
+
Frames = [
|
|
407
|
+
new NeoAnimationSegmentFrame<NeoCollider?>(value: new NeoCollider() {
|
|
408
|
+
Size = new(1, 1),
|
|
409
|
+
Offset = new(1, 1),
|
|
410
|
+
IsTrigger = true
|
|
411
|
+
}) { Index = 1 },
|
|
412
|
+
new NeoAnimationSegmentFrame<NeoCollider?>(value: null) { Index = 2 }
|
|
413
|
+
]
|
|
414
|
+
};
|
|
415
|
+
}
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
The segment's class must fit the target member's class. Like any track target,
|
|
419
|
+
the member must be a writable Save, Session, or Writable leaf on the child, for
|
|
420
|
+
example `@storage(allowed: .Session) public override NeoCollider? Collider;`.
|
|
421
|
+
|
|
391
422
|
## NeoFlow dialogues
|
|
392
423
|
|
|
393
424
|
Lookup dialogue groups use the same collection paths as lookup members:
|
|
@@ -110,7 +110,7 @@ wrappers.
|
|
|
110
110
|
The marker near the top of `SKILL.md` must exactly match the package version:
|
|
111
111
|
|
|
112
112
|
```html
|
|
113
|
-
<!-- reviewed-through-cli: 0.
|
|
113
|
+
<!-- reviewed-through-cli: 0.65.1 -->
|
|
114
114
|
```
|
|
115
115
|
|
|
116
116
|
The quoted version above is checked too, so this instruction cannot go stale
|