using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using ModdingUtils.Utils; using TMPro; using UnboundLib; using UnboundLib.GameModes; using UnboundLib.Utils.UI; using UnityEngine; using UnityEngine.Events; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("0.0.0.0")] namespace LocalSaveSlots; [BepInPlugin("com.emiliano.localsaveslots", "Local Save Slots", "1.0.0")] [BepInProcess("Rounds.exe")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class LocalSaveSlots : BaseUnityPlugin { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static UnityAction <>9__3_0; public static Func <>9__9_0; internal void b__3_0() { } internal string b__9_0(CardInfo c) { return ((Object)((Component)c).gameObject).name; } } [CompilerGenerated] private sealed class <>c__DisplayClass10_0 { public int teamId; internal bool b__0(Player p) { return p.teamID == teamId; } } [CompilerGenerated] private sealed class <>c__DisplayClass10_1 { public string name; internal bool b__1(CardInfo c) { return ((Object)((Component)c).gameObject).name == name; } } [CompilerGenerated] private sealed class d__10 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public LocalSaveSlots <>4__this; public int slot; private IGameModeHandler 5__2; private string[] <>7__wrap2; private int <>7__wrap3; private string 5__5; private Player 5__6; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__10(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { 5__2 = null; <>7__wrap2 = null; 5__5 = null; 5__6 = null; <>1__state = -2; } private bool MoveNext() { //IL_014b: Unknown result type (might be due to invalid IL or missing references) int num = <>1__state; LocalSaveSlots localSaveSlots = <>4__this; switch (num) { default: return false; case 0: { <>1__state = -1; string json = File.ReadAllText(localSaveSlots.GetSavePath(slot)); int num2 = int.Parse(localSaveSlots.GetJsonInt(json, "pointsToWinRound")); int num3 = int.Parse(localSaveSlots.GetJsonInt(json, "roundsToWin")); 5__2 = GameModeManager.CurrentHandler; 5__2.ChangeSetting("pointsToWinRound", (object)num2); 5__2.ChangeSetting("roundsToWinGame", (object)num3); string[] array2 = localSaveSlots.GetJsonString(json, "playerData").Split(new char[1] { ';' }); <>7__wrap2 = array2; <>7__wrap3 = 0; goto IL_029e; } case 1: <>1__state = -1; if (!string.IsNullOrEmpty(5__5)) { List list = new List(); string[] array = 5__5.Split(new char[1] { '|' }); for (int i = 0; i < array.Length; i++) { <>c__DisplayClass10_1 CS$<>8__locals0 = new <>c__DisplayClass10_1 { name = array[i] }; if (!string.IsNullOrEmpty(CS$<>8__locals0.name)) { CardInfo val = ((IEnumerable)CardChoice.instance.cards).FirstOrDefault((Func)((CardInfo c) => ((Object)((Component)c).gameObject).name == CS$<>8__locals0.name)); if ((Object)(object)val != (Object)null) { list.Add(val); } } } if (list.Count > 0) { Cards.instance.AddCardsToPlayer(5__6, list.ToArray(), true, (string[])null, (float[])null, (float[])null, true); <>2__current = null; <>1__state = 2; return true; } } goto IL_0282; case 2: { <>1__state = -1; goto IL_0282; } IL_029e: if (<>7__wrap3 < <>7__wrap2.Length) { string text = <>7__wrap2[<>7__wrap3]; <>c__DisplayClass10_0 CS$<>8__locals1 = new <>c__DisplayClass10_0(); if (!string.IsNullOrEmpty(text)) { string[] array3 = text.Split(new char[1] { '~' }); if (array3.Length >= 5) { CS$<>8__locals1.teamId = int.Parse(array3[0]); int num4 = int.Parse(array3[2]); int num5 = int.Parse(array3[3]); 5__5 = array3[4]; 5__2.SetTeamScore(CS$<>8__locals1.teamId, new TeamScore(num4, num5)); 5__6 = PlayerManager.instance.players.Find((Player p) => p.teamID == CS$<>8__locals1.teamId); if (!((Object)(object)5__6 == (Object)null)) { Cards.instance.RemoveAllCardsFromPlayer(5__6, false); <>2__current = null; <>1__state = 1; return true; } } } goto IL_0290; } <>7__wrap2 = null; ExtensionMethods.InvokeMethod((object)UIHandler.instance.roundCounter, "ReDraw", Array.Empty()); ExtensionMethods.InvokeMethod((object)UIHandler.instance.roundCounterSmall, "ReDraw", Array.Empty()); ((BaseUnityPlugin)localSaveSlots).Logger.LogInfo((object)("Loaded slot " + slot)); return false; IL_0290: <>7__wrap3++; goto IL_029e; IL_0282: 5__5 = null; 5__6 = null; goto IL_0290; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class d__5 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public LocalSaveSlots <>4__this; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__5(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { int num = <>1__state; LocalSaveSlots localSaveSlots = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; if (localSaveSlots.pendingLoadSlot >= 0) { <>2__current = ((MonoBehaviour)localSaveSlots).StartCoroutine(localSaveSlots.LoadFromSlot(localSaveSlots.pendingLoadSlot)); <>1__state = 1; return true; } goto IL_0061; case 1: <>1__state = -1; localSaveSlots.pendingLoadSlot = -1; goto IL_0061; case 2: { <>1__state = -1; return false; } IL_0061: <>2__current = null; <>1__state = 2; return true; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private const int MAX_SAVES = 10; private string saveDir; private int pendingLoadSlot = -1; private void Awake() { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Expected O, but got Unknown saveDir = Path.Combine(Paths.ConfigPath, "LocalSaveSlots"); Directory.CreateDirectory(saveDir); object obj = <>c.<>9__3_0; if (obj == null) { UnityAction val = delegate { }; <>c.<>9__3_0 = val; obj = (object)val; } Unbound.RegisterMenu("Local Save Slots", (UnityAction)obj, (Action)BuildMenu, (GameObject)null, true); ((BaseUnityPlugin)this).Logger.LogInfo((object)"LocalSaveSlots loaded!"); } private void Start() { GameModeManager.AddHook("PickStart", (Func)OnPickStart); } [IteratorStateMachine(typeof(d__5))] private IEnumerator OnPickStart(IGameModeHandler gm) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__5(0) { <>4__this = this }; } private void BuildMenu(GameObject menu) { //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Expected O, but got Unknown //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Expected O, but got Unknown TextMeshProUGUI val = default(TextMeshProUGUI); MenuHandler.CreateText("LOCAL SAVE SLOTS", menu, ref val, 60, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null); MenuHandler.CreateText(" ", menu, ref val, 20, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null); TextMeshProUGUI slotText = default(TextMeshProUGUI); for (int i = 0; i < 10; i++) { int slot = i; string savePath = GetSavePath(slot); MenuHandler.CreateText(File.Exists(savePath) ? ("Slot " + (slot + 1) + " - Round " + GetSavedValue(savePath, "round") + " - " + File.GetLastWriteTime(savePath).ToString("MM/dd HH:mm")) : ("Slot " + (slot + 1) + " - Empty"), menu, ref slotText, 40, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null); MenuHandler.CreateButton("SAVE", menu, (UnityAction)delegate { if (GameModeManager.CurrentHandler == null) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"Cannot save: no active game."); } else { SaveToSlot(slot); string savePath2 = GetSavePath(slot); ((TMP_Text)slotText).text = "Slot " + (slot + 1) + " - Round " + GetSavedValue(savePath2, "round") + " - " + File.GetLastWriteTime(savePath2).ToString("MM/dd HH:mm"); } }, 35, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null); MenuHandler.CreateButton("LOAD", menu, (UnityAction)delegate { if (!File.Exists(GetSavePath(slot))) { ((BaseUnityPlugin)this).Logger.LogInfo((object)("No save in slot " + (slot + 1))); } else if (GameModeManager.CurrentHandler == null) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"Cannot load: no active game."); } else { pendingLoadSlot = slot; ((BaseUnityPlugin)this).Logger.LogInfo((object)("Load queued for slot " + (slot + 1) + ". Will apply at next pick phase.")); } }, 35, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null); MenuHandler.CreateText(" ", menu, ref val, 20, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null); } } private string GetSavePath(int slot) { return Path.Combine(saveDir, "save_slot_" + slot + ".json"); } private string GetSavedValue(string path, string key) { if (!File.Exists(path)) { return "0"; } try { return GetJsonInt(File.ReadAllText(path), key); } catch { return "0"; } } private void SaveToSlot(int slot) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) List players = PlayerManager.instance.players; IGameModeHandler currentHandler = GameModeManager.CurrentHandler; string text = ""; foreach (Player item in players) { TeamScore teamScore = currentHandler.GetTeamScore(item.teamID); string text2 = string.Join("|", item.data.currentCards.Select((CardInfo c) => ((Object)((Component)c).gameObject).name)); string[] obj = new string[11] { text, item.teamID.ToString(), "~", item.playerID.ToString(), "~", null, null, null, null, null, null }; int points = teamScore.points; obj[5] = points.ToString(); obj[6] = "~"; points = teamScore.rounds; obj[7] = points.ToString(); obj[8] = "~"; obj[9] = text2; obj[10] = ";"; text = string.Concat(obj); } int num = (int)currentHandler.Settings["pointsToWinRound"]; int num2 = (int)currentHandler.Settings["roundsToWinGame"]; string contents = "{\"round\":1,\"pointsToWinRound\":" + num + ",\"roundsToWin\":" + num2 + ",\"playerData\":\"" + text + "\"}"; File.WriteAllText(GetSavePath(slot), contents); ((BaseUnityPlugin)this).Logger.LogInfo((object)("Saved to slot " + slot)); } [IteratorStateMachine(typeof(d__10))] private IEnumerator LoadFromSlot(int slot) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__10(0) { <>4__this = this, slot = slot }; } private string GetJsonInt(string json, string key) { string text = "\"" + key + "\":"; int num = json.IndexOf(text) + text.Length; int num2 = json.IndexOfAny(new char[2] { ',', '}' }, num); return json.Substring(num, num2 - num).Trim(); } private string GetJsonString(string json, string key) { string text = "\"" + key + "\":\""; int num = json.IndexOf(text) + text.Length; int num2 = json.IndexOf('"', num); return json.Substring(num, num2 - num); } }