Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[KKS][ExtSave] Avoid error when saving more than 2 GB in the main game #197

Merged
merged 5 commits into from
Apr 9, 2024
Merged
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 54 additions & 31 deletions src/KKS_ExtensibleSaveFormat/KKS.ExtendedSave.SaveData.Hooks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,44 +56,67 @@ private static void SaveDataLoadHook(BinaryReader br, ref WorldData saveData)

#region Saving

// Nope, not patching the save lambda, not doing it, noooope
[HarmonyPostfix, HarmonyPatch(typeof(WorldData), nameof(WorldData.GetBytes), typeof(WorldData))]
private static void SaveDataSaveHook(WorldData saveData, ref byte[] __result)
[HarmonyPrefix, HarmonyPatch(typeof(SaveData.WorldData), nameof(SaveData.WorldData.Save), typeof(string), typeof(string))]
[HarmonyPriority(Priority.Last)]
private static bool WorldDataSaveOverride(SaveData.WorldData __instance, string path, string fileName)
{
try
Illusion.Utils.File.OpenWrite(path + fileName, false, (Action<FileStream>)(f =>
{
SaveDataWriteEvent(saveData);
try
{
using (BinaryWriter binaryWriter = new BinaryWriter((Stream)f))
{
var saveData = __instance;

Logger.Log(BepInEx.Logging.LogLevel.Debug, "SaveData hook!");
// Data to be written by WorldData.GetBytes
byte[] buffer = MessagePackSerializer.Serialize<WorldData>(saveData);
binaryWriter.Write(buffer.Length);
binaryWriter.Write(buffer);
byte[] bytes1 = SaveData.Player.GetBytes(saveData.player);
binaryWriter.Write(bytes1.Length);
binaryWriter.Write(bytes1);
int count = saveData.heroineList.Count;
binaryWriter.Write(count);
for (int index = 0; index < count; ++index)
{
byte[] bytes2 = Heroine.GetBytes(saveData.heroineList[index]);
binaryWriter.Write(bytes2.Length);
binaryWriter.Write(bytes2);
}

Dictionary<string, PluginData> extendedData = GetAllExtendedData(saveData);
if (extendedData == null)
return;
SaveDataWriteEvent(__instance);
Logger.Log(BepInEx.Logging.LogLevel.Debug, "SaveData hook!");

// Append the ext data
using (var ms = new MemoryStream())
{
using (BinaryWriter bw = new BinaryWriter(ms))
{
// Write the original data first
bw.Write(__result);

// Then write our data
bw.Write(Marker);
bw.Write(DataVersion);
byte[] data = MessagePackSerializer.Serialize(extendedData);
bw.Write(data.Length);
bw.Write(data);
}
// Append the ext data
Dictionary<string, PluginData> extendedData = GetAllExtendedData(saveData);

// Replace the result, not the most efficient way but save files shouldn't be big enough to matter since it's all done in memory
__result = ms.ToArray();
if (extendedData != null)
{
binaryWriter.Write(Marker);
binaryWriter.Write(DataVersion);
byte[] data = MessagePackSerializer.Serialize(extendedData);
binaryWriter.Write(data.Length);
binaryWriter.Write(data);
}
}
}
}
catch (Exception ex)
{
UnityEngine.Debug.LogException(ex);
}
catch (Exception ex)
{
Logger.Log(BepInEx.Logging.LogLevel.Message | BepInEx.Logging.LogLevel.Error, "Failed to save the game, the save file may be corrupted! Try saving again in an empty slot.\nError: " + ex.Message);
UnityEngine.Debug.LogException(ex);
ManlyMarco marked this conversation as resolved.
Show resolved Hide resolved
}
}));

return false;
}


[HarmonyPostfix, HarmonyPatch(typeof(WorldData), nameof(WorldData.GetBytes), typeof(WorldData))]
private static void SaveDataSaveHook(WorldData saveData, ref byte[] __result)
ManlyMarco marked this conversation as resolved.
Show resolved Hide resolved
{
// This function should not be called.
// Originally called from SaveData.WorldData.Save(), but the original Save() is not called by the patch.
throw new System.NotSupportedException("Do not use this method, use WorldData.Save instead. More info: https://github.com/IllusionMods/BepisPlugins/pull/197");
}

#endregion
Expand Down