@colyseus/schema 5.0.10 → 5.0.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/build/encoder/ChangeTree.d.ts +0 -1
- package/build/encoder/StateView.d.ts +0 -6
- package/build/index.cjs +19 -55
- package/build/index.cjs.map +1 -1
- package/build/index.js +19 -55
- package/build/index.mjs +19 -55
- package/build/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/encoder/ChangeTree.ts +0 -2
- package/src/encoder/Encoder.ts +3 -16
- package/src/encoder/StateView.ts +16 -35
|
@@ -129,7 +129,6 @@ export declare class ChangeTree<T extends Ref = any> implements ChangeRecorder {
|
|
|
129
129
|
changesNode?: ChangeTreeNode;
|
|
130
130
|
unreliableChangesNode?: ChangeTreeNode;
|
|
131
131
|
visibleViews?: number[];
|
|
132
|
-
invisibleViews?: number[];
|
|
133
132
|
tagViews?: Map<number, number[]>;
|
|
134
133
|
/**
|
|
135
134
|
* Per-view subscription bitmap — same layout as `visibleViews`. Set by
|
|
@@ -64,12 +64,6 @@ export declare class StateView {
|
|
|
64
64
|
private _setSubscribed;
|
|
65
65
|
/** Clear the subscription bit on `tree`. */
|
|
66
66
|
private _clearSubscribed;
|
|
67
|
-
/** True iff this view has previously marked `tree` as invisible. */
|
|
68
|
-
isInvisible(tree: ChangeTree): boolean;
|
|
69
|
-
/** Mark `tree` as invisible to this view (used by encode loop). */
|
|
70
|
-
markInvisible(tree: ChangeTree): void;
|
|
71
|
-
/** Clear invisible bit. */
|
|
72
|
-
unmarkInvisible(tree: ChangeTree): void;
|
|
73
67
|
/**
|
|
74
68
|
* True iff this view shares at least one tag bit with `tree`.
|
|
75
69
|
*
|
package/build/index.cjs
CHANGED
|
@@ -2594,7 +2594,6 @@ class ChangeTree {
|
|
|
2594
2594
|
// per-view WeakSet lookups with direct bitwise ops.
|
|
2595
2595
|
// Lazy: undefined until the tree participates in any view.
|
|
2596
2596
|
visibleViews;
|
|
2597
|
-
invisibleViews;
|
|
2598
2597
|
// Per-(view, tag) bitmap, indexed by tag. Custom tags only —
|
|
2599
2598
|
// DEFAULT_VIEW_TAG visibility lives in `visibleViews`.
|
|
2600
2599
|
tagViews;
|
|
@@ -2946,7 +2945,6 @@ class ChangeTree {
|
|
|
2946
2945
|
// per-view visibility lives on the tree (NOT keyed by refId), so a
|
|
2947
2946
|
// recycled tree must not inherit its previous life's view membership.
|
|
2948
2947
|
this.visibleViews = undefined;
|
|
2949
|
-
this.invisibleViews = undefined;
|
|
2950
2948
|
this.tagViews = undefined;
|
|
2951
2949
|
this.subscribedViews = undefined;
|
|
2952
2950
|
}
|
|
@@ -8006,17 +8004,7 @@ function _fullSyncWalk(ctx, changeTree) {
|
|
|
8006
8004
|
// Visibility gate: when a view is active, a non-visible tree contributes
|
|
8007
8005
|
// nothing itself but we still recurse so descendants (possibly added to
|
|
8008
8006
|
// the view explicitly) are reachable.
|
|
8009
|
-
|
|
8010
|
-
if (ctx.hasView) {
|
|
8011
|
-
const view = ctx.view;
|
|
8012
|
-
if (!view.isChangeTreeVisible(changeTree)) {
|
|
8013
|
-
view.markInvisible(changeTree);
|
|
8014
|
-
visibleHere = false;
|
|
8015
|
-
}
|
|
8016
|
-
else {
|
|
8017
|
-
view.unmarkInvisible(changeTree);
|
|
8018
|
-
}
|
|
8019
|
-
}
|
|
8007
|
+
const visibleHere = !ctx.hasView || ctx.view.isChangeTreeVisible(changeTree);
|
|
8020
8008
|
if (visibleHere) {
|
|
8021
8009
|
const desc = changeTree.encDescriptor;
|
|
8022
8010
|
ctx.changeTree = changeTree;
|
|
@@ -8165,12 +8153,8 @@ class Encoder {
|
|
|
8165
8153
|
let current = queue;
|
|
8166
8154
|
while (current = current.next) {
|
|
8167
8155
|
const changeTree = current.changeTree;
|
|
8168
|
-
if (hasView) {
|
|
8169
|
-
|
|
8170
|
-
view.markInvisible(changeTree);
|
|
8171
|
-
continue;
|
|
8172
|
-
}
|
|
8173
|
-
view.unmarkInvisible(changeTree);
|
|
8156
|
+
if (hasView && !view.isChangeTreeVisible(changeTree)) {
|
|
8157
|
+
continue;
|
|
8174
8158
|
}
|
|
8175
8159
|
const recorder = unreliable ? changeTree.unreliableRecorder : changeTree;
|
|
8176
8160
|
if (!recorder || !recorder.has()) {
|
|
@@ -9862,9 +9846,6 @@ function _clearViewBitFromAllTrees(root, slot, bit) {
|
|
|
9862
9846
|
const v = tree.visibleViews;
|
|
9863
9847
|
if (v !== undefined && slot < v.length)
|
|
9864
9848
|
v[slot] &= clearMask;
|
|
9865
|
-
const i = tree.invisibleViews;
|
|
9866
|
-
if (i !== undefined && slot < i.length)
|
|
9867
|
-
i[slot] &= clearMask;
|
|
9868
9849
|
const s = tree.subscribedViews;
|
|
9869
9850
|
if (s !== undefined && slot < s.length)
|
|
9870
9851
|
s[slot] &= clearMask;
|
|
@@ -10016,32 +9997,6 @@ class StateView {
|
|
|
10016
9997
|
if (slot < arr.length)
|
|
10017
9998
|
arr[slot] &= ~this._bit;
|
|
10018
9999
|
}
|
|
10019
|
-
/** True iff this view has previously marked `tree` as invisible. */
|
|
10020
|
-
isInvisible(tree) {
|
|
10021
|
-
const arr = tree.invisibleViews;
|
|
10022
|
-
const slot = this._slot;
|
|
10023
|
-
return arr !== undefined && slot < arr.length && (arr[slot] & this._bit) !== 0;
|
|
10024
|
-
}
|
|
10025
|
-
/** Mark `tree` as invisible to this view (used by encode loop). */
|
|
10026
|
-
markInvisible(tree) {
|
|
10027
|
-
const slot = this._slot;
|
|
10028
|
-
let arr = tree.invisibleViews;
|
|
10029
|
-
if (arr === undefined) {
|
|
10030
|
-
arr = tree.invisibleViews = [];
|
|
10031
|
-
}
|
|
10032
|
-
while (arr.length <= slot)
|
|
10033
|
-
arr.push(0);
|
|
10034
|
-
arr[slot] |= this._bit;
|
|
10035
|
-
}
|
|
10036
|
-
/** Clear invisible bit. */
|
|
10037
|
-
unmarkInvisible(tree) {
|
|
10038
|
-
const arr = tree.invisibleViews;
|
|
10039
|
-
if (arr === undefined)
|
|
10040
|
-
return;
|
|
10041
|
-
const slot = this._slot;
|
|
10042
|
-
if (slot < arr.length)
|
|
10043
|
-
arr[slot] &= ~this._bit;
|
|
10044
|
-
}
|
|
10045
10000
|
// ──────────────────────────────────────────────────────────────────
|
|
10046
10001
|
// Per-tag, per-view bitmap. Replaces the legacy
|
|
10047
10002
|
// `tags: WeakMap<ChangeTree, Set<number>>` storage. Hot read site is
|
|
@@ -10185,11 +10140,18 @@ class StateView {
|
|
|
10185
10140
|
// below use `metadata?.[...]` null-safe access. Only Schema
|
|
10186
10141
|
// subclasses yield a real Metadata object.
|
|
10187
10142
|
const metadata = obj.constructor[Symbol.metadata];
|
|
10188
|
-
|
|
10189
|
-
//
|
|
10190
|
-
|
|
10143
|
+
// Add to iterable list (only the explicitly added items), deduping
|
|
10144
|
+
// re-adds of an already-visible instance. isVisible must be read
|
|
10145
|
+
// BEFORE markVisible; indexOf runs only on the re-add path.
|
|
10146
|
+
// NOTE: dedup applies to `items` only — a re-add still re-queues the
|
|
10147
|
+
// full snapshot on purpose (shared-view bootstrap re-add: a
|
|
10148
|
+
// late-attached client may not have consumed earlier drains).
|
|
10149
|
+
// Callers wanting cheap idempotence can guard with `view.has(obj)`.
|
|
10150
|
+
if (this.iterable && checkIncludeParent
|
|
10151
|
+
&& (!this.isVisible(changeTree) || this.items.indexOf(obj) === -1)) {
|
|
10191
10152
|
this.items.push(obj);
|
|
10192
10153
|
}
|
|
10154
|
+
this.markVisible(changeTree);
|
|
10193
10155
|
// add parent ChangeTree's
|
|
10194
10156
|
// - if it was invisible to this view
|
|
10195
10157
|
// - if it were previously filtered out
|
|
@@ -10272,18 +10234,20 @@ class StateView {
|
|
|
10272
10234
|
}
|
|
10273
10235
|
else if (!changeTree.isNew || isChildAdded) {
|
|
10274
10236
|
// new structures will be added as part of .encode() call, no need to force it to .encodeView()
|
|
10275
|
-
const isInvisible = this.isInvisible(changeTree);
|
|
10276
10237
|
// Full-sync snapshot: walk the live ref structurally instead of
|
|
10277
10238
|
// iterating a cumulative recorder bucket. Every populated index
|
|
10278
10239
|
// is emitted as ADD (matching the op-coercion previously done
|
|
10279
10240
|
// at encode time). Per-field tags come from the descriptor's
|
|
10280
10241
|
// precomputed `tags[]` array — direct index vs a metadata[i].tag
|
|
10281
10242
|
// object hop.
|
|
10243
|
+
//
|
|
10244
|
+
// Non-matching custom-tagged fields are NEVER included here —
|
|
10245
|
+
// `view.changes` is drained without a per-field tag re-check,
|
|
10246
|
+
// so anything added leaks straight to the wire.
|
|
10282
10247
|
const tags = changeTree.encDescriptor.tags;
|
|
10283
10248
|
changeTree.forEachLive((index) => {
|
|
10284
10249
|
const tagAtIndex = tags[index];
|
|
10285
|
-
if (
|
|
10286
|
-
tagAtIndex === undefined || // "all change" with no tag
|
|
10250
|
+
if (tagAtIndex === undefined || // "all change" with no tag
|
|
10287
10251
|
tagAtIndex === DEFAULT_VIEW_TAG || // visible to all clients
|
|
10288
10252
|
(tag !== DEFAULT_VIEW_TAG && (tagAtIndex & tag) !== 0) // tag bits overlap
|
|
10289
10253
|
) {
|
|
@@ -10435,7 +10399,7 @@ class StateView {
|
|
|
10435
10399
|
}
|
|
10436
10400
|
// ── Streamable-collection unsubscribe (the stream itself) ─────
|
|
10437
10401
|
// Flush DELETE for every sent position and drop pending. After
|
|
10438
|
-
// this, the stream is
|
|
10402
|
+
// this, the stream is no longer visible to this view — any future
|
|
10439
10403
|
// `stream.add()` would still seed broadcast pending (if no views)
|
|
10440
10404
|
// but would NOT re-seed per-view pending (user must re-subscribe).
|
|
10441
10405
|
if (changeTree.isStreamCollection) {
|