@helixdev/helix-manifest 0.2.1-staging.8 → 0.3.0-staging.11
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/README.md +3 -3
- package/dist/schema/manifest-v0.3.schema.json +386 -0
- package/dist/src/index.d.ts +432 -5
- package/dist/src/index.js +2153 -5
- package/dist/src/index.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/schema/manifest-v0.3.schema.json +386 -0
package/dist/src/index.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
export * from './bundle-rules';
|
|
2
2
|
export declare const MANIFEST_FILENAME = "helix.json";
|
|
3
|
-
export declare const MANIFEST_VERSIONS: readonly ["0.1", "0.2"];
|
|
3
|
+
export declare const MANIFEST_VERSIONS: readonly ["0.1", "0.2", "0.3"];
|
|
4
4
|
export declare const PERMISSIONS_V01: readonly ["auth.profile"];
|
|
5
|
-
export
|
|
5
|
+
export declare const PERMISSIONS_V03: readonly ["auth.profile", "multiplayer", "voice.room", "voice.proximity"];
|
|
6
|
+
export type HelixPermission = (typeof PERMISSIONS_V03)[number];
|
|
6
7
|
/**
|
|
7
8
|
* Bundle vocabulary, pinned for main-backend compatibility. A **system** is a
|
|
8
9
|
* versioned runtime framework that hosts abilities (the humanoid character is
|
|
@@ -21,18 +22,375 @@ export type HelixBundleKind = (typeof BUNDLE_KINDS)[number];
|
|
|
21
22
|
*/
|
|
22
23
|
export declare const MAIN_BACKEND_PACKAGE_TYPE: Record<HelixBundleKind, string>;
|
|
23
24
|
export type HelixContentRating = 'unrated' | 'everyone' | 'teen' | 'mature';
|
|
25
|
+
/**
|
|
26
|
+
* A declared custom-state variable's type + constraints (Tier 2 declared state — spec §5). The author
|
|
27
|
+
* declares names -> HelixVarType under `multiplayer.state`; the room realizes them as @colyseus/schema and
|
|
28
|
+
* interprets them. Value vocabulary: number | string | boolean | vec3 | ref (the id of a live player/entity).
|
|
29
|
+
* This is the DECLARATION home; the runtime value union (RoomVarValue) lives in the SDK multiplayer-contract.
|
|
30
|
+
*/
|
|
31
|
+
export type HelixVarType = {
|
|
32
|
+
type: 'number';
|
|
33
|
+
default: number;
|
|
34
|
+
min?: number;
|
|
35
|
+
max?: number;
|
|
36
|
+
integer?: boolean;
|
|
37
|
+
} | {
|
|
38
|
+
type: 'string';
|
|
39
|
+
default: string;
|
|
40
|
+
maxLen?: number;
|
|
41
|
+
enum?: string[];
|
|
42
|
+
} | {
|
|
43
|
+
type: 'boolean';
|
|
44
|
+
default: boolean;
|
|
45
|
+
} | {
|
|
46
|
+
type: 'vec3';
|
|
47
|
+
default: [number, number, number];
|
|
48
|
+
} | {
|
|
49
|
+
type: 'ref';
|
|
50
|
+
of: 'player' | `entity:${string}`;
|
|
51
|
+
default?: null;
|
|
52
|
+
} | {
|
|
53
|
+
type: 'list';
|
|
54
|
+
of: 'number' | 'string' | 'boolean';
|
|
55
|
+
maxLen: number;
|
|
56
|
+
} | {
|
|
57
|
+
type: 'counterMap';
|
|
58
|
+
keys: string[];
|
|
59
|
+
};
|
|
60
|
+
/** A declared bag of custom vars: name -> type. Names are identifiers (see the v0.3 schema pattern). */
|
|
61
|
+
export type HelixVarDecls = Record<string, HelixVarType>;
|
|
62
|
+
/** v0.3 (Tier 2 Phase 1.3): the per-world DECLARED state — room-level + per-player custom vars. */
|
|
63
|
+
export type HelixMultiplayerState = {
|
|
64
|
+
roomVars?: HelixVarDecls;
|
|
65
|
+
playerVars?: HelixVarDecls;
|
|
66
|
+
};
|
|
67
|
+
export type HelixRuleEvent = {
|
|
68
|
+
on: 'tick';
|
|
69
|
+
everyN?: number;
|
|
70
|
+
} | {
|
|
71
|
+
on: 'playerJoin';
|
|
72
|
+
} | {
|
|
73
|
+
on: 'playerLeave';
|
|
74
|
+
} | {
|
|
75
|
+
on: 'playerDisconnect' | 'playerReconnect';
|
|
76
|
+
} | {
|
|
77
|
+
on: 'zoneEnter' | 'zoneExit' | 'zoneInside';
|
|
78
|
+
zone: string;
|
|
79
|
+
} | {
|
|
80
|
+
on: 'playerContact';
|
|
81
|
+
radius: number;
|
|
82
|
+
} | {
|
|
83
|
+
on: 'action';
|
|
84
|
+
name: string;
|
|
85
|
+
} | {
|
|
86
|
+
on: 'stateEnter' | 'stateExit';
|
|
87
|
+
phase: string;
|
|
88
|
+
} | {
|
|
89
|
+
on: 'timerElapsed';
|
|
90
|
+
timer: string;
|
|
91
|
+
} | {
|
|
92
|
+
on: 'entitySpawn' | 'entityDestroy';
|
|
93
|
+
kind: string;
|
|
94
|
+
} | {
|
|
95
|
+
on: 'ownershipChanged';
|
|
96
|
+
kind: string;
|
|
97
|
+
} | {
|
|
98
|
+
on: 'varReached';
|
|
99
|
+
scope: 'room' | 'self';
|
|
100
|
+
var: string;
|
|
101
|
+
cmp: '==' | '!=' | '<' | '<=' | '>' | '>=';
|
|
102
|
+
value: number | string | boolean;
|
|
103
|
+
};
|
|
104
|
+
export type HelixExpr = number | string | boolean | {
|
|
105
|
+
vec3: [number, number, number];
|
|
106
|
+
} | {
|
|
107
|
+
var: string;
|
|
108
|
+
} | {
|
|
109
|
+
ref: HelixRef;
|
|
110
|
+
var: string;
|
|
111
|
+
} | {
|
|
112
|
+
op: 'distance';
|
|
113
|
+
a: HelixExpr;
|
|
114
|
+
b: HelixExpr;
|
|
115
|
+
} | {
|
|
116
|
+
op: '==' | '!=' | '<' | '<=' | '>' | '>=';
|
|
117
|
+
a: HelixExpr;
|
|
118
|
+
b: HelixExpr;
|
|
119
|
+
} | {
|
|
120
|
+
op: '+' | '-' | '*' | '/';
|
|
121
|
+
a: HelixExpr;
|
|
122
|
+
b: HelixExpr;
|
|
123
|
+
} | {
|
|
124
|
+
op: 'and' | 'or';
|
|
125
|
+
of: HelixExpr[];
|
|
126
|
+
} | {
|
|
127
|
+
op: 'not';
|
|
128
|
+
of: HelixExpr;
|
|
129
|
+
} | {
|
|
130
|
+
op: 'aggregate';
|
|
131
|
+
scope: 'players' | `zone:${string}` | `entities:${string}`;
|
|
132
|
+
agg: 'count' | 'sum' | 'min' | 'max' | 'avg';
|
|
133
|
+
field?: string;
|
|
134
|
+
where?: HelixExpr;
|
|
135
|
+
as?: string;
|
|
136
|
+
} | {
|
|
137
|
+
op: 'timerRemaining';
|
|
138
|
+
timer: string;
|
|
139
|
+
key?: HelixRef;
|
|
140
|
+
} | {
|
|
141
|
+
op: 'listLength';
|
|
142
|
+
list: string;
|
|
143
|
+
} | {
|
|
144
|
+
op: 'listAt';
|
|
145
|
+
list: string;
|
|
146
|
+
index: HelixExpr;
|
|
147
|
+
} | {
|
|
148
|
+
op: 'count';
|
|
149
|
+
map: string;
|
|
150
|
+
key: string;
|
|
151
|
+
} | {
|
|
152
|
+
op: 'randomPoint';
|
|
153
|
+
min: [number, number, number];
|
|
154
|
+
max: [number, number, number];
|
|
155
|
+
} | {
|
|
156
|
+
op: 'playerCount' | 'random' | 'timeInState';
|
|
157
|
+
};
|
|
158
|
+
export type HelixRef = string | {
|
|
159
|
+
var: string;
|
|
160
|
+
} | {
|
|
161
|
+
op: 'nearestPlayer';
|
|
162
|
+
from: HelixExpr;
|
|
163
|
+
} | {
|
|
164
|
+
op: 'nearestEntity';
|
|
165
|
+
from: HelixExpr;
|
|
166
|
+
kind?: string;
|
|
167
|
+
} | {
|
|
168
|
+
op: 'aggregate';
|
|
169
|
+
scope: 'players' | `zone:${string}` | `entities:${string}`;
|
|
170
|
+
agg: 'argmax' | 'argmin';
|
|
171
|
+
field: string;
|
|
172
|
+
where?: HelixExpr;
|
|
173
|
+
as?: string;
|
|
174
|
+
};
|
|
175
|
+
export type HelixLvalue = string | {
|
|
176
|
+
ref: HelixRef;
|
|
177
|
+
var: string;
|
|
178
|
+
};
|
|
179
|
+
export type HelixBroadcastTarget = 'all' | HelixRef | {
|
|
180
|
+
team: string;
|
|
181
|
+
};
|
|
182
|
+
export type HelixRuleEffect = {
|
|
183
|
+
do: 'add';
|
|
184
|
+
target: HelixLvalue;
|
|
185
|
+
by: HelixExpr;
|
|
186
|
+
} | {
|
|
187
|
+
do: 'set';
|
|
188
|
+
target: HelixLvalue;
|
|
189
|
+
to: HelixExpr;
|
|
190
|
+
} | {
|
|
191
|
+
do: 'setRef';
|
|
192
|
+
target: HelixLvalue;
|
|
193
|
+
to: HelixRef | null;
|
|
194
|
+
} | {
|
|
195
|
+
do: 'teleport' | 'respawn';
|
|
196
|
+
player: HelixRef;
|
|
197
|
+
to: HelixExpr;
|
|
198
|
+
} | {
|
|
199
|
+
do: 'forEachPlayer';
|
|
200
|
+
as: string;
|
|
201
|
+
where?: HelixExpr;
|
|
202
|
+
then: HelixRuleEffect[];
|
|
203
|
+
} | {
|
|
204
|
+
do: 'forEachEntity';
|
|
205
|
+
kind: string;
|
|
206
|
+
as: string;
|
|
207
|
+
where?: HelixExpr;
|
|
208
|
+
then: HelixRuleEffect[];
|
|
209
|
+
} | {
|
|
210
|
+
do: 'transitionTo';
|
|
211
|
+
phase: string;
|
|
212
|
+
} | {
|
|
213
|
+
do: 'startTimer';
|
|
214
|
+
timer: string;
|
|
215
|
+
seconds: number;
|
|
216
|
+
key?: HelixRef;
|
|
217
|
+
} | {
|
|
218
|
+
do: 'cancelTimer';
|
|
219
|
+
timer: string;
|
|
220
|
+
key?: HelixRef;
|
|
221
|
+
} | {
|
|
222
|
+
do: 'broadcast';
|
|
223
|
+
event: string;
|
|
224
|
+
to: HelixBroadcastTarget;
|
|
225
|
+
payload?: Record<string, HelixExpr | HelixRef>;
|
|
226
|
+
} | {
|
|
227
|
+
do: 'spawnEntity';
|
|
228
|
+
kind: string;
|
|
229
|
+
at: HelixExpr;
|
|
230
|
+
vars?: Record<string, HelixExpr | HelixRef>;
|
|
231
|
+
bind?: 'spawned';
|
|
232
|
+
} | {
|
|
233
|
+
do: 'destroyEntity';
|
|
234
|
+
entity: HelixRef;
|
|
235
|
+
} | {
|
|
236
|
+
do: 'requestOwnership' | 'takeover';
|
|
237
|
+
entity: HelixRef;
|
|
238
|
+
to: HelixRef | null;
|
|
239
|
+
} | {
|
|
240
|
+
do: 'append';
|
|
241
|
+
target: string;
|
|
242
|
+
value: HelixExpr;
|
|
243
|
+
} | {
|
|
244
|
+
do: 'clear';
|
|
245
|
+
target: string;
|
|
246
|
+
} | {
|
|
247
|
+
do: 'addCount';
|
|
248
|
+
target: string;
|
|
249
|
+
key: string;
|
|
250
|
+
by: HelixExpr;
|
|
251
|
+
};
|
|
252
|
+
export type HelixRule = {
|
|
253
|
+
when: HelixRuleEvent;
|
|
254
|
+
if?: HelixExpr;
|
|
255
|
+
then: HelixRuleEffect[];
|
|
256
|
+
};
|
|
257
|
+
export type HelixStateMachine = {
|
|
258
|
+
initial: string;
|
|
259
|
+
phases: string[];
|
|
260
|
+
joinPolicy?: Record<string, {
|
|
261
|
+
joinable?: boolean;
|
|
262
|
+
onLateJoin?: HelixRuleEffect[];
|
|
263
|
+
}>;
|
|
264
|
+
};
|
|
265
|
+
export type HelixTimer = {
|
|
266
|
+
keyed?: 'player' | `entity:${string}`;
|
|
267
|
+
};
|
|
268
|
+
export type HelixFieldType = {
|
|
269
|
+
type: HelixVarType['type'];
|
|
270
|
+
of?: 'player' | `entity:${string}`;
|
|
271
|
+
};
|
|
272
|
+
export type HelixEventDecl = {
|
|
273
|
+
payload?: Record<string, HelixFieldType>;
|
|
274
|
+
};
|
|
275
|
+
export type HelixActionArgType = {
|
|
276
|
+
type: 'number';
|
|
277
|
+
min?: number;
|
|
278
|
+
max?: number;
|
|
279
|
+
integer?: boolean;
|
|
280
|
+
} | {
|
|
281
|
+
type: 'string';
|
|
282
|
+
maxLen?: number;
|
|
283
|
+
enum?: string[];
|
|
284
|
+
} | {
|
|
285
|
+
type: 'boolean';
|
|
286
|
+
} | {
|
|
287
|
+
type: 'vec3';
|
|
288
|
+
} | {
|
|
289
|
+
type: 'ref';
|
|
290
|
+
of: 'player' | `entity:${string}`;
|
|
291
|
+
};
|
|
292
|
+
export type HelixActionDecl = {
|
|
293
|
+
args?: Record<string, HelixActionArgType>;
|
|
294
|
+
};
|
|
295
|
+
export type HelixZone = {
|
|
296
|
+
id: string;
|
|
297
|
+
tracks?: 'players' | `entity:${string}`;
|
|
298
|
+
requireDwell?: number;
|
|
299
|
+
debounce?: number;
|
|
300
|
+
} & ({
|
|
301
|
+
shape: 'box';
|
|
302
|
+
center: [number, number, number];
|
|
303
|
+
size: [number, number, number];
|
|
304
|
+
} | {
|
|
305
|
+
shape: 'sphere';
|
|
306
|
+
center: [number, number, number];
|
|
307
|
+
radius: number;
|
|
308
|
+
});
|
|
309
|
+
export type HelixEntityMotion = {
|
|
310
|
+
type: 'static';
|
|
311
|
+
} | {
|
|
312
|
+
type: 'linear';
|
|
313
|
+
velocity: [number, number, number];
|
|
314
|
+
} | {
|
|
315
|
+
type: 'orbit';
|
|
316
|
+
center: [number, number, number];
|
|
317
|
+
radius: number;
|
|
318
|
+
speed: number;
|
|
319
|
+
} | {
|
|
320
|
+
type: 'waypoints';
|
|
321
|
+
points: [number, number, number][];
|
|
322
|
+
speed: number;
|
|
323
|
+
loop?: boolean;
|
|
324
|
+
} | {
|
|
325
|
+
type: 'seek';
|
|
326
|
+
target: string;
|
|
327
|
+
speed: number;
|
|
328
|
+
};
|
|
329
|
+
export type HelixAttachedZone = {
|
|
330
|
+
offset?: [number, number, number];
|
|
331
|
+
tracks?: 'players' | `entity:${string}`;
|
|
332
|
+
requireDwell?: number;
|
|
333
|
+
debounce?: number;
|
|
334
|
+
} & ({
|
|
335
|
+
shape: 'box';
|
|
336
|
+
size: [number, number, number];
|
|
337
|
+
} | {
|
|
338
|
+
shape: 'sphere';
|
|
339
|
+
radius: number;
|
|
340
|
+
});
|
|
341
|
+
export type HelixEntity = {
|
|
342
|
+
vars?: HelixVarDecls;
|
|
343
|
+
motion?: HelixEntityMotion;
|
|
344
|
+
zone?: HelixAttachedZone;
|
|
345
|
+
authority?: 'server' | 'owner';
|
|
346
|
+
maxSpeed?: number;
|
|
347
|
+
shared?: boolean;
|
|
348
|
+
idleTimeout?: number;
|
|
349
|
+
ownerLifecycle?: 'despawnWithOwner' | 'persist' | 'migrateToServer' | 'hostMigrate';
|
|
350
|
+
transferPolicy?: 'fixed' | 'request' | 'takeover';
|
|
351
|
+
};
|
|
352
|
+
export type HelixMultiplayerConfig = {
|
|
353
|
+
/** Advisory interest radius in meters (drives later StateView interest management; may be ignored in v1). */
|
|
354
|
+
interestRadius?: number;
|
|
355
|
+
/**
|
|
356
|
+
* Minimum players the world needs to be playable (Tier 2 Phase 4.5, spec §14). Default 1 = single-player-safe:
|
|
357
|
+
* the single-player gate then warns (strict → error) if a phase transition is gated on playerCount ≥ 2, since a
|
|
358
|
+
* solo player would be soft-locked. Set ≥ 2 to declare a genuinely multiplayer-only world (the gate stands down).
|
|
359
|
+
*/
|
|
360
|
+
minPlayers?: number;
|
|
361
|
+
/** Server owns authoritative state + validates inputs (Tier 1). Defaulted to true; leave it true in v1. */
|
|
362
|
+
authoritative?: boolean;
|
|
363
|
+
/** Declared per-world custom state (roomVars + per-player vars); the room realizes + interprets it. */
|
|
364
|
+
state?: HelixMultiplayerState;
|
|
365
|
+
/** Declared entity archetypes (Tier 2 Phase 4, spec §9): kind name -> { vars }. spawnEntity/destroyEntity reference them; the room realizes per-kind schema + syncs the entities collection. */
|
|
366
|
+
entities?: Record<string, HelixEntity>;
|
|
367
|
+
/** Declared room-scoped state machine (Tier 2 Phase 3, spec §8): the phase set + the initial phase. */
|
|
368
|
+
states?: HelixStateMachine;
|
|
369
|
+
/** Declared timers (Tier 2 Phase 3, spec §8): name -> {}. startTimer/cancelTimer/timerElapsed/timerRemaining reference them. */
|
|
370
|
+
timers?: Record<string, HelixTimer>;
|
|
371
|
+
/** Declared static spatial zones (Tier 2 Phase 2.3, spec §6) — the room tests membership each tick. */
|
|
372
|
+
zones?: HelixZone[];
|
|
373
|
+
/** Declared server→client broadcast events (Tier 2 Phase 2.5, spec §10.3): name -> payload schema. */
|
|
374
|
+
events?: Record<string, HelixEventDecl>;
|
|
375
|
+
/** Declared client→server actions (Tier 2 Phase 2.5b, spec §11.5): name -> { typed arg schema }. */
|
|
376
|
+
actions?: Record<string, HelixActionDecl>;
|
|
377
|
+
/** Declared behavior rules (Tier 2 Phase 2, spec §7) — the room evaluates them in declared order per tick. */
|
|
378
|
+
rules?: HelixRule[];
|
|
379
|
+
};
|
|
24
380
|
/**
|
|
25
381
|
* contentRating → main-backend ContentRating. 'unrated' has no counterpart there (their enum is
|
|
26
382
|
* Everyone/Teen/Mature) — an unrated bundle cannot federate into the catalog until it is rated.
|
|
27
383
|
*/
|
|
28
384
|
export declare const MAIN_BACKEND_CONTENT_RATING: Record<HelixContentRating, 'Everyone' | 'Teen' | 'Mature' | null>;
|
|
29
385
|
export type HelixManifest = {
|
|
30
|
-
helixVersion: '0.1' | '0.2';
|
|
386
|
+
helixVersion: '0.1' | '0.2' | '0.3';
|
|
31
387
|
title: string;
|
|
32
388
|
slug: string;
|
|
33
389
|
entry: string;
|
|
34
390
|
maxPlayers?: number;
|
|
35
391
|
permissions?: HelixPermission[];
|
|
392
|
+
/** v0.3: present only on multiplayer worlds. */
|
|
393
|
+
multiplayer?: HelixMultiplayerConfig;
|
|
36
394
|
supportsMobile?: boolean;
|
|
37
395
|
requiresAuth?: boolean;
|
|
38
396
|
contentRating?: HelixContentRating;
|
|
@@ -45,15 +403,84 @@ export type HelixManifest = {
|
|
|
45
403
|
/** v0.2: pinned ability dependencies (slug -> semver range), resolved + baked at build. */
|
|
46
404
|
abilities?: Record<string, string>;
|
|
47
405
|
};
|
|
48
|
-
export type NormalizedHelixManifest = Required<Omit<HelixManifest, 'systems' | 'abilities'>> & Pick<HelixManifest, 'systems' | 'abilities'>;
|
|
406
|
+
export type NormalizedHelixManifest = Required<Omit<HelixManifest, 'systems' | 'abilities' | 'multiplayer'>> & Pick<HelixManifest, 'systems' | 'abilities' | 'multiplayer'>;
|
|
49
407
|
export type ManifestValidationResult = {
|
|
50
408
|
valid: true;
|
|
51
409
|
manifest: NormalizedHelixManifest;
|
|
410
|
+
warnings: string[];
|
|
52
411
|
} | {
|
|
53
412
|
valid: false;
|
|
54
413
|
errors: string[];
|
|
55
414
|
};
|
|
56
|
-
export declare
|
|
415
|
+
export declare const PLATFORM_MAX_PLAYERS_PER_ROOM = 24;
|
|
416
|
+
export declare const MULTIPLAYER_CAPS: {
|
|
417
|
+
/** Declared room-level vars. */
|
|
418
|
+
readonly roomVars: 64;
|
|
419
|
+
/** Declared per-player vars (these are realized once PER PLAYER at runtime, so the effective cost scales). */
|
|
420
|
+
readonly playerVars: 64;
|
|
421
|
+
/** Ceiling on a string var's declared `maxLen` (bounds a single synced string). */
|
|
422
|
+
readonly stringMaxLen: 1024;
|
|
423
|
+
/** Values in a string var's `enum`. */
|
|
424
|
+
readonly enumValues: 64;
|
|
425
|
+
/** Ceiling on a `list` collection var's declared `maxLen` (4.5.13 — bounds a single synced array). */
|
|
426
|
+
readonly listMaxLen: 256;
|
|
427
|
+
/** Keys in a `counterMap` collection var's declared key enum (4.5.13). */
|
|
428
|
+
readonly counterKeys: 64;
|
|
429
|
+
/** Declared behavior rules (Tier 2 Phase 2). */
|
|
430
|
+
readonly rules: 128;
|
|
431
|
+
/** Effects in a single rule's `then`. */
|
|
432
|
+
readonly ruleThen: 16;
|
|
433
|
+
/** Max nesting depth of a condition expression (`if`). */
|
|
434
|
+
readonly exprDepth: 8;
|
|
435
|
+
/** Max total nodes in a single condition expression. */
|
|
436
|
+
readonly exprNodes: 64;
|
|
437
|
+
/** Declared state-machine phases (Tier 2 Phase 3, spec §8). One room-scoped machine; this caps its phase set. */
|
|
438
|
+
readonly phases: 32;
|
|
439
|
+
/** Declared timers (Tier 2 Phase 3, spec §8). Each active timer (room-scoped, or × live members when keyed in
|
|
440
|
+
* 3.3) reifies a deadline into synced state — this caps the declared name count. */
|
|
441
|
+
readonly timers: 32;
|
|
442
|
+
/** Floor on a `startTimer` duration (seconds) = one sim tick (1/20s). A shorter timer can't resolve below the
|
|
443
|
+
* tick rate; rejecting it stops a 0s timer from same-tick start→elapse churn. MUST track the room's SIM_HZ. */
|
|
444
|
+
readonly timerMinSeconds: 0.05;
|
|
445
|
+
/** Effects in a single phase's `joinPolicy.onLateJoin` (Tier 2 Phase 3.5). Runs once per late join (≤ player
|
|
446
|
+
* cap/tick), so it's bounded like a playerJoin rule's `then`. */
|
|
447
|
+
readonly joinPolicyEffects: 16;
|
|
448
|
+
/** §3.6/§11.3 cascade-drain depth — the longest within-tick chain of stateEnter/stateExit → transitionTo →
|
|
449
|
+
* stateEnter… Computed statically at publish (a cycle is rejected outright); a config whose chain exceeds
|
|
450
|
+
* this fails publish. Bounds the ×(1+maxCascadeDepth) budget term + MUST stay ≤ the room's MAX_CASCADE_DEPTH
|
|
451
|
+
* runtime backstop (helix-colyseus-server src/tuning.ts). */
|
|
452
|
+
readonly maxCascadeDepth: 16;
|
|
453
|
+
/** Declared zones (Tier 2 Phase 2.3). Membership is O(members × zones)/tick, both capped. */
|
|
454
|
+
readonly zones: 64;
|
|
455
|
+
/** Declared broadcast events (Tier 2 Phase 2.5). */
|
|
456
|
+
readonly events: 64;
|
|
457
|
+
/** Fields in a single broadcast event's payload. */
|
|
458
|
+
readonly broadcastFields: 16;
|
|
459
|
+
/** Declared client→server actions (Tier 2 Phase 2.5b). */
|
|
460
|
+
readonly actions: 64;
|
|
461
|
+
/** Args in a single action's schema. */
|
|
462
|
+
readonly actionArgs: 16;
|
|
463
|
+
/** Declared entity archetypes (Tier 2 Phase 4, spec §9). */
|
|
464
|
+
readonly entityKinds: 32;
|
|
465
|
+
/** Max declared vars per entity kind (realized once PER live entity at runtime, so the effective cost scales). */
|
|
466
|
+
readonly entityVars: 64;
|
|
467
|
+
/** Max live entities of a single kind in a room — bounds the synced entities collection + per-tick entity work.
|
|
468
|
+
* Enforced at RUNTIME (a spawn over the cap is skipped + counted in the H3 metric, never throws). */
|
|
469
|
+
readonly entitiesPerKind: 256;
|
|
470
|
+
/** Ceiling on a zone's extent — any box dimension or a sphere radius, in meters. A sanity bound (a zone
|
|
471
|
+
* test is O(1) regardless of size), generous enough for whole-level kill-planes. */
|
|
472
|
+
readonly zoneMaxExtent: 10000;
|
|
473
|
+
/** §11.2 per-tick budget — the worst-case node-evaluations across ALL rules in one tick: Σ over rules of
|
|
474
|
+
* fireCount(event) × ruleCost, where reductions (aggregate/nearest*) + forEach fanout are weighted by the
|
|
475
|
+
* player cap and contact events by playerCap², all ×(1 + maxCascadeDepth) for the Phase-3 cascade drain
|
|
476
|
+
* (analyzeCascade computes the cycle-free longest chain). Over this → publish fails. PROVISIONAL: a generous
|
|
477
|
+
* bound that catches pathological configs; the precise number wants the S6 load test. */
|
|
478
|
+
readonly tickNodeBudget: 100000;
|
|
479
|
+
};
|
|
480
|
+
export declare const VAR_TYPES: readonly ["number", "string", "boolean", "vec3", "ref", "list", "counterMap"];
|
|
481
|
+
export declare function validateManifest(data: unknown, opts?: {
|
|
482
|
+
strict?: boolean;
|
|
483
|
+
}): ManifestValidationResult;
|
|
57
484
|
export declare function parseManifest(json: string): ManifestValidationResult;
|
|
58
485
|
export declare const PACKAGE_ENVELOPE_VERSION: "1";
|
|
59
486
|
export type HelixPackageEnvelope = {
|