1
0
mirror of https://github.com/tobspr/shapez.io.git synced 2024-10-27 20:34:29 +00:00

Minor fixes

This commit is contained in:
tobspr 2020-10-08 10:41:06 +02:00
parent c65c955984
commit 7b01db5dae
8 changed files with 1658 additions and 1642 deletions

View File

@ -7,6 +7,7 @@ import { BeltComponent } from "../components/belt";
import { Entity } from "../entity"; import { Entity } from "../entity";
import { MetaBuilding } from "../meta_building"; import { MetaBuilding } from "../meta_building";
import { GameRoot } from "../root"; import { GameRoot } from "../root";
import { THEME } from "../theme";
export const arrayBeltVariantToRotation = [enumDirection.top, enumDirection.left, enumDirection.right]; export const arrayBeltVariantToRotation = [enumDirection.top, enumDirection.left, enumDirection.right];
@ -22,7 +23,7 @@ export class MetaBeltBuilding extends MetaBuilding {
} }
getSilhouetteColor() { getSilhouetteColor() {
return "#777"; return THEME.map.chunkOverview.beltColor;
} }
getPlacementSound() { getPlacementSound() {

View File

@ -26,7 +26,7 @@ export class ItemEjectorComponent extends Component {
static getSchema() { static getSchema() {
// The cachedDestSlot, cachedTargetEntity fields are not serialized. // The cachedDestSlot, cachedTargetEntity fields are not serialized.
return { return {
slots: types.array( slots: types.fixedSizeArray(
types.structured({ types.structured({
item: types.nullable(typeItemSingleton), item: types.nullable(typeItemSingleton),
progress: types.float, progress: types.float,

View File

@ -31,7 +31,7 @@ export class WiredPinsComponent extends Component {
static getSchema() { static getSchema() {
return { return {
slots: types.array( slots: types.fixedSizeArray(
types.structured({ types.structured({
value: types.nullable(typeItemSingleton), value: types.nullable(typeItemSingleton),
}) })

View File

@ -32,7 +32,8 @@
}, },
"chunkOverview": { "chunkOverview": {
"empty": "#444856", "empty": "#444856",
"filled": "#646b7d" "filled": "#646b7d",
"beltColor": "#9096a3"
}, },
"wires": { "wires": {

View File

@ -33,7 +33,8 @@
"chunkOverview": { "chunkOverview": {
"empty": "#a6afbb", "empty": "#a6afbb",
"filled": "#c5ccd6" "filled": "#c5ccd6",
"beltColor": "#777"
}, },
"wires": { "wires": {

View File

@ -1,344 +1,351 @@
import { createLogger } from "../core/logging"; import { createLogger } from "../core/logging";
import { import {
BaseDataType, BaseDataType,
TypeArray, TypeArray,
TypeBoolean, TypeBoolean,
TypeClass, TypeClass,
TypeClassData, TypeClassData,
TypeClassFromMetaclass, TypeClassFromMetaclass,
TypeClassId, TypeClassId,
TypeEntity, TypeEntity,
TypeEntityWeakref, TypeEntityWeakref,
TypeEnum, TypeEnum,
TypeFixedClass, TypeFixedClass,
TypeInteger, TypeInteger,
TypeKeyValueMap, TypeKeyValueMap,
TypeMetaClass, TypeMetaClass,
TypeNullable, TypeNullable,
TypeNumber, TypeNumber,
TypePair, TypePair,
TypePositiveInteger, TypePositiveInteger,
TypePositiveNumber, TypePositiveNumber,
TypeString, TypeString,
TypeStructuredObject, TypeStructuredObject,
TypeVector, TypeVector,
} from "./serialization_data_types"; } from "./serialization_data_types";
const logger = createLogger("serialization"); const logger = createLogger("serialization");
// Schema declarations // Schema declarations
export const types = { export const types = {
int: new TypeInteger(), int: new TypeInteger(),
uint: new TypePositiveInteger(), uint: new TypePositiveInteger(),
float: new TypeNumber(), float: new TypeNumber(),
ufloat: new TypePositiveNumber(), ufloat: new TypePositiveNumber(),
string: new TypeString(), string: new TypeString(),
entity: new TypeEntity(), entity: new TypeEntity(),
weakEntityRef: new TypeEntityWeakref(), weakEntityRef: new TypeEntityWeakref(),
vector: new TypeVector(), vector: new TypeVector(),
tileVector: new TypeVector(), tileVector: new TypeVector(),
bool: new TypeBoolean(), bool: new TypeBoolean(),
/** /**
* @param {BaseDataType} wrapped * @param {BaseDataType} wrapped
*/ */
nullable(wrapped) { nullable(wrapped) {
return new TypeNullable(wrapped); return new TypeNullable(wrapped);
}, },
/** /**
* @param {FactoryTemplate<*>|SingletonFactoryTemplate<*>} registry * @param {FactoryTemplate<*>|SingletonFactoryTemplate<*>} registry
*/ */
classId(registry) { classId(registry) {
return new TypeClassId(registry); return new TypeClassId(registry);
}, },
/** /**
* @param {BaseDataType} valueType * @param {BaseDataType} valueType
* @param {boolean=} includeEmptyValues * @param {boolean=} includeEmptyValues
*/ */
keyValueMap(valueType, includeEmptyValues = true) { keyValueMap(valueType, includeEmptyValues = true) {
return new TypeKeyValueMap(valueType, includeEmptyValues); return new TypeKeyValueMap(valueType, includeEmptyValues);
}, },
/** /**
* @param {Object<string, any>} values * @param {Object<string, any>} values
*/ */
enum(values) { enum(values) {
return new TypeEnum(values); return new TypeEnum(values);
}, },
/** /**
* @param {FactoryTemplate<*>} registry * @param {FactoryTemplate<*>} registry
* @param {(GameRoot, any) => object=} resolver * @param {(GameRoot, any) => object=} resolver
*/ */
obj(registry, resolver = null) { obj(registry, resolver = null) {
return new TypeClass(registry, resolver); return new TypeClass(registry, resolver);
}, },
/** /**
* @param {FactoryTemplate<*>} registry * @param {FactoryTemplate<*>} registry
*/ */
objData(registry) { objData(registry) {
return new TypeClassData(registry); return new TypeClassData(registry);
}, },
/** /**
* @param {typeof BasicSerializableObject} cls * @param {typeof BasicSerializableObject} cls
*/ */
knownType(cls) { knownType(cls) {
return new TypeFixedClass(cls); return new TypeFixedClass(cls);
}, },
/** /**
* @param {BaseDataType} innerType * @param {BaseDataType} innerType
*/ */
array(innerType) { array(innerType) {
return new TypeArray(innerType); return new TypeArray(innerType);
}, },
/** /**
* @param {SingletonFactoryTemplate<*>} innerType * @param {BaseDataType} innerType
*/ */
classRef(registry) { fixedSizeArray(innerType) {
return new TypeMetaClass(registry); return new TypeArray(innerType, true);
}, },
/** /**
* @param {Object.<string, BaseDataType>} descriptor * @param {SingletonFactoryTemplate<*>} innerType
*/ */
structured(descriptor) { classRef(registry) {
return new TypeStructuredObject(descriptor); return new TypeMetaClass(registry);
}, },
/** /**
* @param {BaseDataType} a * @param {Object.<string, BaseDataType>} descriptor
* @param {BaseDataType} b */
*/ structured(descriptor) {
pair(a, b) { return new TypeStructuredObject(descriptor);
return new TypePair(a, b); },
},
/**
/** * @param {BaseDataType} a
* @param {typeof BasicSerializableObject} classHandle * @param {BaseDataType} b
* @param {SingletonFactoryTemplate<*>} registry */
*/ pair(a, b) {
classWithMetaclass(classHandle, registry) { return new TypePair(a, b);
return new TypeClassFromMetaclass(classHandle, registry); },
},
}; /**
* @param {typeof BasicSerializableObject} classHandle
/** * @param {SingletonFactoryTemplate<*>} registry
* A full schema declaration */
* @typedef {Object.<string, BaseDataType>} Schema classWithMetaclass(classHandle, registry) {
*/ return new TypeClassFromMetaclass(classHandle, registry);
},
const globalSchemaCache = {}; };
/* dev:start */ /**
const classnamesCache = {}; * A full schema declaration
/* dev:end*/ * @typedef {Object.<string, BaseDataType>} Schema
*/
export class BasicSerializableObject {
/* dev:start */ const globalSchemaCache = {};
/**
* Fixes typeof DerivedComponent is not assignable to typeof Component, compiled out /* dev:start */
* in non-dev builds const classnamesCache = {};
*/ /* dev:end*/
constructor(...args) {}
export class BasicSerializableObject {
/* dev:end */ /* dev:start */
/**
static getId() { * Fixes typeof DerivedComponent is not assignable to typeof Component, compiled out
abstract; * in non-dev builds
} */
constructor(...args) {}
/**
* Should return the serialization schema /* dev:end */
* @returns {Schema}
*/ static getId() {
static getSchema() { abstract;
return {}; }
}
/**
// Implementation * Should return the serialization schema
/** @returns {Schema} */ * @returns {Schema}
static getCachedSchema() { */
const id = this.getId(); static getSchema() {
return {};
/* dev:start */ }
assert(
classnamesCache[id] === this || classnamesCache[id] === undefined, // Implementation
"Class name taken twice: " + id + " (from " + this.name + ")" /** @returns {Schema} */
); static getCachedSchema() {
classnamesCache[id] = this; const id = this.getId();
/* dev:end */
/* dev:start */
const entry = globalSchemaCache[id]; assert(
if (entry) { classnamesCache[id] === this || classnamesCache[id] === undefined,
return entry; "Class name taken twice: " + id + " (from " + this.name + ")"
} );
classnamesCache[id] = this;
const schema = this.getSchema(); /* dev:end */
globalSchemaCache[id] = schema;
return schema; const entry = globalSchemaCache[id];
} if (entry) {
return entry;
/** @returns {object} */ }
serialize() {
return serializeSchema( const schema = this.getSchema();
this, globalSchemaCache[id] = schema;
/** @type {typeof BasicSerializableObject} */ (this.constructor).getCachedSchema() return schema;
); }
}
/** @returns {object} */
/** serialize() {
* @param {any} data return serializeSchema(
* @param {import("./savegame_serializer").GameRoot} root this,
* @returns {string|void} /** @type {typeof BasicSerializableObject} */ (this.constructor).getCachedSchema()
*/ );
deserialize(data, root = null) { }
return deserializeSchema(
this, /**
/** @type {typeof BasicSerializableObject} */ (this.constructor).getCachedSchema(), * @param {any} data
data, * @param {import("./savegame_serializer").GameRoot} root
null, * @returns {string|void}
root */
); deserialize(data, root = null) {
} return deserializeSchema(
this,
/** @returns {string|void} */ /** @type {typeof BasicSerializableObject} */ (this.constructor).getCachedSchema(),
static verify(data) { data,
return verifySchema(this.getCachedSchema(), data); null,
} root
} );
}
/**
* Serializes an object using the given schema, mergin with the given properties /** @returns {string|void} */
* @param {object} obj The object to serialize static verify(data) {
* @param {Schema} schema The schema to use return verifySchema(this.getCachedSchema(), data);
* @param {object=} mergeWith Any additional properties to merge with the schema, useful for super calls }
* @returns {object} Serialized data object }
*/
export function serializeSchema(obj, schema, mergeWith = {}) { /**
for (const key in schema) { * Serializes an object using the given schema, mergin with the given properties
if (!obj.hasOwnProperty(key)) { * @param {object} obj The object to serialize
logger.error("Invalid schema, property", key, "does not exist on", obj, "(schema=", schema, ")"); * @param {Schema} schema The schema to use
assert( * @param {object=} mergeWith Any additional properties to merge with the schema, useful for super calls
obj.hasOwnProperty(key), * @returns {object} Serialized data object
"serialization: invalid schema, property does not exist on object: " + key */
); export function serializeSchema(obj, schema, mergeWith = {}) {
} for (const key in schema) {
if (!schema[key]) { if (!obj.hasOwnProperty(key)) {
assert(false, "Invalid schema (bad key '" + key + "'): " + JSON.stringify(schema)); logger.error("Invalid schema, property", key, "does not exist on", obj, "(schema=", schema, ")");
} assert(
obj.hasOwnProperty(key),
if (G_IS_DEV) { "serialization: invalid schema, property does not exist on object: " + key
try { );
mergeWith[key] = schema[key].serialize(obj[key]); }
} catch (ex) { if (!schema[key]) {
logger.error( assert(false, "Invalid schema (bad key '" + key + "'): " + JSON.stringify(schema));
"Serialization of", }
obj,
"failed on key '" + key + "' ->", if (G_IS_DEV) {
ex, try {
"(schema was", mergeWith[key] = schema[key].serialize(obj[key]);
schema, } catch (ex) {
")" logger.error(
); "Serialization of",
throw ex; obj,
} "failed on key '" + key + "' ->",
} else { ex,
mergeWith[key] = schema[key].serialize(obj[key]); "(schema was",
} schema,
} ")"
return mergeWith; );
} throw ex;
}
/** } else {
* Deserializes data into an object mergeWith[key] = schema[key].serialize(obj[key]);
* @param {object} obj The object to store the deserialized data into }
* @param {Schema} schema The schema to use }
* @param {object} data The serialized data return mergeWith;
* @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 /**
*/ * Deserializes data into an object
export function deserializeSchema(obj, schema, data, baseclassErrorResult = null, root) { * @param {object} obj The object to store the deserialized data into
if (baseclassErrorResult) { * @param {Schema} schema The schema to use
return baseclassErrorResult; * @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
if (!data) { * @returns {string|void} String error code or nothing on success
logger.error("Got 'NULL' data for", obj, "and schema", schema, "!"); */
return "Got null data"; export function deserializeSchema(obj, schema, data, baseclassErrorResult = null, root) {
} if (baseclassErrorResult) {
return baseclassErrorResult;
for (const key in schema) { }
if (!data.hasOwnProperty(key)) {
logger.error("Data", data, "does not contain", key, "(schema:", schema, ")"); if (!data) {
return "Missing key in schema: " + key + " of class " + obj.constructor.name; logger.error("Got 'NULL' data for", obj, "and schema", schema, "!");
} return "Got null data";
if (!schema[key].allowNull() && (data[key] === null || data[key] === undefined)) { }
logger.error("Data", data, "has null value for", key, "(schema:", schema, ")");
return "Non-nullable entry is null: " + key + " of class " + obj.constructor.name; for (const key in schema) {
} if (!data.hasOwnProperty(key)) {
logger.error("Data", data, "does not contain", key, "(schema:", schema, ")");
const errorStatus = schema[key].deserializeWithVerify(data[key], obj, key, obj.root || root); return "Missing key in schema: " + key + " of class " + obj.constructor.name;
if (errorStatus) { }
logger.error( if (!schema[key].allowNull() && (data[key] === null || data[key] === undefined)) {
"Deserialization failed with error '" + errorStatus + "' on object", logger.error("Data", data, "has null value for", key, "(schema:", schema, ")");
obj, return "Non-nullable entry is null: " + key + " of class " + obj.constructor.name;
"and key", }
key,
"(root? =", const errorStatus = schema[key].deserializeWithVerify(data[key], obj, key, obj.root || root);
obj.root ? "y" : "n", if (errorStatus) {
")" logger.error(
); "Deserialization failed with error '" + errorStatus + "' on object",
return errorStatus; obj,
} "and key",
} key,
} "(root? =",
obj.root ? "y" : "n",
/** ")"
* Verifies stored data using the given schema );
* @param {Schema} schema The schema to use return errorStatus;
* @param {object} data The data to verify }
* @returns {string|void} String error code or nothing on success }
*/ }
export function verifySchema(schema, data) {
for (const key in schema) { /**
if (!data.hasOwnProperty(key)) { * Verifies stored data using the given schema
logger.error("Data", data, "does not contain", key, "(schema:", schema, ")"); * @param {Schema} schema The schema to use
return "verify: missing key required by schema in stored data: " + key; * @param {object} data The data to verify
} * @returns {string|void} String error code or nothing on success
if (!schema[key].allowNull() && (data[key] === null || data[key] === undefined)) { */
logger.error("Data", data, "has null value for", key, "(schema:", schema, ")"); export function verifySchema(schema, data) {
return "verify: non-nullable entry is null: " + key; for (const key in schema) {
} if (!data.hasOwnProperty(key)) {
logger.error("Data", data, "does not contain", key, "(schema:", schema, ")");
const errorStatus = schema[key].verifySerializedValue(data[key]); return "verify: missing key required by schema in stored data: " + key;
if (errorStatus) { }
logger.error(errorStatus); if (!schema[key].allowNull() && (data[key] === null || data[key] === undefined)) {
return "verify: " + errorStatus; logger.error("Data", data, "has null value for", key, "(schema:", schema, ")");
} return "verify: non-nullable entry is null: " + key;
} }
}
const errorStatus = schema[key].verifySerializedValue(data[key]);
/** if (errorStatus) {
* Extends a schema by adding the properties from the new schema to the existing base schema logger.error(errorStatus);
* @param {Schema} base return "verify: " + errorStatus;
* @param {Schema} newOne }
* @returns {Schema} }
*/ }
export function extendSchema(base, newOne) {
/** @type {Schema} */ /**
const result = Object.assign({}, base); * Extends a schema by adding the properties from the new schema to the existing base schema
for (const key in newOne) { * @param {Schema} base
if (result.hasOwnProperty(key)) { * @param {Schema} newOne
logger.error("Extend schema got duplicate key:", key); * @returns {Schema}
continue; */
} export function extendSchema(base, newOne) {
result[key] = newOne[key]; /** @type {Schema} */
} const result = Object.assign({}, base);
return result; for (const key in newOne) {
} if (result.hasOwnProperty(key)) {
logger.error("Extend schema got duplicate key:", key);
continue;
}
result[key] = newOne[key];
}
return result;
}

File diff suppressed because it is too large Load Diff

View File

@ -80,7 +80,10 @@ export class SerializerInternal {
for (const componentId in data) { for (const componentId in data) {
if (!entity.components[componentId]) { if (!entity.components[componentId]) {
if (G_IS_DEV && !globalConfig.debug.disableSlowAsserts) { if (G_IS_DEV && !globalConfig.debug.disableSlowAsserts) {
logger.warn("Entity no longer has component:", componentId); // @ts-ignore
if (++window.componentWarningsShown < 100) {
logger.warn("Entity no longer has component:", componentId);
}
} }
continue; continue;
} }