Merge pull request #458 from FunkinCrew/bugfix/a-couple-more-fixes

Bugfix/a couple more fixes
This commit is contained in:
Cameron Taylor 2024-04-03 03:38:37 -04:00 committed by GitHub
commit b7c6b1aaf6
5 changed files with 82 additions and 21 deletions

View file

@ -321,6 +321,13 @@ class FunkinSound extends FlxSound implements ICloneable<FunkinSound>
} }
} }
if (FlxG.sound.music != null)
{
FlxG.sound.music.fadeTween?.cancel();
FlxG.sound.music.stop();
FlxG.sound.music.kill();
}
if (params?.mapTimeChanges ?? true) if (params?.mapTimeChanges ?? true)
{ {
var songMusicData:Null<SongMusicData> = SongRegistry.instance.parseMusicData(key); var songMusicData:Null<SongMusicData> = SongRegistry.instance.parseMusicData(key);
@ -335,19 +342,6 @@ class FunkinSound extends FlxSound implements ICloneable<FunkinSound>
} }
} }
if (FlxG.sound.music != null)
{
FlxG.sound.music.fadeTween?.cancel();
FlxG.sound.music.stop();
FlxG.sound.music.kill();
}
// Apparently HaxeFlixel isn't null safe.
@:nullSafety(Off)
{
FlxG.sound.music = FunkinSound.load(Paths.music('$key/$key'), params?.startingVolume ?? 1.0, true, false, true);
}
var music = FunkinSound.load(Paths.music('$key/$key'), params?.startingVolume ?? 1.0, params.loop ?? true, false, true); var music = FunkinSound.load(Paths.music('$key/$key'), params?.startingVolume ?? 1.0, params.loop ?? true, false, true);
if (music != null) if (music != null)
{ {

View file

@ -14,7 +14,7 @@ import thx.semver.Version;
class Save class Save
{ {
// Version 2.0.2 adds attributes to `optionsChartEditor`, that should return default values if they are null. // Version 2.0.2 adds attributes to `optionsChartEditor`, that should return default values if they are null.
public static final SAVE_DATA_VERSION:thx.semver.Version = "2.0.2"; public static final SAVE_DATA_VERSION:thx.semver.Version = "2.0.3";
public static final SAVE_DATA_VERSION_RULE:thx.semver.VersionRule = "2.0.x"; public static final SAVE_DATA_VERSION_RULE:thx.semver.VersionRule = "2.0.x";
// We load this version's saves from a new save path, to maintain SOME level of backwards compatibility. // We load this version's saves from a new save path, to maintain SOME level of backwards compatibility.
@ -650,9 +650,9 @@ class Save
if (legacySaveData != null) if (legacySaveData != null)
{ {
trace('[SAVE] Found legacy save data, converting...'); trace('[SAVE] Found legacy save data, converting...');
var gameSave = SaveDataMigrator.migrate(legacySaveData); var gameSave = SaveDataMigrator.migrateFromLegacy(legacySaveData);
@:privateAccess @:privateAccess
FlxG.save.mergeData(gameSave.data); FlxG.save.mergeData(gameSave.data, true);
} }
else else
{ {
@ -664,7 +664,7 @@ class Save
trace('[SAVE] Loaded save data.'); trace('[SAVE] Loaded save data.');
@:privateAccess @:privateAccess
var gameSave = SaveDataMigrator.migrate(FlxG.save.data); var gameSave = SaveDataMigrator.migrate(FlxG.save.data);
FlxG.save.mergeData(gameSave.data); FlxG.save.mergeData(gameSave.data, true);
} }
} }

View file

@ -3,6 +3,7 @@ package funkin.save.migrator;
import funkin.save.Save; import funkin.save.Save;
import funkin.save.migrator.RawSaveData_v1_0_0; import funkin.save.migrator.RawSaveData_v1_0_0;
import thx.semver.Version; import thx.semver.Version;
import funkin.util.StructureUtil;
import funkin.util.VersionUtil; import funkin.util.VersionUtil;
@:nullSafety @:nullSafety
@ -26,7 +27,7 @@ class SaveDataMigrator
if (VersionUtil.validateVersion(version, Save.SAVE_DATA_VERSION_RULE)) if (VersionUtil.validateVersion(version, Save.SAVE_DATA_VERSION_RULE))
{ {
// Simply import the structured data. // Simply import the structured data.
var save:Save = new Save(inputData); var save:Save = new Save(StructureUtil.deepMerge(Save.getDefault(), inputData));
return save; return save;
} }
else else

View file

@ -134,7 +134,7 @@ class FreeplayState extends MusicBeatSubState
var stickerSubState:StickerSubState; var stickerSubState:StickerSubState;
public static var rememberedDifficulty:Null<String> = Constants.DEFAULT_DIFFICULTY; public static var rememberedDifficulty:Null<String> = Constants.DEFAULT_DIFFICULTY;
public static var rememberedSongId:Null<String> = null; public static var rememberedSongId:Null<String> = 'tutorial';
public function new(?params:FreeplayStateParams, ?stickers:StickerSubState) public function new(?params:FreeplayStateParams, ?stickers:StickerSubState)
{ {
@ -596,7 +596,7 @@ class FreeplayState extends MusicBeatSubState
// Only now do we know that the filter is actually changing. // Only now do we know that the filter is actually changing.
rememberedSongId = grpCapsules.members[curSelected]?.songData?.songId; rememberedSongId = grpCapsules.members[curSelected]?.songData?.songId ?? rememberedSongId;
for (cap in grpCapsules.members) for (cap in grpCapsules.members)
{ {
@ -939,6 +939,11 @@ class FreeplayState extends MusicBeatSubState
FlxTransitionableState.skipNextTransOut = true; FlxTransitionableState.skipNextTransOut = true;
if (Type.getClass(FlxG.state) == MainMenuState) if (Type.getClass(FlxG.state) == MainMenuState)
{ {
FunkinSound.playMusic('freakyMenu',
{
overrideExisting: true,
restartTrack: false
});
close(); close();
} }
else else
@ -957,7 +962,7 @@ class FreeplayState extends MusicBeatSubState
public override function destroy():Void public override function destroy():Void
{ {
super.destroy(); super.destroy();
var daSong:Null<FreeplaySongData> = grpCapsules.members[curSelected]?.songData; var daSong:Null<FreeplaySongData> = currentFilteredSongs[curSelected];
if (daSong != null) if (daSong != null)
{ {
clearDaCache(daSong.songName); clearDaCache(daSong.songName);

View file

@ -0,0 +1,61 @@
package funkin.util;
import haxe.DynamicAccess;
/**
* Utilities for working with anonymous structures.
*/
class StructureUtil
{
/**
* Merge two structures, with the second overwriting the first.
* Performs a SHALLOW clone, where child structures are not merged.
* @param a The base structure.
* @param b The new structure.
* @return The merged structure.
*/
public static function merge(a:Dynamic, b:Dynamic):Dynamic
{
var result:DynamicAccess<Dynamic> = Reflect.copy(a);
for (field in Reflect.fields(b))
{
result.set(field, Reflect.field(b, field));
}
return result;
}
/**
* Merge two structures, with the second overwriting the first.
* Performs a DEEP clone, where child structures are also merged recursively.
* @param a The base structure.
* @param b The new structure.
* @return The merged structure.
*/
public static function deepMerge(a:Dynamic, b:Dynamic):Dynamic
{
if (a == null) return b;
if (b == null) return null;
if (!Reflect.isObject(a) || !Reflect.isObject(b)) return b;
var result:DynamicAccess<Dynamic> = Reflect.copy(a);
for (field in Reflect.fields(b))
{
if (Reflect.isObject(b))
{
// Note that isObject also returns true for class instances,
// but we just assume that's not a problem here.
result.set(field, deepMerge(Reflect.field(result, field), Reflect.field(b, field)));
}
else
{
// If we're here, b[field] is a primitive.
result.set(field, Reflect.field(b, field));
}
}
return result;
}
}