Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of WaterSaves v1.2.6
WaterSaves.dll
Decompiled 2 hours agousing 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); } } }