parent
b478f4be63
commit
091401e52b
@ -1,82 +1,79 @@
|
||||
import { GameRoot } from "./root";
|
||||
import { globalConfig, IS_DEBUG } from "../core/config";
|
||||
import { createLogger } from "../core/logging";
|
||||
|
||||
// How important it is that a savegame is created
|
||||
/**
|
||||
* @enum {number}
|
||||
*/
|
||||
export const enumSavePriority = {
|
||||
regular: 2,
|
||||
asap: 100,
|
||||
};
|
||||
|
||||
const logger = createLogger("autosave");
|
||||
|
||||
// Internals
|
||||
let MIN_INTERVAL_SECS = 60;
|
||||
|
||||
export class AutomaticSave {
|
||||
constructor(root) {
|
||||
/** @type {GameRoot} */
|
||||
this.root = root;
|
||||
|
||||
// Store the current maximum save importance
|
||||
this.saveImportance = enumSavePriority.regular;
|
||||
|
||||
this.lastSaveAttempt = -1000;
|
||||
}
|
||||
|
||||
setSaveImportance(importance) {
|
||||
this.saveImportance = Math.max(this.saveImportance, importance);
|
||||
}
|
||||
|
||||
doSave() {
|
||||
if (G_IS_DEV && globalConfig.debug.disableSavegameWrite) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.root.gameState.doSave();
|
||||
this.saveImportance = enumSavePriority.regular;
|
||||
}
|
||||
|
||||
update() {
|
||||
if (!this.root.gameInitialized) {
|
||||
// Bad idea
|
||||
return;
|
||||
}
|
||||
|
||||
const saveInterval = this.root.app.settings.getAutosaveIntervalSeconds();
|
||||
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());
|
||||
|
||||
const secondsSinceLastSave = (Date.now() - lastSaveTime) / 1000.0;
|
||||
let shouldSave = false;
|
||||
|
||||
switch (this.saveImportance) {
|
||||
case enumSavePriority.asap:
|
||||
// High always should save
|
||||
shouldSave = true;
|
||||
break;
|
||||
|
||||
case enumSavePriority.regular:
|
||||
// Could determine if there is a good / bad point here
|
||||
shouldSave = secondsSinceLastSave > saveInterval;
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(false, "Unknown save prio: " + this.saveImportance);
|
||||
break;
|
||||
}
|
||||
if (shouldSave) {
|
||||
logger.log("Saving automatically");
|
||||
this.lastSaveAttempt = Date.now();
|
||||
this.doSave();
|
||||
}
|
||||
}
|
||||
}
|
||||
import { globalConfig } from "../core/config";
|
||||
import { createLogger } from "../core/logging";
|
||||
import { GameRoot } from "./root";
|
||||
|
||||
// How important it is that a savegame is created
|
||||
/**
|
||||
* @enum {number}
|
||||
*/
|
||||
export const enumSavePriority = {
|
||||
regular: 2,
|
||||
asap: 100,
|
||||
};
|
||||
|
||||
const logger = createLogger("autosave");
|
||||
|
||||
export class AutomaticSave {
|
||||
constructor(root) {
|
||||
/** @type {GameRoot} */
|
||||
this.root = root;
|
||||
|
||||
// Store the current maximum save importance
|
||||
this.saveImportance = enumSavePriority.regular;
|
||||
|
||||
this.lastSaveAttempt = -1000;
|
||||
}
|
||||
|
||||
setSaveImportance(importance) {
|
||||
this.saveImportance = Math.max(this.saveImportance, importance);
|
||||
}
|
||||
|
||||
doSave() {
|
||||
if (G_IS_DEV && globalConfig.debug.disableSavegameWrite) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.root.gameState.doSave();
|
||||
this.saveImportance = enumSavePriority.regular;
|
||||
}
|
||||
|
||||
update() {
|
||||
if (!this.root.gameInitialized) {
|
||||
// Bad idea
|
||||
return;
|
||||
}
|
||||
|
||||
const saveInterval = this.root.app.settings.getAutosaveIntervalSeconds();
|
||||
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());
|
||||
|
||||
const secondsSinceLastSave = (Date.now() - lastSaveTime) / 1000.0;
|
||||
let shouldSave = false;
|
||||
|
||||
switch (this.saveImportance) {
|
||||
case enumSavePriority.asap:
|
||||
// High always should save
|
||||
shouldSave = true;
|
||||
break;
|
||||
|
||||
case enumSavePriority.regular:
|
||||
// Could determine if there is a good / bad point here
|
||||
shouldSave = secondsSinceLastSave > saveInterval;
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(false, "Unknown save prio: " + this.saveImportance);
|
||||
break;
|
||||
}
|
||||
if (shouldSave) {
|
||||
logger.log("Saving automatically");
|
||||
this.lastSaveAttempt = Date.now();
|
||||
this.doSave();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,91 +1,91 @@
|
||||
import { createLogger } from "../core/logging";
|
||||
import { Vector } from "../core/vector";
|
||||
import { getBuildingDataFromCode } from "../game/building_codes";
|
||||
import { Entity } from "../game/entity";
|
||||
import { GameRoot } from "../game/root";
|
||||
|
||||
const logger = createLogger("serializer_internal");
|
||||
|
||||
// Internal serializer methods
|
||||
export class SerializerInternal {
|
||||
/**
|
||||
* Serializes an array of entities
|
||||
* @param {Array<Entity>} array
|
||||
*/
|
||||
serializeEntityArray(array) {
|
||||
const serialized = [];
|
||||
for (let i = 0; i < array.length; ++i) {
|
||||
const entity = array[i];
|
||||
if (!entity.queuedForDestroy && !entity.destroyed) {
|
||||
serialized.push(entity.serialize());
|
||||
}
|
||||
}
|
||||
return serialized;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {GameRoot} root
|
||||
* @param {Array<any>} array
|
||||
* @returns {string|void}
|
||||
*/
|
||||
deserializeEntityArray(root, array) {
|
||||
for (let i = 0; i < array.length; ++i) {
|
||||
this.deserializeEntity(root, array[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {GameRoot} root
|
||||
* @param {Entity} payload
|
||||
*/
|
||||
deserializeEntity(root, payload) {
|
||||
const staticData = payload.components.StaticMapEntity;
|
||||
assert(staticData, "entity has no static data");
|
||||
|
||||
const code = staticData.code;
|
||||
const data = getBuildingDataFromCode(code);
|
||||
|
||||
const metaBuilding = data.metaInstance;
|
||||
|
||||
const entity = metaBuilding.createEntity({
|
||||
root,
|
||||
origin: Vector.fromSerializedObject(staticData.origin),
|
||||
rotation: staticData.rotation,
|
||||
originalRotation: staticData.originalRotation,
|
||||
rotationVariant: data.rotationVariant,
|
||||
variant: data.variant,
|
||||
});
|
||||
|
||||
entity.uid = payload.uid;
|
||||
|
||||
this.deserializeComponents(root, entity, payload.components);
|
||||
|
||||
root.entityMgr.registerEntity(entity, payload.uid);
|
||||
root.map.placeStaticEntity(entity);
|
||||
}
|
||||
|
||||
/////// COMPONENTS ////
|
||||
|
||||
/**
|
||||
* Deserializes components of an entity
|
||||
* @param {GameRoot} root
|
||||
* @param {Entity} entity
|
||||
* @param {Object.<string, any>} data
|
||||
* @returns {string|void}
|
||||
*/
|
||||
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], root);
|
||||
if (errorStatus) {
|
||||
return errorStatus;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
import { createLogger } from "../core/logging";
|
||||
import { Vector } from "../core/vector";
|
||||
import { getBuildingDataFromCode } from "../game/building_codes";
|
||||
import { Entity } from "../game/entity";
|
||||
import { GameRoot } from "../game/root";
|
||||
|
||||
const logger = createLogger("serializer_internal");
|
||||
|
||||
// Internal serializer methods
|
||||
export class SerializerInternal {
|
||||
/**
|
||||
* Serializes an array of entities
|
||||
* @param {Array<Entity>} array
|
||||
*/
|
||||
serializeEntityArray(array) {
|
||||
const serialized = [];
|
||||
for (let i = 0; i < array.length; ++i) {
|
||||
const entity = array[i];
|
||||
if (!entity.queuedForDestroy && !entity.destroyed) {
|
||||
serialized.push(entity.serialize());
|
||||
}
|
||||
}
|
||||
return serialized;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {GameRoot} root
|
||||
* @param {Array<Entity>} array
|
||||
* @returns {string|void}
|
||||
*/
|
||||
deserializeEntityArray(root, array) {
|
||||
for (let i = 0; i < array.length; ++i) {
|
||||
this.deserializeEntity(root, array[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {GameRoot} root
|
||||
* @param {Entity} payload
|
||||
*/
|
||||
deserializeEntity(root, payload) {
|
||||
const staticData = payload.components.StaticMapEntity;
|
||||
assert(staticData, "entity has no static data");
|
||||
|
||||
const code = staticData.code;
|
||||
const data = getBuildingDataFromCode(code);
|
||||
|
||||
const metaBuilding = data.metaInstance;
|
||||
|
||||
const entity = metaBuilding.createEntity({
|
||||
root,
|
||||
origin: Vector.fromSerializedObject(staticData.origin),
|
||||
rotation: staticData.rotation,
|
||||
originalRotation: staticData.originalRotation,
|
||||
rotationVariant: data.rotationVariant,
|
||||
variant: data.variant,
|
||||
});
|
||||
|
||||
entity.uid = payload.uid;
|
||||
|
||||
this.deserializeComponents(root, entity, payload.components);
|
||||
|
||||
root.entityMgr.registerEntity(entity, payload.uid);
|
||||
root.map.placeStaticEntity(entity);
|
||||
}
|
||||
|
||||
/////// COMPONENTS ////
|
||||
|
||||
/**
|
||||
* Deserializes components of an entity
|
||||
* @param {GameRoot} root
|
||||
* @param {Entity} entity
|
||||
* @param {Object.<string, any>} data
|
||||
* @returns {string|void}
|
||||
*/
|
||||
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], root);
|
||||
if (errorStatus) {
|
||||
return errorStatus;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in new issue