Decompiled source of WaterSaves v1.2.6

WaterSaves.dll

Decompiled 2 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Bootstrap;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("WaterSaves")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("WaterSaves")]
[assembly: AssemblyTitle("WaterSaves")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
}
namespace WaterSaves
{
	[BepInPlugin("WaterGun.WaterSaves", "WaterSaves", "1.2.6")]
	public class Plugin : BaseUnityPlugin
	{
		[HarmonyPatch(typeof(StartOfRound), "SetTimeAndPlanetToSavedSettings")]
		internal class StartOfRoundTranspiler
		{
			[HarmonyTranspiler]
			public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
			{
				//IL_011b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0125: Expected O, but got Unknown
				//IL_0131: Unknown result type (might be due to invalid IL or missing references)
				//IL_013b: Expected O, but got Unknown
				//IL_0145: Unknown result type (might be due to invalid IL or missing references)
				//IL_014f: Expected O, but got Unknown
				if ((Object)(object)GameNetworkManager.Instance != (Object)null && GameNetworkManager.Instance.gameVersionNum < 80)
				{
					return instructions;
				}
				List<CodeInstruction> list = new List<CodeInstruction>(instructions);
				MethodInfo methodInfo = AccessTools.Method(typeof(Random), "Range", new Type[2]
				{
					typeof(int),
					typeof(int)
				}, (Type[])null);
				MethodInfo methodInfo2 = AccessTools.Method(typeof(Plugin), "GetCustomMapSeed", (Type[])null, (Type[])null);
				bool flag = false;
				for (int i = 0; i < list.Count; i++)
				{
					if (!flag && CodeInstructionExtensions.Calls(list[i], methodInfo) && i >= 2 && list[i - 2].opcode == OpCodes.Ldc_I4_0 && list[i - 1].opcode == OpCodes.Ldc_I4 && list[i - 1].operand is int num && num == 100000000)
					{
						list[i - 2] = new CodeInstruction(OpCodes.Nop, (object)null);
						list[i - 1] = new CodeInstruction(OpCodes.Nop, (object)null);
						list[i] = new CodeInstruction(OpCodes.Call, (object)methodInfo2);
						flag = true;
					}
				}
				return list;
			}
		}

		[HarmonyPatch(typeof(StartOfRound))]
		internal class StartOfRound_patches
		{
			[HarmonyPatch("Start")]
			[HarmonyPostfix]
			public static void Start_Post()
			{
				if (!ES3.KeyExists("WaterSaves_SaveName", GameNetworkManager.Instance.currentSaveFileName))
				{
					if (string.IsNullOrEmpty(newFileName))
					{
						newFileName = "Unnamed";
					}
					ES3.Save<string>("WaterSaves_SaveName", newFileName, GameNetworkManager.Instance.currentSaveFileName);
				}
			}
		}

		[HarmonyPatch(typeof(SaveFileUISlot))]
		internal class SaveFileUISlot_patches
		{
			[HarmonyPatch("Awake")]
			[HarmonyPrefix]
			public static bool Awake_Pre(SaveFileUISlot __instance)
			{
				FieldInfo fieldInfo = AccessTools.Field(typeof(SaveFileUISlot), "fileString");
				if (__instance.fileNum == -1)
				{
					fieldInfo.SetValue(__instance, "LCChallengeFile");
				}
				return false;
			}

			[HarmonyPatch("SetButtonColor")]
			[HarmonyPostfix]
			public static void SetButtonColor_Post(SaveFileUISlot __instance)
			{
				if (!((Behaviour)__instance).isActiveAndEnabled)
				{
					return;
				}
				FieldInfo fieldInfo = AccessTools.Field(typeof(SaveFileUISlot), "fileString");
				string text = (string)fieldInfo.GetValue(__instance);
				if (!string.IsNullOrEmpty(text))
				{
					if (__instance.fileNum == saveAmount && GameNetworkManager.Instance.currentSaveFileName == text)
					{
						((Component)((Component)__instance).transform.parent.Find("FileConfig")).gameObject.SetActive(true);
					}
					else if (__instance.fileNum == -1 && GameNetworkManager.Instance.currentSaveFileName == text)
					{
						((Component)((Component)__instance).transform.parent.Find("FileConfig")).gameObject.SetActive(false);
					}
					else if (__instance.fileNum != -1 && GameNetworkManager.Instance.currentSaveFileName == text)
					{
						((Component)((Component)__instance).transform.parent.parent.parent.Find("FileConfig")).gameObject.SetActive(false);
					}
				}
			}
		}

