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

Add example for storing data in the savegame

This commit is contained in:
tobspr 2022-02-01 14:37:53 +01:00
parent 20dca5bcc1
commit bf7e1887a8
7 changed files with 98 additions and 4 deletions

View File

@ -38,6 +38,7 @@ To get into shapez.io modding, I highly recommend checking out all of the exampl
| [modify_theme.js](modify_theme.js) | Modifies the default game themes | Modifying the builtin themes |
| [custom_theme.js](custom_theme.js) | Adds a new UI and map theme | Adding a new game theme |
| [mod_settings.js](mod_settings.js) | Shows a dialog counting how often the mod has been launched | Reading and storing mod settings |
| [storing_data_in_savegame.js](storing_data_in_savegame.js) | Shows how to store custom (structured) data in the savegame | Storing custom data in savegame |
| [modify_existing_building.js](modify_existing_building.js) | Makes the rotator building always unlocked and adds a new statistic to the building panel | Modifying a builtin building, replacing builtin methods |
| [modify_ui.js](modify_ui.js) | Shows how to add custom IU elements to builtin game states (the Main Menu in this case) | Extending builtin UI states, Adding CSS |
| [pasting.js](pasting.js) | Shows a dialog when pasting text in the game | Listening to paste events |

View File

@ -0,0 +1,78 @@
// @ts-nocheck
const METADATA = {
website: "https://tobspr.io",
author: "tobspr",
name: "Mod Example: Storing Data in Savegame",
version: "1",
id: "storing-savegame-data",
description: "Shows how to add custom data to a savegame",
minimumGameVersion: ">=1.5.0",
};
class Mod extends shapez.Mod {
init() {
////////////////////////////////////////////////////////////////////
// Option 1: For simple data
this.signals.gameSerialized.add((root, data) => {
data.modExtraData["storing-savegame-data"] = Math.random();
});
this.signals.gameDeserialized.add((root, data) => {
alert("The value stored in the savegame was: " + data.modExtraData["storing-savegame-data"]);
});
////////////////////////////////////////////////////////////////////
// Option 2: If you need a structured way of storing data
class SomeSerializableObject extends shapez.BasicSerializableObject {
static getId() {
return "SomeSerializableObject";
}
static getSchema() {
return {
someInt: shapez.types.int,
someString: shapez.types.string,
someVector: shapez.types.vector,
// this value is allowed to be null
nullableInt: shapez.types.nullable(shapez.types.int),
// There is a lot more .. be sure to checkout src/js/savegame/serialization.js
// You can have maps, classes, arrays etc..
// And if you need something specific you can always ask in the modding discord.
};
}
constructor() {
super();
this.someInt = 42;
this.someString = "Hello World";
this.someVector = new shapez.Vector(1, 2);
this.nullableInt = null;
}
}
// Store our object in the global game root
this.signals.gameInitialized.add(root => {
root.myObject = new SomeSerializableObject();
});
// Save it within the savegame
this.signals.gameSerialized.add((root, data) => {
data.modExtraData["storing-savegame-data-2"] = root.myObject.serialize();
});
// Restore it when the savegame is loaded
this.signals.gameDeserialized.add((root, data) => {
const errorText = root.myObject.deserialize(data.modExtraData["storing-savegame-data-2"]);
if (errorText) {
alert("Mod failed to deserialize from savegame: " + errorText);
}
alert("The other value stored in the savegame (option 2) was " + root.myObject.someInt);
});
////////////////////////////////////////////////////////////////////
}
}

View File

@ -27,4 +27,7 @@ export const MOD_SIGNALS = {
gameStarted: /** @type {TypedSignal<[GameRoot]>} */ (new Signal()),
stateEntered: /** @type {TypedSignal<[GameState]>} */ (new Signal()),
gameSerialized: /** @type {TypedSignal<[GameRoot, import("../savegame/savegame_typedefs").SerializedGame]>} */ (new Signal()),
gameDeserialized: /** @type {TypedSignal<[GameRoot, import("../savegame/savegame_typedefs").SerializedGame]>} */ (new Signal()),
};

View File

@ -162,6 +162,7 @@ export class Savegame extends ReadWriteProxy {
SavegameInterface_V1009.migrate1008to1009(data);
data.version = 1009;
}
if (data.version === 1009) {
SavegameInterface_V1010.migrate1009to1010(data);
data.version = 1010;

View File

@ -1,9 +1,8 @@
import { ExplainedResult } from "../core/explained_result";
import { createLogger } from "../core/logging";
import { gComponentRegistry } from "../core/global_registries";
import { createLogger } from "../core/logging";
import { MOD_SIGNALS } from "../mods/mod_signals";
import { SerializerInternal } from "./serializer_internal";
import { HUDPinnedShapes } from "../game/hud/parts/pinned_shapes";
import { HUDWaypoints } from "../game/hud/parts/waypoints";
/**
* @typedef {import("../game/component").Component} Component
@ -42,8 +41,12 @@ export class SavegameSerializer {
beltPaths: root.systemMgr.systems.belt.serializePaths(),
pinnedShapes: root.hud.parts.pinnedShapes ? root.hud.parts.pinnedShapes.serialize() : null,
waypoints: root.hud.parts.waypoints ? root.hud.parts.waypoints.serialize() : null,
modExtraData: {},
};
MOD_SIGNALS.gameSerialized.dispatch(root, data);
if (G_IS_DEV) {
if (sanityChecks) {
// Sanity check
@ -151,6 +154,9 @@ export class SavegameSerializer {
return ExplainedResult.bad(errorReason);
}
// Mods
MOD_SIGNALS.gameDeserialized.dispatch(root, savegame);
return ExplainedResult.good();
}
}

View File

@ -25,7 +25,8 @@
* pinnedShapes: any,
* waypoints: any,
* entities: Array<Entity>,
* beltPaths: Array<any>
* beltPaths: Array<any>,
* modExtraData: Object
* }} SerializedGame
*
* @typedef {{

View File

@ -20,5 +20,9 @@ export class SavegameInterface_V1010 extends SavegameInterface_V1009 {
logger.log("Migrating 1009 to 1010");
data.mods = [];
if (data.dump) {
data.dump.modExtraData = {};
}
}
}