Decompiled source of LocalSaveSlots v1.0.3

LocalSaveSlots.dll

Decompiled 3 days ago
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<CardInfo, string> <>9__9_0;

		internal void <Awake>b__3_0()
		{
		}

		internal string <SaveToSlot>b__9_0(CardInfo c)
		{
			return ((Object)((Component)c).gameObject).name;
		}
	}

	[CompilerGenerated]
	private sealed class <>c__DisplayClass10_0
	{
		public int teamId;

		internal bool <LoadFromSlot>b__0(Player p)
		{
			return p.teamID == teamId;
		}
	}

	[CompilerGenerated]
	private sealed class <>c__DisplayClass10_1
	{
		public string name;

		internal bool <LoadFromSlot>b__1(CardInfo c)
		{
			return ((Object)((Component)c).gameObject).name == name;
		}
	}

	[CompilerGenerated]
	private sealed class <LoadFromSlot>d__10 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public LocalSaveSlots <>4__this;

		public int slot;

		private IGameModeHandler <handler>5__2;

		private string[] <>7__wrap2;

		private int <>7__wrap3;

		private string <cardNames>5__5;

		private Player <player>5__6;

		object IEnumerator<object>.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		object IEnumerator.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		[DebuggerHidden]
		public <LoadFromSlot>d__10(int <>1__state)
		{
			this.<>1__state = <>1__state;
		}

		[DebuggerHidden]
		void IDisposable.Dispose()
		{
			<handler>5__2 = null;
			<>7__wrap2 = null;
			<cardNames>5__5 = null;
			<player>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"));
				<handler>5__2 = GameModeManager.CurrentHandler;
				<handler>5__2.ChangeSetting("pointsToWinRound", (object)num2);
				<handler>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(<cardNames>5__5))
				{
					List<CardInfo> list = new List<CardInfo>();
					string[] array = <cardNames>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<CardInfo>)CardChoice.instance.cards).FirstOrDefault((Func<CardInfo, bool>)((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(<player>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]);
							<cardNames>5__5 = array3[4];
							<handler>5__2.SetTeamScore(CS$<>8__locals1.teamId, new TeamScore(num4, num5));
							<player>5__6 = PlayerManager.instance.players.Find((Player p) => p.teamID == CS$<>8__locals1.teamId);
							if (!((Object)(object)<player>5__6 == (Object)null))
							{
								Cards.instance.RemoveAllCardsFromPlayer(<player>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<object>());
				ExtensionMethods.InvokeMethod((object)UIHandler.instance.roundCounterSmall, "ReDraw", Array.Empty<object>());
				((BaseUnityPlugin)localSaveSlots).Logger.LogInfo((object)("Loaded slot " + slot));
				return false;
				IL_0290:
				<>7__wrap3++;
				goto IL_029e;
				IL_0282:
				<cardNames>5__5 = null;
				<player>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 <OnPickStart>d__5 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public LocalSaveSlots <>4__this;

		object IEnumerator<object>.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		object IEnumerator.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		[DebuggerHidden]
		public <OnPickStart>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<GameObject>)BuildMenu, (GameObject)null, true);
		((BaseUnityPlugin)this).Logger.LogInfo((object)"LocalSaveSlots loaded!");
	}

	private void Start()
	{
		GameModeManager.AddHook("PickStart", (Func<IGameModeHandler, IEnumerator>)OnPickStart);
	}

	[IteratorStateMachine(typeof(<OnPickStart>d__5))]
	private IEnumerator OnPickStart(IGameModeHandler gm)
	{
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <OnPickStart>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<Player> 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(<LoadFromSlot>d__10))]
	private IEnumerator LoadFromSlot(int slot)
	{
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <LoadFromSlot>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);
	}
}