mirror of
https://github.com/tobspr/shapez.io.git
synced 2025-12-13 18:21:51 +00:00
Allow adding custom themesw
This commit is contained in:
parent
a4df63549b
commit
2a83853b1c
@ -1,6 +1,5 @@
|
||||
/**
|
||||
* This example shows how to replace builtin sprites, in this case
|
||||
* the color sprites
|
||||
* This example shows how to add custom css
|
||||
*/
|
||||
registerMod(() => {
|
||||
return class ModImpl extends shapez.Mod {
|
||||
|
||||
101
mod_examples/custom_theme.js
Normal file
101
mod_examples/custom_theme.js
Normal file
@ -0,0 +1,101 @@
|
||||
/**
|
||||
* This example shows how to add a new theme to the game
|
||||
*/
|
||||
registerMod(() => {
|
||||
return class ModImpl extends shapez.Mod {
|
||||
constructor(app, modLoader) {
|
||||
super(
|
||||
app,
|
||||
{
|
||||
website: "https://tobspr.io",
|
||||
author: "tobspr",
|
||||
name: "Mod Example: Custom Game Theme",
|
||||
version: "1",
|
||||
id: "custom-theme",
|
||||
description: "Shows how to add a custom game theme",
|
||||
},
|
||||
modLoader
|
||||
);
|
||||
}
|
||||
|
||||
init() {
|
||||
console.log("CUSTOM GAME THEME NOW");
|
||||
this.modInterface.registerGameTheme({
|
||||
id: "my-theme",
|
||||
name: "My fancy theme",
|
||||
theme: RESOURCES["my-theme.json"],
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
const RESOURCES = {
|
||||
"my-theme.json": {
|
||||
map: {
|
||||
background: "#abc",
|
||||
grid: "#ccc",
|
||||
gridLineWidth: 1,
|
||||
|
||||
selectionOverlay: "rgba(74, 163, 223, 0.7)",
|
||||
selectionOutline: "rgba(74, 163, 223, 0.5)",
|
||||
selectionBackground: "rgba(74, 163, 223, 0.2)",
|
||||
|
||||
chunkBorders: "rgba(0, 30, 50, 0.03)",
|
||||
|
||||
directionLock: {
|
||||
regular: {
|
||||
color: "rgb(74, 237, 134)",
|
||||
background: "rgba(74, 237, 134, 0.2)",
|
||||
},
|
||||
wires: {
|
||||
color: "rgb(74, 237, 134)",
|
||||
background: "rgba(74, 237, 134, 0.2)",
|
||||
},
|
||||
},
|
||||
|
||||
colorBlindPickerTile: "rgba(50, 50, 50, 0.4)",
|
||||
|
||||
resources: {
|
||||
shape: "#eaebec",
|
||||
red: "#ffbfc1",
|
||||
green: "#cbffc4",
|
||||
blue: "#bfdaff",
|
||||
},
|
||||
|
||||
chunkOverview: {
|
||||
empty: "#a6afbb",
|
||||
filled: "#c5ccd6",
|
||||
beltColor: "#777",
|
||||
},
|
||||
|
||||
wires: {
|
||||
overlayColor: "rgba(97, 161, 152, 0.75)",
|
||||
previewColor: "rgb(97, 161, 152, 0.4)",
|
||||
highlightColor: "rgba(72, 137, 255, 1)",
|
||||
},
|
||||
|
||||
connectedMiners: {
|
||||
overlay: "rgba(40, 50, 60, 0.5)",
|
||||
textColor: "#fff",
|
||||
textColorCapped: "#ef5072",
|
||||
background: "rgba(40, 50, 60, 0.8)",
|
||||
},
|
||||
|
||||
zone: {
|
||||
borderSolid: "rgba(23, 192, 255, 1)",
|
||||
outerColor: "rgba(240, 240, 255, 0.5)",
|
||||
},
|
||||
},
|
||||
|
||||
items: {
|
||||
outline: "#55575a",
|
||||
outlineWidth: 0.75,
|
||||
circleBackground: "rgba(40, 50, 65, 0.1)",
|
||||
},
|
||||
|
||||
shapeTooltip: {
|
||||
background: "#dee1ea",
|
||||
outline: "#54565e",
|
||||
},
|
||||
},
|
||||
};
|
||||
30
mod_examples/modify_theme.js
Normal file
30
mod_examples/modify_theme.js
Normal file
@ -0,0 +1,30 @@
|
||||
/**
|
||||
* This example shows how to modify the builtin themes. If you want to create your own theme,
|
||||
* be sure to check out the "custom_theme" example
|
||||
*/
|
||||
registerMod(() => {
|
||||
return class ModImpl extends shapez.Mod {
|
||||
constructor(app, modLoader) {
|
||||
super(
|
||||
app,
|
||||
{
|
||||
website: "https://tobspr.io",
|
||||
author: "tobspr",
|
||||
name: "Mod Example: Modify Builtin Themes",
|
||||
version: "1",
|
||||
id: "modify-theme",
|
||||
description: "Shows how to modify builtin themes",
|
||||
},
|
||||
modLoader
|
||||
);
|
||||
}
|
||||
|
||||
init() {
|
||||
shapez.THEMES.light.map.background = "#eee";
|
||||
shapez.THEMES.light.items.outline = "#000";
|
||||
|
||||
shapez.THEMES.dark.map.background = "#245";
|
||||
shapez.THEMES.dark.items.outline = "#fff";
|
||||
}
|
||||
};
|
||||
});
|
||||
@ -65,12 +65,20 @@ if (typeof document.hidden !== "undefined") {
|
||||
}
|
||||
|
||||
export class Application {
|
||||
constructor() {
|
||||
/**
|
||||
* Boots the application
|
||||
*/
|
||||
async boot() {
|
||||
console.log("Booting ...");
|
||||
|
||||
assert(!GLOBAL_APP, "Tried to construct application twice");
|
||||
logger.log("Creating application, platform =", getPlatformName());
|
||||
setGlobalApp(this);
|
||||
MODS.app = this;
|
||||
|
||||
// MODS
|
||||
await MODS.initMods();
|
||||
|
||||
this.unloaded = false;
|
||||
|
||||
// Global stuff
|
||||
@ -132,6 +140,31 @@ export class Application {
|
||||
// Store the mouse position, or null if not available
|
||||
/** @type {Vector|null} */
|
||||
this.mousePosition = null;
|
||||
|
||||
this.registerStates();
|
||||
this.registerEventListeners();
|
||||
|
||||
Loader.linkAppAfterBoot(this);
|
||||
|
||||
if (G_WEGAME_VERSION) {
|
||||
this.stateMgr.moveToState("WegameSplashState");
|
||||
}
|
||||
|
||||
// Check for mobile
|
||||
else if (IS_MOBILE) {
|
||||
this.stateMgr.moveToState("MobileWarningState");
|
||||
} else {
|
||||
this.stateMgr.moveToState("PreloadState");
|
||||
}
|
||||
|
||||
// Starting rendering
|
||||
this.ticker.frameEmitted.add(this.onFrameEmitted, this);
|
||||
this.ticker.bgFrameEmitted.add(this.onBackgroundFrame, this);
|
||||
this.ticker.start();
|
||||
|
||||
window.focus();
|
||||
|
||||
MOD_SIGNALS.appBooted.dispatch();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -152,8 +185,6 @@ export class Application {
|
||||
this.analytics = new GoogleAnalyticsImpl(this);
|
||||
this.gameAnalytics = new ShapezGameAnalytics(this);
|
||||
this.achievementProvider = new NoAchievementProvider(this);
|
||||
|
||||
MOD_SIGNALS.platformInstancesInitialized.dispatch();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -329,38 +360,6 @@ export class Application {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Boots the application
|
||||
*/
|
||||
async boot() {
|
||||
console.log("Booting ...");
|
||||
|
||||
await MODS.initMods();
|
||||
|
||||
this.registerStates();
|
||||
this.registerEventListeners();
|
||||
|
||||
Loader.linkAppAfterBoot(this);
|
||||
|
||||
if (G_WEGAME_VERSION) {
|
||||
this.stateMgr.moveToState("WegameSplashState");
|
||||
}
|
||||
|
||||
// Check for mobile
|
||||
else if (IS_MOBILE) {
|
||||
this.stateMgr.moveToState("MobileWarningState");
|
||||
} else {
|
||||
this.stateMgr.moveToState("PreloadState");
|
||||
}
|
||||
|
||||
// Starting rendering
|
||||
this.ticker.frameEmitted.add(this.onFrameEmitted, this);
|
||||
this.ticker.bgFrameEmitted.add(this.onBackgroundFrame, this);
|
||||
this.ticker.start();
|
||||
|
||||
window.focus();
|
||||
}
|
||||
|
||||
/**
|
||||
* Deinitializes the application
|
||||
*/
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
import { MOD_SIGNALS } from "../mods/mod_signals";
|
||||
|
||||
export const THEMES = {
|
||||
dark: require("./themes/dark.json"),
|
||||
light: require("./themes/light.json"),
|
||||
@ -9,5 +7,4 @@ export let THEME = THEMES.light;
|
||||
|
||||
export function applyGameTheme(id) {
|
||||
THEME = THEMES[id];
|
||||
MOD_SIGNALS.preprocessTheme.dispatch({ id, theme: THEME });
|
||||
}
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
{
|
||||
"uiStyle": "dark",
|
||||
"map": {
|
||||
"background": "#3e3f47",
|
||||
"grid": "rgba(255, 255, 255, 0.02)",
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
{
|
||||
"uiStyle": "light",
|
||||
"map": {
|
||||
"background": "#fff",
|
||||
"grid": "#fafafa",
|
||||
|
||||
@ -23,6 +23,7 @@ import { MODS_ADDITIONAL_SYSTEMS } from "../game/game_system_manager";
|
||||
import { MOD_CHUNK_DRAW_HOOKS } from "../game/map_chunk_view";
|
||||
import { KEYMAPPINGS } from "../game/key_action_mapper";
|
||||
import { HUDModalDialogs } from "../game/hud/parts/modal_dialogs";
|
||||
import { THEMES } from "../game/theme";
|
||||
|
||||
export class ModInterface {
|
||||
/**
|
||||
@ -322,4 +323,25 @@ export class ModInterface {
|
||||
}
|
||||
`);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Object} param0
|
||||
* @param {string} param0.id
|
||||
* @param {string} param0.name
|
||||
* @param {Object} param0.theme
|
||||
*/
|
||||
registerGameTheme({ id, name, theme }) {
|
||||
THEMES[id] = theme;
|
||||
this.registerTranslations("en", {
|
||||
settings: {
|
||||
labels: {
|
||||
theme: {
|
||||
themes: {
|
||||
[id]: name,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,10 +10,9 @@ import { Signal } from "../core/signal";
|
||||
// Single file to avoid circular deps
|
||||
|
||||
export const MOD_SIGNALS = {
|
||||
postInit: new Signal(),
|
||||
platformInstancesInitialized: new Signal(),
|
||||
// Called when the application has booted and instances like the app settings etc are available
|
||||
appBooted: new Signal(),
|
||||
|
||||
preprocessTheme: /** @type {TypedSignal<[Object]>} */ (new Signal()),
|
||||
modifyLevelDefinitions: /** @type {TypedSignal<[Array[Object]]>} */ (new Signal()),
|
||||
modifyUpgrades: /** @type {TypedSignal<[Object]>} */ (new Signal()),
|
||||
|
||||
|
||||
@ -95,7 +95,7 @@ export class ModLoader {
|
||||
mods.forEach(modCode => {
|
||||
try {
|
||||
const func = new Function(modCode);
|
||||
const response = func();
|
||||
func();
|
||||
} catch (ex) {
|
||||
console.error(ex);
|
||||
alert("Failed to parse mod (launch with --dev for more info): " + ex);
|
||||
@ -118,7 +118,6 @@ export class ModLoader {
|
||||
}
|
||||
});
|
||||
this.modLoadQueue = [];
|
||||
this.signals.postInit.dispatch();
|
||||
|
||||
delete window.registerMod;
|
||||
}
|
||||
|
||||
@ -122,7 +122,7 @@ export const autosaveIntervals = [
|
||||
},
|
||||
];
|
||||
|
||||
const refreshRateOptions = ["30", "60", "120", "180", "240"];
|
||||
export const refreshRateOptions = ["30", "60", "120", "180", "240"];
|
||||
|
||||
if (G_IS_DEV) {
|
||||
refreshRateOptions.unshift("10");
|
||||
@ -133,163 +133,161 @@ if (G_IS_DEV) {
|
||||
refreshRateOptions.push("10000");
|
||||
}
|
||||
|
||||
/** @type {Array<BaseSetting>} */
|
||||
export const allApplicationSettings = [
|
||||
new EnumSetting("language", {
|
||||
options: Object.keys(LANGUAGES),
|
||||
valueGetter: key => key,
|
||||
textGetter: key => LANGUAGES[key].name,
|
||||
category: enumCategories.general,
|
||||
restartRequired: true,
|
||||
changeCb: (app, id) => null,
|
||||
magicValue: "auto-detect",
|
||||
}),
|
||||
/** @returns {Array<BaseSetting>} */
|
||||
function initializeSettings() {
|
||||
return [
|
||||
new EnumSetting("language", {
|
||||
options: Object.keys(LANGUAGES),
|
||||
valueGetter: key => key,
|
||||
textGetter: key => LANGUAGES[key].name,
|
||||
category: enumCategories.general,
|
||||
restartRequired: true,
|
||||
changeCb: (app, id) => null,
|
||||
magicValue: "auto-detect",
|
||||
}),
|
||||
|
||||
new EnumSetting("uiScale", {
|
||||
options: uiScales.sort((a, b) => a.size - b.size),
|
||||
valueGetter: scale => scale.id,
|
||||
textGetter: scale => T.settings.labels.uiScale.scales[scale.id],
|
||||
category: enumCategories.userInterface,
|
||||
restartRequired: false,
|
||||
changeCb:
|
||||
new EnumSetting("uiScale", {
|
||||
options: uiScales.sort((a, b) => a.size - b.size),
|
||||
valueGetter: scale => scale.id,
|
||||
textGetter: scale => T.settings.labels.uiScale.scales[scale.id],
|
||||
category: enumCategories.userInterface,
|
||||
restartRequired: false,
|
||||
changeCb:
|
||||
/**
|
||||
* @param {Application} app
|
||||
*/
|
||||
(app, id) => app.updateAfterUiScaleChanged(),
|
||||
}),
|
||||
|
||||
new RangeSetting(
|
||||
"soundVolume",
|
||||
enumCategories.general,
|
||||
/**
|
||||
* @param {Application} app
|
||||
*/
|
||||
(app, id) => app.updateAfterUiScaleChanged(),
|
||||
}),
|
||||
|
||||
new RangeSetting(
|
||||
"soundVolume",
|
||||
enumCategories.general,
|
||||
/**
|
||||
* @param {Application} app
|
||||
*/
|
||||
(app, value) => app.sound.setSoundVolume(value)
|
||||
),
|
||||
new RangeSetting(
|
||||
"musicVolume",
|
||||
enumCategories.general,
|
||||
/**
|
||||
* @param {Application} app
|
||||
*/
|
||||
(app, value) => app.sound.setMusicVolume(value)
|
||||
),
|
||||
|
||||
new BoolSetting(
|
||||
"fullscreen",
|
||||
enumCategories.general,
|
||||
/**
|
||||
* @param {Application} app
|
||||
*/
|
||||
(app, value) => {
|
||||
if (app.platformWrapper.getSupportsFullscreen()) {
|
||||
app.platformWrapper.setFullscreen(value);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* @param {Application} app
|
||||
*/ app => app.restrictionMgr.getHasExtendedSettings()
|
||||
),
|
||||
|
||||
new BoolSetting(
|
||||
"enableColorBlindHelper",
|
||||
enumCategories.general,
|
||||
/**
|
||||
* @param {Application} app
|
||||
*/
|
||||
(app, value) => null
|
||||
),
|
||||
|
||||
new BoolSetting("offerHints", enumCategories.userInterface, (app, value) => {}),
|
||||
|
||||
new EnumSetting("theme", {
|
||||
options: Object.keys(THEMES),
|
||||
valueGetter: theme => theme,
|
||||
textGetter: theme => T.settings.labels.theme.themes[theme],
|
||||
category: enumCategories.userInterface,
|
||||
restartRequired: false,
|
||||
changeCb:
|
||||
(app, value) => app.sound.setSoundVolume(value)
|
||||
),
|
||||
new RangeSetting(
|
||||
"musicVolume",
|
||||
enumCategories.general,
|
||||
/**
|
||||
* @param {Application} app
|
||||
*/
|
||||
(app, id) => {
|
||||
applyGameTheme(id);
|
||||
document.documentElement.setAttribute("data-theme", id);
|
||||
(app, value) => app.sound.setMusicVolume(value)
|
||||
),
|
||||
|
||||
new BoolSetting(
|
||||
"fullscreen",
|
||||
enumCategories.general,
|
||||
/**
|
||||
* @param {Application} app
|
||||
*/
|
||||
(app, value) => {
|
||||
if (app.platformWrapper.getSupportsFullscreen()) {
|
||||
app.platformWrapper.setFullscreen(value);
|
||||
}
|
||||
},
|
||||
enabledCb: /**
|
||||
* @param {Application} app
|
||||
*/ app => app.restrictionMgr.getHasExtendedSettings(),
|
||||
}),
|
||||
/**
|
||||
* @param {Application} app
|
||||
*/ app => app.restrictionMgr.getHasExtendedSettings()
|
||||
),
|
||||
|
||||
new EnumSetting("autosaveInterval", {
|
||||
options: autosaveIntervals,
|
||||
valueGetter: interval => interval.id,
|
||||
textGetter: interval => T.settings.labels.autosaveInterval.intervals[interval.id],
|
||||
category: enumCategories.advanced,
|
||||
restartRequired: false,
|
||||
changeCb:
|
||||
new BoolSetting(
|
||||
"enableColorBlindHelper",
|
||||
enumCategories.general,
|
||||
/**
|
||||
* @param {Application} app
|
||||
*/
|
||||
(app, id) => null,
|
||||
}),
|
||||
(app, value) => null
|
||||
),
|
||||
|
||||
new EnumSetting("scrollWheelSensitivity", {
|
||||
options: scrollWheelSensitivities.sort((a, b) => a.scale - b.scale),
|
||||
valueGetter: scale => scale.id,
|
||||
textGetter: scale => T.settings.labels.scrollWheelSensitivity.sensitivity[scale.id],
|
||||
category: enumCategories.advanced,
|
||||
restartRequired: false,
|
||||
changeCb:
|
||||
/**
|
||||
new BoolSetting("offerHints", enumCategories.userInterface, (app, value) => {}),
|
||||
|
||||
new EnumSetting("theme", {
|
||||
options: Object.keys(THEMES),
|
||||
valueGetter: theme => theme,
|
||||
textGetter: theme => T.settings.labels.theme.themes[theme],
|
||||
category: enumCategories.userInterface,
|
||||
restartRequired: false,
|
||||
changeCb:
|
||||
/**
|
||||
* @param {Application} app
|
||||
*/
|
||||
(app, id) => {
|
||||
applyGameTheme(id);
|
||||
document.documentElement.setAttribute("data-theme", id);
|
||||
},
|
||||
enabledCb: /**
|
||||
* @param {Application} app
|
||||
*/
|
||||
(app, id) => app.updateAfterUiScaleChanged(),
|
||||
}),
|
||||
*/ app => app.restrictionMgr.getHasExtendedSettings(),
|
||||
}),
|
||||
|
||||
new EnumSetting("movementSpeed", {
|
||||
options: movementSpeeds.sort((a, b) => a.multiplier - b.multiplier),
|
||||
valueGetter: multiplier => multiplier.id,
|
||||
textGetter: multiplier => T.settings.labels.movementSpeed.speeds[multiplier.id],
|
||||
category: enumCategories.advanced,
|
||||
restartRequired: false,
|
||||
changeCb: (app, id) => {},
|
||||
}),
|
||||
new EnumSetting("autosaveInterval", {
|
||||
options: autosaveIntervals,
|
||||
valueGetter: interval => interval.id,
|
||||
textGetter: interval => T.settings.labels.autosaveInterval.intervals[interval.id],
|
||||
category: enumCategories.advanced,
|
||||
restartRequired: false,
|
||||
changeCb:
|
||||
/**
|
||||
* @param {Application} app
|
||||
*/
|
||||
(app, id) => null,
|
||||
}),
|
||||
|
||||
new BoolSetting("enableMousePan", enumCategories.advanced, (app, value) => {}),
|
||||
new BoolSetting("shapeTooltipAlwaysOn", enumCategories.advanced, (app, value) => {}),
|
||||
new BoolSetting("alwaysMultiplace", enumCategories.advanced, (app, value) => {}),
|
||||
new BoolSetting("zoomToCursor", enumCategories.advanced, (app, value) => {}),
|
||||
new BoolSetting("clearCursorOnDeleteWhilePlacing", enumCategories.advanced, (app, value) => {}),
|
||||
new BoolSetting("enableTunnelSmartplace", enumCategories.advanced, (app, value) => {}),
|
||||
new BoolSetting("vignette", enumCategories.userInterface, (app, value) => {}),
|
||||
new BoolSetting("compactBuildingInfo", enumCategories.userInterface, (app, value) => {}),
|
||||
new BoolSetting("disableCutDeleteWarnings", enumCategories.advanced, (app, value) => {}),
|
||||
new BoolSetting("rotationByBuilding", enumCategories.advanced, (app, value) => {}),
|
||||
new BoolSetting("displayChunkBorders", enumCategories.advanced, (app, value) => {}),
|
||||
new BoolSetting("pickMinerOnPatch", enumCategories.advanced, (app, value) => {}),
|
||||
new RangeSetting("mapResourcesScale", enumCategories.advanced, () => null),
|
||||
new EnumSetting("scrollWheelSensitivity", {
|
||||
options: scrollWheelSensitivities.sort((a, b) => a.scale - b.scale),
|
||||
valueGetter: scale => scale.id,
|
||||
textGetter: scale => T.settings.labels.scrollWheelSensitivity.sensitivity[scale.id],
|
||||
category: enumCategories.advanced,
|
||||
restartRequired: false,
|
||||
changeCb:
|
||||
/**
|
||||
* @param {Application} app
|
||||
*/
|
||||
(app, id) => app.updateAfterUiScaleChanged(),
|
||||
}),
|
||||
|
||||
new EnumSetting("refreshRate", {
|
||||
options: refreshRateOptions,
|
||||
valueGetter: rate => rate,
|
||||
textGetter: rate => T.settings.tickrateHz.replace("<amount>", rate),
|
||||
category: enumCategories.performance,
|
||||
restartRequired: false,
|
||||
changeCb: (app, id) => {},
|
||||
enabledCb: /**
|
||||
* @param {Application} app
|
||||
*/ app => app.restrictionMgr.getHasExtendedSettings(),
|
||||
}),
|
||||
new EnumSetting("movementSpeed", {
|
||||
options: movementSpeeds.sort((a, b) => a.multiplier - b.multiplier),
|
||||
valueGetter: multiplier => multiplier.id,
|
||||
textGetter: multiplier => T.settings.labels.movementSpeed.speeds[multiplier.id],
|
||||
category: enumCategories.advanced,
|
||||
restartRequired: false,
|
||||
changeCb: (app, id) => {},
|
||||
}),
|
||||
|
||||
new BoolSetting("lowQualityMapResources", enumCategories.performance, (app, value) => {}),
|
||||
new BoolSetting("disableTileGrid", enumCategories.performance, (app, value) => {}),
|
||||
new BoolSetting("lowQualityTextures", enumCategories.performance, (app, value) => {}),
|
||||
new BoolSetting("simplifiedBelts", enumCategories.performance, (app, value) => {}),
|
||||
];
|
||||
new BoolSetting("enableMousePan", enumCategories.advanced, (app, value) => {}),
|
||||
new BoolSetting("shapeTooltipAlwaysOn", enumCategories.advanced, (app, value) => {}),
|
||||
new BoolSetting("alwaysMultiplace", enumCategories.advanced, (app, value) => {}),
|
||||
new BoolSetting("zoomToCursor", enumCategories.advanced, (app, value) => {}),
|
||||
new BoolSetting("clearCursorOnDeleteWhilePlacing", enumCategories.advanced, (app, value) => {}),
|
||||
new BoolSetting("enableTunnelSmartplace", enumCategories.advanced, (app, value) => {}),
|
||||
new BoolSetting("vignette", enumCategories.userInterface, (app, value) => {}),
|
||||
new BoolSetting("compactBuildingInfo", enumCategories.userInterface, (app, value) => {}),
|
||||
new BoolSetting("disableCutDeleteWarnings", enumCategories.advanced, (app, value) => {}),
|
||||
new BoolSetting("rotationByBuilding", enumCategories.advanced, (app, value) => {}),
|
||||
new BoolSetting("displayChunkBorders", enumCategories.advanced, (app, value) => {}),
|
||||
new BoolSetting("pickMinerOnPatch", enumCategories.advanced, (app, value) => {}),
|
||||
new RangeSetting("mapResourcesScale", enumCategories.advanced, () => null),
|
||||
|
||||
export function getApplicationSettingById(id) {
|
||||
return allApplicationSettings.find(setting => setting.id === id);
|
||||
new EnumSetting("refreshRate", {
|
||||
options: refreshRateOptions,
|
||||
valueGetter: rate => rate,
|
||||
textGetter: rate => T.settings.tickrateHz.replace("<amount>", rate),
|
||||
category: enumCategories.performance,
|
||||
restartRequired: false,
|
||||
changeCb: (app, id) => {},
|
||||
enabledCb: /**
|
||||
* @param {Application} app
|
||||
*/ app => app.restrictionMgr.getHasExtendedSettings(),
|
||||
}),
|
||||
|
||||
new BoolSetting("lowQualityMapResources", enumCategories.performance, (app, value) => {}),
|
||||
new BoolSetting("disableTileGrid", enumCategories.performance, (app, value) => {}),
|
||||
new BoolSetting("lowQualityTextures", enumCategories.performance, (app, value) => {}),
|
||||
new BoolSetting("simplifiedBelts", enumCategories.performance, (app, value) => {}),
|
||||
];
|
||||
}
|
||||
|
||||
class SettingsStorage {
|
||||
@ -339,6 +337,8 @@ class SettingsStorage {
|
||||
export class ApplicationSettings extends ReadWriteProxy {
|
||||
constructor(app) {
|
||||
super(app, "app_settings.bin");
|
||||
|
||||
this.settingHandles = initializeSettings();
|
||||
}
|
||||
|
||||
initialize() {
|
||||
@ -347,8 +347,8 @@ export class ApplicationSettings extends ReadWriteProxy {
|
||||
.then(() => {
|
||||
// Apply default setting callbacks
|
||||
const settings = this.getAllSettings();
|
||||
for (let i = 0; i < allApplicationSettings.length; ++i) {
|
||||
const handle = allApplicationSettings[i];
|
||||
for (let i = 0; i < this.settingHandles.length; ++i) {
|
||||
const handle = this.settingHandles[i];
|
||||
handle.apply(this.app, settings[handle.id]);
|
||||
}
|
||||
})
|
||||
@ -360,6 +360,10 @@ export class ApplicationSettings extends ReadWriteProxy {
|
||||
return this.writeAsync();
|
||||
}
|
||||
|
||||
getSettingHandleById(id) {
|
||||
return this.settingHandles.find(setting => setting.id === id);
|
||||
}
|
||||
|
||||
// Getters
|
||||
|
||||
/**
|
||||
@ -457,20 +461,18 @@ export class ApplicationSettings extends ReadWriteProxy {
|
||||
* @param {string|boolean|number} value
|
||||
*/
|
||||
updateSetting(key, value) {
|
||||
for (let i = 0; i < allApplicationSettings.length; ++i) {
|
||||
const setting = allApplicationSettings[i];
|
||||
if (setting.id === key) {
|
||||
if (!setting.validate(value)) {
|
||||
assertAlways(false, "Bad setting value: " + key);
|
||||
}
|
||||
this.getAllSettings()[key] = value;
|
||||
if (setting.changeCb) {
|
||||
setting.changeCb(this.app, value);
|
||||
}
|
||||
return this.writeAsync();
|
||||
}
|
||||
const setting = this.getSettingHandleById(key);
|
||||
if (!setting) {
|
||||
assertAlways(false, "Unknown setting: " + key);
|
||||
}
|
||||
assertAlways(false, "Unknown setting: " + key);
|
||||
if (!setting.validate(value)) {
|
||||
assertAlways(false, "Bad setting value: " + key);
|
||||
}
|
||||
this.getAllSettings()[key] = value;
|
||||
if (setting.changeCb) {
|
||||
setting.changeCb(this.app, value);
|
||||
}
|
||||
return this.writeAsync();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -510,8 +512,15 @@ export class ApplicationSettings extends ReadWriteProxy {
|
||||
}
|
||||
|
||||
const settings = data.settings;
|
||||
for (let i = 0; i < allApplicationSettings.length; ++i) {
|
||||
const setting = allApplicationSettings[i];
|
||||
|
||||
// MODS
|
||||
if (!THEMES[settings.theme]) {
|
||||
console.warn("Resetting theme because its no longer available: " + settings.theme);
|
||||
settings.theme = "light";
|
||||
}
|
||||
|
||||
for (let i = 0; i < this.settingHandles.length; ++i) {
|
||||
const setting = this.settingHandles[i];
|
||||
const storedValue = settings[setting.id];
|
||||
if (!setting.validate(storedValue)) {
|
||||
return ExplainedResult.bad(
|
||||
@ -690,6 +699,12 @@ export class ApplicationSettings extends ReadWriteProxy {
|
||||
data.version = 31;
|
||||
}
|
||||
|
||||
// MODS
|
||||
if (!THEMES[data.settings.theme]) {
|
||||
console.warn("Resetting theme because its no longer available: " + data.settings.theme);
|
||||
data.settings.theme = "light";
|
||||
}
|
||||
|
||||
return ExplainedResult.good();
|
||||
}
|
||||
}
|
||||
|
||||
@ -20,7 +20,6 @@ import { HUDModalDialogs } from "../game/hud/parts/modal_dialogs";
|
||||
import { MODS } from "../mods/modloader";
|
||||
import { PlatformWrapperImplBrowser } from "../platform/browser/wrapper";
|
||||
import { PlatformWrapperImplElectron } from "../platform/electron/wrapper";
|
||||
import { getApplicationSettingById } from "../profile/application_settings";
|
||||
import { T } from "../translations";
|
||||
|
||||
const trim = require("trim");
|
||||
@ -468,7 +467,7 @@ export class MainMenuState extends GameState {
|
||||
|
||||
onLanguageChooseClicked() {
|
||||
this.app.analytics.trackUiClick("choose_language");
|
||||
const setting = /** @type {EnumSetting} */ (getApplicationSettingById("language"));
|
||||
const setting = /** @type {EnumSetting} */ (this.app.settings.getSettingHandleById("language"));
|
||||
|
||||
const { optionSelected } = this.dialogs.showOptionChooser(T.settings.labels.language.title, {
|
||||
active: this.app.settings.getLanguage(),
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { THIRDPARTY_URLS } from "../core/config";
|
||||
import { TextualGameState } from "../core/textual_game_state";
|
||||
import { formatSecondsToTimeAgo } from "../core/utils";
|
||||
import { allApplicationSettings, enumCategories } from "../profile/application_settings";
|
||||
import { enumCategories } from "../profile/application_settings";
|
||||
import { T } from "../translations";
|
||||
|
||||
export class SettingsState extends TextualGameState {
|
||||
@ -88,8 +88,8 @@ export class SettingsState extends TextualGameState {
|
||||
categoriesHTML[catName] = `<div class="category" data-category="${catName}">`;
|
||||
});
|
||||
|
||||
for (let i = 0; i < allApplicationSettings.length; ++i) {
|
||||
const setting = allApplicationSettings[i];
|
||||
for (let i = 0; i < this.app.settings.settingHandles.length; ++i) {
|
||||
const setting = this.app.settings.settingHandles[i];
|
||||
|
||||
if ((G_CHINA_VERSION || G_WEGAME_VERSION) && setting.id === "language") {
|
||||
continue;
|
||||
@ -171,7 +171,7 @@ export class SettingsState extends TextualGameState {
|
||||
}
|
||||
|
||||
initSettings() {
|
||||
allApplicationSettings.forEach(setting => {
|
||||
this.app.settings.settingHandles.forEach(setting => {
|
||||
if ((G_CHINA_VERSION || G_WEGAME_VERSION) && setting.id === "language") {
|
||||
return;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user