@colyseus/schema 5.0.11 → 5.0.12
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/build/Metadata.d.ts +20 -12
- package/build/annotations.d.ts +23 -10
- package/build/codegen/cli.cjs +615 -204
- package/build/codegen/cli.cjs.map +1 -1
- package/build/codegen/languages/dart.d.ts +20 -0
- package/build/codegen/types.d.ts +20 -0
- package/build/decoder/Resync.d.ts +3 -3
- package/build/encoder/ChangeTree.d.ts +22 -9
- package/build/encoder/EncodeDescriptor.d.ts +11 -12
- package/build/encoder/StateView.d.ts +26 -2
- package/build/encoder/changeTree/inheritedFlags.d.ts +1 -1
- package/build/encoder/streaming.d.ts +7 -0
- package/build/index.cjs +374 -232
- package/build/index.cjs.map +1 -1
- package/build/index.d.ts +1 -1
- package/build/index.js +374 -232
- package/build/index.mjs +373 -231
- package/build/index.mjs.map +1 -1
- package/build/types/builder.d.ts +31 -22
- package/build/types/custom/StreamSchema.d.ts +1 -1
- package/build/types/symbols.d.ts +4 -10
- package/package.json +1 -1
- package/src/Metadata.ts +58 -31
- package/src/annotations.ts +56 -32
- package/src/codegen/api.ts +2 -1
- package/src/codegen/languages/c.ts +21 -3
- package/src/codegen/languages/csharp.ts +7 -1
- package/src/codegen/languages/dart.ts +274 -0
- package/src/codegen/languages/haxe.ts +7 -1
- package/src/codegen/languages/lua.ts +16 -4
- package/src/codegen/languages/ts.ts +5 -0
- package/src/codegen/parser.ts +97 -3
- package/src/codegen/types.ts +24 -0
- package/src/decoder/Resync.ts +8 -8
- package/src/encoder/ChangeRecorder.ts +1 -1
- package/src/encoder/ChangeTree.ts +41 -26
- package/src/encoder/EncodeDescriptor.ts +17 -38
- package/src/encoder/EncodeOperation.ts +3 -1
- package/src/encoder/Encoder.ts +97 -21
- package/src/encoder/Root.ts +18 -20
- package/src/encoder/StateView.ts +102 -12
- package/src/encoder/changeTree/inheritedFlags.ts +10 -10
- package/src/encoder/changeTree/liveIteration.ts +9 -9
- package/src/encoder/streaming.ts +8 -0
- package/src/encoding/spec.ts +1 -1
- package/src/index.ts +2 -2
- package/src/types/builder.ts +35 -31
- package/src/types/custom/StreamSchema.ts +1 -1
- package/src/types/symbols.ts +4 -11
- package/src/bench_bloat.ts +0 -173
- package/src/bench_churn.ts +0 -121
- package/src/bench_decode.ts +0 -221
- package/src/bench_decode_mem.ts +0 -165
- package/src/bench_encode.ts +0 -108
- package/src/bench_init.ts +0 -150
- package/src/bench_static.ts +0 -109
- package/src/bench_stream.ts +0 -295
- package/src/bench_view_cmp.ts +0 -142
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { File, Context } from "../types.js";
|
|
2
|
+
import { GenerateOptions } from "../api.js";
|
|
3
|
+
export declare const name = "Dart/Flutter";
|
|
4
|
+
/**
|
|
5
|
+
* Dart Code Generator
|
|
6
|
+
*
|
|
7
|
+
* Emits typed façades over the `colyseus` Flutter package's runtime: one
|
|
8
|
+
* `SchemaRef` subclass per schema, with typed getters over the shared native
|
|
9
|
+
* handle. Collection getters return `MapSchema<T>` / `ArraySchema<T>`, which
|
|
10
|
+
* also carry the field they came from — that is what
|
|
11
|
+
* `callbacks.onAdd(state.players, ...)` registers against.
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Generate individual files for each class/interface/enum
|
|
15
|
+
*/
|
|
16
|
+
export declare function generate(context: Context, options: GenerateOptions): File[];
|
|
17
|
+
/**
|
|
18
|
+
* Generate a single bundled file containing all classes, interfaces, and enums
|
|
19
|
+
*/
|
|
20
|
+
export declare function renderBundle(context: Context, options: GenerateOptions): File;
|
package/build/codegen/types.d.ts
CHANGED
|
@@ -37,11 +37,31 @@ export declare class Enum implements IStructure {
|
|
|
37
37
|
properties: Property[];
|
|
38
38
|
addProperty(property: Property): void;
|
|
39
39
|
}
|
|
40
|
+
/**
|
|
41
|
+
* Statically-extracted `t.quantized()` options. `wrap` is already normalized
|
|
42
|
+
* from the source's `mode` string; emitters derive `range`/`span` via
|
|
43
|
+
* {@link resolveQuantized} so every language ships identical precomputed values.
|
|
44
|
+
*/
|
|
45
|
+
export interface QuantizedProperty {
|
|
46
|
+
min: number;
|
|
47
|
+
max: number;
|
|
48
|
+
bits: 8 | 16 | 32;
|
|
49
|
+
wrap: boolean;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Mirror of the runtime's `resolveQuantize()` scale math (wrap spreads 2^bits
|
|
53
|
+
* steps across [min,max); clamp maps the endpoints onto 0 and 2^bits-1).
|
|
54
|
+
*/
|
|
55
|
+
export declare function resolveQuantized(q: QuantizedProperty): {
|
|
56
|
+
range: number;
|
|
57
|
+
span: number;
|
|
58
|
+
};
|
|
40
59
|
export declare class Property {
|
|
41
60
|
index: number;
|
|
42
61
|
name: string;
|
|
43
62
|
type: string;
|
|
44
63
|
childType: string;
|
|
64
|
+
quantized?: QuantizedProperty;
|
|
45
65
|
deprecated?: boolean;
|
|
46
66
|
}
|
|
47
67
|
export interface File {
|
|
@@ -42,8 +42,8 @@ export declare function resyncTouchEntry(decoder: Decoder, ref: any, operation:
|
|
|
42
42
|
/**
|
|
43
43
|
* Mark a collection as present in the payload — even with zero entries.
|
|
44
44
|
* The sweep only prunes collections reported here: absence means "not part
|
|
45
|
-
* of full-sync" (@
|
|
46
|
-
* live data. Reflected clients have no @
|
|
45
|
+
* of full-sync" (@patchOnly, view-invisible), where pruning would destroy
|
|
46
|
+
* live data. Reflected clients have no @patchOnly metadata, so payload
|
|
47
47
|
* presence is the only reliable signal.
|
|
48
48
|
*/
|
|
49
49
|
export declare function resyncMarkPresent(decoder: Decoder, refId: number): void;
|
|
@@ -52,7 +52,7 @@ export declare function resyncMarkPresent(decoder: Decoder, refId: number): void
|
|
|
52
52
|
* entry the snapshot did not visit.
|
|
53
53
|
*
|
|
54
54
|
* Walks the tree from the root — NOT `root.refs` — for three reasons:
|
|
55
|
-
* `@
|
|
55
|
+
* `@patchOnly` fields are never part of a snapshot and must be left alone;
|
|
56
56
|
* entries of subtrees removed by the sweep itself are left to the GC's
|
|
57
57
|
* transitive walk (sweeping them directly would double-decrement shared
|
|
58
58
|
* children); and collections the snapshot never mentions (emptied
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*
|
|
9
9
|
* - parentChain.ts addParent / removeParent / find / has / getAll
|
|
10
10
|
* - liveIteration.ts forEachLive
|
|
11
|
-
* - inheritedFlags.ts filter / unreliable /
|
|
11
|
+
* - inheritedFlags.ts filter / unreliable / patchOnly / static inheritance
|
|
12
12
|
* - treeAttachment.ts setRoot / setParent / forEachChild(+WithCtx)
|
|
13
13
|
*
|
|
14
14
|
* Public surface on ChangeTree is unchanged — methods are thin pass-throughs
|
|
@@ -51,6 +51,7 @@ export interface ChangeTreeNode {
|
|
|
51
51
|
export interface ChangeTreeList {
|
|
52
52
|
next?: ChangeTreeNode;
|
|
53
53
|
tail?: ChangeTreeNode;
|
|
54
|
+
nextPosition: number;
|
|
54
55
|
}
|
|
55
56
|
export declare function createChangeTreeList(): ChangeTreeList;
|
|
56
57
|
export interface ParentChain {
|
|
@@ -59,7 +60,7 @@ export interface ParentChain {
|
|
|
59
60
|
next?: ParentChain;
|
|
60
61
|
}
|
|
61
62
|
export declare const IS_FILTERED = 1, IS_VISIBILITY_SHARED = 2, IS_NEW = 4;
|
|
62
|
-
export declare const IS_UNRELIABLE = 8,
|
|
63
|
+
export declare const IS_UNRELIABLE = 8, IS_PATCH_ONLY = 16, IS_FULL_STATE_ONLY = 32;
|
|
63
64
|
export declare const IS_STREAM_COLLECTION = 64;
|
|
64
65
|
export declare const NEEDS_RESTAGE = 128;
|
|
65
66
|
/**
|
|
@@ -95,8 +96,8 @@ export declare class ChangeTree<T extends Ref = any> implements ChangeRecorder {
|
|
|
95
96
|
refTarget: T;
|
|
96
97
|
metadata: Metadata;
|
|
97
98
|
/**
|
|
98
|
-
* Per-class cache of encoder fn / filter fn / isSchema /
|
|
99
|
-
*
|
|
99
|
+
* Per-class cache of encoder fn / filter fn / isSchema / metadata /
|
|
100
|
+
* per-field arrays, looked up once at construction. The encode loop reads
|
|
100
101
|
* `tree.encDescriptor` and never touches `ref.constructor` again. See
|
|
101
102
|
* EncodeDescriptor.ts.
|
|
102
103
|
*/
|
|
@@ -148,10 +149,10 @@ export declare class ChangeTree<T extends Ref = any> implements ChangeRecorder {
|
|
|
148
149
|
set isNew(v: boolean);
|
|
149
150
|
get isUnreliable(): boolean;
|
|
150
151
|
set isUnreliable(v: boolean);
|
|
151
|
-
get
|
|
152
|
-
set
|
|
153
|
-
get
|
|
154
|
-
set
|
|
152
|
+
get isPatchOnly(): boolean;
|
|
153
|
+
set isPatchOnly(v: boolean);
|
|
154
|
+
get isFullStateOnly(): boolean;
|
|
155
|
+
set isFullStateOnly(v: boolean);
|
|
155
156
|
get isStreamCollection(): boolean;
|
|
156
157
|
set isStreamCollection(v: boolean);
|
|
157
158
|
get needsRestage(): boolean;
|
|
@@ -159,7 +160,7 @@ export declare class ChangeTree<T extends Ref = any> implements ChangeRecorder {
|
|
|
159
160
|
get hasFilteredFields(): boolean;
|
|
160
161
|
ensureUnreliableRecorder(): ChangeRecorder;
|
|
161
162
|
isFieldUnreliable(index: number): boolean;
|
|
162
|
-
|
|
163
|
+
isFieldFullStateOnly(index: number): boolean;
|
|
163
164
|
isFieldStream(index: number): boolean;
|
|
164
165
|
constructor(ref: T);
|
|
165
166
|
private _opAt;
|
|
@@ -218,6 +219,18 @@ export declare class ChangeTree<T extends Ref = any> implements ChangeRecorder {
|
|
|
218
219
|
* fields (see annotations.ts), so the per-field unreliable flag here
|
|
219
220
|
* always means "primitive value updates" — the structural-ADD-routes-
|
|
220
221
|
* reliable footgun for ref-type fields can't reach this code path.
|
|
222
|
+
*
|
|
223
|
+
* `!isNew` holds an `@unreliable` field on the RELIABLE channel until this
|
|
224
|
+
* tree's own ADD has shipped there. A decoder can only apply a field write
|
|
225
|
+
* to a ref it already knows, so a value emitted before the ADD is dropped —
|
|
226
|
+
* permanently, if the field is never written again. `isNew` clears in
|
|
227
|
+
* `endEncode()`, i.e. after a reliable pass, and recording reliably is
|
|
228
|
+
* itself what enqueues the tree for that pass; the state is self-clearing
|
|
229
|
+
* and no tree can be stranded on the wrong channel. Mirrors `encodeAll`,
|
|
230
|
+
* which has always seeded these fields for late joiners.
|
|
231
|
+
*
|
|
232
|
+
* Ordering matters: `isFieldUnreliable` short-circuits on the class-level
|
|
233
|
+
* `hasAnyUnreliable`, so schemas without the modifier never read `flags`.
|
|
221
234
|
*/
|
|
222
235
|
private _routeAndRecord;
|
|
223
236
|
change(index: number, operation?: OPERATION): void;
|
|
@@ -7,34 +7,33 @@ export interface EncodeDescriptor {
|
|
|
7
7
|
isSchema: boolean;
|
|
8
8
|
/**
|
|
9
9
|
* Bit i set iff field i has a @view tag. 0 for collection trees.
|
|
10
|
-
* Lets `encodeChangeCb` do a single bitwise op instead of a
|
|
11
|
-
*
|
|
10
|
+
* Lets `encodeChangeCb` do a single bitwise op instead of a per-field
|
|
11
|
+
* metadata[i]?.tag chase. Fields 0–31 only, like the bitmasks below —
|
|
12
|
+
* `encodeChangeCb` reads `tags` past that.
|
|
12
13
|
*/
|
|
13
14
|
filterBitmask: number;
|
|
14
15
|
/**
|
|
15
16
|
* Class-level "any field has the flag" booleans + per-field bitmasks.
|
|
16
|
-
* Hot path: per-mutation `_routeAndRecord` calls `
|
|
17
|
+
* Hot path: per-mutation `_routeAndRecord` calls `isFieldFullStateOnly` and
|
|
17
18
|
* `isFieldUnreliable`. The common case is "no static/unreliable fields
|
|
18
19
|
* anywhere on this class" (booleans short-circuit before the symbol-keyed
|
|
19
20
|
* metadata lookup); the secondary common case is "this class has some
|
|
20
21
|
* such fields and we need to know if THIS field is one" — the bitmask
|
|
21
22
|
* answers in one bitwise op instead of an `Array.includes` linear scan.
|
|
22
23
|
*
|
|
23
|
-
* Bitmasks cover fields 0–31 only
|
|
24
|
-
*
|
|
25
|
-
* filter-bitmask path.
|
|
24
|
+
* Bitmasks cover fields 0–31 only — shift counts wrap at 32. Fields ≥32
|
|
25
|
+
* fall back to `Metadata.hasXAtIndex`.
|
|
26
26
|
*/
|
|
27
|
-
|
|
27
|
+
hasAnyFullStateOnly: boolean;
|
|
28
28
|
hasAnyUnreliable: boolean;
|
|
29
29
|
hasAnyStream: boolean;
|
|
30
30
|
/**
|
|
31
|
-
* Class-level "any field carries a `@view` tag"
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
* decide whether a parent tree must be included in a view's bootstrap.
|
|
31
|
+
* Class-level "any field carries a `@view` tag". Read by
|
|
32
|
+
* `ChangeTree.hasFilteredFields` to decide whether a parent tree must
|
|
33
|
+
* be included in a view's bootstrap.
|
|
35
34
|
*/
|
|
36
35
|
hasAnyView: boolean;
|
|
37
|
-
|
|
36
|
+
fullStateOnlyBitmask: number;
|
|
38
37
|
unreliableBitmask: number;
|
|
39
38
|
/**
|
|
40
39
|
* Bit i set iff field i holds a `t.stream(...)` collection. Hot encode
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { ChangeTree, Ref } from "./ChangeTree.js";
|
|
2
2
|
import { OPERATION } from "../encoding/spec.js";
|
|
3
|
+
import type { StreamSchema } from "../types/custom/StreamSchema.js";
|
|
4
|
+
import type { MapSchema } from "../types/custom/MapSchema.js";
|
|
5
|
+
import type { SetSchema } from "../types/custom/SetSchema.js";
|
|
6
|
+
import type { CollectionSchema } from "../types/custom/CollectionSchema.js";
|
|
3
7
|
export declare function createView(iterable?: boolean): StateView;
|
|
4
8
|
export declare class StateView {
|
|
5
9
|
iterable: boolean;
|
|
@@ -145,9 +149,29 @@ export declare class StateView {
|
|
|
145
149
|
* enqueued into `_pendingByView` so the priority pass drains them
|
|
146
150
|
* respecting `maxPerTick`.
|
|
147
151
|
*
|
|
148
|
-
*
|
|
149
|
-
*
|
|
152
|
+
* On a streaming collection, pass a `priority` callback to order THIS
|
|
153
|
+
* client's backlog. It receives only the element, so whatever the
|
|
154
|
+
* client sorts by is captured in the closure — nothing is attached to
|
|
155
|
+
* the view, and both the element and the captured entity stay typed:
|
|
156
|
+
*
|
|
157
|
+
* ```ts
|
|
158
|
+
* onJoin(client) {
|
|
159
|
+
* const player = this.state.players.get(client.sessionId);
|
|
160
|
+
* client.view.subscribe(this.state.enemies, (enemy) =>
|
|
161
|
+
* -((enemy.x - player.x) ** 2 + (enemy.y - player.y) ** 2));
|
|
162
|
+
* }
|
|
163
|
+
* ```
|
|
164
|
+
*
|
|
165
|
+
* A per-view callback overrides the collection's declaration-scope
|
|
166
|
+
* `.priority()` for this client only.
|
|
167
|
+
*
|
|
168
|
+
* Idempotent on re-subscribe: subscribing to an already-subscribed
|
|
169
|
+
* collection is a no-op, EXCEPT that a supplied `priority` always
|
|
170
|
+
* replaces the previous one — re-subscribe to retarget the ordering.
|
|
171
|
+
* Omitting the argument leaves any existing callback in place; pass
|
|
172
|
+
* `null` to drop it and fall back to the declaration-scope callback.
|
|
150
173
|
*/
|
|
174
|
+
subscribe<V>(collection: StreamSchema<V> | MapSchema<V, any> | SetSchema<V> | CollectionSchema<V>, priority?: ((element: V) => number) | null): this;
|
|
151
175
|
subscribe(collection: Ref): this;
|
|
152
176
|
/**
|
|
153
177
|
* End a persistent subscription. Queues DELETE for every already-sent
|
|
@@ -6,7 +6,7 @@ import { type ChangeTree, type Ref } from "../ChangeTree.js";
|
|
|
6
6
|
*/
|
|
7
7
|
export declare function checkIsFiltered(tree: ChangeTree, parent: Ref, parentIndex: number, _isNewChangeTree: boolean): void;
|
|
8
8
|
/**
|
|
9
|
-
* Inherit filter / unreliable /
|
|
9
|
+
* Inherit filter / unreliable / patchOnly / static classification from
|
|
10
10
|
* the parent field's annotation. Collections (MapSchema / ArraySchema /
|
|
11
11
|
* etc.) inherit these from the Schema field that holds them.
|
|
12
12
|
*
|
|
@@ -30,6 +30,13 @@ export interface StreamableState {
|
|
|
30
30
|
* Instance-level override: assign to `stream.priority`.
|
|
31
31
|
*/
|
|
32
32
|
priority?: (view: any, element: any) => number;
|
|
33
|
+
/**
|
|
34
|
+
* Per-view priority registered by `StateView.subscribe(collection, fn)`.
|
|
35
|
+
* Takes precedence over the declaration-scope `priority` for that view.
|
|
36
|
+
* Receives only the element — the client's own entity is captured in
|
|
37
|
+
* the closure, so nothing has to be attached to the view.
|
|
38
|
+
*/
|
|
39
|
+
priorityByView?: Map<number, (element: any) => number>;
|
|
33
40
|
}
|
|
34
41
|
export declare function createStreamableState(): StreamableState;
|
|
35
42
|
/** Allocate `_stream` on first use (idempotent). Returns the state. */
|