feat(loader): mutex-skip + per-instance identity + synthetic Steam identity patches
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
74
SVSimLoader/Patches/MultiInstancePatches.cs
Normal file
74
SVSimLoader/Patches/MultiInstancePatches.cs
Normal file
@@ -0,0 +1,74 @@
|
||||
using Cute;
|
||||
using HarmonyLib;
|
||||
|
||||
namespace SVSimLoader.Patches
|
||||
{
|
||||
[HarmonyPatch]
|
||||
public static class MultiInstancePatches
|
||||
{
|
||||
// (1) Defeat the machine-wide single-instance guard. createMutex is private, so target it
|
||||
// by string name. Prefix returning false skips the original (Application.Quit never runs).
|
||||
[HarmonyPatch(typeof(BootApp), "createMutex")]
|
||||
[HarmonyPrefix]
|
||||
public static bool SkipMutex()
|
||||
{
|
||||
if (!SvSimConfig.SecondaryInstance) return true; // primary/normal: run original
|
||||
Plugin.Log.LogWarning("Multi-instance: skipping BootApp.createMutex single-instance guard.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// (2) Redirect the three identity keys to the per-instance file store. Other keys fall
|
||||
// through to the original (return true).
|
||||
private static bool IsIdentityKey(string key) =>
|
||||
key == "UDID" || key == "VIEWER_ID" || key == "SHORT_UDID";
|
||||
|
||||
[HarmonyPatch(typeof(SavedataManager), nameof(SavedataManager.GetString))]
|
||||
[HarmonyPrefix]
|
||||
public static bool GetString(string key, string defaultValue, ref string __result)
|
||||
{
|
||||
if (!SvSimConfig.SecondaryInstance || !IsIdentityKey(key)) return true;
|
||||
__result = InstanceIdentityStore.TryGet(key, out var v) ? v : defaultValue;
|
||||
return false;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(SavedataManager), nameof(SavedataManager.SetString))]
|
||||
[HarmonyPrefix]
|
||||
public static bool SetString(string key, string value)
|
||||
{
|
||||
if (!SvSimConfig.SecondaryInstance || !IsIdentityKey(key)) return true;
|
||||
InstanceIdentityStore.Set(key, value);
|
||||
return false;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(SavedataManager), nameof(SavedataManager.GetInt))]
|
||||
[HarmonyPrefix]
|
||||
public static bool GetInt(string key, int defaultValue, ref int __result)
|
||||
{
|
||||
if (!SvSimConfig.SecondaryInstance || !IsIdentityKey(key)) return true;
|
||||
__result = InstanceIdentityStore.TryGet(key, out var v) && int.TryParse(v, out var i) ? i : defaultValue;
|
||||
return false;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(SavedataManager), nameof(SavedataManager.SetInt))]
|
||||
[HarmonyPrefix]
|
||||
public static bool SetInt(string key, int value)
|
||||
{
|
||||
if (!SvSimConfig.SecondaryInstance || !IsIdentityKey(key)) return true;
|
||||
InstanceIdentityStore.Set(key, value.ToString());
|
||||
return false;
|
||||
}
|
||||
|
||||
// (3) Force a synthetic Steam identity. setSTEAMPlatformData runs in Certification.Start();
|
||||
// a postfix overwrites SteamID/SteamSessionTicket (private setters) via Traverse.
|
||||
[HarmonyPatch(typeof(Certification), "setSTEAMPlatformData")]
|
||||
[HarmonyPostfix]
|
||||
public static void ForceSteamIdentity()
|
||||
{
|
||||
if (!SvSimConfig.SecondaryInstance) return;
|
||||
Traverse.Create(typeof(Certification)).Property("SteamID").SetValue(SvSimConfig.FakeSteamId);
|
||||
Traverse.Create(typeof(Certification)).Property("SteamSessionTicket").SetValue(SvSimConfig.FakeTicket);
|
||||
Plugin.Log.LogWarning(
|
||||
$"Multi-instance: forced SteamID={SvSimConfig.FakeSteamId}, ticket={SvSimConfig.FakeTicket}.");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user