		[HarmonyPatch(typeof(DeleteFileButton))]
		internal class DeleteFileButtonPatches
		{
			[HarmonyPatch("DeleteFile")]
			[HarmonyPrefix]
			public static bool DeleteFile_Pre(DeleteFileButton __instance)
			{
				int fileToDelete = __instance.fileToDelete;
				if (fileToDelete < 0)
				{
					return false;
				}
				string text = $"LCSaveFile{fileToDelete + 1}";
				if (ES3.FileExists(text))
				{
					ES3.DeleteFile(text);
					string modDataPath = GetModDataPath(text);
					if (File.Exists(modDataPath))
					{
						File.Delete(modDataPath);
					}
					MenuManager obj = Object.FindObjectOfType<MenuManager>();
					if (obj != null)
					{
						obj.MenuAudio.PlayOneShot(__instance.deleteFileSFX);
					}
				}
				int i;
				for (i = fileToDelete + 2; ES3.FileExists($"LCSaveFile{i}"); i++)
				{
				}
				for (int j = fileToDelete + 2; j < i; j++)
				{
					ES3.RenameFile($"LCSaveFile{j}", $"WaterSavesTemp{j}");
				}
				for (int k = fileToDelete + 2; k < i; k++)
				{
					string modDataPath2 = GetModDataPath($"LCSaveFile{k}");
					string modDataPath3 = GetModDataPath($"WaterSavesTemp{k}");
					if (File.Exists(modDataPath2))
					{
						File.Move(modDataPath2, modDataPath3);
					}
				}
				for (int l = fileToDelete + 2; l < i; l++)
				{
					ES3.RenameFile($"WaterSavesTemp{l}", $"LCSaveFile{l - 1}");
				}
				for (int m = fileToDelete + 2; m < i; m++)
				{
					string modDataPath4 = GetModDataPath($"WaterSavesTemp{m}");
					string modDataPath5 = GetModDataPath($"LCSaveFile{m - 1}");
					if (File.Exists(modDataPath4))
					{
						File.Move(modDataPath4, modDataPath5);
					}
				}
				FieldInfo fieldInfo = AccessTools.Field(typeof(SaveFileUISlot), "fileString");
				SaveFileUISlot[] array = Object.FindObjectsOfType<SaveFileUISlot>(true);
				saveAmount = GetSaveCount();
				SaveFileUISlot[] array2 = array;
				foreach (SaveFileUISlot val in array2)
				{
					if (((Object)val).name == "NewFile")
					{
						val.fileNum--;
						fieldInfo?.SetValue(val, $"LCSaveFile{saveAmount + 1}");
					}
					else if (val.fileNum == fileToDelete)
					{
						Object.Destroy((Object)(object)((Component)val).gameObject);
					}
					else if (val.fileNum > fileToDelete)
					{
						val.fileNum--;
						string text2 = $"LCSaveFile{val.fileNum + 1}";
						fieldInfo?.SetValue(val, text2);
						if (ES3.KeyExists("WaterSaves_SaveName", text2))
						{
							((TMP_Text)val.fileNameText).text = ES3.Load<string>("WaterSaves_SaveName", text2);
						}
						else
						{
							((TMP_Text)val.fileNameText).text = $"File {val.fileNum + 1}";
						}
					}
				}
				return false;
			}

			private static string GetModDataPath(string saveName)
			{
				return Path.Combine(Application.persistentDataPath, saveName + ".moddata");
			}
		}

		[HarmonyPatch(typeof(MenuManager))]
		internal class MenuManager_patches
		{
			[HarmonyPatch("Awake")]
			[HarmonyPostfix]
			public static void Awake_Post(MenuManager __instance)
			{
				saveAmount = GetSaveCount();
				__instance.filesCompatible = new bool[saveAmount + 1];
				for (int i = 0; i < __instance.filesCompatible.Length; i++)
				{
					__instance.filesCompatible[i] = true;
				}
				Debug.Log((object)saveAmount);
			}

