@colyseus/schema 3.0.0-alpha.34 → 3.0.0-alpha.35

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.
Files changed (63) hide show
  1. package/bin/schema-debug +4 -3
  2. package/build/cjs/index.js +465 -303
  3. package/build/cjs/index.js.map +1 -1
  4. package/build/esm/index.mjs +465 -303
  5. package/build/esm/index.mjs.map +1 -1
  6. package/build/umd/index.js +465 -303
  7. package/lib/Metadata.d.ts +5 -5
  8. package/lib/Metadata.js +17 -17
  9. package/lib/Metadata.js.map +1 -1
  10. package/lib/Schema.js +24 -17
  11. package/lib/Schema.js.map +1 -1
  12. package/lib/annotations.js +11 -11
  13. package/lib/annotations.js.map +1 -1
  14. package/lib/bench_encode.js +12 -5
  15. package/lib/bench_encode.js.map +1 -1
  16. package/lib/decoder/Decoder.js +1 -1
  17. package/lib/decoder/Decoder.js.map +1 -1
  18. package/lib/encoder/ChangeTree.d.ts +23 -7
  19. package/lib/encoder/ChangeTree.js +183 -106
  20. package/lib/encoder/ChangeTree.js.map +1 -1
  21. package/lib/encoder/EncodeOperation.d.ts +2 -1
  22. package/lib/encoder/EncodeOperation.js +2 -2
  23. package/lib/encoder/EncodeOperation.js.map +1 -1
  24. package/lib/encoder/Encoder.d.ts +3 -5
  25. package/lib/encoder/Encoder.js +93 -61
  26. package/lib/encoder/Encoder.js.map +1 -1
  27. package/lib/encoder/Root.d.ts +12 -7
  28. package/lib/encoder/Root.js +41 -20
  29. package/lib/encoder/Root.js.map +1 -1
  30. package/lib/encoder/StateView.d.ts +5 -5
  31. package/lib/encoder/StateView.js +29 -23
  32. package/lib/encoder/StateView.js.map +1 -1
  33. package/lib/encoding/encode.js +12 -9
  34. package/lib/encoding/encode.js.map +1 -1
  35. package/lib/types/TypeContext.js +2 -1
  36. package/lib/types/TypeContext.js.map +1 -1
  37. package/lib/types/custom/ArraySchema.js +27 -13
  38. package/lib/types/custom/ArraySchema.js.map +1 -1
  39. package/lib/types/custom/MapSchema.d.ts +3 -1
  40. package/lib/types/custom/MapSchema.js +7 -4
  41. package/lib/types/custom/MapSchema.js.map +1 -1
  42. package/lib/types/symbols.d.ts +8 -6
  43. package/lib/types/symbols.js +9 -7
  44. package/lib/types/symbols.js.map +1 -1
  45. package/lib/utils.js +6 -3
  46. package/lib/utils.js.map +1 -1
  47. package/package.json +1 -1
  48. package/src/Metadata.ts +22 -22
  49. package/src/Schema.ts +33 -25
  50. package/src/annotations.ts +12 -12
  51. package/src/bench_encode.ts +15 -6
  52. package/src/decoder/Decoder.ts +1 -1
  53. package/src/encoder/ChangeTree.ts +220 -115
  54. package/src/encoder/EncodeOperation.ts +5 -1
  55. package/src/encoder/Encoder.ts +110 -68
  56. package/src/encoder/Root.ts +41 -21
  57. package/src/encoder/StateView.ts +32 -28
  58. package/src/encoding/encode.ts +12 -9
  59. package/src/types/TypeContext.ts +2 -1
  60. package/src/types/custom/ArraySchema.ts +39 -17
  61. package/src/types/custom/MapSchema.ts +12 -5
  62. package/src/types/symbols.ts +10 -9
  63. package/src/utils.ts +7 -3
package/lib/utils.js CHANGED
@@ -14,15 +14,18 @@ function dumpChanges(schema) {
14
14
  ops: {},
15
15
  refs: []
16
16
  };
