Decompiled source of MatchmakingSaves v1.0.1

MatchmakingSaves.dll

Decompiled 3 hours ago
using 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"));
		}
	}
}