From f2b3469530d68413e681125945fcc8812b70cf4a Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Sun, 25 Jan 2026 12:56:02 -0800 Subject: [PATCH] WIP --- src/App.svelte | 4 + src/app.css | 21 + src/core/opfs.js | 147 ++++++- src/core/savegame/BinaryReader.js | 164 ++++++++ src/core/savegame/BinaryWriter.js | 172 ++++++++ src/core/savegame/PlayersParser.js | 54 +++ src/core/savegame/PlayersSerializer.js | 62 +++ src/core/savegame/SaveGameParser.js | 396 ++++++++++++++++++ src/core/savegame/SaveGameSerializer.js | 329 +++++++++++++++ src/core/savegame/constants.js | 191 +++++++++ src/core/savegame/index.js | 284 +++++++++++++ src/lib/ConfigToast.svelte | 4 +- src/lib/SaveEditorPage.svelte | 168 ++++++++ src/lib/config/ExtrasTab.svelte | 11 +- .../save-editor/MissionScoresEditor.svelte | 215 ++++++++++ src/lib/save-editor/PlayerInfoEditor.svelte | 298 +++++++++++++ src/lib/save-editor/SaveSlotCard.svelte | 77 ++++ src/lib/save-editor/SaveSlotList.svelte | 54 +++ src/lib/save-editor/ScoreColorButton.svelte | 64 +++ src/stores.js | 12 +- 20 files changed, 2722 insertions(+), 5 deletions(-) create mode 100644 src/core/savegame/BinaryReader.js create mode 100644 src/core/savegame/BinaryWriter.js create mode 100644 src/core/savegame/PlayersParser.js create mode 100644 src/core/savegame/PlayersSerializer.js create mode 100644 src/core/savegame/SaveGameParser.js create mode 100644 src/core/savegame/SaveGameSerializer.js create mode 100644 src/core/savegame/constants.js create mode 100644 src/core/savegame/index.js create mode 100644 src/lib/SaveEditorPage.svelte create mode 100644 src/lib/save-editor/MissionScoresEditor.svelte create mode 100644 src/lib/save-editor/PlayerInfoEditor.svelte create mode 100644 src/lib/save-editor/SaveSlotCard.svelte create mode 100644 src/lib/save-editor/SaveSlotList.svelte create mode 100644 src/lib/save-editor/ScoreColorButton.svelte diff --git a/src/App.svelte b/src/App.svelte index 7f3bd8f..81dfbdd 100644 --- a/src/App.svelte +++ b/src/App.svelte @@ -8,6 +8,7 @@ import ReadMePage from './lib/ReadMePage.svelte'; import ConfigurePage from './lib/ConfigurePage.svelte'; import FreeStuffPage from './lib/FreeStuffPage.svelte'; + import SaveEditorPage from './lib/SaveEditorPage.svelte'; import UpdatePopup from './lib/UpdatePopup.svelte'; import GoodbyePopup from './lib/GoodbyePopup.svelte'; import ConfigToast from './lib/ConfigToast.svelte'; @@ -76,6 +77,9 @@
+
+ +
+
+ Save Editor +
diff --git a/src/lib/save-editor/MissionScoresEditor.svelte b/src/lib/save-editor/MissionScoresEditor.svelte new file mode 100644 index 0000000..6486747 --- /dev/null +++ b/src/lib/save-editor/MissionScoresEditor.svelte @@ -0,0 +1,215 @@ + + +
+

Mission Scores

+ +
+ {#key missionData} +
+
+
+ {#each actors as actor} +
{actor.name}
+ {/each} +
+ + {#each missions as mission} +
+
{mission.name}
+ {#each actors as actor} +
+ handleScoreChange(mission.key, actor.id, 'score', c)} + title="Score" + /> + handleScoreChange(mission.key, actor.id, 'highScore', c)} + title="High Score" + isHighScore={true} + /> +
+ {/each} +
+ {/each} +
+ {/key} +
+ +
+ + Grey + + + Yellow + + + Blue + + + Red + + | + H = High Score +
+
+ + diff --git a/src/lib/save-editor/PlayerInfoEditor.svelte b/src/lib/save-editor/PlayerInfoEditor.svelte new file mode 100644 index 0000000..5acd1f5 --- /dev/null +++ b/src/lib/save-editor/PlayerInfoEditor.svelte @@ -0,0 +1,298 @@ + + +
+

Player Info

+ +
+ Name +
+ {#each nameSlots as char, i} + handleSlotBeforeInput(i, e)} + onkeydown={(e) => handleSlotKeydown(i, e)} + onfocus={handleSlotFocus} + bind:this={slotRefs[i]} + /> + {/each} +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+
+ + diff --git a/src/lib/save-editor/SaveSlotCard.svelte b/src/lib/save-editor/SaveSlotCard.svelte new file mode 100644 index 0000000..2d9f1dd --- /dev/null +++ b/src/lib/save-editor/SaveSlotCard.svelte @@ -0,0 +1,77 @@ + + + + + diff --git a/src/lib/save-editor/SaveSlotList.svelte b/src/lib/save-editor/SaveSlotList.svelte new file mode 100644 index 0000000..8f75398 --- /dev/null +++ b/src/lib/save-editor/SaveSlotList.svelte @@ -0,0 +1,54 @@ + + +
+

Save Slots

+ {#if existingSlots.length === 0} +

No save files found

+ {:else} +
+ {#each existingSlots as slot} + onSelect(slot.slotNumber)} + /> + {/each} +
+ {/if} +
+ + diff --git a/src/lib/save-editor/ScoreColorButton.svelte b/src/lib/save-editor/ScoreColorButton.svelte new file mode 100644 index 0000000..a0fb94c --- /dev/null +++ b/src/lib/save-editor/ScoreColorButton.svelte @@ -0,0 +1,64 @@ + + + + + diff --git a/src/stores.js b/src/stores.js index 97dd8f4..cf9e708 100644 --- a/src/stores.js +++ b/src/stores.js @@ -7,7 +7,8 @@ function getInitialPage() { const pageMap = { '#read-me': 'read-me', '#configure': 'configure', - '#free-stuff': 'free-stuff' + '#free-stuff': 'free-stuff', + '#save-editor': 'save-editor' }; return pageMap[hash] || 'main'; } @@ -35,6 +36,7 @@ export const installState = writable({ // Config toast export const configToastVisible = writable(false); +export const configToastMessage = writable('Settings saved'); // Debug UI visible (set when game reaches intro animation) export const debugUIVisible = writable(false); @@ -44,3 +46,11 @@ export const gameRunning = writable(false); // Service worker registration export const swRegistration = writable(null); + +// Save editor state +export const saveEditorState = writable({ + slots: [], // Array of SaveSlot objects + selectedSlot: null, // Currently selected slot number + loading: true, + error: null +});