Add multiple performance settings

pull/568/head
tobspr 4 years ago
parent 9e76606674
commit 9085f32ec3

@ -12,6 +12,7 @@ export const CHANGELOG = [
"Fix rare crash regarding the buildings toolbar (by isaisstillalive)",
"Fixed some phrases (by EnderDoom77)",
"Zoom towards mouse cursor (by Dimava)",
"Added multiple settings to optimize the performance",
"Updated the soundtrack again, it is now 40 minutes in total!",
"Updated and added new translations (Thanks to all contributors!)",
"Allow editing waypoints (by isaisstillalive)",

@ -46,6 +46,7 @@ export const globalConfig = {
// Map
mapChunkSize: 16,
mapChunkOverviewMinZoom: 0.9,
mapChunkWorldSize: null, // COMPUTED
// Belt speeds
// NOTICE: Update webpack.production.config too!
@ -110,6 +111,8 @@ export const IS_MOBILE = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
// Automatic calculations
globalConfig.minerSpeedItemsPerSecond = globalConfig.beltSpeedItemsPerSecond / 5;
globalConfig.mapChunkWorldSize = globalConfig.mapChunkSize * globalConfig.tileSize;
// Dynamic calculations
if (globalConfig.debug.disableMapOverview) {
globalConfig.mapChunkOverviewMinZoom = 0;

@ -1,8 +1,6 @@
/* typehints:start */
import { InGameState } from "../states/ingame";
import { Application } from "../application";
/* typehints:end */
import { BufferMaintainer } from "../core/buffer_maintainer";
import { disableImageSmoothing, enableImageSmoothing, registerCanvas } from "../core/buffer_utils";
import { globalConfig } from "../core/config";
@ -10,12 +8,16 @@ import { getDeviceDPI, resizeHighDPICanvas } from "../core/dpi_manager";
import { DrawParameters } from "../core/draw_parameters";
import { gMetaBuildingRegistry } from "../core/global_registries";
import { createLogger } from "../core/logging";
import { Rectangle } from "../core/rectangle";
import { randomInt } from "../core/utils";
import { Vector } from "../core/vector";
import { Savegame } from "../savegame/savegame";
import { SavegameSerializer } from "../savegame/savegame_serializer";
import { InGameState } from "../states/ingame";
import { AutomaticSave } from "./automatic_save";
import { MetaHubBuilding } from "./buildings/hub";
import { Camera } from "./camera";
import { DynamicTickrate } from "./dynamic_tickrate";
import { EntityManager } from "./entity_manager";
import { GameSystemManager } from "./game_system_manager";
import { HubGoals } from "./hub_goals";
@ -23,15 +25,12 @@ import { GameHUD } from "./hud/hud";
import { KeyActionMapper } from "./key_action_mapper";
import { GameLogic } from "./logic";
import { MapView } from "./map_view";
import { GameRoot, enumLayer } from "./root";
import { defaultBuildingVariant } from "./meta_building";
import { ProductionAnalytics } from "./production_analytics";
import { enumLayer, GameRoot } from "./root";
import { ShapeDefinitionManager } from "./shape_definition_manager";
import { SoundProxy } from "./sound_proxy";
import { GameTime } from "./time/game_time";
import { ProductionAnalytics } from "./production_analytics";
import { randomInt } from "../core/utils";
import { defaultBuildingVariant } from "./meta_building";
import { DynamicTickrate } from "./dynamic_tickrate";
import { Rectangle } from "../core/rectangle";
const logger = createLogger("ingame/core");
@ -233,10 +232,6 @@ export class GameCore {
tick(deltaMs) {
const root = this.root;
if (root.hud.parts.processingOverlay.hasTasks() || root.hud.parts.processingOverlay.isRunning()) {
return true;
}
// Extract current real time
root.time.updateRealtimeNow();
@ -326,14 +321,6 @@ export class GameCore {
const root = this.root;
const systems = root.systemMgr.systems;
const taskRunner = root.hud.parts.processingOverlay;
if (taskRunner.hasTasks()) {
if (!taskRunner.isRunning()) {
taskRunner.process();
}
return;
}
this.root.dynamicTickrate.onFrameRendered();
if (!this.shouldRender()) {
@ -357,15 +344,16 @@ export class GameCore {
// Compute optimal zoom level and atlas scale
const zoomLevel = root.camera.zoomLevel;
const lowQuality = root.app.settings.getAllSettings().lowQualityTextures;
const effectiveZoomLevel =
(zoomLevel / globalConfig.assetsDpi) * getDeviceDPI() * globalConfig.assetsSharpness;
let desiredAtlasScale = "0.1";
if (effectiveZoomLevel > 0.75) {
if (effectiveZoomLevel > 0.75 && !lowQuality) {
desiredAtlasScale = "1";
} else if (effectiveZoomLevel > 0.5) {
} else if (effectiveZoomLevel > 0.5 && !lowQuality) {
desiredAtlasScale = "0.75";
} else if (effectiveZoomLevel > 0.25) {
} else if (effectiveZoomLevel > 0.25 && !lowQuality) {
desiredAtlasScale = "0.5";
} else if (effectiveZoomLevel > 0.1) {
desiredAtlasScale = "0.25";
@ -380,7 +368,7 @@ export class GameCore {
root: root,
});
if (G_IS_DEV && (globalConfig.debug.testCulling || globalConfig.debug.hideFog)) {
if (G_IS_DEV && globalConfig.debug.testCulling) {
context.clearRect(0, 0, root.gameWidth, root.gameHeight);
}

@ -8,7 +8,6 @@ import { TrailerMaker } from "./trailer_maker";
import { Signal } from "../../core/signal";
import { DrawParameters } from "../../core/draw_parameters";
import { HUDProcessingOverlay } from "./parts/processing_overlay";
import { HUDBuildingsToolbar } from "./parts/buildings_toolbar";
import { HUDBuildingPlacer } from "./parts/building_placer";
import { HUDBlueprintPlacer } from "./parts/blueprint_placer";
@ -57,7 +56,6 @@ export class GameHUD {
*/
initialize() {
this.parts = {
processingOverlay: new HUDProcessingOverlay(this.root),
buildingsToolbar: new HUDBuildingsToolbar(this.root),
wiresToolbar: new HUDWiresToolbar(this.root),
blueprintPlacer: new HUDBlueprintPlacer(this.root),

@ -1,112 +0,0 @@
import { DynamicDomAttach } from "../dynamic_dom_attach";
import { BaseHUDPart } from "../base_hud_part";
import { makeDiv } from "../../../core/utils";
import { Signal } from "../../../core/signal";
import { InputReceiver } from "../../../core/input_receiver";
import { createLogger } from "../../../core/logging";
const logger = createLogger("hud/processing_overlay");
export class HUDProcessingOverlay extends BaseHUDPart {
constructor(root) {
super(root);
this.tasks = [];
this.computeTimeout = null;
this.root.signals.performAsync.add(this.queueTask, this);
this.allTasksFinished = new Signal();
this.inputReceiver = new InputReceiver("processing-overlay");
this.root.signals.aboutToDestruct.add(() =>
this.root.app.inputMgr.destroyReceiver(this.inputReceiver)
);
}
createElements(parent) {
this.element = makeDiv(
parent,
"rg_HUD_ProcessingOverlay",
["hudElement"],
`
<span class="prefab_LoadingTextWithAnim">
Computing
</span>
`
);
}
initialize() {
this.domWatcher = new DynamicDomAttach(this.root, this.element, {
timeToKeepSeconds: 0,
});
}
queueTask(task, name) {
if (!this.root.gameInitialized) {
// Tasks before the game started can be done directlry
task();
return;
}
task.__name = name;
this.tasks.push(task);
}
hasTasks() {
return this.tasks.length > 0;
}
isRunning() {
return this.computeTimeout !== null;
}
processSync() {
const now = performance.now();
while (this.tasks.length > 0) {
const workload = this.tasks[0];
workload.call();
this.tasks.shift();
}
const duration = performance.now() - now;
if (duration > 100) {
logger.log("Tasks done slow (SYNC!) within", (performance.now() - now).toFixed(2), "ms");
}
}
process() {
this.root.app.inputMgr.makeSureAttachedAndOnTop(this.inputReceiver);
this.domWatcher.update(true);
if (this.tasks.length === 0) {
logger.warn("No tasks but still called process");
return;
}
if (this.computeTimeout) {
assert(false, "Double compute queued");
clearTimeout(this.computeTimeout);
}
this.computeTimeout = setTimeout(() => {
const now = performance.now();
while (this.tasks.length > 0) {
const workload = this.tasks[0];
workload.call();
this.tasks.shift();
}
const duration = performance.now() - now;
if (duration > 100) {
logger.log("Tasks done slow within", (performance.now() - now).toFixed(2), "ms");
}
this.domWatcher.update(false);
this.root.app.inputMgr.makeSureDetached(this.inputReceiver);
clearTimeout(this.computeTimeout);
this.computeTimeout = null;
this.allTasksFinished.dispatch();
});
}
}

@ -63,7 +63,7 @@ export class HUDScreenshotExporter extends BaseHUDPart {
}
logger.log("ChunkSizePixels:", chunkSizePixels);
const chunkScale = chunkSizePixels / (globalConfig.mapChunkSize * globalConfig.tileSize);
const chunkScale = chunkSizePixels / globalConfig.mapChunkWorldSize;
logger.log("Scale:", chunkScale);
logger.log("Allocating buffer, if the factory grew too big it will crash here");
@ -79,10 +79,10 @@ export class HUDScreenshotExporter extends BaseHUDPart {
logger.log("Got buffer, rendering now ...");
const visibleRect = new Rectangle(
minChunk.x * globalConfig.mapChunkSize * globalConfig.tileSize,
minChunk.y * globalConfig.mapChunkSize * globalConfig.tileSize,
dimensions.x * globalConfig.mapChunkSize * globalConfig.tileSize,
dimensions.y * globalConfig.mapChunkSize * globalConfig.tileSize
minChunk.x * globalConfig.mapChunkWorldSize,
minChunk.y * globalConfig.mapChunkWorldSize,
dimensions.x * globalConfig.mapChunkWorldSize,
dimensions.y * globalConfig.mapChunkWorldSize
);
const parameters = new DrawParameters({
context,

@ -1,7 +1,12 @@
import { GameRoot, enumLayer } from "./root";
import { globalConfig } from "../core/config";
import { createLogger } from "../core/logging";
import { clamp, fastArrayDeleteValueIfContained, make2DUndefinedArray } from "../core/utils";
import {
clamp,
fastArrayDeleteValueIfContained,
make2DUndefinedArray,
fastArrayDeleteValue,
} from "../core/utils";
import { Vector } from "../core/vector";
import { BaseItem } from "./base_item";
import { enumColors } from "./colors";
@ -39,6 +44,15 @@ export class MapChunk {
/** @type {Array<Entity>} */
this.containedEntities = [];
/**
* Which entities this chunk contains, sorted by layer
* @type {Object<enumLayer, Array<Entity>>}
*/
this.containedEntitiesByLayer = {
[enumLayer.regular]: [],
[enumLayer.wires]: [],
};
/**
* Store which patches we have so we can render them in the overview
* @type {Array<{pos: Vector, item: BaseItem, size: number }>}
@ -403,8 +417,9 @@ export class MapChunk {
assert(contents === null || !oldContents, "Tile already used: " + tileX + " / " + tileY);
if (oldContents) {
// Remove from list
// Remove from list (the old contents must be reigstered)
fastArrayDeleteValueIfContained(this.containedEntities, oldContents);
fastArrayDeleteValueIfContained(this.containedEntitiesByLayer[layer], oldContents);
}
if (layer === enumLayer.regular) {
@ -417,6 +432,10 @@ export class MapChunk {
if (this.containedEntities.indexOf(contents) < 0) {
this.containedEntities.push(contents);
}
if (this.containedEntitiesByLayer[layer].indexOf(contents) < 0) {
this.containedEntitiesByLayer[layer].push(contents);
}
}
}
}

@ -69,13 +69,14 @@ export class MapChunkView extends MapChunk {
redrawMethod: this.generateOverlayBuffer.bind(this),
});
const dims = globalConfig.mapChunkSize * globalConfig.tileSize;
const dims = globalConfig.mapChunkWorldSize;
// Draw chunk "pixel" art
parameters.context.imageSmoothingEnabled = false;
parameters.context.drawImage(sprite, this.x * dims, this.y * dims, dims, dims);
parameters.context.imageSmoothingEnabled = true;
// Draw patch items
if (this.root.currentLayer === enumLayer.regular) {
for (let i = 0; i < this.patches.length; ++i) {
const patch = this.patches[i];

@ -195,17 +195,19 @@ export class MapView extends BaseMap {
);
}
const dpi = this.backgroundCacheDPI;
parameters.context.scale(1 / dpi, 1 / dpi);
parameters.context.fillStyle = this.cachedBackgroundPattern;
parameters.context.fillRect(
parameters.visibleRect.x * dpi,
parameters.visibleRect.y * dpi,
parameters.visibleRect.w * dpi,
parameters.visibleRect.h * dpi
);
parameters.context.scale(dpi, dpi);
if (!this.root.app.settings.getAllSettings().disableTileGrid) {
const dpi = this.backgroundCacheDPI;
parameters.context.scale(1 / dpi, 1 / dpi);
parameters.context.fillStyle = this.cachedBackgroundPattern;
parameters.context.fillRect(
parameters.visibleRect.x * dpi,
parameters.visibleRect.y * dpi,
parameters.visibleRect.w * dpi,
parameters.visibleRect.h * dpi
);
parameters.context.scale(dpi, dpi);
}
this.drawVisibleChunks(parameters, MapChunkView.prototype.drawBackgroundLayer);
@ -233,16 +235,16 @@ export class MapView extends BaseMap {
for (let chunkY = chunkStartY; chunkY <= chunkEndY; ++chunkY) {
parameters.context.fillStyle = "#ffaaaa";
parameters.context.fillRect(
chunkX * globalConfig.mapChunkSize * globalConfig.tileSize,
chunkY * globalConfig.mapChunkSize * globalConfig.tileSize,
globalConfig.mapChunkSize * globalConfig.tileSize,
chunkX * globalConfig.mapChunkWorldSize,
chunkY * globalConfig.mapChunkWorldSize,
globalConfig.mapChunkWorldSize,
3
);
parameters.context.fillRect(
chunkX * globalConfig.mapChunkSize * globalConfig.tileSize,
chunkY * globalConfig.mapChunkSize * globalConfig.tileSize,
chunkX * globalConfig.mapChunkWorldSize,
chunkY * globalConfig.mapChunkWorldSize,
3,
globalConfig.mapChunkSize * globalConfig.tileSize
globalConfig.mapChunkWorldSize
);
}
}

@ -162,9 +162,6 @@ export class GameRoot {
// Called right after game is initialized
postLoadHook: /** @type {TypedSignal<[]>} */ (new Signal()),
// Can be used to trigger an async task
performAsync: /** @type {TypedSignal<[function]>} */ (new Signal()),
shapeDelivered: /** @type {TypedSignal<[ShapeDefinition]>} */ (new Signal()),
itemProduced: /** @type {TypedSignal<[BaseItem]>} */ (new Signal()),

@ -4,6 +4,7 @@ import { BOOL_TRUE_SINGLETON, BOOL_FALSE_SINGLETON } from "../items/boolean_item
import { MapChunkView } from "../map_chunk_view";
import { globalConfig } from "../../core/config";
import { Loader } from "../../core/loader";
import { enumLayer } from "../root";
export class LeverSystem extends GameSystemWithFilter {
constructor(root) {
@ -31,23 +32,19 @@ export class LeverSystem extends GameSystemWithFilter {
* @param {MapChunkView} chunk
*/
drawChunk(parameters, chunk) {
const contents = chunk.contents;
for (let y = 0; y < globalConfig.mapChunkSize; ++y) {
for (let x = 0; x < globalConfig.mapChunkSize; ++x) {
const entity = contents[x][y];
if (entity && entity.components.Lever) {
const sprite = entity.components.Lever.toggled ? this.spriteOn : this.spriteOff;
const origin = entity.components.StaticMapEntity.origin;
sprite.drawCached(
parameters,
origin.x * globalConfig.tileSize,
origin.y * globalConfig.tileSize,
globalConfig.tileSize,
globalConfig.tileSize
);
}
const contents = chunk.containedEntitiesByLayer[enumLayer.regular];
for (let i = 0; i < contents.length; ++i) {
const entity = contents[i];
if (entity && entity.components.Lever) {
const sprite = entity.components.Lever.toggled ? this.spriteOn : this.spriteOff;
const origin = entity.components.StaticMapEntity.origin;
sprite.drawCached(
parameters,
origin.x * globalConfig.tileSize,
origin.y * globalConfig.tileSize,
globalConfig.tileSize,
globalConfig.tileSize
);
}
}
}

@ -1,7 +1,8 @@
import { GameSystem } from "../game_system";
import { DrawParameters } from "../../core/draw_parameters";
import { globalConfig } from "../../core/config";
import { DrawParameters } from "../../core/draw_parameters";
import { GameSystem } from "../game_system";
import { MapChunkView } from "../map_chunk_view";
import { THEME } from "../theme";
export class MapResourcesSystem extends GameSystem {
/**
@ -10,39 +11,106 @@ export class MapResourcesSystem extends GameSystem {
* @param {MapChunkView} chunk
*/
drawChunk(parameters, chunk) {
const basicChunkBackground = this.root.buffers.getForKey({
key: "chunkres",
subKey: chunk.renderKey,
w: globalConfig.mapChunkSize,
h: globalConfig.mapChunkSize,
dpi: 1,
redrawMethod: this.generateChunkBackground.bind(this, chunk),
});
parameters.context.imageSmoothingEnabled = false;
parameters.context.drawImage(
basicChunkBackground,
chunk.tileX * globalConfig.tileSize,
chunk.tileY * globalConfig.tileSize,
globalConfig.mapChunkWorldSize,
globalConfig.mapChunkWorldSize
);
parameters.context.imageSmoothingEnabled = true;
parameters.context.globalAlpha = 0.5;
if (this.root.app.settings.getAllSettings().lowQualityMapResources) {
// LOW QUALITY: Draw patch items only
for (let i = 0; i < chunk.patches.length; ++i) {
const patch = chunk.patches[i];
patch.item.draw(
chunk.x * globalConfig.mapChunkWorldSize + patch.pos.x * globalConfig.tileSize,
chunk.y * globalConfig.mapChunkWorldSize + patch.pos.y * globalConfig.tileSize,
parameters,
Math.min(80, 40 / parameters.zoomLevel)
);
}
} else {
// HIGH QUALITY: Draw all items
const layer = chunk.lowerLayer;
for (let x = 0; x < globalConfig.mapChunkSize; ++x) {
const row = layer[x];
const worldX = (chunk.tileX + x) * globalConfig.tileSize;
for (let y = 0; y < globalConfig.mapChunkSize; ++y) {
const lowerItem = row[y];
if (lowerItem) {
const worldY = (chunk.tileY + y) * globalConfig.tileSize;
if (
!parameters.visibleRect.containsRect4Params(
worldX,
worldY,
globalConfig.tileSize,
globalConfig.tileSize
)
) {
// Clipped
continue;
}
// parameters.context.fillStyle = lowerItem.getBackgroundColorAsResource();
// parameters.context.fillRect(worldX, worldY, globalConfig.tileSize, globalConfig.tileSize);
lowerItem.draw(
worldX + globalConfig.halfTileSize,
worldY + globalConfig.halfTileSize,
parameters
);
}
}
}
}
parameters.context.globalAlpha = 1;
}
/**
*
* @param {MapChunkView} chunk
* @param {HTMLCanvasElement} canvas
* @param {CanvasRenderingContext2D} context
* @param {number} w
* @param {number} h
* @param {number} dpi
*/
generateChunkBackground(chunk, canvas, context, w, h, dpi) {
if (this.root.app.settings.getAllSettings().disableTileGrid) {
// The map doesn't draw a background, so we have to
context.fillStyle = THEME.map.background;
context.fillRect(0, 0, w, h);
} else {
context.clearRect(0, 0, w, h);
}
context.globalAlpha = 0.5;
const layer = chunk.lowerLayer;
for (let x = 0; x < globalConfig.mapChunkSize; ++x) {
const row = layer[x];
const worldX = (chunk.tileX + x) * globalConfig.tileSize;
for (let y = 0; y < globalConfig.mapChunkSize; ++y) {
const lowerItem = row[y];
if (lowerItem) {
const worldY = (chunk.tileY + y) * globalConfig.tileSize;
if (
!parameters.visibleRect.containsRect4Params(
worldX,
worldY,
globalConfig.tileSize,
globalConfig.tileSize
)
) {
// Clipped
continue;
}
parameters.context.fillStyle = lowerItem.getBackgroundColorAsResource();
parameters.context.fillRect(worldX, worldY, globalConfig.tileSize, globalConfig.tileSize);
lowerItem.draw(
worldX + globalConfig.halfTileSize,
worldY + globalConfig.halfTileSize,
parameters
);
const item = row[y];
if (item) {
context.fillStyle = item.getBackgroundColorAsResource();
context.fillRect(x, y, 1, 1);
}
}
}
parameters.context.globalAlpha = 1;
}
}

@ -153,11 +153,6 @@ export class GameTime extends BasicSerializableObject {
);
break;
}
// If we queued async tasks, perform them next frame and do not update anymore
if (this.root.hud.parts.processingOverlay.hasTasks()) {
break;
}
}
}

@ -19,6 +19,7 @@ const logger = createLogger("application_settings");
export const enumCategories = {
general: "general",
userInterface: "userInterface",
performance: "performance",
advanced: "advanced",
};
@ -148,34 +149,34 @@ export const allApplicationSettings = [
}),
new BoolSetting(
"fullscreen",
"soundsMuted",
enumCategories.general,
/**
* @param {Application} app
*/
(app, value) => {
if (app.platformWrapper.getSupportsFullscreen()) {
app.platformWrapper.setFullscreen(value);
}
},
!IS_DEMO
(app, value) => app.sound.setSoundsMuted(value)
),
new BoolSetting(
"soundsMuted",
"musicMuted",
enumCategories.general,
/**
* @param {Application} app
*/
(app, value) => app.sound.setSoundsMuted(value)
(app, value) => app.sound.setMusicMuted(value)
),
new BoolSetting(
"musicMuted",
"fullscreen",
enumCategories.general,
/**
* @param {Application} app
*/
(app, value) => app.sound.setMusicMuted(value)
(app, value) => {
if (app.platformWrapper.getSupportsFullscreen()) {
app.platformWrapper.setFullscreen(value);
}
},
!IS_DEMO
),
new BoolSetting(
@ -187,7 +188,6 @@ export const allApplicationSettings = [
(app, value) => null
),
// GAME
new BoolSetting("offerHints", enumCategories.userInterface, (app, value) => {}),
new EnumSetting("theme", {
@ -220,16 +220,6 @@ export const allApplicationSettings = [
(app, id) => null,
}),
new EnumSetting("refreshRate", {
options: ["60", "75", "100", "120", "144", "165", "250", G_IS_DEV ? "10" : "500"],
valueGetter: rate => rate,
textGetter: rate => rate + " Hz",
category: enumCategories.advanced,
restartRequired: false,
changeCb: (app, id) => {},
enabled: !IS_DEMO,
}),
new EnumSetting("scrollWheelSensitivity", {
options: scrollWheelSensitivities.sort((a, b) => a.scale - b.scale),
valueGetter: scale => scale.id,
@ -258,6 +248,20 @@ export const allApplicationSettings = [
new BoolSetting("compactBuildingInfo", enumCategories.userInterface, (app, value) => {}),
new BoolSetting("disableCutDeleteWarnings", enumCategories.advanced, (app, value) => {}),
new BoolSetting("rotationByBuilding", enumCategories.advanced, (app, value) => {}),
new EnumSetting("refreshRate", {
options: ["60", "75", "100", "120", "144", "165", "250", "500"],
valueGetter: rate => rate,
textGetter: rate => rate + " Hz",
category: enumCategories.performance,
restartRequired: false,
changeCb: (app, id) => {},
enabled: !IS_DEMO,
}),
new BoolSetting("lowQualityMapResources", enumCategories.performance, (app, value) => {}),
new BoolSetting("disableTileGrid", enumCategories.performance, (app, value) => {}),
new BoolSetting("lowQualityTextures", enumCategories.performance, (app, value) => {}),
];
export function getApplicationSettingById(id) {
@ -288,6 +292,10 @@ class SettingsStorage {
this.enableColorBlindHelper = false;
this.lowQualityMapResources = false;
this.disableTileGrid = false;
this.lowQualityTextures = false;
/**
* @type {Object.<string, number>}
*/
@ -487,7 +495,7 @@ export class ApplicationSettings extends ReadWriteProxy {
}
getCurrentVersion() {
return 18;
return 21;
}
/** @param {{settings: SettingsStorage, version: number}} data */
@ -565,6 +573,21 @@ export class ApplicationSettings extends ReadWriteProxy {
data.version = 18;
}
if (data.version < 19) {
data.settings.lowQualityMapResources = false;
data.version = 19;
}
if (data.version < 20) {
data.settings.disableTileGrid = false;
data.version = 20;
}
if (data.version < 21) {
data.settings.lowQualityTextures = false;
data.version = 21;
}
return ExplainedResult.good();
}
}

@ -381,17 +381,6 @@ export class InGameState extends GameState {
}
}
// // Check if we can show an ad
// // DISABLED
// if (this.stage === stages.s10_gameRunning && !this.core.root.hud.parts.processingOverlay.hasTasks()) {
// if (this.app.isRenderable() && this.app.adProvider.getCanShowVideoAd()) {
// this.saveThenGoToState("WatchAdState", {
// nextStateId: "RunningGameState",
// nextStatePayload: this.creationPayload,
// });
// }
// }
if (this.stage === stages.s10_gameRunning) {
this.core.tick(dt);
}

@ -670,6 +670,7 @@ settings:
general: General
userInterface: User Interface
advanced: Advanced
performance: Performance
versionBadges:
dev: Development
@ -759,9 +760,9 @@ settings:
light: Light
refreshRate:
title: Simulation Target
title: Tick Rate
description: >-
If you have a 144hz monitor, change the refresh rate here so the game will properly simulate at higher refresh rates. This might actually decrease the FPS if your computer is too slow.
The game will automatically adjust the tickrate to be between this target tickrate and half of it. For example, with a tickrate of 60hz, the game will try to stay at 60hz, and if your computer can't handle it it will go down until it eventually reaches 30hz.
alwaysMultiplace:
title: Multiplace
@ -798,6 +799,22 @@ settings:
description: >-
Disables the warning dialogs brought up when cutting/deleting more than 100 entities.
lowQualityMapResources:
title: Low Quality Map Resources
description: >-
Simplifies the rendering of resources on the map when zoomed in to improve performance.
It even looks cleaner, so be sure to try it out!
disableTileGrid:
title: Disable Grid
description: >-
Disabling the tile grid can help with the performance. This also makes the game look cleaner!
lowQualityTextures:
title: Low quality textures (Ugly)
description: >-
Uses low quality textures to save performance. This will make the game look very ugly!
keybindings:
title: Keybindings
hint: >-

Loading…
Cancel
Save