			[HarmonyPatch("Start")]
			[HarmonyPrefix]
			public static void Start_Pre(MenuManager __instance)
			{
				//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
				//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
				//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
				//IL_0101: Unknown result type (might be due to invalid IL or missing references)
				//IL_0394: Unknown result type (might be due to invalid IL or missing references)
				//IL_039e: Expected O, but got Unknown
				//IL_03ae: Unknown result type (might be due to invalid IL or missing references)
				//IL_03b8: Expected O, but got Unknown
				//IL_0520: Unknown result type (might be due to invalid IL or missing references)
				//IL_0534: Unknown result type (might be due to invalid IL or missing references)
				//IL_0539: Unknown result type (might be due to invalid IL or missing references)
				//IL_0555: Unknown result type (might be due to invalid IL or missing references)
				//IL_0569: Unknown result type (might be due to invalid IL or missing references)
				//IL_056e: Unknown result type (might be due to invalid IL or missing references)
				//IL_04ab: Unknown result type (might be due to invalid IL or missing references)
				//IL_04b5: Expected O, but got Unknown
				GameObject hostPanel = __instance.HostSettingsScreen;
				if ((Object)(object)hostPanel == (Object)null)
				{
					return;
				}
				Transform val = __instance.HostSettingsScreen.transform.Find("FilesPanel");
				if ((Object)(object)val == (Object)null)
				{
					return;
				}
				if (GameNetworkManager.Instance.disableSteam && !Chainloader.PluginInfos.ContainsKey("uk.1a3.lobbyimprovements"))
				{
					Transform obj = __instance.HostSettingsOptionsLAN.transform.Find("Local");
					obj.localPosition += new Vector3(0f, -14f, 0f);
					Transform obj2 = __instance.HostSettingsOptionsLAN.transform.Find("AllowRemote");
					obj2.localPosition += new Vector3(0f, -14f, 0f);
					Transform val2 = __instance.HostSettingsOptionsLAN.transform.Find("ServerNameField");
					((Component)val2).gameObject.SetActive(true);
					((Component)val2.Find("Text Area/Placeholder")).GetComponent<TMP_Text>().text = "File name...";
					__instance.lobbyNameInputField = ((Component)val2).GetComponent<TMP_InputField>();
				}
				GameObject val3 = Object.Instantiate<GameObject>(WaterSavesMenu, hostPanel.transform);
				if (GameNetworkManager.Instance.gameVersionNum < 73)
				{
					((Component)val3.transform.Find("UpgradedFilesPanel/FilesScroll")).GetComponent<ScrollRect>().scrollSensitivity = 1f;
				}
				FieldInfo field = AccessTools.Field(typeof(SaveFileUISlot), "fileString");
				Transform val4 = val3.transform.Find("UpgradedFilesPanel/FilesScroll/Content/FileSelector");
				Transform val5 = val3.transform.Find("UpgradedFilesPanel/NewFile");
				Transform fileConfig = val3.transform.Find("UpgradedFilesPanel/FileConfig");
				for (int i = 0; i < saveAmount; i++)
				{
					Transform val6 = Object.Instantiate<Transform>(val4, val3.transform.Find("UpgradedFilesPanel/FilesScroll/Content"));
					Button component = ((Component)val6.Find("DeleteButton")).GetComponent<Button>();
					Button component2 = ((Component)val6.Find("RenameButton")).GetComponent<Button>();
					Transform deleteFileConfirm = hostPanel.transform.parent.Find("DeleteFileConfirmation");
					((Component)val6).gameObject.SetActive(true);
					((Object)((Component)val6).gameObject).name = $"File{i}";
					SaveFileUISlot saveFile = ((Component)val6).GetComponent<SaveFileUISlot>();
					saveFile.fileNum = i;
					field.SetValue(saveFile, $"LCSaveFile{i + 1}");
					if (!ES3.KeyExists("WaterSaves_SaveName", (string)field.GetValue(saveFile)))
					{
						((TMP_Text)saveFile.fileNameText).text = $"File {i + 1}";
					}
					else
					{
						((TMP_Text)saveFile.fileNameText).text = ES3.Load<string>("WaterSaves_SaveName", (string)field.GetValue(saveFile));
					}
					((UnityEvent)component.onClick).AddListener((UnityAction)delegate
					{
						((Component)deleteFileConfirm).gameObject.SetActive(true);
						((Selectable)((Component)deleteFileConfirm.Find("Panel/Back")).GetComponent<Button>()).Select();
						((Component)deleteFileConfirm.Find("Panel/Delete")).GetComponent<DeleteFileButton>().SetFileToDelete(saveFile.fileNum);
						hostPanel.gameObject.SetActive(false);
					});
					((UnityEvent)component2.onClick).AddListener((UnityAction)delegate
					{
						string text = __instance.lobbyNameInputField.text;
						if (string.IsNullOrEmpty(text))
						{
							((TMP_Text)saveFile.fileNameText).text = "Unnamed";
						}
						else
						{
							((TMP_Text)saveFile.fileNameText).text = text;
						}
						ES3.Save<string>("WaterSaves_SaveName", ((TMP_Text)saveFile.fileNameText).text, (string)field.GetValue(saveFile));
					});
				}
				if (saveAmount != 0)
				{
					((Component)val5.parent.Find("FileConfig")).gameObject.SetActive(false);
				}
				((Component)val5).GetComponent<SaveFileUISlot>().fileNum = saveAmount;
				field.SetValue(((Component)val5).GetComponent<SaveFileUISlot>(), $"LCSaveFile{saveAmount + 1}");
				int num = (newFileSeed = Random.Range(0, 100000000));
				if (GameNetworkManager.Instance.gameVersionNum >= 80)
				{
					((Component)fileConfig.Find("Seed/SeedNumberField")).GetComponent<TMP_InputField>().text = num.ToString();
					((UnityEvent)((Component)fileConfig.Find("Seed/Randomize")).GetComponent<Button>().onClick).AddListener((UnityAction)delegate
					{
						int num2 = (newFileSeed = Random.Range(0, 100000000));
						((Component)fileConfig.Find("Seed/SeedNumberField")).GetComponent<TMP_InputField>().text = num2.ToString();
					});
					((UnityEvent<string>)(object)((Component)fileConfig.Find("Seed/SeedNumberField")).GetComponent<TMP_InputField>().onEndEdit).AddListener((UnityAction<string>)delegate(string str)
					{
						int num2 = ((!string.IsNullOrEmpty(str)) ? int.Parse(str) : 0);
						num2 = Mathf.Clamp(num2, 0, 99999999);
						((Component)fileConfig.Find("Seed/SeedNumberField")).GetComponent<TMP_InputField>().text = num2.ToString();
						newFileSeed = num2;
					});
				}
				else
				{
					Object.Destroy((Object)(object)((Component)fileConfig.Find("Seed")).gameObject);
					Debug.LogWarning((object)"This is pre v80 game build (Seed file options are disabled)");
					Transform obj3 = fileConfig.Find("File");
					obj3.localPosition += new Vector3(0f, 10f, 0f);
					Transform obj4 = fileConfig.Find("File");
					obj4.localScale += new Vector3(0.25f, 0.25f, 0.25f);
				}
				((UnityEvent<string>)(object)((Component)fileConfig.Find("File/FileNameField")).GetComponent<TMP_InputField>().onEndEdit).AddListener((UnityAction<string>)delegate(string str)
				{
					newFileName = str;
				});
				Object.Destroy((Object)(object)((Component)val).gameObject);
			}

