From d18f40f4dd2f06da63a0a4dd23912d2ed6e8c6bf Mon Sep 17 00:00:00 2001 From: SokyranTheDragon <36712560+SokyranTheDragon@users.noreply.github.com> Date: Sun, 6 Oct 2024 22:20:46 +0200 Subject: [PATCH] Update desync stuff checker to look for mote saturation checks (#477) Checks to mote saturation are (generally) going to be unique to a specific player and changing game's behavior based on it may cause desyncs. --- Source/DebugActions.cs | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/Source/DebugActions.cs b/Source/DebugActions.cs index 69ad43d..e565192 100644 --- a/Source/DebugActions.cs +++ b/Source/DebugActions.cs @@ -46,7 +46,7 @@ private class DesyncSourceSearchWindow : Window private bool doVanilla = false; public override bool IsDebug => true; - public override Vector2 InitialSize => new(525f, 615f); + public override Vector2 InitialSize => new(525f, 640f); public override float Margin => 32f; public DesyncSourceSearchWindow() @@ -163,6 +163,7 @@ internal enum StuffToSearch [NonBasic] GetHashCode, [NonBasic] PatchedSyncMethods, [NonBasic] LongEvents, + MoteSaturation, } private static readonly MethodInfo FindCurrentMap = AccessTools.DeclaredPropertyGetter(typeof(Find), nameof(Find.CurrentMap)); @@ -198,6 +199,16 @@ internal enum StuffToSearch [typeof(Action), typeof(string), typeof(string), typeof(bool), typeof(Action), typeof(bool)]), }.Where(x => x != null).ToHashSet(); + // We could also add check for MoteCounter.moteCount field, but it's + // private, so it should be very unlikely that anyone is using it. + private static readonly HashSet MoteSaturationMethods = new[] + { + AccessTools.DeclaredPropertyGetter(typeof(MoteCounter), nameof(MoteCounter.MoteCount)), + AccessTools.DeclaredPropertyGetter(typeof(MoteCounter), nameof(MoteCounter.Saturation)), + AccessTools.DeclaredPropertyGetter(typeof(MoteCounter), nameof(MoteCounter.Saturated)), + AccessTools.DeclaredPropertyGetter(typeof(MoteCounter), nameof(MoteCounter.SaturatedLowPriority)), + }.Where(x => x != null).ToHashSet(); + [DebugAction(CategoryName, "Unsafe stuff logger", allowedGameStates = AllowedGameStates.Entry)] public static void OpenDesyncSourceSearchWindow() => Find.WindowStack.Add(new DesyncSourceSearchWindow()); @@ -391,6 +402,13 @@ public static void LogUnpatchedStuff(HashSet selectedStuff, bool Log.Warning("== In majority of cases, long events are completely safe. However, there are 2 potential situations that can cause issues with them. The first is asynchronous long events, and the second is long events queued during game startup. =="); Log.Message(found.Append("\n").Join(delimiter: "\n")); } + + if (log.TryGetValue(StuffToSearch.MoteSaturation, out found) && found.Any()) + { + Log.Warning("== Mote saturation checks found: =="); + Log.Warning("== Code that runs based on how saturated the motes are may cause desyncs as mote saturation may differ between players. =="); + Log.Message(found.Append("\n").Join(delimiter: "\n")); + } } else Log.Warning("== No unpatched RNG or potentially unsafe methods found =="); @@ -518,6 +536,9 @@ internal static HashSet FindRng(MethodBase baseMethod) case MethodInfo method when LongEventMethods.Contains(method): foundStuff.Add(StuffToSearch.LongEvents); break; + case MethodInfo method when MoteSaturationMethods.Contains(method): + foundStuff.Add(StuffToSearch.MoteSaturation); + break; } }