Further performance improvements, show indicator while game is saving

pull/670/head
tobspr 4 years ago
parent bba29b8a8b
commit 1ebfafd8de

@ -56,6 +56,17 @@
transform: scale(1.1, 1.1);
}
}
&.saving {
@include InlineAnimation(0.4s ease-in-out infinite) {
50% {
opacity: 0.5;
transform: scale(0.8);
}
}
pointer-events: none;
cursor: default;
}
}
&.settings {

@ -25,21 +25,27 @@ export const gBuildingVariants = {
// Set later
};
/**
* Mapping from 'metaBuildingId/variant/rotationVariant' to building code
* @type {Map<string, number>}
*/
const variantsCache = new Map();
/**
* Registers a new variant
* @param {number} id
* @param {number} code
* @param {typeof MetaBuilding} meta
* @param {string} variant
* @param {number} rotationVariant
*/
export function registerBuildingVariant(
id,
code,
meta,
variant = "default" /* FIXME: Circular dependency, actually its defaultBuildingVariant */,
rotationVariant = 0
) {
assert(!gBuildingVariants[id], "Duplicate id: " + id);
gBuildingVariants[id] = {
assert(!gBuildingVariants[code], "Duplicate id: " + code);
gBuildingVariants[code] = {
metaClass: meta,
variant,
rotationVariant,
@ -58,26 +64,29 @@ export function getBuildingDataFromCode(code) {
return gBuildingVariants[code];
}
/**
* Builds the cache for the codes
*/
export function buildBuildingCodeCache() {
for (const code in gBuildingVariants) {
const data = gBuildingVariants[code];
const hash = data.metaInstance.getId() + "/" + data.variant + "/" + data.rotationVariant;
variantsCache.set(hash, +code);
}
}
/**
* Finds the code for a given variant
* @param {MetaBuilding} metaBuilding
* @param {string} variant
* @param {number} rotationVariant
* @returns {number}
*/
export function getCodeFromBuildingData(metaBuilding, variant, rotationVariant) {
for (const key in gBuildingVariants) {
const data = gBuildingVariants[key];
if (
data.metaInstance.getId() === metaBuilding.getId() &&
data.variant === variant &&
data.rotationVariant === rotationVariant
) {
return +key;
}
const hash = metaBuilding.getId() + "/" + variant + "/" + rotationVariant;
const result = variantsCache.get(hash);
if (G_IS_DEV) {
assertAlways(!!result, "Building not found by data: " + hash);
}
assertAlways(
false,
"Building not found by data: " + metaBuilding.getId() + " / " + variant + " / " + rotationVariant
);
return 0;
return result;
}

@ -67,11 +67,8 @@ export class EntityManager extends BasicSerializableObject {
}
assert(!entity.destroyed, `Attempting to register destroyed entity ${entity}`);
if (G_IS_DEV && uid !== null) {
if (G_IS_DEV && !globalConfig.debug.disableSlowAsserts && uid !== null) {
assert(!this.findByUid(uid, false), "Entity uid already taken: " + uid);
}
if (uid !== null) {
assert(uid >= 0 && uid < Number.MAX_SAFE_INTEGER, "Invalid uid passed: " + uid);
}

@ -5,6 +5,7 @@ import { enumNotificationType } from "./notifications";
import { T } from "../../../translations";
import { KEYMAPPINGS } from "../../key_action_mapper";
import { DynamicDomAttach } from "../dynamic_dom_attach";
import { TrackedState } from "../../../core/tracked_state";
export class HUDGameMenu extends BaseHUDPart {
createElements(parent) {
@ -97,12 +98,17 @@ export class HUDGameMenu extends BaseHUDPart {
initialize() {
this.root.signals.gameSaved.add(this.onGameSaved, this);
this.trackedIsSaving = new TrackedState(this.onIsSavingChanged, this);
}
update() {
let playSound = false;
let notifications = new Set();
// Check whether we are saving
this.trackedIsSaving.set(!!this.root.gameState.currentSavePromise);
// Update visibility of buttons
for (let i = 0; i < this.visibilityToUpdate.length; ++i) {
const { condition, domAttach } = this.visibilityToUpdate[i];
@ -154,6 +160,10 @@ export class HUDGameMenu extends BaseHUDPart {
});
}
onIsSavingChanged(isSaving) {
this.saveButton.classList.toggle("saving", isSaving);
}
onGameSaved() {
this.saveButton.classList.toggle("animEven");
this.saveButton.classList.toggle("animOdd");

@ -1,7 +1,6 @@
import { BaseHUDPart } from "../base_hud_part";
import { makeDiv } from "../../../core/utils";
import { T } from "../../../translations";
import { IS_DEMO } from "../../../core/config";
import { BaseHUDPart } from "../base_hud_part";
/** @enum {string} */
export const enumNotificationType = {

@ -66,32 +66,34 @@ export class MapView extends BaseMap {
* @param {DrawParameters} drawParameters
*/
drawStaticEntityDebugOverlays(drawParameters) {
const cullRange = drawParameters.visibleRect.toTileCullRectangle();
const top = cullRange.top();
const right = cullRange.right();
const bottom = cullRange.bottom();
const left = cullRange.left();
const border = 1;
const minY = top - border;
const maxY = bottom + border;
const minX = left - border;
const maxX = right + border - 1;
// Render y from top down for proper blending
for (let y = minY; y <= maxY; ++y) {
for (let x = minX; x <= maxX; ++x) {
// const content = this.tiles[x][y];
const chunk = this.getChunkAtTileOrNull(x, y);
if (!chunk) {
continue;
}
const content = chunk.getTileContentFromWorldCoords(x, y);
if (content) {
let isBorder = x <= left - 1 || x >= right + 1 || y <= top - 1 || y >= bottom + 1;
if (!isBorder) {
content.drawDebugOverlays(drawParameters);
if (G_IS_DEV && (globalConfig.debug.showAcceptorEjectors || globalConfig.debug.showEntityBounds)) {
const cullRange = drawParameters.visibleRect.toTileCullRectangle();
const top = cullRange.top();
const right = cullRange.right();
const bottom = cullRange.bottom();
const left = cullRange.left();
const border = 1;
const minY = top - border;
const maxY = bottom + border;
const minX = left - border;
const maxX = right + border - 1;
// Render y from top down for proper blending
for (let y = minY; y <= maxY; ++y) {
for (let x = minX; x <= maxX; ++x) {
// const content = this.tiles[x][y];
const chunk = this.getChunkAtTileOrNull(x, y);
if (!chunk) {
continue;
}
const content = chunk.getTileContentFromWorldCoords(x, y);
if (content) {
let isBorder = x <= left - 1 || x >= right + 1 || y <= top - 1 || y >= bottom + 1;
if (!isBorder) {
content.drawDebugOverlays(drawParameters);
}
}
}
}

@ -12,7 +12,7 @@ import { MetaStackerBuilding } from "./buildings/stacker";
import { enumTrashVariants, MetaTrashBuilding } from "./buildings/trash";
import { enumUndergroundBeltVariants, MetaUndergroundBeltBuilding } from "./buildings/underground_belt";
import { MetaWireBuilding } from "./buildings/wire";
import { gBuildingVariants, registerBuildingVariant } from "./building_codes";
import { buildBuildingCodeCache, gBuildingVariants, registerBuildingVariant } from "./building_codes";
import { defaultBuildingVariant } from "./meta_building";
import { MetaConstantSignalBuilding } from "./buildings/constant_signal";
import { MetaLogicGateBuilding, enumLogicGateVariants } from "./buildings/logic_gate";
@ -174,4 +174,7 @@ export function initBuildingCodesAfterResourcesLoaded() {
);
variant.silhouetteColor = variant.metaInstance.getSilhouetteColor();
}
// Update caches
buildBuildingCodeCache();
}

@ -64,9 +64,15 @@ export class InGameState extends GameState {
this.loadingOverlay = null;
/** @type {Savegame} */
this.savegame;
this.savegame = null;
this.boundInputFilter = this.filterInput.bind(this);
/**
* Whether we are currently saving the game
* @TODO: This doesn't realy fit here
*/
this.currentSavePromise = null;
}
/**
@ -427,12 +433,26 @@ export class InGameState extends GameState {
return Promise.resolve();
}
// First update the game data
if (this.currentSavePromise) {
logger.warn("Skipping double save and returning same promise");
return this.currentSavePromise;
}
logger.log("Starting to save game ...");
this.core.root.signals.gameSaved.dispatch();
this.savegame.updateData(this.core.root);
return this.savegame.writeSavegameAndMetadata().catch(err => {
logger.warn("Failed to save:", err);
});
this.currentSavePromise = this.savegame
.writeSavegameAndMetadata()
.catch(err => {
// Catch errors
logger.warn("Failed to save:", err);
})
.then(() => {
// Clear promise
logger.log("Saved!");
this.core.root.signals.gameSaved.dispatch();
this.currentSavePromise = null;
});
return this.currentSavePromise;
}
}

Loading…
Cancel
Save