@tamgl/colyseus-schema
Version:
Binary state serializer with delta encoding for games
102 lines • 4.17 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Root = void 0;
const spec_1 = require("../encoding/spec");
const ChangeTree_1 = require("./ChangeTree");
class Root {
constructor(types) {
this.types = types;
this.nextUniqueId = 0;
this.refCount = {};
this.changeTrees = {};
// all changes
this.allChanges = [];
this.allFilteredChanges = []; // TODO: do not initialize it if filters are not used
// pending changes to be encoded
this.changes = [];
this.filteredChanges = []; // TODO: do not initialize it if filters are not used
}
getNextUniqueId() {
return this.nextUniqueId++;
}
add(changeTree) {
// FIXME: move implementation of `ensureRefId` to `Root` class
changeTree.ensureRefId();
const isNewChangeTree = (this.changeTrees[changeTree.refId] === undefined);
if (isNewChangeTree) {
this.changeTrees[changeTree.refId] = changeTree;
}
const previousRefCount = this.refCount[changeTree.refId];
if (previousRefCount === 0) {
//
// When a ChangeTree is re-added, it means that it was previously removed.
// We need to re-add all changes to the `changes` map.
//
const ops = changeTree.allChanges.operations;
let len = ops.length;
while (len--) {
changeTree.indexedOperations[ops[len]] = spec_1.OPERATION.ADD;
(0, ChangeTree_1.setOperationAtIndex)(changeTree.changes, len);
}
}
this.refCount[changeTree.refId] = (previousRefCount || 0) + 1;
return isNewChangeTree;
}
remove(changeTree) {
const refCount = (this.refCount[changeTree.refId]) - 1;
if (refCount <= 0) {
//
// Only remove "root" reference if it's the last reference
//
changeTree.root = undefined;
delete this.changeTrees[changeTree.refId];
this.removeChangeFromChangeSet("allChanges", changeTree);
this.removeChangeFromChangeSet("changes", changeTree);
if (changeTree.filteredChanges) {
this.removeChangeFromChangeSet("allFilteredChanges", changeTree);
this.removeChangeFromChangeSet("filteredChanges", changeTree);
}
this.refCount[changeTree.refId] = 0;
changeTree.forEachChild((child, _) => this.remove(child));
}
else {
this.refCount[changeTree.refId] = refCount;
//
// When losing a reference to an instance, it is best to move the
// ChangeTree to the end of the encoding queue.
//
// This way, at decoding time, the instance that contains the
// ChangeTree will be available before the ChangeTree itself. If the
// containing instance is not available, the Decoder will throw
// "refId not found" error.
//
if (changeTree.filteredChanges !== undefined) {
this.removeChangeFromChangeSet("filteredChanges", changeTree);
(0, ChangeTree_1.enqueueChangeTree)(this, changeTree, "filteredChanges");
}
else {
this.removeChangeFromChangeSet("changes", changeTree);
(0, ChangeTree_1.enqueueChangeTree)(this, changeTree, "changes");
}
}
return refCount;
}
removeChangeFromChangeSet(changeSetName, changeTree) {
const changeSet = this[changeSetName];
const changeSetIndex = changeSet.indexOf(changeTree);
if (changeSetIndex !== -1) {
changeTree[changeSetName].queueRootIndex = -1;
changeSet[changeSetIndex] = undefined;
return true;
}
// if (spliceOne(changeSet, changeSet.indexOf(changeTree))) {
// changeTree[changeSetName].queueRootIndex = -1;
// return true;
// }
}
clear() {
this.changes.length = 0;
}
}
exports.Root = Root;
//# sourceMappingURL=Root.js.map