using System; using System.Collections; using System.Collections.Generic; using System.Reflection; using System.Runtime.CompilerServices; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using UnityEngine; [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: AssemblyVersion("0.0.0.0")] namespace PublicGameSaves; [BepInPlugin("com.nikola.publicgamesaves", "PublicGameSaves", "1.1.0")] public class PublicGameSavesPlugin : BaseUnityPlugin { public const string PluginGuid = "com.nikola.publicgamesaves"; public const string PluginName = "PublicGameSaves"; public const string PluginVersion = "1.1.0"; internal static PublicGameSavesPlugin Instance; internal static ManualLogSource Log; internal static ConfigEntry SavePublicGames; internal static ConfigEntry SaveMatchmakingGames; internal static bool PublicSaveFlow; internal static string PendingServerName; private void Awake() { //IL_0056: Unknown result type (might be due to invalid IL or missing references) Instance = this; Log = ((BaseUnityPlugin)this).Logger; SavePublicGames = ((BaseUnityPlugin)this).Config.Bind("Saving", "SavePublicGames", true, "Save progress in public (server list) games, exactly like private games. Host only."); SaveMatchmakingGames = ((BaseUnityPlugin)this).Config.Bind("Saving", "SaveMatchmakingGames", true, "Save progress when you end up hosting a random matchmaking game. Host only."); new Harmony("com.nikola.publicgamesaves").PatchAll(Assembly.GetExecutingAssembly()); Log.LogInfo((object)"PublicGameSaves 1.1.0 loaded."); } internal static void EnableSavingForPublicLobbies(StatsManager statsManager) { try { FieldInfo fieldInfo = AccessTools.Field(typeof(StatsManager), "savedLobbyTypes"); if (!(fieldInfo.GetValue(statsManager) is IList list)) { Log.LogWarning((object)"savedLobbyTypes not found - saving in public games will not work."); return; } Type enumType = list.GetType().GetGenericArguments()[0]; if (SavePublicGames.Value) { object value = Enum.ToObject(enumType, 1); if (!list.Contains(value)) { list.Add(value); } } if (SaveMatchmakingGames.Value) { object value2 = Enum.ToObject(enumType, 2); if (!list.Contains(value2)) { list.Add(value2); } } Log.LogInfo((object)("Saving enabled for lobby types: " + ListToString(list))); } catch (Exception ex) { Log.LogError((object)("Failed to patch savedLobbyTypes: " + ex)); } } private static string ListToString(IList list) { string text = ""; foreach (object item in list) { text = text + ((text.Length <= 0) ? "" : ", ") + item; } return text; } internal static void StartPublicGame(string saveFileName, List backups) { AccessTools.Field(typeof(DataDirector), "networkServerName").SetValue(DataDirector.instance, PendingServerName); SemiFunc.MenuActionRandomMatchmaking(saveFileName, backups); Type type = typeof(GameManager).Assembly.GetType("LobbyTypes"); object obj = Enum.ToObject(type, 1); AccessTools.Method(typeof(GameManager), "SetLobbyType", (Type[])null, (Type[])null).Invoke(GameManager.instance, new object[1] { obj }); Log.LogInfo((object)((saveFileName != null) ? ("Hosting public server '" + PendingServerName + "' from save: " + saveFileName) : ("Hosting public server '" + PendingServerName + "' with a new save."))); } } [HarmonyPatch(typeof(StatsManager), "Awake")] internal static class StatsManager_Awake_Patch { private static void Postfix(StatsManager __instance) { PublicGameSavesPlugin.EnableSavingForPublicLobbies(__instance); } } [HarmonyPatch(typeof(MenuPageServerListCreateNew), "ButtonConfirm")] internal static class MenuPageServerListCreateNew_ButtonConfirm_Patch { private static readonly FieldInfo TextCurrentField = AccessTools.Field(typeof(MenuTextInput), "textCurrent"); private static bool Prefix(MenuPageServerListCreateNew __instance) { string text = ((!((Object)(object)__instance.menuTextInput != (Object)null)) ? null : (TextCurrentField.GetValue(__instance.menuTextInput) as string)); if (string.IsNullOrWhiteSpace(text)) { return true; } PublicGameSavesPlugin.PendingServerName = text; PublicGameSavesPlugin.PublicSaveFlow = 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 CurrentSaveFileNameField = AccessTools.Field(typeof(MenuPageSaves), "currentSaveFileName"); private static readonly FieldInfo CurrentSaveFileBackupsField = AccessTools.Field(typeof(MenuPageSaves), "currentSaveFileBackups"); private static bool Prefix(MenuPageSaves __instance) { if (!PublicGameSavesPlugin.PublicSaveFlow) { return true; } string text = CurrentSaveFileNameField.GetValue(__instance) as string; if (string.IsNullOrEmpty(text)) { return false; } List backups = CurrentSaveFileBackupsField.GetValue(__instance) as List; PublicGameSavesPlugin.PublicSaveFlow = false; PublicGameSavesPlugin.StartPublicGame(text, backups); return 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_005b: Unknown result type (might be due to invalid IL or missing references) if (!PublicGameSavesPlugin.PublicSaveFlow) { 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) { PublicGameSavesPlugin.Log.LogWarning((object)("Save limit check failed, continuing: " + ex.Message)); } PublicGameSavesPlugin.PublicSaveFlow = false; PublicGameSavesPlugin.StartPublicGame(null, null); return false; } } [HarmonyPatch(typeof(MenuPageSaves), "OnGoBack")] internal static class MenuPageSaves_OnGoBack_Patch { private static bool Prefix() { if (!PublicGameSavesPlugin.PublicSaveFlow) { return true; } PublicGameSavesPlugin.PublicSaveFlow = false; MenuManager.instance.PageCloseAll(); MenuManager.instance.PageOpen((MenuPageIndex)14, false); return false; } } [HarmonyPatch(typeof(MenuPageSaves), "UpdateGameModeHeader")] internal static class MenuPageSaves_UpdateGameModeHeader_Patch { private static void Postfix(MenuPageSaves __instance) { if (!PublicGameSavesPlugin.PublicSaveFlow) { return; } object value = AccessTools.Field(typeof(MenuPageSaves), "gameModeHeader").GetValue(__instance); if (value != null) { PropertyInfo property = value.GetType().GetProperty("text"); if (property != null) { property.SetValue(value, "Public Game", null); } } } } [HarmonyPatch(typeof(MenuPageMain), "Start")] internal static class MenuPageMain_Start_Patch { private static void Postfix() { PublicGameSavesPlugin.PublicSaveFlow = false; } }