17
- $root.changes.forEach((operations, changeTree) => {
17
+ // for (const refId in $root.changes) {
18
+ $root.changes.forEach(changeTree => {
19
+ const changes = changeTree.indexedOperations;
18
20
  dump.refs.push(`refId#${changeTree.refId}`);
19
- operations.forEach((op, index) => {
21
+ for (const index in changes) {
22
+ const op = changes[index];
20
23
  const opName = spec_1.OPERATION[op];
21
24
  if (!dump.ops[opName]) {
22
25
  dump.ops[opName] = 0;
23
26
  }
24
27
  dump.ops[spec_1.OPERATION[op]]++;
25
- });
28
+ }
26
29
  });
27
30
  return dump;
28
31
  }
package/lib/utils.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":";;AAeA,8BAIC;AAED,kCAkBC;AAED,0CAeC;AAvDD,0CAA4C;AAC5C,6CAA2C;AAa3C,SAAgB,SAAS,CAAC,KAAa;IACnC,OAAO,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAC3C,CAAC,CAAC,KAAK,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CACpC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AACf,CAAC;AAED,SAAgB,WAAW,CAAC,MAAc;IACtC,MAAM,KAAK,GAAG,MAAM,CAAC,kBAAQ,CAAC,CAAC,IAAI,CAAC;IAEpC,MAAM,IAAI,GAAe;QACrB,GAAG,EAAE,EAAE;QACP,IAAI,EAAE,EAAE;KACX,CAAC;IAEF,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,UAAU,EAAE,UAAU,EAAE,EAAE;QAC7C,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,UAAU,CAAC,KAAK,EAAE,CAAC,CAAC;QAC5C,UAAU,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,KAAK,EAAE,EAAE;YAC7B,MAAM,MAAM,GAAG,gBAAS,CAAC,EAAE,CAAC,CAAC;YAC7B,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;gBAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAAC,CAAC;YAChD,IAAI,CAAC,GAAG,CAAC,gBAAS,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;QAC9B,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IAEH,OAAO,IAAI,CAAC;AAChB,CAAC;AAED,SAAgB,eAAe,CAAC,MAAc;IAC1C,+CAA+C;IAC/C,IAAI,CAAC,MAAM,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC;QAChC,OAAO,MAAM,CAAC;IAClB,CAAC;IAED,gDAAgD;IAChD,IAAI,WAAW,GAAG,CAAC,CAAC;IACpB,OAAO,MAAM,GAAG,CAAC,EAAE,CAAC;QAChB,MAAM,KAAK,CAAC,CAAC;QACb,WAAW,EAAE,CAAC;IAClB,CAAC;IAED,6BAA6B;IAC7B,OAAO,CAAC,IAAI,WAAW,CAAC;AAC5B,CAAC","sourcesContent":["import type { Schema } from \"./Schema\";\nimport { OPERATION } from \"./encoding/spec\";\nimport { $changes } from \"./types/symbols\";\n\ntype ChangeItem = [string, number | string, any?];\n\ninterface ChangeDump {\n ops: {\n ADD?: number;\n REMOVE?: number;\n REPLACE?: number;\n },\n refs: string[],\n}\n\nexport function getIndent(level: number) {\n return (new Array(level).fill(0)).map((_, i) =>\n (i === level - 1) ? `└─ ` : ` `\n ).join(\"\");\n}\n\nexport function dumpChanges(schema: Schema) {\n const $root = schema[$changes].root;\n\n const dump: ChangeDump = {\n ops: {},\n refs: []\n };\n\n $root.changes.forEach((operations, changeTree) => {\n dump.refs.push(`refId#${changeTree.refId}`);\n operations.forEach((op, index) => {\n const opName = OPERATION[op];\n if (!dump.ops[opName]) { dump.ops[opName] = 0; }\n dump.ops[OPERATION[op]]++;\n });\n });\n\n return dump;\n}\n\nexport function getNextPowerOf2(number: number) {\n // If number is already a power of 2, return it\n if ((number & (number - 1)) === 0) {\n return number;\n }\n\n // Find the position of the most significant bit\n let msbPosition = 0;\n while (number > 0) {\n number >>= 1;\n msbPosition++;\n }\n\n // Return the next power of 2\n return 1 << msbPosition;\n}"]}
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":";;AAeA,8BAIC;AAED,kCAsBC;AAED,0CAeC;AA3DD,0CAA4C;AAC5C,6CAA2C;AAa3C,SAAgB,SAAS,CAAC,KAAa;IACnC,OAAO,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAC3C,CAAC,CAAC,KAAK,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CACpC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AACf,CAAC;AAED,SAAgB,WAAW,CAAC,MAAc;IACtC,MAAM,KAAK,GAAG,MAAM,CAAC,kBAAQ,CAAC,CAAC,IAAI,CAAC;IAEpC,MAAM,IAAI,GAAe;QACrB,GAAG,EAAE,EAAE;QACP,IAAI,EAAE,EAAE;KACX,CAAC;IAEF,uCAAuC;IACvC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE;QAC/B,MAAM,OAAO,GAAG,UAAU,CAAC,iBAAiB,CAAC;QAE7C,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,UAAU,CAAC,KAAK,EAAE,CAAC,CAAC;QAC5C,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC1B,MAAM,EAAE,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;YAC1B,MAAM,MAAM,GAAG,gBAAS,CAAC,EAAE,CAAC,CAAC;YAC7B,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;gBAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAAC,CAAC;YAChD,IAAI,CAAC,GAAG,CAAC,gBAAS,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;QAC9B,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,OAAO,IAAI,CAAC;AAChB,CAAC;AAED,SAAgB,eAAe,CAAC,MAAc;IAC1C,+CAA+C;IAC/C,IAAI,CAAC,MAAM,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC;QAChC,OAAO,MAAM,CAAC;IAClB,CAAC;IAED,gDAAgD;IAChD,IAAI,WAAW,GAAG,CAAC,CAAC;IACpB,OAAO,MAAM,GAAG,CAAC,EAAE,CAAC;QAChB,MAAM,KAAK,CAAC,CAAC;QACb,WAAW,EAAE,CAAC;IAClB,CAAC;IAED,6BAA6B;IAC7B,OAAO,CAAC,IAAI,WAAW,CAAC;AAC5B,CAAC","sourcesContent":["import type { Schema } from \"./Schema\";\nimport { OPERATION } from \"./encoding/spec\";\nimport { $changes } from \"./types/symbols\";\n\ntype ChangeItem = [string, number | string, any?];\n\ninterface ChangeDump {\n ops: {\n ADD?: number;\n REMOVE?: number;\n REPLACE?: number;\n },\n refs: string[],\n}\n\nexport function getIndent(level: number) {\n return (new Array(level).fill(0)).map((_, i) =>\n (i === level - 1) ? `└─ ` : ` `\n ).join(\"\");\n}\n\nexport function dumpChanges(schema: Schema) {\n const $root = schema[$changes].root;\n\n const dump: ChangeDump = {\n ops: {},\n refs: []\n };\n\n // for (const refId in $root.changes) {\n $root.changes.forEach(changeTree => {\n const changes = changeTree.indexedOperations;\n\n dump.refs.push(`refId#${changeTree.refId}`);\n for (const index in changes) {\n const op = changes[index];\n const opName = OPERATION[op];\n if (!dump.ops[opName]) { dump.ops[opName] = 0; }\n dump.ops[OPERATION[op]]++;\n }\n });\n\n return dump;\n}\n\nexport function getNextPowerOf2(number: number) {\n // If number is already a power of 2, return it\n if ((number & (number - 1)) === 0) {\n return number;\n }\n\n // Find the position of the most significant bit\n let msbPosition = 0;\n while (number > 0) {\n number >>= 1;\n msbPosition++;\n }\n\n // Return the next power of 2\n return 1 << msbPosition;\n}"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@colyseus/schema",
3
- "version": "3.0.0-alpha.34",
3
+ "version": "3.0.0-alpha.35",
4
4
  "description": "Binary state serializer with delta encoding for games",
