mirror of
https://github.com/tobspr/shapez.io.git
synced 2025-06-07 10:03:59 +00:00
Store wires state on save
This commit is contained in:
parent
b478f4be63
commit
091401e52b
@ -1,82 +1,79 @@
|
|||||||
import { GameRoot } from "./root";
|
import { globalConfig } from "../core/config";
|
||||||
import { globalConfig, IS_DEBUG } from "../core/config";
|
import { createLogger } from "../core/logging";
|
||||||
import { createLogger } from "../core/logging";
|
import { GameRoot } from "./root";
|
||||||
|
|
||||||
// How important it is that a savegame is created
|
// How important it is that a savegame is created
|
||||||
/**
|
/**
|
||||||
* @enum {number}
|
* @enum {number}
|
||||||
*/
|
*/
|
||||||
export const enumSavePriority = {
|
export const enumSavePriority = {
|
||||||
regular: 2,
|
regular: 2,
|
||||||
asap: 100,
|
asap: 100,
|
||||||
};
|
};
|
||||||
|
|
||||||
const logger = createLogger("autosave");
|
const logger = createLogger("autosave");
|
||||||
|
|
||||||
// Internals
|
export class AutomaticSave {
|
||||||
let MIN_INTERVAL_SECS = 60;
|
constructor(root) {
|
||||||
|
/** @type {GameRoot} */
|
||||||
export class AutomaticSave {
|
this.root = root;
|
||||||
constructor(root) {
|
|
||||||
/** @type {GameRoot} */
|
// Store the current maximum save importance
|
||||||
this.root = root;
|
this.saveImportance = enumSavePriority.regular;
|
||||||
|
|
||||||
// Store the current maximum save importance
|
this.lastSaveAttempt = -1000;
|
||||||
this.saveImportance = enumSavePriority.regular;
|
}
|
||||||
|
|
||||||
this.lastSaveAttempt = -1000;
|
setSaveImportance(importance) {
|
||||||
}
|
this.saveImportance = Math.max(this.saveImportance, importance);
|
||||||
|
}
|
||||||
setSaveImportance(importance) {
|
|
||||||
this.saveImportance = Math.max(this.saveImportance, importance);
|
doSave() {
|
||||||
}
|
if (G_IS_DEV && globalConfig.debug.disableSavegameWrite) {
|
||||||
|
return;
|
||||||
doSave() {
|
}
|
||||||
if (G_IS_DEV && globalConfig.debug.disableSavegameWrite) {
|
|
||||||
return;
|
this.root.gameState.doSave();
|
||||||
}
|
this.saveImportance = enumSavePriority.regular;
|
||||||
|
}
|
||||||
this.root.gameState.doSave();
|
|
||||||
this.saveImportance = enumSavePriority.regular;
|
update() {
|
||||||
}
|
if (!this.root.gameInitialized) {
|
||||||
|
// Bad idea
|
||||||
update() {
|
return;
|
||||||
if (!this.root.gameInitialized) {
|
}
|
||||||
// Bad idea
|
|
||||||
return;
|
const saveInterval = this.root.app.settings.getAutosaveIntervalSeconds();
|
||||||
}
|
if (!saveInterval) {
|
||||||
|
// Disabled
|
||||||
const saveInterval = this.root.app.settings.getAutosaveIntervalSeconds();
|
return;
|
||||||
if (!saveInterval) {
|
}
|
||||||
// Disabled
|
|
||||||
return;
|
// Check when the last save was, but make sure that if it fails, we don't spam
|
||||||
}
|
const lastSaveTime = Math.max(this.lastSaveAttempt, this.root.savegame.getRealLastUpdate());
|
||||||
|
|
||||||
// Check when the last save was, but make sure that if it fails, we don't spam
|
const secondsSinceLastSave = (Date.now() - lastSaveTime) / 1000.0;
|
||||||
const lastSaveTime = Math.max(this.lastSaveAttempt, this.root.savegame.getRealLastUpdate());
|
let shouldSave = false;
|
||||||
|
|
||||||
const secondsSinceLastSave = (Date.now() - lastSaveTime) / 1000.0;
|
switch (this.saveImportance) {
|
||||||
let shouldSave = false;
|
case enumSavePriority.asap:
|
||||||
|
// High always should save
|
||||||
switch (this.saveImportance) {
|
shouldSave = true;
|
||||||
case enumSavePriority.asap:
|
break;
|
||||||
// High always should save
|
|
||||||
shouldSave = true;
|
case enumSavePriority.regular:
|
||||||
break;
|
// Could determine if there is a good / bad point here
|
||||||
|
shouldSave = secondsSinceLastSave > saveInterval;
|
||||||
case enumSavePriority.regular:
|
break;
|
||||||
// Could determine if there is a good / bad point here
|
|
||||||
shouldSave = secondsSinceLastSave > saveInterval;
|
default:
|
||||||
break;
|
assert(false, "Unknown save prio: " + this.saveImportance);
|
||||||
|
break;
|
||||||
default:
|
}
|
||||||
assert(false, "Unknown save prio: " + this.saveImportance);
|
if (shouldSave) {
|
||||||
break;
|
logger.log("Saving automatically");
|
||||||
}
|
this.lastSaveAttempt = Date.now();
|
||||||
if (shouldSave) {
|
this.doSave();
|
||||||
logger.log("Saving automatically");
|
}
|
||||||
this.lastSaveAttempt = Date.now();
|
}
|
||||||
this.doSave();
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -142,14 +142,14 @@ export class GameSystemManager {
|
|||||||
// WIRES section
|
// WIRES section
|
||||||
add("lever", LeverSystem);
|
add("lever", LeverSystem);
|
||||||
|
|
||||||
|
// Wires must be before all gate, signal etc logic!
|
||||||
|
add("wire", WireSystem);
|
||||||
|
|
||||||
// IMPORTANT: We have 2 phases: In phase 1 we compute the output values of all gates,
|
// IMPORTANT: We have 2 phases: In phase 1 we compute the output values of all gates,
|
||||||
// processors etc. In phase 2 we propagate it through the wires network
|
// processors etc. In phase 2 we propagate it through the wires network
|
||||||
add("logicGate", LogicGateSystem);
|
add("logicGate", LogicGateSystem);
|
||||||
add("beltReader", BeltReaderSystem);
|
add("beltReader", BeltReaderSystem);
|
||||||
|
|
||||||
// Wires must be after all gate, signal etc logic!
|
|
||||||
add("wire", WireSystem);
|
|
||||||
|
|
||||||
add("display", DisplaySystem);
|
add("display", DisplaySystem);
|
||||||
|
|
||||||
add("itemProcessorOverlays", ItemProcessorOverlaysSystem);
|
add("itemProcessorOverlays", ItemProcessorOverlaysSystem);
|
||||||
|
@ -120,6 +120,7 @@ export class WireSystem extends GameSystemWithFilter {
|
|||||||
this.root.signals.entityAdded.add(this.queueRecomputeIfWire, this);
|
this.root.signals.entityAdded.add(this.queueRecomputeIfWire, this);
|
||||||
|
|
||||||
this.needsRecompute = true;
|
this.needsRecompute = true;
|
||||||
|
this.isFirstRecompute = true;
|
||||||
|
|
||||||
this.staleArea = new StaleAreaDetector({
|
this.staleArea = new StaleAreaDetector({
|
||||||
root: this.root,
|
root: this.root,
|
||||||
@ -157,23 +158,28 @@ export class WireSystem extends GameSystemWithFilter {
|
|||||||
|
|
||||||
this.networks = [];
|
this.networks = [];
|
||||||
|
|
||||||
// Clear all network references
|
|
||||||
const wireEntities = this.root.entityMgr.getAllWithComponent(WireComponent);
|
const wireEntities = this.root.entityMgr.getAllWithComponent(WireComponent);
|
||||||
for (let i = 0; i < wireEntities.length; ++i) {
|
|
||||||
wireEntities[i].components.Wire.linkedNetwork = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const tunnelEntities = this.root.entityMgr.getAllWithComponent(WireTunnelComponent);
|
const tunnelEntities = this.root.entityMgr.getAllWithComponent(WireTunnelComponent);
|
||||||
for (let i = 0; i < tunnelEntities.length; ++i) {
|
|
||||||
tunnelEntities[i].components.WireTunnel.linkedNetworks = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
const pinEntities = this.root.entityMgr.getAllWithComponent(WiredPinsComponent);
|
const pinEntities = this.root.entityMgr.getAllWithComponent(WiredPinsComponent);
|
||||||
for (let i = 0; i < pinEntities.length; ++i) {
|
|
||||||
const slots = pinEntities[i].components.WiredPins.slots;
|
// Clear all network references, but not on the first update since thats the deserializing one
|
||||||
for (let k = 0; k < slots.length; ++k) {
|
if (!this.isFirstRecompute) {
|
||||||
slots[k].linkedNetwork = null;
|
for (let i = 0; i < wireEntities.length; ++i) {
|
||||||
|
wireEntities[i].components.Wire.linkedNetwork = null;
|
||||||
}
|
}
|
||||||
|
for (let i = 0; i < tunnelEntities.length; ++i) {
|
||||||
|
tunnelEntities[i].components.WireTunnel.linkedNetworks = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < pinEntities.length; ++i) {
|
||||||
|
const slots = pinEntities[i].components.WiredPins.slots;
|
||||||
|
for (let k = 0; k < slots.length; ++k) {
|
||||||
|
slots[k].linkedNetwork = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
logger.log("Recomputing wires first time");
|
||||||
|
this.isFirstRecompute = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
VERBOSE_WIRES && logger.log("Recomputing slots");
|
VERBOSE_WIRES && logger.log("Recomputing slots");
|
||||||
|
@ -1,91 +1,91 @@
|
|||||||
import { createLogger } from "../core/logging";
|
import { createLogger } from "../core/logging";
|
||||||
import { Vector } from "../core/vector";
|
import { Vector } from "../core/vector";
|
||||||
import { getBuildingDataFromCode } from "../game/building_codes";
|
import { getBuildingDataFromCode } from "../game/building_codes";
|
||||||
import { Entity } from "../game/entity";
|
import { Entity } from "../game/entity";
|
||||||
import { GameRoot } from "../game/root";
|
import { GameRoot } from "../game/root";
|
||||||
|
|
||||||
const logger = createLogger("serializer_internal");
|
const logger = createLogger("serializer_internal");
|
||||||
|
|
||||||
// Internal serializer methods
|
// Internal serializer methods
|
||||||
export class SerializerInternal {
|
export class SerializerInternal {
|
||||||
/**
|
/**
|
||||||
* Serializes an array of entities
|
* Serializes an array of entities
|
||||||
* @param {Array<Entity>} array
|
* @param {Array<Entity>} array
|
||||||
*/
|
*/
|
||||||
serializeEntityArray(array) {
|
serializeEntityArray(array) {
|
||||||
const serialized = [];
|
const serialized = [];
|
||||||
for (let i = 0; i < array.length; ++i) {
|
for (let i = 0; i < array.length; ++i) {
|
||||||
const entity = array[i];
|
const entity = array[i];
|
||||||
if (!entity.queuedForDestroy && !entity.destroyed) {
|
if (!entity.queuedForDestroy && !entity.destroyed) {
|
||||||
serialized.push(entity.serialize());
|
serialized.push(entity.serialize());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return serialized;
|
return serialized;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {GameRoot} root
|
* @param {GameRoot} root
|
||||||
* @param {Array<any>} array
|
* @param {Array<Entity>} array
|
||||||
* @returns {string|void}
|
* @returns {string|void}
|
||||||
*/
|
*/
|
||||||
deserializeEntityArray(root, array) {
|
deserializeEntityArray(root, array) {
|
||||||
for (let i = 0; i < array.length; ++i) {
|
for (let i = 0; i < array.length; ++i) {
|
||||||
this.deserializeEntity(root, array[i]);
|
this.deserializeEntity(root, array[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {GameRoot} root
|
* @param {GameRoot} root
|
||||||
* @param {Entity} payload
|
* @param {Entity} payload
|
||||||
*/
|
*/
|
||||||
deserializeEntity(root, payload) {
|
deserializeEntity(root, payload) {
|
||||||
const staticData = payload.components.StaticMapEntity;
|
const staticData = payload.components.StaticMapEntity;
|
||||||
assert(staticData, "entity has no static data");
|
assert(staticData, "entity has no static data");
|
||||||
|
|
||||||
const code = staticData.code;
|
const code = staticData.code;
|
||||||
const data = getBuildingDataFromCode(code);
|
const data = getBuildingDataFromCode(code);
|
||||||
|
|
||||||
const metaBuilding = data.metaInstance;
|
const metaBuilding = data.metaInstance;
|
||||||
|
|
||||||
const entity = metaBuilding.createEntity({
|
const entity = metaBuilding.createEntity({
|
||||||
root,
|
root,
|
||||||
origin: Vector.fromSerializedObject(staticData.origin),
|
origin: Vector.fromSerializedObject(staticData.origin),
|
||||||
rotation: staticData.rotation,
|
rotation: staticData.rotation,
|
||||||
originalRotation: staticData.originalRotation,
|
originalRotation: staticData.originalRotation,
|
||||||
rotationVariant: data.rotationVariant,
|
rotationVariant: data.rotationVariant,
|
||||||
variant: data.variant,
|
variant: data.variant,
|
||||||
});
|
});
|
||||||
|
|
||||||
entity.uid = payload.uid;
|
entity.uid = payload.uid;
|
||||||
|
|
||||||
this.deserializeComponents(root, entity, payload.components);
|
this.deserializeComponents(root, entity, payload.components);
|
||||||
|
|
||||||
root.entityMgr.registerEntity(entity, payload.uid);
|
root.entityMgr.registerEntity(entity, payload.uid);
|
||||||
root.map.placeStaticEntity(entity);
|
root.map.placeStaticEntity(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
/////// COMPONENTS ////
|
/////// COMPONENTS ////
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deserializes components of an entity
|
* Deserializes components of an entity
|
||||||
* @param {GameRoot} root
|
* @param {GameRoot} root
|
||||||
* @param {Entity} entity
|
* @param {Entity} entity
|
||||||
* @param {Object.<string, any>} data
|
* @param {Object.<string, any>} data
|
||||||
* @returns {string|void}
|
* @returns {string|void}
|
||||||
*/
|
*/
|
||||||
deserializeComponents(root, entity, data) {
|
deserializeComponents(root, entity, data) {
|
||||||
for (const componentId in data) {
|
for (const componentId in data) {
|
||||||
if (!entity.components[componentId]) {
|
if (!entity.components[componentId]) {
|
||||||
logger.warn("Entity no longer has component:", componentId);
|
logger.warn("Entity no longer has component:", componentId);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const errorStatus = entity.components[componentId].deserialize(data[componentId], root);
|
const errorStatus = entity.components[componentId].deserialize(data[componentId], root);
|
||||||
if (errorStatus) {
|
if (errorStatus) {
|
||||||
return errorStatus;
|
return errorStatus;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user