1
0
mirror of https://github.com/tobspr/shapez.io.git synced 2025-12-13 18:21:51 +00:00

Support for mod settings

This commit is contained in:
tobspr 2022-01-17 12:15:57 +01:00
parent fd0ae12a84
commit 54a69c9725
20 changed files with 148 additions and 60 deletions

View File

@ -316,7 +316,7 @@ async function writeFileSafe(filename, contents) {
}
ipcMain.handle("fs-job", async (event, job) => {
const filenameSafe = job.filename.replace(/[^a-z\.\-_0-9]/i, "");
const filenameSafe = job.filename.replace(/[^a-z\.\-_0-9]/i, "_");
const fname = path.join(storePath, filenameSafe);
switch (job.type) {
case "read": {

View File

@ -1,3 +1,4 @@
// @ts-nocheck
const METADATA = {
website: "https://tobspr.io",
author: "tobspr",

View File

@ -1,3 +1,4 @@
// @ts-nocheck
const METADATA = {
website: "https://tobspr.io",
author: "tobspr",

View File

@ -1,3 +1,4 @@
// @ts-nocheck
const METADATA = {
website: "https://tobspr.io",
author: "tobspr",

View File

@ -1,3 +1,4 @@
// @ts-nocheck
const METADATA = {
website: "https://tobspr.io",
author: "tobspr",

View File

@ -1,3 +1,4 @@
// @ts-nocheck
const METADATA = {
website: "https://tobspr.io",
author: "tobspr",

View File

@ -1,3 +1,4 @@
// @ts-nocheck
const METADATA = {
website: "https://tobspr.io",
author: "tobspr",

View File

@ -1,3 +1,4 @@
// @ts-nocheck
const METADATA = {
website: "https://tobspr.io",
author: "tobspr",

View File

@ -1,3 +1,4 @@
// @ts-nocheck
const METADATA = {
website: "https://tobspr.io",
author: "tobspr",

View File

@ -1,3 +1,4 @@
// @ts-nocheck
const METADATA = {
website: "https://tobspr.io",
author: "tobspr",

View File

@ -0,0 +1,31 @@
// @ts-nocheck
const METADATA = {
website: "https://tobspr.io",
author: "tobspr",
name: "Mod Example: Mod Settings",
version: "1",
id: "base",
description: "Shows how to add settings to your mod",
settings: {
timesLaunched: 0,
},
};
class Mod extends shapez.Mod {
init() {
// Increment the setting every time we launch the mod
this.settings.timesLaunched++;
this.saveSettings();
// Show a dialog in the main menu wit the settings
this.signals.stateEntered.add(state => {
if (state instanceof shapez.MainMenuState) {
this.dialogs.showInfo(
"Welcome back",
"You have launched this mod " + this.settings.timesLaunched + " times"
);
}
});
}
}

View File

@ -1,3 +1,4 @@
// @ts-nocheck
const METADATA = {
website: "https://tobspr.io",
author: "tobspr",

View File

@ -1,3 +1,4 @@
// @ts-nocheck
const METADATA = {
website: "https://tobspr.io",
author: "tobspr",

View File

@ -1,3 +1,4 @@
// @ts-nocheck
const METADATA = {
website: "https://tobspr.io",
author: "tobspr",

View File

@ -1,3 +1,4 @@
// @ts-nocheck
const METADATA = {
website: "https://tobspr.io",
author: "tobspr",

View File

@ -1,3 +1,4 @@
// @ts-nocheck
const METADATA = {
website: "https://tobspr.io",
author: "tobspr",

View File

@ -1,3 +1,4 @@
// @ts-nocheck
const METADATA = {
website: "https://tobspr.io",
author: "tobspr",

View File

@ -77,7 +77,12 @@ export class Application {
MODS.app = this;
// MODS
try {
await MODS.initMods();
} catch (ex) {
alert("Failed to load mods (launch with --dev for more info): \n\n" + ex);
}
this.unloaded = false;

View File

@ -7,17 +7,23 @@ import { MOD_SIGNALS } from "./mod_signals";
export class Mod {
/**
* @param {Application} app
* @param {ModLoader} modLoader
* @param {import("./modloader").ModMetadata} meta
* @param {object} param0
* @param {Application} param0.app
* @param {ModLoader} param0.modLoader
* @param {import("./modloader").ModMetadata} param0.meta
* @param {Object} param0.settings
* @param {() => Promise<void>} param0.saveSettings
*/
constructor(app, modLoader, meta) {
constructor({ app, modLoader, meta, settings, saveSettings }) {
this.app = app;
this.modLoader = modLoader;
this.metadata = meta;
this.signals = MOD_SIGNALS;
this.modInterface = modLoader.modInterface;
this.settings = settings;
this.saveSettings = saveSettings;
}
init() {

View File

@ -3,6 +3,9 @@ import { Application } from "../application";
/* typehints:end */
import { globalConfig } from "../core/config";
import { createLogger } from "../core/logging";
import { StorageImplBrowserIndexedDB } from "../platform/browser/storage_indexed_db";
import { StorageImplElectron } from "../platform/electron/storage";
import { FILE_NOT_FOUND } from "../platform/storage";
import { Mod } from "./mod";
import { ModInterface } from "./mod_interface";
import { MOD_SIGNALS } from "./mod_signals";
@ -17,6 +20,7 @@ const LOG = createLogger("mods");
* website: string;
* description: string;
* id: string;
* settings: []
* }} ModMetadata
*/
@ -80,12 +84,20 @@ export class ModLoader {
}
async initMods() {
LOG.log("hook:init");
if (!G_IS_STANDALONE && !G_IS_DEV) {
this.initialized = true;
return;
}
// Create a storage for reading mod settings
const storage = G_IS_STANDALONE
? new StorageImplElectron(this.app)
: new StorageImplBrowserIndexedDB(this.app);
await storage.initialize();
LOG.log("hook:init", this.app, this.app.storage);
this.exposeExports();
if (G_IS_STANDALONE || G_IS_DEV) {
try {
let mods = [];
if (G_IS_STANDALONE) {
mods = await ipcRenderer.invoke("get-mods");
@ -110,11 +122,7 @@ export class ModLoader {
window.$shapez_registerMod = (modClass, meta) => {
if (this.modLoadQueue.some(entry => entry.meta.id === meta.id)) {
console.warn(
"Not registering mod",
meta,
"since a mod with the same id is already loaded"
);
console.warn("Not registering mod", meta, "since a mod with the same id is already loaded");
return;
}
this.modLoadQueue.push({
@ -142,22 +150,45 @@ export class ModLoader {
});
delete window.$shapez_registerMod;
this.initialized = true;
for (let i = 0; i < this.modLoadQueue.length; i++) {
const { modClass, meta } = this.modLoadQueue[i];
const modDataFile = "modsettings_" + meta.id + "__" + meta.version + ".json";
let settings = meta.settings;
if (meta.settings) {
try {
const storedSettings = await storage.readFileAsync(modDataFile);
settings = JSON.parse(storedSettings);
} catch (ex) {
alert("Failed to load mods (launch with --dev for more info): \n\n" + ex);
if (ex === FILE_NOT_FOUND) {
// Write default data
await storage.writeFileAsync(modDataFile, JSON.stringify(meta.settings));
} else {
alert("Failed to load settings for " + meta.id + ", will use defaults:\n\n" + ex);
}
}
}
this.initialized = true;
this.modLoadQueue.forEach(({ modClass, meta }) => {
try {
const mod = new modClass(this.app, this, meta);
const mod = new modClass({
app: this.app,
modLoader: this,
meta,
settings,
saveSettings: () => storage.writeFileAsync(modDataFile, JSON.stringify(mod.settings)),
});
mod.init();
this.mods.push(mod);
} catch (ex) {
console.error(ex);
alert("Failed to initialize mods (launch with --dev for more info): \n\n" + ex);
}
});
}
this.modLoadQueue = [];
}
}