5
5
  "bin": {
6
6
  "schema-codegen": "./bin/schema-codegen",
package/src/Metadata.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { getPropertyDescriptor, type DefinitionType } from "./annotations";
2
2
  import { getType } from "./types/registry";
3
- import { $descriptors } from "./types/symbols";
3
+ import { $descriptors, $fieldIndexesByViewTag, $numFields, $refTypeFieldIndexes, $viewFieldIndexes } from "./types/symbols";
4
4
 
5
5
  export type MetadataField = {
6
6
  type: DefinitionType,
@@ -12,10 +12,10 @@ export type MetadataField = {
12
12
  };
13
13
 
14
14
  export type Metadata =
15
- { [-1]: number; } & // number of fields
16
- { [-2]: number[]; } & // all field indexes with "view" tag
17
- { [-3]: {[tag: number]: number[]}; } & // field indexes by "view" tag
18
- { [-4]: number[]; } & // all field indexes containing Ref types (Schema, ArraySchema, MapSchema, etc)
15
+ { [$numFields]: number; } & // number of fields
16
+ { [$viewFieldIndexes]: number[]; } & // all field indexes with "view" tag
17
+ { [$fieldIndexesByViewTag]: {[tag: number]: number[]}; } & // field indexes by "view" tag
18
+ { [$refTypeFieldIndexes]: number[]; } & // all field indexes containing Ref types (Schema, ArraySchema, MapSchema, etc)
19
19
  { [field: number]: MetadataField; } & // index => field name
20
20
  { [field: string]: number; } & // field name => field metadata
21
21
  { [$descriptors]: { [field: string]: PropertyDescriptor } } // property descriptors
@@ -61,7 +61,7 @@ export const Metadata = {
61
61
  }
62
62
 
63
63
  // map -1 as last field index
64
- Object.defineProperty(metadata, -1, {
64
+ Object.defineProperty(metadata, $numFields, {
65
65
  value: index,
66
66
  enumerable: false,
67
67
  configurable: true
@@ -76,14 +76,14 @@ export const Metadata = {
76
76
 
77
77
  // if child Ref/complex type, add to -4
78
78
  if (typeof (metadata[index].type) !== "string") {
79
- if (metadata[-4] === undefined) {
80
- Object.defineProperty(metadata, -4, {
79
+ if (metadata[$refTypeFieldIndexes] === undefined) {
80
+ Object.defineProperty(metadata, $refTypeFieldIndexes, {
81
81
  value: [],
82
82
  enumerable: false,
83
83
  configurable: true,
84
84
  });
85
85
  }
86
- metadata[-4].push(index);
86
+ metadata[$refTypeFieldIndexes].push(index);
87
87
  }
88
88
  },
89
89
 
@@ -94,29 +94,29 @@ export const Metadata = {
94
94
  // add 'tag' to the field
95
95
  field.tag = tag;
96
96
 
97
- if (!metadata[-2]) {
97
+ if (!metadata[$viewFieldIndexes]) {
98
98
  // -2: all field indexes with "view" tag
99
- Object.defineProperty(metadata, -2, {
99
+ Object.defineProperty(metadata, $viewFieldIndexes, {
100
100
  value: [],
101
101
  enumerable: false,
102
102
  configurable: true
103
103
  });
104
104
 
105
105
  // -3: field indexes by "view" tag
106
- Object.defineProperty(metadata, -3, {
106
+ Object.defineProperty(metadata, $fieldIndexesByViewTag, {
107
107
  value: {},
108
108
  enumerable: false,
109
109
  configurable: true
110
110
  });
111
111
  }
112
112
 
113
- metadata[-2].push(index);
113
+ metadata[$viewFieldIndexes].push(index);
114
114
 
115
- if (!metadata[-3][tag]) {
116
- metadata[-3][tag] = [];
115
+ if (!metadata[$fieldIndexesByViewTag][tag]) {
116
+ metadata[$fieldIndexesByViewTag][tag] = [];
117
117
  }
118
118
 
119
- metadata[-3][tag].push(index);
119
+ metadata[$fieldIndexesByViewTag][tag].push(index);
120
120
  },
121
121
 
122
122
  setFields(target: any, fields: { [field: string]: DefinitionType }) {
@@ -154,7 +154,7 @@ export const Metadata = {
154
154
  //
155
155
  const metadata = {};
156
156
  klass[Symbol.metadata] = metadata;
157
- Object.defineProperty(metadata, -1, {
157
+ Object.defineProperty(metadata, $numFields, {
158
158
  value: 0,
159
159
  enumerable: false,
160
160
  configurable: true,
@@ -172,7 +172,7 @@ export const Metadata = {
172
172
  // assign parent metadata to current
173
173
  Object.assign(metadata, parentMetadata);
174
174
 
175
- for (let i = 0; i <= parentMetadata[-1]; i++) {
175
+ for (let i = 0; i <= parentMetadata[$numFields]; i++) {
176
176
  const fieldName = parentMetadata[i].name;
177
177
  Object.defineProperty(metadata, fieldName, {
178
178
  value: parentMetadata[fieldName],
@@ -181,8 +181,8 @@ export const Metadata = {
181
181
  });
182
182
  }
183
183
 
184
- Object.defineProperty(metadata, -1, {
185
- value: parentMetadata[-1],
184
+ Object.defineProperty(metadata, $numFields, {
185
+ value: parentMetadata[$numFields],
186
186
  enumerable: false,
187
187
  configurable: true,
188
188
  writable: true,
@@ -198,14 +198,14 @@ export const Metadata = {
198
198
  isValidInstance(klass: any) {
199
199
  return (
200
200
  klass.constructor[Symbol.metadata] &&
201
- Object.prototype.hasOwnProperty.call(klass.constructor[Symbol.metadata], -1) as boolean
201
+ Object.prototype.hasOwnProperty.call(klass.constructor[Symbol.metadata], $numFields) as boolean
202
202
  );
203
203
  },
204
204
 
205
205
  getFields(klass: any) {
206
206
  const metadata: Metadata = klass[Symbol.metadata];
207
207
  const fields = {};
208
- for (let i = 0; i <= metadata[-1]; i++) {
208
+ for (let i = 0; i <= metadata[$numFields]; i++) {
209
209
  fields[metadata[i].name] = metadata[i].type;
210
210
  }
211
211
  return fields;
package/src/Schema.ts CHANGED
@@ -3,7 +3,7 @@ import { DEFAULT_VIEW_TAG, DefinitionType } from "./annotations";
3
3
 
4
4
  import { NonFunctionPropNames, ToJSON } from './types/HelperTypes';
5
5
 
6
- import { ChangeTree, Ref } from './encoder/ChangeTree';
6
+ import { ChangeSet, ChangeTree, Ref } from './encoder/ChangeTree';
7
7
  import { $changes, $decoder, $deleteByIndex, $descriptors, $encoder, $filter, $getByIndex, $track } from './types/symbols';
8
8
  import { StateView } from './encoder/StateView';
9
9
 
@@ -19,6 +19,8 @@ export abstract class Schema {
19
19
  static [$encoder] = encodeSchemaOperation;
20
20
  static [$decoder] = decodeSchemaOperation;
21
21
 
22
+ // public [$changes]: ChangeTree;
23
+
22
24
  /**
23
25
  * Assign the property descriptors required to track changes on this instance.
24
26
  * @param instance
@@ -84,14 +86,7 @@ export abstract class Schema {
84
86
  // inline
85
87
  // Schema.initialize(this);
86
88
  //
87
-
88
- Object.defineProperty(this, $changes, {
89
- value: new ChangeTree(this),
90
- enumerable: false,
91
- writable: true
92
- });
93
-
94
- Object.defineProperties(this, this.constructor[Symbol.metadata]?.[$descriptors] || {});
89
+ Schema.initialize(this);
95
90
 
96
91
  //
97
92
  // Assign initial values
@@ -187,7 +182,7 @@ export abstract class Schema {
187
182
  const contents = (jsonContents) ? ` - ${JSON.stringify(ref.toJSON())}` : "";
188
183
 
189
184
  let output = "";
190
- output += `${getIndent(level)}${ref.constructor.name} (${ref[$changes].refId})${contents}\n`;
185
+ output += `${getIndent(level)}${ref.constructor.name} (refId: ${ref[$changes].refId})${contents}\n`;
191
186
 
192
187
  changeTree.forEachChild((childChangeTree) =>
193
188
  output += this.debugRefIds(childChangeTree.ref, jsonContents, level + 1));
@@ -204,31 +199,41 @@ export abstract class Schema {
204
199
  * @returns
205
200
  */
206
201
  static debugChanges(instance: Ref, isEncodeAll: boolean = false) {
207
- const changeTree = instance[$changes];
202
+ const changeTree: ChangeTree = instance[$changes];
208
203
 
209
204
  const changeSet = (isEncodeAll) ? changeTree.allChanges : changeTree.changes;
210
205
  const changeSetName = (isEncodeAll) ? "allChanges" : "changes";
211
206
 
212
207
  let output = `${instance.constructor.name} (${changeTree.refId}) -> .${changeSetName}:\n`;
213
208
 
214
- function dumpChangeSet(changeSet: Map<number, OPERATION>) {
215
- Array.from(changeSet)
216
- .sort((a, b) => a[0] - b[0])
217
- .forEach(([index, operation]) =>
218
- output += `- [${index}]: ${OPERATION[operation]} (${JSON.stringify(changeTree.getValue(index, isEncodeAll))})\n`
219
- );
209
+ function dumpChangeSet(changeSet: ChangeSet) {
210
+ changeSet.operations
211
+ .filter(op => op)
212
+ .forEach((index) => {
213
+ const operation = changeTree.indexedOperations[index];
214
+ console.log({ index, operation })
215
+ output += `- [${index}]: ${OPERATION[operation]} (${JSON.stringify(changeTree.getValue(Number(index), isEncodeAll))})\n`
216
+ });
220
217
  }
221
218
 
222
219
  dumpChangeSet(changeSet);
223
220
 
224
221
  // display filtered changes
225
- if (!isEncodeAll && changeTree.filteredChanges?.size > 0) {
222
+ if (
223
+ !isEncodeAll &&
224
+ changeTree.filteredChanges &&
225
+ (changeTree.filteredChanges.operations).filter(op => op).length > 0
226
+ ) {
226
227
  output += `${instance.constructor.name} (${changeTree.refId}) -> .filteredChanges:\n`;
227
228
  dumpChangeSet(changeTree.filteredChanges);
228
229
  }
229
230
 
230
231
  // display filtered changes
231
- if (isEncodeAll && changeTree.allFilteredChanges?.size > 0) {
232
+ if (
233
+ isEncodeAll &&
234
+ changeTree.allFilteredChanges &&
235
+ (changeTree.allFilteredChanges.operations).filter(op => op).length > 0
236
+ ) {
232
237
  output += `${instance.constructor.name} (${changeTree.refId}) -> .allFilteredChanges:\n`;
233
238
  dumpChangeSet(changeTree.allFilteredChanges);
234
239
  }
@@ -240,12 +245,15 @@ export abstract class Schema {
240
245
  let output = "";
241
246
 
242
247
  const rootChangeTree = ref[$changes];
248
+ const root = rootChangeTree.root;
243
249
  const changeTrees: Map<ChangeTree, ChangeTree[]> = new Map();
244
250
 
245
251
  let totalInstances = 0;
246
252
  let totalOperations = 0;
247
253
 
248
- for (const [changeTree, changes] of (rootChangeTree.root[changeSetName].entries())) {
254
+ for (const [refId, changes] of Object.entries(root[changeSetName])) {
255
+ const changeTree = root.changeTrees[refId];
256
+
249
257
  let includeChangeTree = false;
250
258
  let parentChangeTrees: ChangeTree[] = [];
251
259
  let parentChangeTree = changeTree.parent?.[$changes];
@@ -266,7 +274,7 @@ export abstract class Schema {
266
274
 
267
275
  if (includeChangeTree) {
268
276
  totalInstances += 1;
269
- totalOperations += changes.size;
277
+ totalOperations += Object.keys(changes).length;
270
278
  changeTrees.set(changeTree, parentChangeTrees.reverse());
271
279
  }
272
280
  }
@@ -287,17 +295,17 @@ export abstract class Schema {
287
295
  }
288
296
  });
289
297
 
290
- const changes = changeTree.changes;
298
+ const changes = changeTree.indexedOperations;
291
299
  const level = parentChangeTrees.length;
292
300
  const indent = getIndent(level);
293
301
 
294
302
  const parentIndex = (level > 0) ? `(${changeTree.parentIndex}) ` : "";
295
- output += `${indent}${parentIndex}${changeTree.ref.constructor.name} (refId: ${changeTree.refId}) - changes: ${changes.size}\n`;
303
+ output += `${indent}${parentIndex}${changeTree.ref.constructor.name} (refId: ${changeTree.refId}) - changes: ${Object.keys(changes).length}\n`;
296
304
 
297
- for (const [index, operation] of changes) {
305
+ for (const index in changes) {
306
+ const operation = changes[index];
298
307
  output += `${getIndent(level + 1)}${OPERATION[operation]}: ${index}\n`;
299
308
  }
300
-
301
309
  }
302
310
 
303
311
  return `${output}`;
@@ -3,7 +3,7 @@ import { Schema } from './Schema';
3
3
  import { ArraySchema } from './types/custom/ArraySchema';
4
4
  import { MapSchema } from './types/custom/MapSchema';
5
5
  import { Metadata } from "./Metadata";
6
- import { $changes, $childType, $descriptors, $track } from "./types/symbols";
6
+ import { $changes, $childType, $descriptors, $numFields, $track } from "./types/symbols";
7
7
  import { TypeDefinition, getType } from "./types/registry";
8
8
  import { OPERATION } from "./encoding/spec";
9
9
  import { TypeContext } from "./types/TypeContext";
@@ -82,8 +82,8 @@ export function entity(constructor, context: ClassDecoratorContext) {
82
82
  // // detect index for this field, considering inheritance
83
83
  // //
84
84
  // const parent = Object.getPrototypeOf(context.metadata);
85
- // let fieldIndex: number = context.metadata[-1] // current structure already has fields defined
86
- // ?? (parent && parent[-1]) // parent structure has fields defined
85
+ // let fieldIndex: number = context.metadata[$numFields] // current structure already has fields defined
86
+ // ?? (parent && parent[$numFields]) // parent structure has fields defined
87
87
  // ?? -1; // no fields defined
88
88
  // fieldIndex++;
89
89
 
@@ -237,8 +237,8 @@ export function view<T> (tag: number = DEFAULT_VIEW_TAG) {
237
237
  // //
238
238
  // metadata[fieldIndex] = {
239
239
  // type: undefined,
240
- // index: (metadata[-1] // current structure already has fields defined
241
- // ?? (parentMetadata && parentMetadata[-1]) // parent structure has fields defined
240
+ // index: (metadata[$numFields] // current structure already has fields defined
241
+ // ?? (parentMetadata && parentMetadata[$numFields]) // parent structure has fields defined
242
242
  // ?? -1) + 1 // no fields defined
243
243
  // }
244
244
  // }
@@ -265,8 +265,8 @@ export function unreliable<T> (target: T, field: string) {
265
265
  // //
266
266
  // metadata[field] = {
267
267
  // type: undefined,
268
- // index: (metadata[-1] // current structure already has fields defined
269
- // ?? (parentMetadata && parentMetadata[-1]) // parent structure has fields defined
268
+ // index: (metadata[$numFields] // current structure already has fields defined
269
+ // ?? (parentMetadata && parentMetadata[$numFields]) // parent structure has fields defined
270
270
  // ?? -1) + 1 // no fields defined
271
271
  // }
272
272
  // }
@@ -319,8 +319,8 @@ export function type (
319
319
  //
320
320
  // detect index for this field, considering inheritance
321
321
  //
322
- fieldIndex = metadata[-1] // current structure already has fields defined
323
- ?? (parentMetadata && parentMetadata[-1]) // parent structure has fields defined
322
+ fieldIndex = metadata[$numFields] // current structure already has fields defined
323
+ ?? (parentMetadata && parentMetadata[$numFields]) // parent structure has fields defined
324
324
  ?? -1; // no fields defined
325
325
  fieldIndex++;
326
326
  }
@@ -368,7 +368,7 @@ export function getPropertyDescriptor(
368
368
  return {
369
369
  get: function () { return this[fieldCached]; },
370
370
  set: function (this: Schema, value: any) {
371
- const previousValue = this[fieldCached] || undefined;
371
+ const previousValue = this[fieldCached] ?? undefined;
372
372
 
373
373
  // skip if value is the same as cached.
374
374
  if (value === previousValue) { return; }
@@ -454,8 +454,8 @@ export function deprecated(throws: boolean = true): PropertyDecorator {
454
454
  // //
455
455
  // metadata[field] = {
456
456
  // type: undefined,
457
- // index: (metadata[-1] // current structure already has fields defined
458
- // ?? (parentMetadata && parentMetadata[-1]) // parent structure has fields defined
457
+ // index: (metadata[$numFields] // current structure already has fields defined
458
+ // ?? (parentMetadata && parentMetadata[$numFields]) // parent structure has fields defined
459
459
  // ?? -1) + 1 // no fields defined
460
460
  // }
461
461
  // }
@@ -1,8 +1,5 @@
1
1
  import { nanoid } from "nanoid";
2
2
  import { Schema, type, MapSchema, ArraySchema, Encoder } from ".";
3
- import * as benchmark from "benchmark";
4
-
5
- const suite = new benchmark.Suite();
6
3
 
7
4
  class Attribute extends Schema {
8
5
  @type("string") name: string;
@@ -66,8 +63,13 @@ now = Date.now();
66
63
  // }
67
64
  // console.log(Date.now() - now);
68
65
 
66
+ const total = 100;
69
67
  const allEncodes = Date.now();
70
- for (let i = 0; i < 100; i++) {
68
+
69
+ let avgTimeToEncode = 0;
70
+ let avgTimeToMakeChanges = 0;
71
+
72
+ for (let i = 0; i < total; i++) {
71
73
  now = Date.now();
72
74
  for (let j = 0; j < 50; j++) {
73
75
  const player = new Player();
@@ -87,13 +89,20 @@ for (let i = 0; i < 100; i++) {
87
89
  player.items.set(`item-${k}`, item);
88
90
  }
89
91
  }
90
- console.log("time to make changes:", Date.now() - now);
92
+ const timeToMakeChanges = Date.now() - now;
93
+ console.log("time to make changes:", timeToMakeChanges);
94
+ avgTimeToMakeChanges += timeToMakeChanges;
91
95
 
92
96
  now = Date.now();
93
97
  encoder.encode();
94
98
  encoder.discardChanges();
95
- console.log("time to encode:", Date.now() - now);
99
+
100
+ const timeToEncode = Date.now() - now;
101
+ console.log("time to encode:", timeToEncode);
102
+ avgTimeToEncode += timeToEncode;
96
103
  }
104
+ console.log("avg time to encode:", (avgTimeToEncode) / total);
105
+ console.log("avg time to make changes:", (avgTimeToMakeChanges) / total);
97
106
  console.log("time for all encodes:", Date.now() - allEncodes);
98
107
 
99
108
  console.log(Array.from(encoder.encodeAll()).length, "bytes");
@@ -68,7 +68,7 @@ export class Decoder<T extends Schema = any> {
68
68
  ref[$onDecodeEnd]?.()
69
69
  ref = nextRef;
70
70
 
71
- decoder = ref['constructor'][$decoder];
71
+ decoder = ref.constructor[$decoder];
72
72
 
73
73
  continue;
74
74
  }