			[HarmonyPatch("Start")]
			[HarmonyPostfix]
			public static void Postfix(MenuManager __instance)
			{
				int saveCount = GetSaveCount();
				if (__instance.filesCompatible == null || __instance.filesCompatible.Length < saveCount)
				{
					Array.Resize(ref __instance.filesCompatible, saveCount);
				}
				bool flag = false;
				for (int i = 3; i < saveCount; i++)
				{
					string text = $"LCSaveFile{i + 1}";
					if (!ES3.FileExists(text))
					{
						continue;
					}
					try
					{
						int num = ES3.Load<int>("FileGameVers", text, 0);
						if (num < GameNetworkManager.Instance.compatibleFileCutoffVersion)
						{
							__instance.filesCompatible[i] = false;
							flag = true;
							Debug.LogWarning((object)$"WaterSaves: Save {i + 1} is incompatible.");
						}
						else
						{
							__instance.filesCompatible[i] = true;
						}
					}
					catch (Exception arg)
					{
						Debug.LogError((object)$"[WaterSaves]: Failed to check save {i + 1}: {arg}");
					}
				}
				if (flag)
				{
					Debug.LogWarning((object)"[WaterSaves]: One or more additional save files are incompatible.");
					MethodInfo methodInfo = ((GameNetworkManager.Instance.gameVersionNum < 80) ? AccessTools.Method(typeof(MenuManager), "DisplayMenuNotification", new Type[2]
					{
						typeof(string),
						typeof(string)
					}, (Type[])null) : AccessTools.Method(typeof(MenuManager), "DisplayMenuNotification", new Type[3]
					{
						typeof(string),
						typeof(string),
						typeof(bool)
					}, (Type[])null));
					methodInfo.Invoke(__instance, new object[2]
					{
						$"Some of your save files may not be compatible with version {GameNetworkManager.Instance.compatibleFileCutoffVersion} and may be corrupted if you play them.",
						"[ Back ]"
					});
				}
			}
		}

		private const string GUID = "WaterGun.WaterSaves";

		private const string NAME = "WaterSaves";

		private const string VER = "1.2.6";

		public static GameObject WaterSavesMenu;

		public static int newFileSeed = 0;

		public static string newFileName = "";

		public static int saveAmount = -1;

		private void Awake()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			Harmony val = new Harmony("WaterGun.WaterSaves");
			val.PatchAll();
			string text = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "watersaves");
			AssetBundle val2 = AssetBundle.LoadFromFile(text);
			WaterSavesMenu = val2.LoadAsset<GameObject>("Assets/LethalCompany/Mods/WaterSaves/WaterSavesUI.prefab");
			Debug.Log((object)"[WaterSaves]: Loaded!");
		}

		public static int GetSaveCount()
		{
			return Directory.GetFiles(Application.persistentDataPath, "LCSaveFile*", SearchOption.TopDirectoryOnly).Count((string file) => Regex.IsMatch(Path.GetFileName(file), "^LCSaveFile\\d+$"));
		}

		public static int GetCustomMapSeed()
		{
			return (GameNetworkManager.Instance.gameVersionNum >= 80) ? newFileSeed : Random.Range(0, 100000000);
		}
	}
}