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 PersistentPurchases v1.2.0
plugins/PersistentPurchases/PersistentPurchases.dll
Decompiled 2 years agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using Unity.Netcode; using UnityEngine; using UnityEngine.UIElements.Collections; [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("PersistentPurchases")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyDescription("Keeps bought ship objects after failing to meet quota")] [assembly: AssemblyFileVersion("1.1.1.0")] [assembly: AssemblyInformationalVersion("1.1.1")] [assembly: AssemblyProduct("PersistentPurchases")] [assembly: AssemblyTitle("PersistentPurchases")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.1.1.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace PersistentPurchases { [HarmonyPatch] public class Patches { [HarmonyPostfix] [HarmonyPatch(typeof(Terminal), "Start")] [HarmonyPriority(-23)] public static void generateConfig() { Plugin.setupConfig(StartOfRound.Instance.unlockablesList.unlockables); } [HarmonyPrefix] [HarmonyPatch(typeof(StartOfRound), "ResetShip")] public static void storeUnlocked(StartOfRound __instance, out List<Tuple<int, Vector3, Vector3>> __state) { //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) Plugin.log.LogInfo((object)"Taking note of bought unlockables"); __state = new List<Tuple<int, Vector3, Vector3>>(); List<UnlockableItem> unlockables = __instance.unlockablesList.unlockables; for (int i = 0; i < unlockables.Count; i++) { Plugin.log.LogDebug((object)$"{unlockables[i].unlockableName} - unlocked({unlockables[i].hasBeenUnlockedByPlayer}) - should persist({Plugin.unlockableConfig[i].Value})"); if (unlockables[i].hasBeenUnlockedByPlayer && Plugin.unlockableConfig[i].Value) { __state.Add(Tuple.Create<int, Vector3, Vector3>(i, unlockables[i].placedPosition, unlockables[i].placedRotation)); } } } [HarmonyPostfix] [HarmonyPatch(typeof(StartOfRound), "ResetShip")] public static void loadUnlocked(StartOfRound __instance, List<Tuple<int, Vector3, Vector3>> __state) { //IL_00c5: Unknown result type (might be due to invalid IL or missing references) Plugin.log.LogInfo((object)"Rebuying unlockables"); foreach (Tuple<int, Vector3, Vector3> item in __state) { Plugin.log.LogDebug((object)__instance.unlockablesList.unlockables[item.Item1].unlockableName); UnlockableItem val = __instance.unlockablesList.unlockables[item.Item1]; __instance.BuyShipUnlockableServerRpc(item.Item1, TimeOfDay.Instance.quotaVariables.startingCredits); if (__instance.SpawnedShipUnlockables.ContainsKey(item.Item1)) { NetworkObject component = DictionaryExtensions.Get<int, GameObject>((IDictionary<int, GameObject>)__instance.SpawnedShipUnlockables, item.Item1, (GameObject)null).GetComponent<NetworkObject>(); if ((Object)(object)component != (Object)null) { ShipBuildModeManager.Instance.StoreObjectServerRpc(NetworkObjectReference.op_Implicit(component), 0); } else { Plugin.log.LogWarning((object)("Failed to find NetworkObject for " + val.unlockableName)); } } else { Plugin.log.LogWarning((object)("SpawnedShipUnlockables did not contain " + val.unlockableName)); } } } } [HarmonyPatch(typeof(GameNetworkManager), "ResetSavedGameValues")] public class RemoveUneccesaryAndAnnoyingReset { private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { Plugin.log.LogInfo((object)"Beginning patching of GameNetworkManager.ResetSavedGameValues"); List<CodeInstruction> list = new List<CodeInstruction>(instructions); bool flag = false; for (int i = 0; i < list.Count; i++) { if (CodeInstructionExtensions.Calls(list[i], typeof(GameNetworkManager).GetMethod("ResetUnlockablesListValues"))) { flag = true; list[i - 1].opcode = OpCodes.Nop; list[i].opcode = OpCodes.Nop; list[i].operand = null; break; } } if (flag) { Plugin.log.LogInfo((object)"Patched GameNetworkManager.ResetSavedGameValues"); } else { Plugin.log.LogError((object)"Failed to patch GameNetworkManager.ResetSavedGameValues!"); } return list.AsEnumerable(); } } [BepInPlugin("PersistentPurchases", "PersistentPurchases", "1.1.1")] public class Plugin : BaseUnityPlugin { public static ConfigEntry<bool> placeUnlockables; public static ManualLogSource log = new ManualLogSource("PersistentPurchases"); public static Harmony harmony = new Harmony("PersistentPurchases"); public static string[] knownFurniture = new string[19] { "Cozy lights", "Television", "Cupboard", "File Cabinet", "Toilet", "Shower", "Light switch", "Record player", "Table", "Bunkbeds", "Terminal", "Romantic table", "JackOLantern", "Welcome mat", "Goldfish", "Plushie pajama man", "SmallRug", "LargeRug", "FatalitiesSign" }; public static List<ConfigFile> despair = new List<ConfigFile>(); public static List<ConfigEntry<bool>> unlockableConfig = new List<ConfigEntry<bool>>(); private void Awake() { Logger.Sources.Add((ILogSource)(object)log); despair.Add(((BaseUnityPlugin)this).Config); harmony.PatchAll(typeof(Patches)); harmony.PatchAll(typeof(RemoveUneccesaryAndAnnoyingReset)); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin PersistentPurchases is loaded!"); } public static void setupConfig(List<UnlockableItem> unlockables) { log.LogInfo((object)$"Registering {unlockables.Count} unlockables"); for (int i = 0; i < unlockables.Count; i++) { log.LogDebug((object)(unlockables[i].unlockableName ?? "")); unlockableConfig.Add(despair[0].Bind<bool>("Unlockables", unlockables[i].unlockableName, unlockables[i].unlockableType == 0 || knownFurniture.Contains(unlockables[i].unlockableName), (ConfigDescription)null)); } } } public static class PluginInfo { public const string PLUGIN_GUID = "PersistentPurchases"; public const string PLUGIN_NAME = "PersistentPurchases"; public const string PLUGIN_VERSION = "1.1.1"; } }