Fixed Steam multiplayer save and Lan multiplayer save were shared issue
This commit is contained in:
@@ -15,6 +15,7 @@ using MegaCrit.Sts2.Core.Platform;
|
||||
using MegaCrit.Sts2.Core.Runs;
|
||||
using MegaCrit.Sts2.Core.Saves;
|
||||
|
||||
// ReSharper disable MemberCanBePrivate.Global
|
||||
// ReSharper disable UnusedType.Global
|
||||
// ReSharper disable ClassNeverInstantiated.Global
|
||||
|
||||
@@ -137,7 +138,7 @@ namespace SlayTheSpire2.LAN.Multiplayer.Helpers
|
||||
ushort port, int maxPlayers)
|
||||
{
|
||||
var readSaveResult =
|
||||
SaveManager.Instance.LoadAndCanonicalizeMultiplayerRunSave(
|
||||
LanRunSaveManagerHelper.LoadAndCanonicalizeMultiplayerRunSave(
|
||||
PlatformUtil.GetLocalPlayerId(PlatformType.None));
|
||||
if (!readSaveResult.Success || readSaveResult.SaveData == null)
|
||||
{
|
||||
@@ -176,7 +177,7 @@ namespace SlayTheSpire2.LAN.Multiplayer.Helpers
|
||||
return;
|
||||
|
||||
var readSaveResult =
|
||||
SaveManager.Instance.LoadAndCanonicalizeMultiplayerRunSave(
|
||||
LanRunSaveManagerHelper.LoadAndCanonicalizeMultiplayerRunSave(
|
||||
PlatformUtil.GetLocalPlayerId(PlatformType.None));
|
||||
if (readSaveResult is { Success: true, SaveData: not null })
|
||||
{
|
||||
@@ -205,7 +206,7 @@ namespace SlayTheSpire2.LAN.Multiplayer.Helpers
|
||||
$"ERROR: Failed to load multiplayer run save: status={readSaveResult.Status}. Deleting current run...");
|
||||
}
|
||||
|
||||
SaveManager.Instance.DeleteCurrentMultiplayerRun();
|
||||
LanRunSaveManagerHelper.DeleteCurrentMultiplayerRun();
|
||||
updateButtons();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
using HarmonyLib;
|
||||
using MegaCrit.Sts2.Core.Logging;
|
||||
using MegaCrit.Sts2.Core.Runs;
|
||||
using MegaCrit.Sts2.Core.Saves;
|
||||
using MegaCrit.Sts2.Core.Saves.Managers;
|
||||
using MegaCrit.Sts2.Core.Saves.Migrations;
|
||||
|
||||
// ReSharper disable MemberCanBePrivate.Global
|
||||
// ReSharper disable ClassNeverInstantiated.Global
|
||||
|
||||
namespace SlayTheSpire2.LAN.Multiplayer.Helpers
|
||||
{
|
||||
internal class LanRunSaveManagerHelper
|
||||
{
|
||||
public static ISaveStore SaveStore =>
|
||||
Traverse.Create(SaveManager.Instance).Field("_saveStore").GetValue<ISaveStore>();
|
||||
|
||||
public static MigrationManager MigrationManager => Traverse.Create(SaveManager.Instance)
|
||||
.Field("_migrationManager").GetValue<MigrationManager>();
|
||||
|
||||
public static IProfileIdProvider ProfileIdProvider => SaveManager.Instance;
|
||||
|
||||
public static string CurrentMultiplayerRunSavePath =>
|
||||
RunSaveManager.GetRunSavePath(ProfileIdProvider.CurrentProfileId, "current_lan_run_mp.save");
|
||||
|
||||
public static bool HasMultiplayerRunSave => SaveStore.FileExists(CurrentMultiplayerRunSavePath);
|
||||
|
||||
public static ReadSaveResult<SerializableRun> LoadAndCanonicalizeMultiplayerRunSave(ulong localPlayerId)
|
||||
{
|
||||
var readSaveResult = LoadMultiplayerRunSave();
|
||||
if (readSaveResult is { Success: true, SaveData: not null })
|
||||
{
|
||||
try
|
||||
{
|
||||
var data = RunManager.CanonicalizeSave(readSaveResult.SaveData, localPlayerId);
|
||||
return new ReadSaveResult<SerializableRun>(data, ReadSaveStatus.Success);
|
||||
}
|
||||
catch (Exception value)
|
||||
{
|
||||
Log.Error($"Multiplayer run save validation failed: {value}");
|
||||
RenameBrokenMultiplayerRunSave(ReadSaveStatus.ValidationFailed);
|
||||
return new ReadSaveResult<SerializableRun>(ReadSaveStatus.ValidationFailed,
|
||||
$"Save file validation failed: {value}");
|
||||
}
|
||||
}
|
||||
|
||||
return readSaveResult;
|
||||
}
|
||||
|
||||
public static ReadSaveResult<SerializableRun> LoadMultiplayerRunSave()
|
||||
{
|
||||
var readSaveResult = MigrationManager.LoadSave<SerializableRun>(CurrentMultiplayerRunSavePath);
|
||||
if (readSaveResult.Success)
|
||||
{
|
||||
return readSaveResult;
|
||||
}
|
||||
|
||||
if (readSaveResult.Status == ReadSaveStatus.FileNotFound)
|
||||
{
|
||||
Log.Info("Multiplayer run save file not found at " + CurrentMultiplayerRunSavePath);
|
||||
}
|
||||
else if (!readSaveResult.Status.IsRecoverable())
|
||||
{
|
||||
Log.Error(
|
||||
$"Failed to load multiplayer run save: status={readSaveResult.Status} msg={readSaveResult.ErrorMessage}");
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Warn(
|
||||
$"Multiplayer run save had recoverable issues: status={readSaveResult.Status} msg={readSaveResult.ErrorMessage}");
|
||||
}
|
||||
|
||||
return readSaveResult;
|
||||
}
|
||||
|
||||
public static void DeleteCurrentMultiplayerRun()
|
||||
{
|
||||
SaveStore.DeleteFile(CurrentMultiplayerRunSavePath);
|
||||
}
|
||||
|
||||
public static void RenameBrokenMultiplayerRunSave(ReadSaveStatus status)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (HasMultiplayerRunSave)
|
||||
{
|
||||
var text = CorruptFileHandler.GenerateCorruptFilePath(CurrentMultiplayerRunSavePath, status);
|
||||
SaveStore.RenameFile(CurrentMultiplayerRunSavePath, text);
|
||||
Log.Error(
|
||||
$"Corrupt multiplayer run save detected: Renamed '{CurrentMultiplayerRunSavePath}' to '{text}'");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Warn("Failed to rename broken multiplayer run save: " + ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,8 @@ namespace SlayTheSpire2.LAN.Multiplayer.Helpers
|
||||
|
||||
public readonly SettingsModel SettingsModel;
|
||||
|
||||
private readonly GodotFileIo _modsDir = new($"{UserDataPathProvider.GetAccountScopedBasePath(null)}/mods");
|
||||
private readonly GodotFileIo _modsDir =
|
||||
new(Path.Combine(UserDataPathProvider.GetAccountScopedBasePath(null), "mods"));
|
||||
|
||||
private SettingsHelper()
|
||||
{
|
||||
|
||||
@@ -5,7 +5,6 @@ using MegaCrit.Sts2.Core.Helpers;
|
||||
using MegaCrit.Sts2.Core.Nodes.GodotExtensions;
|
||||
using MegaCrit.Sts2.Core.Nodes.Screens.MainMenu;
|
||||
using MegaCrit.Sts2.Core.Runs;
|
||||
using MegaCrit.Sts2.Core.Saves;
|
||||
using SlayTheSpire2.LAN.Multiplayer.Helpers;
|
||||
|
||||
// ReSharper disable UnusedMember.Global
|
||||
@@ -111,17 +110,18 @@ namespace SlayTheSpire2.LAN.Multiplayer.Patchs
|
||||
{
|
||||
if (NMultiplayerSubmenuButtonHelpers.LanHostButton != null)
|
||||
{
|
||||
NMultiplayerSubmenuButtonHelpers.LanHostButton.Visible = !SaveManager.Instance.HasMultiplayerRunSave;
|
||||
NMultiplayerSubmenuButtonHelpers.LanHostButton.Visible = !LanRunSaveManagerHelper.HasMultiplayerRunSave;
|
||||
}
|
||||
|
||||
if (NMultiplayerSubmenuButtonHelpers.LanLoadButton != null)
|
||||
{
|
||||
NMultiplayerSubmenuButtonHelpers.LanLoadButton.Visible = SaveManager.Instance.HasMultiplayerRunSave;
|
||||
NMultiplayerSubmenuButtonHelpers.LanLoadButton.Visible = LanRunSaveManagerHelper.HasMultiplayerRunSave;
|
||||
}
|
||||
|
||||
if (NMultiplayerSubmenuButtonHelpers.LanAbandonButton != null)
|
||||
{
|
||||
NMultiplayerSubmenuButtonHelpers.LanAbandonButton.Visible = SaveManager.Instance.HasMultiplayerRunSave;
|
||||
NMultiplayerSubmenuButtonHelpers.LanAbandonButton.Visible =
|
||||
LanRunSaveManagerHelper.HasMultiplayerRunSave;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace SlayTheSpire2.LAN.Multiplayer.Patchs
|
||||
[HarmonyPatch(typeof(NSettingsScreen), "_Ready")]
|
||||
internal class NSettingsScreenPatch
|
||||
{
|
||||
public static void Prefix(NSettingsScreen __instance)
|
||||
private static void Prefix(NSettingsScreen __instance)
|
||||
{
|
||||
var moddingNode = __instance.GetNode("%Modding");
|
||||
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
using System.Text.Json;
|
||||
using HarmonyLib;
|
||||
using MegaCrit.Sts2.Core.Helpers;
|
||||
using MegaCrit.Sts2.Core.Multiplayer.Game;
|
||||
using MegaCrit.Sts2.Core.Platform;
|
||||
using MegaCrit.Sts2.Core.Rooms;
|
||||
using MegaCrit.Sts2.Core.Runs;
|
||||
using MegaCrit.Sts2.Core.Saves;
|
||||
using MegaCrit.Sts2.Core.Saves.Managers;
|
||||
using SlayTheSpire2.LAN.Multiplayer.Helpers;
|
||||
|
||||
// ReSharper disable UnusedMember.Global
|
||||
// ReSharper disable UnusedType.Global
|
||||
|
||||
namespace SlayTheSpire2.LAN.Multiplayer.Patchs
|
||||
{
|
||||
[HarmonyPatch(typeof(RunSaveManager), "SaveRun")]
|
||||
internal class RunSaveManagerSaveRunPatch
|
||||
{
|
||||
private static bool Prefix(RunSaveManager __instance, AbstractRoom? preFinishedRoom, bool ____forceSynchronous,
|
||||
ISaveStore ____saveStore, Action? ___Saved, ref Task __result)
|
||||
{
|
||||
if (!RunManager.Instance.ShouldSave || (RunManager.Instance.NetService.Type != NetGameType.Singleplayer &&
|
||||
RunManager.Instance.NetService.Type != NetGameType.Host))
|
||||
return false;
|
||||
|
||||
__result = TaskHelper.RunSafely(SaveRun(__instance, preFinishedRoom, ____forceSynchronous, ____saveStore,
|
||||
___Saved));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static async Task SaveRun(RunSaveManager runSaveManager, AbstractRoom? preFinishedRoom,
|
||||
bool forceSynchronous,
|
||||
ISaveStore saveStore, Action? saved)
|
||||
{
|
||||
var value = RunManager.Instance.ToSave(preFinishedRoom);
|
||||
var savePath = RunManager.Instance.NetService.Type.IsMultiplayer()
|
||||
? RunManager.Instance.NetService.Platform == PlatformType.None
|
||||
? LanRunSaveManagerHelper.CurrentMultiplayerRunSavePath
|
||||
: Traverse.Create(runSaveManager).Property("CurrentMultiplayerRunSavePath").GetValue<string>()
|
||||
: Traverse.Create(runSaveManager).Property("CurrentRunSavePath").GetValue<string>();
|
||||
using var stream = new MemoryStream();
|
||||
if (!forceSynchronous)
|
||||
{
|
||||
await JsonSerializer.SerializeAsync(stream, value,
|
||||
JsonSerializationUtility.GetTypeInfo<SerializableRun>(), CancellationToken.None);
|
||||
}
|
||||
else
|
||||
{
|
||||
await JsonSerializer.SerializeAsync(stream, value,
|
||||
JsonSerializationUtility.GetTypeInfo<SerializableRun>());
|
||||
}
|
||||
|
||||
stream.Seek(0L, SeekOrigin.Begin);
|
||||
await saveStore.WriteFileAsync(savePath, stream.ToArray());
|
||||
|
||||
saved?.Invoke();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,8 @@
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<AssemblyVersion>1.1.0.0</AssemblyVersion>
|
||||
<FileVersion>1.1.0.0</FileVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
Reference in New Issue
Block a user