@colyseus/schema 4.0.0 → 4.0.1
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/lib/encoder/Encoder.d.ts
CHANGED
|
@@ -6,16 +6,16 @@ import type { StateView } from "./StateView";
|
|
|
6
6
|
import type { ChangeSetName } from "./ChangeTree";
|
|
7
7
|
export declare class Encoder<T extends Schema = any> {
|
|
8
8
|
static BUFFER_SIZE: number;
|
|
9
|
-
sharedBuffer: Uint8Array
|
|
9
|
+
sharedBuffer: Uint8Array;
|
|
10
10
|
context: TypeContext;
|
|
11
11
|
state: T;
|
|
12
12
|
root: Root;
|
|
13
13
|
constructor(state: T);
|
|
14
14
|
protected setState(state: T): void;
|
|
15
|
-
encode(it?: Iterator, view?: StateView, buffer?: Uint8Array
|
|
16
|
-
encodeAll(it?: Iterator, buffer?: Uint8Array
|
|
17
|
-
encodeAllView(view: StateView, sharedOffset: number, it: Iterator, bytes?: Uint8Array
|
|
18
|
-
encodeView(view: StateView, sharedOffset: number, it: Iterator, bytes?: Uint8Array
|
|
15
|
+
encode(it?: Iterator, view?: StateView, buffer?: Uint8Array, changeSetName?: ChangeSetName, isEncodeAll?: boolean, initialOffset?: number): Uint8Array;
|
|
16
|
+
encodeAll(it?: Iterator, buffer?: Uint8Array): Uint8Array<ArrayBufferLike>;
|
|
17
|
+
encodeAllView(view: StateView, sharedOffset: number, it: Iterator, bytes?: Uint8Array): Uint8Array<ArrayBufferLike>;
|
|
18
|
+
encodeView(view: StateView, sharedOffset: number, it: Iterator, bytes?: Uint8Array): Uint8Array<ArrayBufferLike>;
|
|
19
19
|
discardChanges(): void;
|
|
20
20
|
tryEncodeTypeId(bytes: Uint8Array, baseType: typeof Schema, targetType: typeof Schema, it: Iterator): void;
|
|
21
21
|
get hasChanges(): boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Encoder.js","sourceRoot":"","sources":["../../src/encoder/Encoder.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Schema } from \"../Schema\";\nimport { TypeContext } from \"../types/TypeContext\";\nimport { $changes, $encoder, $filter, $getByIndex, $refId } from \"../types/symbols\";\n\nimport { encode } from \"../encoding/encode\";\nimport type { Iterator } from \"../encoding/decode\";\n\nimport { OPERATION, SWITCH_TO_STRUCTURE, TYPE_ID } from '../encoding/spec';\nimport { Root } from \"./Root\";\n\nimport type { StateView } from \"./StateView\";\nimport type { Metadata } from \"../Metadata\";\nimport type { ChangeSetName, ChangeTree, ChangeTreeList, ChangeTreeNode } from \"./ChangeTree\";\nimport { createChangeTreeList } from \"./ChangeTree\";\n\nfunction concatBytes(a: Uint8Array, b: Uint8Array): Uint8Array {\n const result = new Uint8Array(a.length + b.length);\n result.set(a, 0);\n result.set(b, a.length);\n return result;\n}\n\nexport class Encoder<T extends Schema = any> {\n static BUFFER_SIZE = 8 * 1024; // 8KB\n sharedBuffer = new Uint8Array(Encoder.BUFFER_SIZE);\n\n context: TypeContext;\n state: T;\n\n root: Root;\n\n constructor(state: T) {\n //\n // Use .cache() here to avoid re-creating a new context for every new room instance.\n //\n // We may need to make this optional in case of dynamically created\n // schemas - which would lead to memory leaks\n //\n this.context = TypeContext.cache(state.constructor as typeof Schema);\n this.root = new Root(this.context);\n\n this.setState(state);\n\n // console.log(\">>>>>>>>>>>>>>>> Encoder types\");\n // this.context.schemas.forEach((id, schema) => {\n // console.log(\"type:\", id, schema.name, Object.keys(schema[Symbol.metadata]));\n // });\n }\n\n protected setState(state: T) {\n this.state = state;\n this.state[$changes].setRoot(this.root);\n }\n\n encode(\n it: Iterator = { offset: 0 },\n view?: StateView,\n buffer = this.sharedBuffer,\n changeSetName: ChangeSetName = \"changes\",\n isEncodeAll = changeSetName === \"allChanges\",\n initialOffset = it.offset // cache current offset in case we need to resize the buffer\n ): Uint8Array {\n const hasView = (view !== undefined);\n const rootChangeTree = this.state[$changes];\n\n let current: ChangeTreeList | ChangeTreeNode = this.root[changeSetName];\n\n while (current = current.next) {\n const changeTree = (current as ChangeTreeNode).changeTree;\n\n if (hasView) {\n if (!view.isChangeTreeVisible(changeTree)) {\n // console.log(\"MARK AS INVISIBLE:\", { ref: changeTree.ref.constructor.name, refId: changeTree.ref[$refId], raw: changeTree.ref.toJSON() });\n view.invisible.add(changeTree);\n continue; // skip this change tree\n }\n view.invisible.delete(changeTree); // remove from invisible list\n }\n\n const changeSet = changeTree[changeSetName];\n const ref = changeTree.ref;\n\n // TODO: avoid iterating over change tree if no changes were made\n const numChanges = changeSet.operations.length;\n if (numChanges === 0) { continue; }\n\n const ctor = ref.constructor;\n const encoder = ctor[$encoder];\n const filter = ctor[$filter];\n const metadata = ctor[Symbol.metadata];\n\n // skip root `refId` if it's the first change tree\n // (unless it \"hasView\", which will need to revisit the root)\n if (hasView || it.offset > initialOffset || changeTree !== rootChangeTree) {\n buffer[it.offset++] = SWITCH_TO_STRUCTURE & 255;\n encode.number(buffer, ref[$refId], it);\n }\n\n for (let j = 0; j < numChanges; j++) {\n const fieldIndex = changeSet.operations[j];\n\n if (fieldIndex < 0) {\n // \"pure\" operation without fieldIndex (e.g. CLEAR, REVERSE, etc.)\n // encode and continue early - no need to reach $filter check\n buffer[it.offset++] = Math.abs(fieldIndex) & 255;\n continue;\n }\n\n const operation = (isEncodeAll)\n ? OPERATION.ADD\n : changeTree.indexedOperations[fieldIndex];\n\n //\n // first pass (encodeAll), identify \"filtered\" operations without encoding them\n // they will be encoded per client, based on their view.\n //\n // TODO: how can we optimize filtering out \"encode all\" operations?\n // TODO: avoid checking if no view tags were defined\n //\n if (fieldIndex === undefined || operation === undefined || (filter && !filter(ref, fieldIndex, view))) {\n // console.log(\"ADD AS INVISIBLE:\", fieldIndex, changeTree.ref.constructor.name)\n // view?.invisible.add(changeTree);\n continue;\n }\n\n encoder(this, buffer, changeTree, fieldIndex, operation, it, isEncodeAll, hasView, metadata);\n }\n }\n\n if (it.offset > buffer.byteLength) {\n // we can assume that n + 1 BUFFER_SIZE will suffice given that we are likely done with encoding at this point\n // multiples of BUFFER_SIZE are faster to allocate than arbitrary sizes\n const newSize = Math.ceil(it.offset / Encoder.BUFFER_SIZE) * Encoder.BUFFER_SIZE;\n\n console.warn(`@colyseus/schema buffer overflow. Encoded state is higher than default BUFFER_SIZE. Use the following to increase default BUFFER_SIZE:\n\n import { Encoder } from \"@colyseus/schema\";\n Encoder.BUFFER_SIZE = ${Math.round(newSize / 1024)} * 1024; // ${Math.round(newSize / 1024)} KB\n`);\n\n //\n // resize buffer and re-encode (TODO: can we avoid re-encoding here?)\n // -> No we probably can't unless we catch the need for resize before encoding which is likely more computationally expensive than resizing on demand\n //\n const newBuffer = new Uint8Array(newSize);\n newBuffer.set(buffer); // copy previous encoding steps beyond the initialOffset\n buffer = newBuffer;\n\n // assign resized buffer to local sharedBuffer\n if (buffer === this.sharedBuffer) {\n this.sharedBuffer = buffer;\n }\n\n return this.encode({ offset: initialOffset }, view, buffer, changeSetName, isEncodeAll);\n\n } else {\n\n return buffer.subarray(0, it.offset);\n }\n }\n\n encodeAll(it: Iterator = { offset: 0 }, buffer = this.sharedBuffer) {\n return this.encode(it, undefined, buffer, \"allChanges\", true);\n }\n\n encodeAllView(view: StateView, sharedOffset: number, it: Iterator, bytes = this.sharedBuffer) {\n const viewOffset = it.offset;\n\n // try to encode \"filtered\" changes\n this.encode(it, view, bytes, \"allFilteredChanges\", true, viewOffset);\n\n return concatBytes(\n bytes.subarray(0, sharedOffset),\n bytes.subarray(viewOffset, it.offset)\n );\n }\n\n encodeView(view: StateView, sharedOffset: number, it: Iterator, bytes = this.sharedBuffer) {\n const viewOffset = it.offset;\n\n // encode visibility changes (add/remove for this view)\n for (const [refId, changes] of view.changes) {\n const changeTree: ChangeTree = this.root.changeTrees[refId];\n\n if (changeTree === undefined) {\n // detached instance, remove from view and skip.\n // console.log(\"detached instance, remove from view and skip.\", refId);\n view.changes.delete(refId);\n continue;\n }\n\n const keys = Object.keys(changes);\n if (keys.length === 0) {\n // FIXME: avoid having empty changes if no changes were made\n // console.log(\"changes.size === 0, skip\", refId, changeTree.ref.constructor.name);\n continue;\n }\n\n const ref = changeTree.ref;\n\n const ctor = ref.constructor;\n const encoder = ctor[$encoder];\n const metadata = ctor[Symbol.metadata];\n\n bytes[it.offset++] = SWITCH_TO_STRUCTURE & 255;\n encode.number(bytes, ref[$refId], it);\n\n for (let i = 0, numChanges = keys.length; i < numChanges; i++) {\n const index = Number(keys[i]);\n // workaround when using view.add() on item that has been deleted from state (see test \"adding to view item that has been removed from state\")\n const value = changeTree.ref[$getByIndex](index);\n const operation = (value !== undefined && changes[index]) || OPERATION.DELETE;\n\n // isEncodeAll = false\n // hasView = true\n encoder(this, bytes, changeTree, index, operation, it, false, true, metadata);\n }\n }\n\n //\n // TODO: only clear view changes after all views are encoded\n // (to allow re-using StateView's for multiple clients)\n //\n // clear \"view\" changes after encoding\n view.changes.clear();\n\n // try to encode \"filtered\" changes\n this.encode(it, view, bytes, \"filteredChanges\", false, viewOffset);\n\n return concatBytes(\n bytes.subarray(0, sharedOffset),\n bytes.subarray(viewOffset, it.offset)\n );\n }\n\n discardChanges() {\n // discard shared changes\n let current = this.root.changes.next;\n while (current) {\n current.changeTree.endEncode('changes');\n current = current.next;\n }\n this.root.changes = createChangeTreeList();\n\n // discard filtered changes\n current = this.root.filteredChanges.next;\n while (current) {\n current.changeTree.endEncode('filteredChanges');\n current = current.next;\n }\n this.root.filteredChanges = createChangeTreeList();\n }\n\n tryEncodeTypeId (bytes: Uint8Array, baseType: typeof Schema, targetType: typeof Schema, it: Iterator) {\n const baseTypeId = this.context.getTypeId(baseType);\n const targetTypeId = this.context.getTypeId(targetType);\n\n if (targetTypeId === undefined) {\n console.warn(`@colyseus/schema WARNING: Class \"${targetType.name}\" is not registered on TypeRegistry - Please either tag the class with @entity or define a @type() field.`);\n return;\n }\n\n if (baseTypeId !== targetTypeId) {\n bytes[it.offset++] = TYPE_ID & 255;\n encode.number(bytes, targetTypeId, it);\n }\n }\n\n get hasChanges() {\n return (\n this.root.changes.next !== undefined ||\n this.root.filteredChanges.next !== undefined\n );\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"Encoder.js","sourceRoot":"","sources":["../../src/encoder/Encoder.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Schema } from \"../Schema\";\nimport { TypeContext } from \"../types/TypeContext\";\nimport { $changes, $encoder, $filter, $getByIndex, $refId } from \"../types/symbols\";\n\nimport { encode } from \"../encoding/encode\";\nimport type { Iterator } from \"../encoding/decode\";\n\nimport { OPERATION, SWITCH_TO_STRUCTURE, TYPE_ID } from '../encoding/spec';\nimport { Root } from \"./Root\";\n\nimport type { StateView } from \"./StateView\";\nimport type { ChangeSetName, ChangeTree, ChangeTreeList, ChangeTreeNode } from \"./ChangeTree\";\nimport { createChangeTreeList } from \"./ChangeTree\";\n\nfunction concatBytes(a: Uint8Array, b: Uint8Array): Uint8Array {\n const result = new Uint8Array(a.length + b.length);\n result.set(a, 0);\n result.set(b, a.length);\n return result;\n}\n\nexport class Encoder<T extends Schema = any> {\n static BUFFER_SIZE = 8 * 1024; // 8KB\n sharedBuffer: Uint8Array = new Uint8Array(Encoder.BUFFER_SIZE);\n\n context: TypeContext;\n state: T;\n\n root: Root;\n\n constructor(state: T) {\n //\n // Use .cache() here to avoid re-creating a new context for every new room instance.\n //\n // We may need to make this optional in case of dynamically created\n // schemas - which would lead to memory leaks\n //\n this.context = TypeContext.cache(state.constructor as typeof Schema);\n this.root = new Root(this.context);\n\n this.setState(state);\n\n // console.log(\">>>>>>>>>>>>>>>> Encoder types\");\n // this.context.schemas.forEach((id, schema) => {\n // console.log(\"type:\", id, schema.name, Object.keys(schema[Symbol.metadata]));\n // });\n }\n\n protected setState(state: T) {\n this.state = state;\n this.state[$changes].setRoot(this.root);\n }\n\n encode(\n it: Iterator = { offset: 0 },\n view?: StateView,\n buffer: Uint8Array = this.sharedBuffer,\n changeSetName: ChangeSetName = \"changes\",\n isEncodeAll = changeSetName === \"allChanges\",\n initialOffset = it.offset // cache current offset in case we need to resize the buffer\n ): Uint8Array {\n const hasView = (view !== undefined);\n const rootChangeTree = this.state[$changes];\n\n let current: ChangeTreeList | ChangeTreeNode = this.root[changeSetName];\n\n while (current = current.next) {\n const changeTree = (current as ChangeTreeNode).changeTree;\n\n if (hasView) {\n if (!view.isChangeTreeVisible(changeTree)) {\n // console.log(\"MARK AS INVISIBLE:\", { ref: changeTree.ref.constructor.name, refId: changeTree.ref[$refId], raw: changeTree.ref.toJSON() });\n view.invisible.add(changeTree);\n continue; // skip this change tree\n }\n view.invisible.delete(changeTree); // remove from invisible list\n }\n\n const changeSet = changeTree[changeSetName];\n const ref = changeTree.ref;\n\n // TODO: avoid iterating over change tree if no changes were made\n const numChanges = changeSet.operations.length;\n if (numChanges === 0) { continue; }\n\n const ctor = ref.constructor;\n const encoder = ctor[$encoder];\n const filter = ctor[$filter];\n const metadata = ctor[Symbol.metadata];\n\n // skip root `refId` if it's the first change tree\n // (unless it \"hasView\", which will need to revisit the root)\n if (hasView || it.offset > initialOffset || changeTree !== rootChangeTree) {\n buffer[it.offset++] = SWITCH_TO_STRUCTURE & 255;\n encode.number(buffer, ref[$refId], it);\n }\n\n for (let j = 0; j < numChanges; j++) {\n const fieldIndex = changeSet.operations[j];\n\n if (fieldIndex < 0) {\n // \"pure\" operation without fieldIndex (e.g. CLEAR, REVERSE, etc.)\n // encode and continue early - no need to reach $filter check\n buffer[it.offset++] = Math.abs(fieldIndex) & 255;\n continue;\n }\n\n const operation = (isEncodeAll)\n ? OPERATION.ADD\n : changeTree.indexedOperations[fieldIndex];\n\n //\n // first pass (encodeAll), identify \"filtered\" operations without encoding them\n // they will be encoded per client, based on their view.\n //\n // TODO: how can we optimize filtering out \"encode all\" operations?\n // TODO: avoid checking if no view tags were defined\n //\n if (fieldIndex === undefined || operation === undefined || (filter && !filter(ref, fieldIndex, view))) {\n // console.log(\"ADD AS INVISIBLE:\", fieldIndex, changeTree.ref.constructor.name)\n // view?.invisible.add(changeTree);\n continue;\n }\n\n encoder(this, buffer, changeTree, fieldIndex, operation, it, isEncodeAll, hasView, metadata);\n }\n }\n\n if (it.offset > buffer.byteLength) {\n // we can assume that n + 1 BUFFER_SIZE will suffice given that we are likely done with encoding at this point\n // multiples of BUFFER_SIZE are faster to allocate than arbitrary sizes\n const newSize = Math.ceil(it.offset / Encoder.BUFFER_SIZE) * Encoder.BUFFER_SIZE;\n\n console.warn(`@colyseus/schema buffer overflow. Encoded state is higher than default BUFFER_SIZE. Use the following to increase default BUFFER_SIZE:\n\n import { Encoder } from \"@colyseus/schema\";\n Encoder.BUFFER_SIZE = ${Math.round(newSize / 1024)} * 1024; // ${Math.round(newSize / 1024)} KB\n`);\n\n //\n // resize buffer and re-encode (TODO: can we avoid re-encoding here?)\n // -> No we probably can't unless we catch the need for resize before encoding which is likely more computationally expensive than resizing on demand\n //\n const newBuffer = new Uint8Array(newSize);\n newBuffer.set(buffer); // copy previous encoding steps beyond the initialOffset\n buffer = newBuffer;\n\n // assign resized buffer to local sharedBuffer\n if (buffer === this.sharedBuffer) {\n this.sharedBuffer = buffer;\n }\n\n return this.encode({ offset: initialOffset }, view, buffer, changeSetName, isEncodeAll);\n\n } else {\n\n return buffer.subarray(0, it.offset);\n }\n }\n\n encodeAll(\n it: Iterator = { offset: 0 },\n buffer: Uint8Array = this.sharedBuffer\n ) {\n return this.encode(it, undefined, buffer, \"allChanges\", true);\n }\n\n encodeAllView(\n view: StateView,\n sharedOffset: number,\n it: Iterator,\n bytes: Uint8Array = this.sharedBuffer\n ) {\n const viewOffset = it.offset;\n\n // try to encode \"filtered\" changes\n this.encode(it, view, bytes, \"allFilteredChanges\", true, viewOffset);\n\n return concatBytes(\n bytes.subarray(0, sharedOffset),\n bytes.subarray(viewOffset, it.offset)\n );\n }\n\n encodeView(\n view: StateView,\n sharedOffset: number,\n it: Iterator,\n bytes: Uint8Array = this.sharedBuffer\n ) {\n const viewOffset = it.offset;\n\n // encode visibility changes (add/remove for this view)\n for (const [refId, changes] of view.changes) {\n const changeTree: ChangeTree = this.root.changeTrees[refId];\n\n if (changeTree === undefined) {\n // detached instance, remove from view and skip.\n // console.log(\"detached instance, remove from view and skip.\", refId);\n view.changes.delete(refId);\n continue;\n }\n\n const keys = Object.keys(changes);\n if (keys.length === 0) {\n // FIXME: avoid having empty changes if no changes were made\n // console.log(\"changes.size === 0, skip\", refId, changeTree.ref.constructor.name);\n continue;\n }\n\n const ref = changeTree.ref;\n\n const ctor = ref.constructor;\n const encoder = ctor[$encoder];\n const metadata = ctor[Symbol.metadata];\n\n bytes[it.offset++] = SWITCH_TO_STRUCTURE & 255;\n encode.number(bytes, ref[$refId], it);\n\n for (let i = 0, numChanges = keys.length; i < numChanges; i++) {\n const index = Number(keys[i]);\n // workaround when using view.add() on item that has been deleted from state (see test \"adding to view item that has been removed from state\")\n const value = changeTree.ref[$getByIndex](index);\n const operation = (value !== undefined && changes[index]) || OPERATION.DELETE;\n\n // isEncodeAll = false\n // hasView = true\n encoder(this, bytes, changeTree, index, operation, it, false, true, metadata);\n }\n }\n\n //\n // TODO: only clear view changes after all views are encoded\n // (to allow re-using StateView's for multiple clients)\n //\n // clear \"view\" changes after encoding\n view.changes.clear();\n\n // try to encode \"filtered\" changes\n this.encode(it, view, bytes, \"filteredChanges\", false, viewOffset);\n\n return concatBytes(\n bytes.subarray(0, sharedOffset),\n bytes.subarray(viewOffset, it.offset)\n );\n }\n\n discardChanges() {\n // discard shared changes\n let current = this.root.changes.next;\n while (current) {\n current.changeTree.endEncode('changes');\n current = current.next;\n }\n this.root.changes = createChangeTreeList();\n\n // discard filtered changes\n current = this.root.filteredChanges.next;\n while (current) {\n current.changeTree.endEncode('filteredChanges');\n current = current.next;\n }\n this.root.filteredChanges = createChangeTreeList();\n }\n\n tryEncodeTypeId(\n bytes: Uint8Array,\n baseType: typeof Schema,\n targetType: typeof Schema,\n it: Iterator\n ) {\n const baseTypeId = this.context.getTypeId(baseType);\n const targetTypeId = this.context.getTypeId(targetType);\n\n if (targetTypeId === undefined) {\n console.warn(`@colyseus/schema WARNING: Class \"${targetType.name}\" is not registered on TypeRegistry - Please either tag the class with @entity or define a @type() field.`);\n return;\n }\n\n if (baseTypeId !== targetTypeId) {\n bytes[it.offset++] = TYPE_ID & 255;\n encode.number(bytes, targetTypeId, it);\n }\n }\n\n get hasChanges() {\n return (\n this.root.changes.next !== undefined ||\n this.root.filteredChanges.next !== undefined\n );\n }\n}\n"]}
|
package/package.json
CHANGED
package/src/encoder/Encoder.ts
CHANGED
|
@@ -9,7 +9,6 @@ import { OPERATION, SWITCH_TO_STRUCTURE, TYPE_ID } from '../encoding/spec';
|
|
|
9
9
|
import { Root } from "./Root";
|
|
10
10
|
|
|
11
11
|
import type { StateView } from "./StateView";
|
|
12
|
-
import type { Metadata } from "../Metadata";
|
|
13
12
|
import type { ChangeSetName, ChangeTree, ChangeTreeList, ChangeTreeNode } from "./ChangeTree";
|
|
14
13
|
import { createChangeTreeList } from "./ChangeTree";
|
|
15
14
|
|
|
@@ -22,7 +21,7 @@ function concatBytes(a: Uint8Array, b: Uint8Array): Uint8Array {
|
|
|
22
21
|
|
|
23
22
|
export class Encoder<T extends Schema = any> {
|
|
24
23
|
static BUFFER_SIZE = 8 * 1024; // 8KB
|
|
25
|
-
sharedBuffer = new Uint8Array(Encoder.BUFFER_SIZE);
|
|
24
|
+
sharedBuffer: Uint8Array = new Uint8Array(Encoder.BUFFER_SIZE);
|
|
26
25
|
|
|
27
26
|
context: TypeContext;
|
|
28
27
|
state: T;
|
|
@@ -55,7 +54,7 @@ export class Encoder<T extends Schema = any> {
|
|
|
55
54
|
encode(
|
|
56
55
|
it: Iterator = { offset: 0 },
|
|
57
56
|
view?: StateView,
|
|
58
|
-
buffer = this.sharedBuffer,
|
|
57
|
+
buffer: Uint8Array = this.sharedBuffer,
|
|
59
58
|
changeSetName: ChangeSetName = "changes",
|
|
60
59
|
isEncodeAll = changeSetName === "allChanges",
|
|
61
60
|
initialOffset = it.offset // cache current offset in case we need to resize the buffer
|
|
@@ -159,11 +158,19 @@ export class Encoder<T extends Schema = any> {
|
|
|
159
158
|
}
|
|
160
159
|
}
|
|
161
160
|
|
|
162
|
-
encodeAll(
|
|
161
|
+
encodeAll(
|
|
162
|
+
it: Iterator = { offset: 0 },
|
|
163
|
+
buffer: Uint8Array = this.sharedBuffer
|
|
164
|
+
) {
|
|
163
165
|
return this.encode(it, undefined, buffer, "allChanges", true);
|
|
164
166
|
}
|
|
165
167
|
|
|
166
|
-
encodeAllView(
|
|
168
|
+
encodeAllView(
|
|
169
|
+
view: StateView,
|
|
170
|
+
sharedOffset: number,
|
|
171
|
+
it: Iterator,
|
|
172
|
+
bytes: Uint8Array = this.sharedBuffer
|
|
173
|
+
) {
|
|
167
174
|
const viewOffset = it.offset;
|
|
168
175
|
|
|
169
176
|
// try to encode "filtered" changes
|
|
@@ -175,7 +182,12 @@ export class Encoder<T extends Schema = any> {
|
|
|
175
182
|
);
|
|
176
183
|
}
|
|
177
184
|
|
|
178
|
-
encodeView(
|
|
185
|
+
encodeView(
|
|
186
|
+
view: StateView,
|
|
187
|
+
sharedOffset: number,
|
|
188
|
+
it: Iterator,
|
|
189
|
+
bytes: Uint8Array = this.sharedBuffer
|
|
190
|
+
) {
|
|
179
191
|
const viewOffset = it.offset;
|
|
180
192
|
|
|
181
193
|
// encode visibility changes (add/remove for this view)
|
|
@@ -251,7 +263,12 @@ export class Encoder<T extends Schema = any> {
|
|
|
251
263
|
this.root.filteredChanges = createChangeTreeList();
|
|
252
264
|
}
|
|
253
265
|
|
|
254
|
-
tryEncodeTypeId
|
|
266
|
+
tryEncodeTypeId(
|
|
267
|
+
bytes: Uint8Array,
|
|
268
|
+
baseType: typeof Schema,
|
|
269
|
+
targetType: typeof Schema,
|
|
270
|
+
it: Iterator
|
|
271
|
+
) {
|
|
255
272
|
const baseTypeId = this.context.getTypeId(baseType);
|
|
256
273
|
const targetTypeId = this.context.getTypeId(targetType);
|
|
257
274
|
|