UNPKG

deadem

Version:

JavaScript (Node.js & Browsers) parser for Deadlock (Valve Source 2 Engine) demo/replay files

270 lines (219 loc) 6.29 kB
import Assert from '#core/Assert.js'; import Logger from '#core/Logger.js'; import Class from './Class.js'; import Server from './Server.js'; import Entity from './entity/Entity.js'; import StringTableEvent from './enums/StringTableEvent.js'; import StringTableType from './enums/StringTableType.js'; import Serializer from './fields/Serializer.js'; import SerializerKey from './fields/SerializerKey.js'; import StringTableContainer from './tables/string/StringTableContainer.js'; class Demo { /** * @public * @constructor * @param {Logger} logger */ constructor(logger = Logger.CONSOLE_INFO) { Assert.isTrue(logger instanceof Logger); this._classBaselines = new Map(); this._classes = { byId: new Map(), byName: new Map() }; this._entities = new Map(); this._serializers = new Map(); this._server = null; this._stringTableContainer = new StringTableContainer(logger); this._stringTableContainer.subscribe(StringTableEvent.TABLE_CHANGED, this._handleTableChanged.bind(this)); this._stringTableContainer.subscribe(StringTableEvent.TABLE_REMOVED, this._handleTableRemoved.bind(this)); } /** * @public * @returns {Server|null} */ get server() { return this._server; } /** * @public * @returns {StringTableContainer} */ get stringTableContainer() { return this._stringTableContainer; } /** * @public * @param {number} index * @returns {Entity|null} */ deleteEntity(index) { Assert.isTrue(Number.isInteger(index)); const entity = this._entities.get(index) || null; if (entity !== null) { this._entities.delete(index); } return entity; } /** * @public * @param {number} id * @returns {Buffer|null} */ getClassBaselineById(id) { Assert.isTrue(Number.isInteger(id)); return this._classBaselines.get(id) || null; } /** * @public * @param {number} id * @returns {Class|null} */ getClassById(id) { Assert.isTrue(Number.isInteger(id)); return this._classes.byId.get(id) || null; } /** * @public * @param {String} name * @returns {Class|null} */ getClassByName(name) { Assert.isTrue(typeof name === 'string' && name.length > 0); return this._classes.byName.get(name) || null; } /** * @public * @returns {Array<Class>} */ getClasses() { return Array.from(this._classes.byId.values()); } /** * @public * @returns {Array<Entity>} */ getEntities() { return Array.from(this._entities.values()); } /** * @public * @param {string} className * @returns {Array<Entity>} */ getEntitiesByClassName(className) { return Array.from(this._entities.values()).filter(entity => entity.class.name === className); } /** * @public * @param {number} index * @returns {Entity|null} */ getEntity(index) { Assert.isTrue(Number.isInteger(index)); return this._entities.get(index) || null; } /** * @public * @param {number} handle * @returns {Entity|null} */ getEntityByHandle(handle) { Assert.isTrue(Number.isInteger(handle)); return this._entities.get(handle & 0x3FFF) || null; } /** * @public * @param {SerializerKey} key * @returns {Serializer|null} */ getSerializerByKey(key) { Assert.isTrue(key instanceof SerializerKey); return this._serializers.get(key.toString()) || null; } /** * @public * @returns {{ classBaselines: number, classes: number, entities: number, serializers: number }} */ getStats() { return { classBaselines: this._classBaselines.size, classes: this._classes.byId.size, entities: this._entities.size, serializers: this._serializers.size }; } /** * @public * @param {Class} clazz */ registerClass(clazz) { Assert.isTrue(clazz instanceof Class); this._classes.byId.set(clazz.id, clazz); this._classes.byName.set(clazz.name, clazz); } /** * @public * @param {Entity} entity */ registerEntity(entity) { Assert.isTrue(entity instanceof Entity); this._entities.set(entity.index, entity); } /** * @public * @param {Serializer} serializer */ registerSerializer(serializer) { Assert.isTrue(serializer instanceof Serializer); this._serializers.set(serializer.key.toString(), serializer); } /** * @public * @param {Server} server */ registerServer(server) { Assert.isTrue(server instanceof Server); this._server = server; } /** * @protected * @param {StringTableContainer} stringTableContainer * @param {StringTable} stringTable */ _handleTableChanged(stringTableContainer, stringTable) { switch (stringTable.type) { case StringTableType.INSTANCE_BASE_LINE: { const entries = stringTable.getEntries(); entries.forEach((entry) => { const key = parseInt(entry.key); if (Number.isNaN(key)) { throw new Error(`Unexpected key [ ${entry.key} ] for table [ ${stringTable.type.code} ]`); } this._classBaselines.set(key, entry.value); }); break; } default: { break; } } } /** * @protected * @param {StringTableContainer} stringTableContainer * @param {StringTable} stringTable */ _handleTableRemoved(stringTableContainer, stringTable) { switch (stringTable.type) { case StringTableType.INSTANCE_BASE_LINE: { this._classBaselines.clear(); break; } default: { break; } } } } export default Demo;