mirror of
https://github.com/FunkinCrew/Funkin.git
synced 2024-11-24 08:38:16 -05:00
Update save data format and error handling.
This commit is contained in:
parent
24ad7f4a39
commit
dff4135fc9
7 changed files with 122 additions and 38 deletions
2
hmm.json
2
hmm.json
|
@ -11,7 +11,7 @@
|
|||
"name": "flixel",
|
||||
"type": "git",
|
||||
"dir": null,
|
||||
"ref": "f2b090d6c608471e730b051c8ee22b8b378964b1",
|
||||
"ref": "ffa691cb2d2d81de35b900a4411e4062ac84ab58",
|
||||
"url": "https://github.com/FunkinCrew/flixel"
|
||||
},
|
||||
{
|
||||
|
|
|
@ -1,25 +1,23 @@
|
|||
package funkin.save;
|
||||
|
||||
import flixel.util.FlxSave;
|
||||
import funkin.util.FileUtil;
|
||||
import funkin.input.Controls.Device;
|
||||
import funkin.play.scoring.Scoring;
|
||||
import funkin.play.scoring.Scoring.ScoringRank;
|
||||
import funkin.save.migrator.RawSaveData_v1_0_0;
|
||||
import funkin.save.migrator.SaveDataMigrator;
|
||||
import funkin.save.migrator.SaveDataMigrator;
|
||||
import funkin.ui.debug.charting.ChartEditorState.ChartEditorLiveInputStyle;
|
||||
import funkin.ui.debug.charting.ChartEditorState.ChartEditorTheme;
|
||||
import funkin.ui.debug.stageeditor.StageEditorState.StageEditorTheme;
|
||||
import funkin.util.FileUtil;
|
||||
import funkin.util.SerializerUtil;
|
||||
import thx.semver.Version;
|
||||
import thx.semver.Version;
|
||||
|
||||
@:nullSafety
|
||||
class Save
|
||||
{
|
||||
public static final SAVE_DATA_VERSION:thx.semver.Version = "2.0.6";
|
||||
public static final SAVE_DATA_VERSION_RULE:thx.semver.VersionRule = "2.0.x";
|
||||
public static final SAVE_DATA_VERSION:thx.semver.Version = "2.1.0";
|
||||
public static final SAVE_DATA_VERSION_RULE:thx.semver.VersionRule = ">=2.1.0 <2.2.0";
|
||||
|
||||
// We load this version's saves from a new save path, to maintain SOME level of backwards compatibility.
|
||||
static final SAVE_PATH:String = 'FunkinCrew';
|
||||
|
@ -965,32 +963,57 @@ class Save
|
|||
|
||||
FlxG.save.bind('$SAVE_NAME${slot}', SAVE_PATH);
|
||||
|
||||
if (FlxG.save.isEmpty())
|
||||
switch (FlxG.save.status)
|
||||
{
|
||||
trace('[SAVE] Save data is empty, checking for legacy save data...');
|
||||
var legacySaveData = fetchLegacySaveData();
|
||||
if (legacySaveData != null)
|
||||
{
|
||||
trace('[SAVE] Found legacy save data, converting...');
|
||||
var gameSave = SaveDataMigrator.migrateFromLegacy(legacySaveData);
|
||||
case EMPTY:
|
||||
trace('[SAVE] Save data in slot ${slot} is empty, checking for legacy save data...');
|
||||
var legacySaveData = fetchLegacySaveData();
|
||||
if (legacySaveData != null)
|
||||
{
|
||||
trace('[SAVE] Found legacy save data, converting...');
|
||||
var gameSave = SaveDataMigrator.migrateFromLegacy(legacySaveData);
|
||||
FlxG.save.mergeData(gameSave.data, true);
|
||||
return gameSave;
|
||||
}
|
||||
else
|
||||
{
|
||||
trace('[SAVE] No legacy save data found.');
|
||||
var gameSave = new Save();
|
||||
FlxG.save.mergeData(gameSave.data, true);
|
||||
return gameSave;
|
||||
}
|
||||
case ERROR(_):
|
||||
return handleSaveDataError(slot);
|
||||
case BOUND(_, _):
|
||||
trace('[SAVE] Loaded existing save data in slot ${slot}.');
|
||||
var gameSave = SaveDataMigrator.migrate(FlxG.save.data);
|
||||
FlxG.save.mergeData(gameSave.data, true);
|
||||
|
||||
return gameSave;
|
||||
}
|
||||
else
|
||||
{
|
||||
trace('[SAVE] No legacy save data found.');
|
||||
var gameSave = new Save();
|
||||
FlxG.save.mergeData(gameSave.data, true);
|
||||
return gameSave;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Call this when there is an error loading the save data in slot X.
|
||||
*/
|
||||
static function handleSaveDataError(slot:Int):Save
|
||||
{
|
||||
var msg = 'There was an error loading your save data in slot ${slot}.';
|
||||
msg += '\nPlease report this issue to the developers.';
|
||||
lime.app.Application.current.window.alert(msg, "Save Data Failure");
|
||||
|
||||
// Don't touch that slot anymore.
|
||||
// Instead, load the next available slot.
|
||||
|
||||
var nextSlot = slot + 1;
|
||||
|
||||
if (nextSlot < 1000)
|
||||
{
|
||||
return loadFromSlot(nextSlot);
|
||||
}
|
||||
else
|
||||
{
|
||||
trace('[SAVE] Found existing save data.');
|
||||
var gameSave = SaveDataMigrator.migrate(FlxG.save.data);
|
||||
FlxG.save.mergeData(gameSave.data, true);
|
||||
|
||||
return gameSave;
|
||||
throw "End of save data slots. Can't load any more.";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1055,7 +1078,15 @@ class Save
|
|||
{
|
||||
var targetSaveData = new FlxSave();
|
||||
targetSaveData.bind('$SAVE_NAME${slot}', SAVE_PATH);
|
||||
return !targetSaveData.isEmpty();
|
||||
switch (targetSaveData.status)
|
||||
{
|
||||
case EMPTY:
|
||||
return false;
|
||||
case ERROR(_):
|
||||
return false;
|
||||
case BOUND(_, _):
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -5,6 +5,14 @@ All notable changes to this project will be documented in this file.
|
|||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [2.1.0] - 2024-10-18
|
||||
This version introduces changes to save data loading in order to improve compatibility with older versions.
|
||||
### Changed
|
||||
- `optionsStageEditor.theme` converted from an Enum to a String to fix save data compatibility issues.
|
||||
- In the future, Enum values should not be used in order to prevent incompatibilities caused by introducing new types to the save data that older versions cannot parse.
|
||||
- `optionsChartEditor.theme` converted from an Enum to a String to fix save data compatibility issues.
|
||||
- `optionsChartEditor.chartEditorLiveInputStyle` converted from an Enum to a String to fix save data compatibility issues.
|
||||
|
||||
## [2.0.6] - 2024-10-11
|
||||
### Added
|
||||
- `optionsStageEditor` to `Save` for storing user preferences for the stage editor.
|
||||
|
|
|
@ -32,6 +32,10 @@ class SaveDataMigrator
|
|||
var save:Save = new Save(saveDataWithDefaults);
|
||||
return save;
|
||||
}
|
||||
else if (VersionUtil.validateVersion(version, "2.0.x"))
|
||||
{
|
||||
return migrate_v2_0_0(inputData);
|
||||
}
|
||||
else
|
||||
{
|
||||
var message:String = 'Error migrating save data, expected ${Save.SAVE_DATA_VERSION}.';
|
||||
|
@ -43,6 +47,20 @@ class SaveDataMigrator
|
|||
}
|
||||
}
|
||||
|
||||
static function migrate_v2_0_0(inputData:Dynamic):Save
|
||||
{
|
||||
// Import the structured data.
|
||||
var saveDataWithDefaults:RawSaveData = cast thx.Objects.deepCombine(Save.getDefault(), inputData);
|
||||
|
||||
// Reset these values to valid ones.
|
||||
saveDataWithDefaults.optionsChartEditor.chartEditorLiveInputStyle = funkin.ui.debug.charting.ChartEditorLiveInputStyle.None;
|
||||
saveDataWithDefaults.optionsChartEditor.theme = funkin.ui.debug.charting.ChartEditorTheme.Light;
|
||||
saveDataWithDefaults.optionsStageEditor.theme = funkin.ui.debug.stageeditor.StageEditorTheme.Light;
|
||||
|
||||
var save:Save = new Save(saveDataWithDefaults);
|
||||
return save;
|
||||
}
|
||||
|
||||
/**
|
||||
* Migrate from 1.x to the latest version.
|
||||
*/
|
||||
|
|
26
source/funkin/save/migrator/SaveData_v2_0_0.hx
Normal file
26
source/funkin/save/migrator/SaveData_v2_0_0.hx
Normal file
|
@ -0,0 +1,26 @@
|
|||
package funkin.save.migrator;
|
||||
|
||||
// Internal enums used to ensure old save data can be parsed by the default Haxe unserializer.
|
||||
// In the future, only primitive types and abstract enums should be used in save data!
|
||||
|
||||
@:native("funkin.ui.debug.stageeditor.StageEditorTheme")
|
||||
enum StageEditorTheme
|
||||
{
|
||||
Light;
|
||||
Dark;
|
||||
}
|
||||
|
||||
@:native("funkin.ui.debug.charting.ChartEditorTheme")
|
||||
enum ChartEditorTheme
|
||||
{
|
||||
Light;
|
||||
Dark;
|
||||
}
|
||||
|
||||
@:native("funkin.ui.debug.charting.ChartEditorLiveInputStyle")
|
||||
enum ChartEditorLiveInputStyle
|
||||
{
|
||||
None;
|
||||
NumberKeys;
|
||||
WASDKeys;
|
||||
}
|
|
@ -5654,7 +5654,8 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
|
|||
function handleHelpKeybinds():Void
|
||||
{
|
||||
// F1 = Open Help
|
||||
if (FlxG.keys.justPressed.F1 && !isHaxeUIDialogOpen) {
|
||||
if (FlxG.keys.justPressed.F1 && !isHaxeUIDialogOpen)
|
||||
{
|
||||
this.openUserGuideDialog();
|
||||
}
|
||||
}
|
||||
|
@ -6543,22 +6544,22 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
|
|||
/**
|
||||
* Available input modes for the chart editor state. Numbers/arrows/WASD available for other keybinds.
|
||||
*/
|
||||
enum ChartEditorLiveInputStyle
|
||||
enum abstract ChartEditorLiveInputStyle(String)
|
||||
{
|
||||
/**
|
||||
* No hotkeys to place notes at the playbar.
|
||||
*/
|
||||
None;
|
||||
var None;
|
||||
|
||||
/**
|
||||
* 1/2/3/4 to place notes on opponent's side, 5/6/7/8 to place notes on player's side.
|
||||
*/
|
||||
NumberKeys;
|
||||
var NumberKeys;
|
||||
|
||||
/**
|
||||
* WASD to place notes on opponent's side, Arrow keys to place notes on player's side.
|
||||
*/
|
||||
WASDKeys;
|
||||
var WASDKeys;
|
||||
}
|
||||
|
||||
typedef ChartEditorParams =
|
||||
|
@ -6577,15 +6578,15 @@ typedef ChartEditorParams =
|
|||
/**
|
||||
* Available themes for the chart editor state.
|
||||
*/
|
||||
enum ChartEditorTheme
|
||||
enum abstract ChartEditorTheme(String)
|
||||
{
|
||||
/**
|
||||
* The default theme for the chart editor.
|
||||
*/
|
||||
Light;
|
||||
var Light;
|
||||
|
||||
/**
|
||||
* A theme which introduces darker colors.
|
||||
*/
|
||||
Dark;
|
||||
var Dark;
|
||||
}
|
||||
|
|
|
@ -1458,17 +1458,17 @@ class StageEditorState extends UIState
|
|||
/**
|
||||
* Available themes for the stage editor state.
|
||||
*/
|
||||
enum StageEditorTheme
|
||||
enum abstract StageEditorTheme(String)
|
||||
{
|
||||
/**
|
||||
* The default theme for the stage editor.
|
||||
*/
|
||||
Light;
|
||||
var Light;
|
||||
|
||||
/**
|
||||
* A theme which introduces stage colors.
|
||||
*/
|
||||
Dark;
|
||||
var Dark;
|
||||
}
|
||||
|
||||
enum StageEditorDialogType
|
||||
|
|
Loading…
Reference in a new issue