@colyseus/schema 3.0.10 → 3.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/cjs/index.js +95 -88
- package/build/cjs/index.js.map +1 -1
- package/build/esm/index.mjs +95 -88
- package/build/esm/index.mjs.map +1 -1
- package/build/umd/index.js +95 -88
- package/lib/Metadata.js +1 -2
- package/lib/Metadata.js.map +1 -1
- package/lib/annotations.js +4 -3
- package/lib/annotations.js.map +1 -1
- package/lib/decoder/DecodeOperation.js +0 -13
- package/lib/decoder/DecodeOperation.js.map +1 -1
- package/lib/encoder/ChangeTree.d.ts +1 -0
- package/lib/encoder/ChangeTree.js +2 -1
- package/lib/encoder/ChangeTree.js.map +1 -1
- package/lib/encoder/Encoder.d.ts +0 -1
- package/lib/encoder/Encoder.js +22 -30
- package/lib/encoder/Encoder.js.map +1 -1
- package/lib/encoder/Root.d.ts +1 -1
- package/lib/encoder/Root.js +20 -3
- package/lib/encoder/Root.js.map +1 -1
- package/lib/encoder/StateView.d.ts +2 -4
- package/lib/encoder/StateView.js +19 -13
- package/lib/encoder/StateView.js.map +1 -1
- package/lib/types/custom/ArraySchema.js +5 -1
- package/lib/types/custom/ArraySchema.js.map +1 -1
- package/lib/types/custom/MapSchema.js +23 -22
- package/lib/types/custom/MapSchema.js.map +1 -1
- package/package.json +1 -1
- package/src/Metadata.ts +1 -2
- package/src/annotations.ts +4 -4
- package/src/decoder/DecodeOperation.ts +0 -14
- package/src/encoder/ChangeTree.ts +3 -4
- package/src/encoder/Encoder.ts +25 -41
- package/src/encoder/Root.ts +21 -4
- package/src/encoder/StateView.ts +22 -15
- package/src/types/custom/ArraySchema.ts +8 -1
- package/src/types/custom/MapSchema.ts +24 -27
package/src/encoder/Root.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { OPERATION } from "../encoding/spec";
|
|
2
2
|
import { TypeContext } from "../types/TypeContext";
|
|
3
3
|
import { spliceOne } from "../types/utils";
|
|
4
|
-
import { ChangeTree, setOperationAtIndex } from "./ChangeTree";
|
|
4
|
+
import { ChangeTree, enqueueChangeTree, setOperationAtIndex } from "./ChangeTree";
|
|
5
5
|
|
|
6
6
|
export class Root {
|
|
7
7
|
protected nextUniqueId: number = 0;
|
|
@@ -71,6 +71,23 @@ export class Root {
|
|
|
71
71
|
|
|
72
72
|
} else {
|
|
73
73
|
this.refCount[changeTree.refId] = refCount;
|
|
74
|
+
|
|
75
|
+
//
|
|
76
|
+
// When losing a reference to an instance, it is best to move the
|
|
77
|
+
// ChangeTree to the end of the encoding queue.
|
|
78
|
+
//
|
|
79
|
+
// This way, at decoding time, the instance that contains the
|
|
80
|
+
// ChangeTree will be available before the ChangeTree itself. If the
|
|
81
|
+
// containing instance is not available, the Decoder will throw
|
|
82
|
+
// "refId not found" error.
|
|
83
|
+
//
|
|
84
|
+
if (changeTree.filteredChanges !== undefined) {
|
|
85
|
+
this.removeChangeFromChangeSet("filteredChanges", changeTree);
|
|
86
|
+
enqueueChangeTree(this, changeTree, "filteredChanges");
|
|
87
|
+
} else {
|
|
88
|
+
this.removeChangeFromChangeSet("changes", changeTree);
|
|
89
|
+
enqueueChangeTree(this, changeTree, "changes");
|
|
90
|
+
}
|
|
74
91
|
}
|
|
75
92
|
|
|
76
93
|
changeTree.forEachChild((child, _) => this.remove(child));
|
|
@@ -80,10 +97,10 @@ export class Root {
|
|
|
80
97
|
|
|
81
98
|
removeChangeFromChangeSet(changeSetName: "allChanges" | "changes" | "filteredChanges" | "allFilteredChanges", changeTree: ChangeTree) {
|
|
82
99
|
const changeSet = this[changeSetName];
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
spliceOne(changeSet, index);
|
|
100
|
+
if (spliceOne(changeSet, changeSet.indexOf(changeTree))) {
|
|
101
|
+
changeTree[changeSetName].queueRootIndex = -1;
|
|
86
102
|
// changeSet[index] = undefined;
|
|
103
|
+
return true;
|
|
87
104
|
}
|
|
88
105
|
}
|
|
89
106
|
|
package/src/encoder/StateView.ts
CHANGED
|
@@ -25,7 +25,8 @@ export class StateView {
|
|
|
25
25
|
* Manual "ADD" operations for changes per ChangeTree, specific to this view.
|
|
26
26
|
* (This is used to force encoding a property, even if it was not changed)
|
|
27
27
|
*/
|
|
28
|
-
|
|
28
|
+
// TODO: use map here!? may fix encode ordering issue
|
|
29
|
+
changes = new Map<number, IndexedOperations>();
|
|
29
30
|
|
|
30
31
|
// TODO: allow to set multiple tags at once
|
|
31
32
|
add(obj: Ref, tag: number = DEFAULT_VIEW_TAG, checkIncludeParent: boolean = true) {
|
|
@@ -43,17 +44,17 @@ export class StateView {
|
|
|
43
44
|
// - if it was invisible to this view
|
|
44
45
|
// - if it were previously filtered out
|
|
45
46
|
if (checkIncludeParent && changeTree.parent) {
|
|
46
|
-
this.
|
|
47
|
+
this.addParentOf(changeTree, tag);
|
|
47
48
|
}
|
|
48
49
|
|
|
49
50
|
//
|
|
50
51
|
// TODO: when adding an item of a MapSchema, the changes may not
|
|
51
52
|
// be set (only the parent's changes are set)
|
|
52
53
|
//
|
|
53
|
-
let changes = this.changes
|
|
54
|
+
let changes = this.changes.get(changeTree.refId);
|
|
54
55
|
if (changes === undefined) {
|
|
55
56
|
changes = {};
|
|
56
|
-
this.changes
|
|
57
|
+
this.changes.set(changeTree.refId, changes);
|
|
57
58
|
}
|
|
58
59
|
|
|
59
60
|
// set tag
|
|
@@ -118,28 +119,34 @@ export class StateView {
|
|
|
118
119
|
return this;
|
|
119
120
|
}
|
|
120
121
|
|
|
121
|
-
protected
|
|
122
|
+
protected addParentOf(childChangeTree: ChangeTree, tag: number) {
|
|
123
|
+
const changeTree = childChangeTree.parent[$changes];
|
|
124
|
+
const parentIndex = childChangeTree.parentIndex;
|
|
125
|
+
|
|
122
126
|
// view must have all "changeTree" parent tree
|
|
123
127
|
this.items.add(changeTree);
|
|
124
128
|
|
|
125
129
|
// add parent's parent
|
|
126
130
|
const parentChangeTree: ChangeTree = changeTree.parent?.[$changes];
|
|
127
131
|
if (parentChangeTree && (parentChangeTree.filteredChanges !== undefined)) {
|
|
128
|
-
this.
|
|
132
|
+
this.addParentOf(changeTree, tag);
|
|
129
133
|
}
|
|
130
134
|
|
|
131
|
-
|
|
132
|
-
|
|
135
|
+
if (
|
|
136
|
+
// parent is already available, no need to add it!
|
|
137
|
+
!this.invisible.has(changeTree) &&
|
|
138
|
+
// item is being replaced, no need to add parent
|
|
139
|
+
changeTree.indexedOperations[parentIndex] !== OPERATION.DELETE_AND_ADD
|
|
140
|
+
) {
|
|
133
141
|
return;
|
|
134
142
|
}
|
|
135
143
|
|
|
136
144
|
// add parent's tag properties
|
|
137
145
|
if (changeTree.getChange(parentIndex) !== OPERATION.DELETE) {
|
|
138
|
-
|
|
139
|
-
let changes = this.changes[changeTree.refId];
|
|
146
|
+
let changes = this.changes.get(changeTree.refId);
|
|
140
147
|
if (changes === undefined) {
|
|
141
148
|
changes = {};
|
|
142
|
-
this.changes
|
|
149
|
+
this.changes.set(changeTree.refId, changes);
|
|
143
150
|
}
|
|
144
151
|
|
|
145
152
|
if (!this.tags) {
|
|
@@ -171,10 +178,10 @@ export class StateView {
|
|
|
171
178
|
const ref = changeTree.ref;
|
|
172
179
|
const metadata: Metadata = ref.constructor[Symbol.metadata];
|
|
173
180
|
|
|
174
|
-
let changes = this.changes
|
|
181
|
+
let changes = this.changes.get(changeTree.refId);
|
|
175
182
|
if (changes === undefined) {
|
|
176
183
|
changes = {};
|
|
177
|
-
this.changes
|
|
184
|
+
this.changes.set(changeTree.refId, changes);
|
|
178
185
|
}
|
|
179
186
|
|
|
180
187
|
if (tag === DEFAULT_VIEW_TAG) {
|
|
@@ -182,10 +189,10 @@ export class StateView {
|
|
|
182
189
|
const parent = changeTree.parent;
|
|
183
190
|
if (!Metadata.isValidInstance(parent)) {
|
|
184
191
|
const parentChangeTree = parent[$changes];
|
|
185
|
-
let changes = this.changes
|
|
192
|
+
let changes = this.changes.get(parentChangeTree.refId);
|
|
186
193
|
if (changes === undefined) {
|
|
187
194
|
changes = {};
|
|
188
|
-
this.changes
|
|
195
|
+
this.changes.set(parentChangeTree.refId, changes);
|
|
189
196
|
}
|
|
190
197
|
// DELETE / DELETE BY REF ID
|
|
191
198
|
changes[changeTree.parentIndex] = OPERATION.DELETE;
|
|
@@ -92,7 +92,8 @@ export class ArraySchema<V = any> implements Array<V>, Collection<number, V> {
|
|
|
92
92
|
if (setValue[$changes]) {
|
|
93
93
|
assertInstanceType(setValue, obj[$childType] as typeof Schema, obj, key);
|
|
94
94
|
|
|
95
|
-
|
|
95
|
+
const previousValue = obj.items[key as unknown as number];
|
|
96
|
+
if (previousValue !== undefined) {
|
|
96
97
|
if (setValue[$changes].isNew) {
|
|
97
98
|
this[$changes].indexedOperation(Number(key), OPERATION.MOVE_AND_ADD);
|
|
98
99
|
|
|
@@ -103,10 +104,16 @@ export class ArraySchema<V = any> implements Array<V>, Collection<number, V> {
|
|
|
103
104
|
this[$changes].indexedOperation(Number(key), OPERATION.MOVE);
|
|
104
105
|
}
|
|
105
106
|
}
|
|
107
|
+
|
|
108
|
+
// remove root reference from previous value
|
|
109
|
+
previousValue[$changes].root?.remove(previousValue[$changes]);
|
|
110
|
+
|
|
106
111
|
} else if (setValue[$changes].isNew) {
|
|
107
112
|
this[$changes].indexedOperation(Number(key), OPERATION.ADD);
|
|
108
113
|
}
|
|
109
114
|
|
|
115
|
+
setValue[$changes].setParent(this, obj[$changes].root, key);
|
|
116
|
+
|
|
110
117
|
} else {
|
|
111
118
|
obj.$changeAt(Number(key), setValue);
|
|
112
119
|
}
|
|
@@ -86,41 +86,38 @@ export class MapSchema<V=any, K extends string = string> implements Map<K, V>, C
|
|
|
86
86
|
key = key.toString() as K;
|
|
87
87
|
|
|
88
88
|
const changeTree = this[$changes];
|
|
89
|
+
const isRef = (value[$changes]) !== undefined;
|
|
89
90
|
|
|
90
|
-
|
|
91
|
-
|
|
91
|
+
let index: number;
|
|
92
|
+
let operation: OPERATION;
|
|
92
93
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
94
|
+
// IS REPLACE?
|
|
95
|
+
if (typeof(changeTree.indexes[key]) !== "undefined") {
|
|
96
|
+
index = changeTree.indexes[key];
|
|
97
|
+
operation = OPERATION.REPLACE;
|
|
96
98
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
99
|
+
const previousValue = this.$items.get(key);
|
|
100
|
+
if (previousValue === value) {
|
|
101
|
+
// if value is the same, avoid re-encoding it.
|
|
102
|
+
return;
|
|
100
103
|
|
|
101
|
-
|
|
104
|
+
} else if (isRef) {
|
|
105
|
+
// if is schema, force ADD operation if value differ from previous one.
|
|
106
|
+
operation = OPERATION.DELETE_AND_ADD;
|
|
107
|
+
|
|
108
|
+
// remove reference from previous value
|
|
109
|
+
if (previousValue !== undefined) {
|
|
110
|
+
previousValue[$changes].root?.remove(previousValue[$changes]);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
} else {
|
|
115
|
+
index = changeTree.indexes[$numFields] ?? 0;
|
|
116
|
+
operation = OPERATION.ADD;
|
|
102
117
|
|
|
103
|
-
//
|
|
104
|
-
// (encoding)
|
|
105
|
-
// set a unique id to relate directly with this key/value.
|
|
106
|
-
//
|
|
107
|
-
if (!isReplace) {
|
|
108
118
|
this.$indexes.set(index, key);
|
|
109
119
|
changeTree.indexes[key] = index;
|
|
110
120
|
changeTree.indexes[$numFields] = index + 1;
|
|
111
|
-
|
|
112
|
-
} else if (
|
|
113
|
-
!isRef &&
|
|
114
|
-
this.$items.get(key) === value
|
|
115
|
-
) {
|
|
116
|
-
// if value is the same, avoid re-encoding it.
|
|
117
|
-
return;
|
|
118
|
-
|
|
119
|
-
} else if (
|
|
120
|
-
isRef && // if is schema, force ADD operation if value differ from previous one.
|
|
121
|
-
this.$items.get(key) !== value
|
|
122
|
-
) {
|
|
123
|
-
operation = OPERATION.ADD;
|
|
124
121
|
}
|
|
125
122
|
|
|
126
123
|
this.$items.set(key, value);
|