mirror of
https://github.com/tobspr/shapez.io.git
synced 2026-03-02 03:39:21 +00:00
Optimize performance by using singletons for items
This commit is contained in:
@@ -1,8 +1,11 @@
|
||||
import { createLogger } from "../core/logging";
|
||||
import {
|
||||
BaseDataType,
|
||||
TypeArray,
|
||||
TypeBoolean,
|
||||
TypeClass,
|
||||
TypeClassData,
|
||||
TypeClassFromMetaclass,
|
||||
TypeClassId,
|
||||
TypeEntity,
|
||||
TypeEntityWeakref,
|
||||
@@ -17,12 +20,9 @@ import {
|
||||
TypePositiveInteger,
|
||||
TypePositiveNumber,
|
||||
TypeString,
|
||||
TypeVector,
|
||||
TypeClassFromMetaclass,
|
||||
TypeClassData,
|
||||
TypeStructuredObject,
|
||||
TypeVector,
|
||||
} from "./serialization_data_types";
|
||||
import { createLogger } from "../core/logging";
|
||||
|
||||
const logger = createLogger("serialization");
|
||||
|
||||
@@ -69,9 +69,10 @@ export const types = {
|
||||
|
||||
/**
|
||||
* @param {FactoryTemplate<*>} registry
|
||||
* @param {(GameRoot, any) => object=} resolver
|
||||
*/
|
||||
obj(registry) {
|
||||
return new TypeClass(registry);
|
||||
obj(registry, resolver = null) {
|
||||
return new TypeClass(registry, resolver);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -190,12 +191,18 @@ export class BasicSerializableObject {
|
||||
);
|
||||
}
|
||||
|
||||
/** @returns {string|void} */
|
||||
deserialize(data) {
|
||||
/**
|
||||
* @param {any} data
|
||||
* @param {import("./savegame_serializer").GameRoot} root
|
||||
* @returns {string|void}
|
||||
*/
|
||||
deserialize(data, root = null) {
|
||||
return deserializeSchema(
|
||||
this,
|
||||
/** @type {typeof BasicSerializableObject} */ (this.constructor).getCachedSchema(),
|
||||
data
|
||||
data,
|
||||
null,
|
||||
root
|
||||
);
|
||||
}
|
||||
|
||||
@@ -253,9 +260,10 @@ export function serializeSchema(obj, schema, mergeWith = {}) {
|
||||
* @param {Schema} schema The schema to use
|
||||
* @param {object} data The serialized data
|
||||
* @param {string|void|null=} baseclassErrorResult Convenience, if this is a string error code, do nothing and return it
|
||||
* @param {import("../game/root").GameRoot=} root Optional game root reference
|
||||
* @returns {string|void} String error code or nothing on success
|
||||
*/
|
||||
export function deserializeSchema(obj, schema, data, baseclassErrorResult = null) {
|
||||
export function deserializeSchema(obj, schema, data, baseclassErrorResult = null, root) {
|
||||
if (baseclassErrorResult) {
|
||||
return baseclassErrorResult;
|
||||
}
|
||||
@@ -275,7 +283,7 @@ export function deserializeSchema(obj, schema, data, baseclassErrorResult = null
|
||||
return "Non-nullable entry is null: " + key + " of class " + obj.constructor.name;
|
||||
}
|
||||
|
||||
const errorStatus = schema[key].deserializeWithVerify(data[key], obj, key, obj.root);
|
||||
const errorStatus = schema[key].deserializeWithVerify(data[key], obj, key, obj.root || root);
|
||||
if (errorStatus) {
|
||||
logger.error(
|
||||
"Deserialization failed with error '" + errorStatus + "' on object",
|
||||
|
||||
@@ -595,10 +595,12 @@ export class TypeClass extends BaseDataType {
|
||||
/**
|
||||
*
|
||||
* @param {FactoryTemplate<*>} registry
|
||||
* @param {(GameRoot, object) => object} customResolver
|
||||
*/
|
||||
constructor(registry) {
|
||||
constructor(registry, customResolver = null) {
|
||||
super();
|
||||
this.registry = registry;
|
||||
this.customResolver = customResolver;
|
||||
}
|
||||
|
||||
serialize(value) {
|
||||
@@ -640,14 +642,23 @@ export class TypeClass extends BaseDataType {
|
||||
* @returns {string|void} String error code or null on success
|
||||
*/
|
||||
deserialize(value, targetObject, targetKey, root) {
|
||||
const instanceClass = this.registry.findById(value.$);
|
||||
if (!instanceClass || !instanceClass.prototype) {
|
||||
return "Invalid class id (runtime-err): " + value.$ + "->" + instanceClass;
|
||||
}
|
||||
const instance = Object.create(instanceClass.prototype);
|
||||
const errorState = instance.deserialize(value.data);
|
||||
if (errorState) {
|
||||
return errorState;
|
||||
let instance;
|
||||
|
||||
if (this.customResolver) {
|
||||
instance = this.customResolver(root, value);
|
||||
if (!instance) {
|
||||
return "Failed to call custom resolver";
|
||||
}
|
||||
} else {
|
||||
const instanceClass = this.registry.findById(value.$);
|
||||
if (!instanceClass || !instanceClass.prototype) {
|
||||
return "Invalid class id (runtime-err): " + value.$ + "->" + instanceClass;
|
||||
}
|
||||
instance = Object.create(instanceClass.prototype);
|
||||
const errorState = instance.deserialize(value.data);
|
||||
if (errorState) {
|
||||
return errorState;
|
||||
}
|
||||
}
|
||||
targetObject[targetKey] = instance;
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ export class SerializerInternal {
|
||||
|
||||
entity.uid = payload.uid;
|
||||
|
||||
this.deserializeComponents(entity, payload.components);
|
||||
this.deserializeComponents(root, entity, payload.components);
|
||||
|
||||
root.entityMgr.registerEntity(entity, payload.uid);
|
||||
root.map.placeStaticEntity(entity);
|
||||
@@ -70,18 +70,19 @@ export class SerializerInternal {
|
||||
|
||||
/**
|
||||
* Deserializes components of an entity
|
||||
* @param {GameRoot} root
|
||||
* @param {Entity} entity
|
||||
* @param {Object.<string, any>} data
|
||||
* @returns {string|void}
|
||||
*/
|
||||
deserializeComponents(entity, data) {
|
||||
deserializeComponents(root, entity, data) {
|
||||
for (const componentId in data) {
|
||||
if (!entity.components[componentId]) {
|
||||
logger.warn("Entity no longer has component:", componentId);
|
||||
continue;
|
||||
}
|
||||
|
||||
const errorStatus = entity.components[componentId].deserialize(data[componentId]);
|
||||
const errorStatus = entity.components[componentId].deserialize(data[componentId], root);
|
||||
if (errorStatus) {
|
||||
return errorStatus;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user