Decompiled source of SaveUtility v1.0.5

ScheduleOneSaveUtility.dll

Decompiled a month ago
using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using HarmonyLib;
using MelonLoader;
using ScheduleOne.DevUtilities;
using ScheduleOne.Persistence;
using ScheduleOne.Persistence.Datas;
using ScheduleOne.UI.MainMenu;
using ScheduleOneSaveUtility;
using ScheduleOneSaveUtility.UI;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: MelonInfo(typeof(Core), "SaveUtility", "1.0.0", "MaxtorCoder", null)]
[assembly: MelonGame("TVGS", "Schedule I")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("ScheduleOneSaveUtility")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.5")]
[assembly: AssemblyProduct("ScheduleOneSaveUtility")]
[assembly: AssemblyTitle("ScheduleOneSaveUtility")]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace ScheduleOneSaveUtility
{
	public class Core : MelonMod
	{
		public override void OnInitializeMelon()
		{
			((MelonBase)this).LoggerInstance.Msg("Initialized.");
		}

		public override void OnSceneWasLoaded(int buildIndex, string sceneName)
		{
			if (sceneName == "Menu")
			{
				UIManager.FindContinueButton();
			}
		}
	}
}
namespace ScheduleOneSaveUtility.UI
{
	public static class UIManager
	{
		private static GameObject _continueButtonPrefab;

		public static void FindContinueButton()
		{
			_continueButtonPrefab = GameObject.Find("MainMenu/Home/Bank/Continue");
		}

		public static void AddDuplicateSaveButtons()
		{
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Expected O, but got Unknown
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Expected O, but got Unknown
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)_continueButtonPrefab))
			{
				Melon<Core>.Logger.Error("Failed to find continue button in main menu...");
				return;
			}
			GameObject val = GameObject.Find("MainMenu/Continue/Container");
			for (int i = 0; i < val.transform.childCount; i++)
			{
				Transform child = val.transform.GetChild(i);
				if (!Object.op_Implicit((Object)(object)child))
				{
					Melon<Core>.Logger.Error($"Slot for index: {i} is null.");
					continue;
				}
				Transform val2 = child.Find("Container");
				if (!Object.op_Implicit((Object)(object)val2))
				{
					Melon<Core>.Logger.Error($"Container {i} could not be found or is not active.");
					continue;
				}
				int saveIndex = i;
				GameObject obj = UIUtils.CreateButtonFromPrefab("Duplicate", 16f, _continueButtonPrefab, null, (UnityAction)delegate
				{
					DuplicateSaveButtonEvent(saveIndex);
				});
				obj.transform.SetParent(((Component)val2).transform, false);
				obj.transform.position = ((Component)val2).transform.position;
				obj.transform.localPosition = new Vector3(451f, 15f, 0f);
				GameObject obj2 = UIUtils.CreateButtonFromPrefab("Delete", 16f, _continueButtonPrefab, (Color?)new Color(1f, 0.28f, 0.14f, 1f), (UnityAction)delegate
				{
					DeleteSaveButtonEvent(saveIndex);
				});
				obj2.transform.SetParent(((Component)val2).transform, false);
				obj2.transform.position = ((Component)val2).transform.position;
				obj2.transform.localPosition = new Vector3(575f, 15f, 0f);
			}
		}

		private static void DuplicateSaveButtonEvent(int currentSaveIndex)
		{
			SaveInfo val = LoadManager.SaveGames[currentSaveIndex];
			if (val == null)
			{
				return;
			}
			int num = -1;
			for (int i = 0; i < LoadManager.SaveGames.Length; i++)
			{
				if (LoadManager.SaveGames[i] == null)
				{
					num = i;
					break;
				}
			}
			if (num != -1)
			{
				string text = Path.Combine(Singleton<SaveManager>.Instance.IndividualSavesContainerPath, $"SaveGame_{num + 1}");
				if (!Directory.Exists(text))
				{
					val.SaveSlotNumber = num + 1;
					val.DateCreated = DateTime.Now;
					val.OrganisationName = (val.OrganisationName.Contains("Duplicate") ? val.OrganisationName.Replace($"Duplicate {num - 1}", $"Duplicate {num}") : $"{val.OrganisationName} (Duplicate {num})");
					Melon<Core>.Logger.Msg($"Saving game {currentSaveIndex} -> {num} ({val.OrganisationName})");
					CopyDirectory(Path.Combine(Singleton<SaveManager>.Instance.IndividualSavesContainerPath, $"SaveGame_{currentSaveIndex + 1}"), text, recursive: true);
					GameData val2 = JsonUtility.FromJson<GameData>(File.ReadAllText(Path.Combine(text, "Game.json")));
					val2.OrganisationName = val.OrganisationName;
					File.WriteAllText(Path.Combine(text, "Game.json"), JsonUtility.ToJson((object)val2));
					Singleton<LoadManager>.Instance.RefreshSaveInfo();
				}
			}
		}

		private static void DeleteSaveButtonEvent(int currentSaveIndex)
		{
			if (LoadManager.SaveGames[currentSaveIndex] != null)
			{
				Directory.Delete(Path.Combine(Singleton<SaveManager>.Instance.IndividualSavesContainerPath, $"SaveGame_{currentSaveIndex + 1}"), recursive: true);
				Singleton<LoadManager>.Instance.RefreshSaveInfo();
			}
		}

		private static void CopyDirectory(string sourceDir, string destinationDir, bool recursive)
		{
			DirectoryInfo directoryInfo = new DirectoryInfo(sourceDir);
			if (!directoryInfo.Exists)
			{
				throw new DirectoryNotFoundException("Source directory not found: " + directoryInfo.FullName);
			}
			DirectoryInfo[] directories = directoryInfo.GetDirectories();
			Directory.CreateDirectory(destinationDir);
			FileInfo[] files = directoryInfo.GetFiles();
			foreach (FileInfo fileInfo in files)
			{
				string destFileName = Path.Combine(destinationDir, fileInfo.Name);
				fileInfo.CopyTo(destFileName);
			}
			if (recursive)
			{
				DirectoryInfo[] array = directories;
				foreach (DirectoryInfo directoryInfo2 in array)
				{
					string destinationDir2 = Path.Combine(destinationDir, directoryInfo2.Name);
					CopyDirectory(directoryInfo2.FullName, destinationDir2, recursive: true);
				}
			}
		}
	}
	public static class UIUtils
	{
		public static GameObject CreateButtonFromPrefab(string text, float fontSize, GameObject prefab, Color? fontColor = null, UnityAction onClick = null)
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = Object.Instantiate<GameObject>(prefab);
			((Object)val).name = text + "Button";
			TextMeshProUGUI componentInChildren = val.GetComponentInChildren<TextMeshProUGUI>();
			((TMP_Text)componentInChildren).text = text;
			((TMP_Text)componentInChildren).fontSize = fontSize;
			if (fontColor.HasValue)
			{
				((Graphic)componentInChildren).color = fontColor.Value;
			}
			if (onClick != null)
			{
				Button component = val.GetComponent<Button>();
				((UnityEventBase)component.onClick).RemoveAllListeners();
				((UnityEvent)component.onClick).AddListener(onClick);
			}
			return val;
		}
	}
}
namespace ScheduleOneSaveUtility.Patches.UI
{
	[HarmonyPatch(typeof(ContinueScreen))]
	public class ContinueScreenPatches
	{
		[HarmonyPatch("Update")]
		[HarmonyPostfix]
		public static void UpdatePostfix(ContinueScreen __instance)
		{
			if (!Object.op_Implicit((Object)(object)((Component)__instance).gameObject.GetComponent<ContinueScreenComponent>()))
			{
				((Component)__instance).gameObject.AddComponent<ContinueScreenComponent>();
			}
		}
	}
	public class ContinueScreenComponent : MonoBehaviour
	{
		private void Awake()
		{
			Debug.Log((object)"Adding \"Duplicate Save\" buttons...");
			UIManager.AddDuplicateSaveButtons();
		}
	}
}