Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of MatchmakingSaves v1.0.1
MatchmakingSaves.dll
Decompiled 3 hours agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.0.0.0")] [module: UnverifiableCode] [BepInPlugin("com.matchmakingsaves.repo", "MatchmakingSaves", "1.0.1")] public class MatchmakingSavesPlugin : BaseUnityPlugin { internal static ManualLogSource Log; internal static ConfigEntry<bool> Enabled; internal static ConfigEntry<bool> SaveMatchmakingGames; internal static ConfigEntry<bool> RequireAlwaysHostRandom; internal static ConfigEntry<bool> TimingLogs; internal static bool PickerFlow; internal static bool Bypass; private void Awake() { //IL_0090: Unknown result type (might be due to invalid IL or missing references) Log = ((BaseUnityPlugin)this).Logger; Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Show the save picker when starting random matchmaking. Turn off for fully vanilla matchmaking."); TimingLogs = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "TimingLogs", false, "Log how long loading/saving a save file takes ([timing] lines in LogOutput.log)."); RequireAlwaysHostRandom = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "RequireAlwaysHostRandom", true, "Only show the save picker when the AlwaysHostRandom mod is loaded (a save can only be used when you host). Disable AlwaysHostRandom in the mod manager to play normal matchmaking."); SaveMatchmakingGames = ((BaseUnityPlugin)this).Config.Bind<bool>("Saving", "SaveMatchmakingGames", true, "Write the save file while you host a random matchmaking game."); new Harmony("com.matchmakingsaves.repo").PatchAll(Assembly.GetExecutingAssembly()); Log.LogInfo((object)"MatchmakingSaves 1.0.1 loaded."); } internal static bool AlwaysHostRandomLoaded() { try { foreach (PluginInfo value in Chainloader.PluginInfos.Values) { string text = value.Metadata.Name ?? ""; string text2 = value.Metadata.GUID ?? ""; if (text.IndexOf("AlwaysHostRandom", StringComparison.OrdinalIgnoreCase) >= 0 || text2.IndexOf("AlwaysHostRandom", StringComparison.OrdinalIgnoreCase) >= 0) { return true; } } } catch (Exception ex) { Log.LogWarning((object)("Could not check for AlwaysHostRandom: " + ex.Message)); } return false; } internal static void EnableSavingForMatchmaking(StatsManager statsManager) { try { if (!SaveMatchmakingGames.Value) { return; } if (!(AccessTools.Field(typeof(StatsManager), "savedLobbyTypes").GetValue(statsManager) is IList list)) { Log.LogWarning((object)"savedLobbyTypes not found - saving in matchmaking will not work."); return; } object value = Enum.Parse(list.GetType().GetGenericArguments()[0], "Matchmaking"); if (!list.Contains(value)) { list.Add(value); } Log.LogInfo((object)"Saving enabled for Matchmaking lobbies."); } catch (Exception ex) { Log.LogError((object)("Failed to patch savedLobbyTypes: " + ex)); } } } [HarmonyPatch(typeof(SemiFunc), "MenuActionRandomMatchmaking")] internal static class SemiFunc_MenuActionRandomMatchmaking_Patch { private static bool Prefix(string saveFileName, List<string> saveFileBackups) { if (!MatchmakingSavesPlugin.Enabled.Value) { return true; } if (MatchmakingSavesPlugin.Bypass) { return true; } if (saveFileName != null) { return true; } if (MatchmakingSavesPlugin.RequireAlwaysHostRandom.Value && !MatchmakingSavesPlugin.AlwaysHostRandomLoaded()) { MatchmakingSavesPlugin.Log.LogInfo((object)"AlwaysHostRandom not loaded: vanilla matchmaking."); return true; } MatchmakingSavesPlugin.Log.LogInfo((object)"Random matchmaking intercepted: opening save picker."); MatchmakingSavesPlugin.PickerFlow = true; SemiFunc.MainMenuSetMultiplayer(); MenuManager.instance.PageCloseAll(); MenuManager.instance.PageOpen((MenuPageIndex)11, false); return false; } } [HarmonyPatch(typeof(MenuPageSaves), "OnLoadGame")] internal static class MenuPageSaves_OnLoadGame_Patch { private static readonly FieldInfo NameField = AccessTools.Field(typeof(MenuPageSaves), "currentSaveFileName"); private static readonly FieldInfo BackupsField = AccessTools.Field(typeof(MenuPageSaves), "currentSaveFileBackups"); private static bool Prefix(MenuPageSaves __instance) { if (!MatchmakingSavesPlugin.PickerFlow) { return true; } string text = NameField.GetValue(__instance) as string; if (string.IsNullOrEmpty(text)) { return false; } List<string> backups = BackupsField.GetValue(__instance) as List<string>; MatchmakingSavesPlugin.PickerFlow = false; StartMatchmaking(text, backups); return false; } internal static void StartMatchmaking(string name, List<string> backups) { MatchmakingSavesPlugin.Bypass = true; try { SemiFunc.MenuActionRandomMatchmaking(name, backups); MatchmakingSavesPlugin.Log.LogInfo((object)((name != null) ? ("Random matchmaking started with save: " + name) : "Random matchmaking started with a new save.")); } finally { MatchmakingSavesPlugin.Bypass = false; } } } [HarmonyPatch(typeof(MenuPageSaves), "OnNewGame")] internal static class MenuPageSaves_OnNewGame_Patch { private static readonly FieldInfo MaxSaveFilesField = AccessTools.Field(typeof(MenuPageSaves), "maxSaveFiles"); private static readonly FieldInfo SaveFilesField = AccessTools.Field(typeof(MenuPageSaves), "saveFiles"); private static bool Prefix(MenuPageSaves __instance) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) if (!MatchmakingSavesPlugin.PickerFlow) { return true; } try { int num = (int)MaxSaveFilesField.GetValue(__instance); ICollection collection = SaveFilesField.GetValue(__instance) as ICollection; if (num > 0 && collection != null && collection.Count >= num) { MenuManager.instance.PageCloseAllAddedOnTop(); MenuManager.instance.PagePopUp("Save File Limit Reached", Color.red, "You can only have " + num + " save files at a time. Please delete some save files to make room for new ones.", "OK", true); return false; } } catch (Exception ex) { MatchmakingSavesPlugin.Log.LogWarning((object)("Save limit check failed, continuing: " + ex.Message)); } MatchmakingSavesPlugin.PickerFlow = false; MenuPageSaves_OnLoadGame_Patch.StartMatchmaking(null, null); return false; } } [HarmonyPatch(typeof(MenuPageSaves), "OnGoBack")] internal static class MenuPageSaves_OnGoBack_Patch { private static void Prefix() { MatchmakingSavesPlugin.PickerFlow = false; } } [HarmonyPatch(typeof(MenuPageMain), "Start")] internal static class MenuPageMain_Start_Patch { private static void Postfix() { MatchmakingSavesPlugin.PickerFlow = false; } } [HarmonyPatch(typeof(StatsManager), "Awake")] internal static class StatsManager_Awake_Patch { private static void Postfix(StatsManager __instance) { MatchmakingSavesPlugin.EnableSavingForMatchmaking(__instance); } } [HarmonyPatch(typeof(StatsManager), "LoadGame")] internal static class StatsManager_LoadGame_Timing { private static void Prefix(out Stopwatch __state) { __state = Stopwatch.StartNew(); } private static void Postfix(Stopwatch __state) { if (MatchmakingSavesPlugin.TimingLogs.Value && __state != null) { MatchmakingSavesPlugin.Log.LogInfo((object)("[timing] StatsManager.LoadGame took " + __state.ElapsedMilliseconds + " ms")); } } } [HarmonyPatch(typeof(StatsManager), "SaveFileSave")] internal static class StatsManager_SaveFileSave_Timing { private static void Prefix(out Stopwatch __state) { __state = Stopwatch.StartNew(); } private static void Postfix(Stopwatch __state) { if (MatchmakingSavesPlugin.TimingLogs.Value && __state != null) { MatchmakingSavesPlugin.Log.LogInfo((object)("[timing] StatsManager.SaveFileSave took " + __state.ElapsedMilliseconds + " ms")); } } }