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 KeepMySuitOn v1.0.1
KarmyDev.KeepMySuitOn.dll
Decompiled 9 months agousing System; using System.Collections; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using GameNetcodeStuff; using HarmonyLib; using Microsoft.CodeAnalysis; using Unity.Netcode; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: IgnoresAccessChecksTo("AmazingAssets.TerrainToMesh")] [assembly: IgnoresAccessChecksTo("Assembly-CSharp-firstpass")] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: IgnoresAccessChecksTo("ClientNetworkTransform")] [assembly: IgnoresAccessChecksTo("com.olegknyazev.softmask")] [assembly: IgnoresAccessChecksTo("DissonanceVoip")] [assembly: IgnoresAccessChecksTo("EasyTextEffects")] [assembly: IgnoresAccessChecksTo("Facepunch Transport for Netcode for GameObjects")] [assembly: IgnoresAccessChecksTo("Facepunch.Steamworks.Win64")] [assembly: IgnoresAccessChecksTo("Unity.AI.Navigation")] [assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging")] [assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging.DocCodeExamples")] [assembly: IgnoresAccessChecksTo("Unity.Burst")] [assembly: IgnoresAccessChecksTo("Unity.Burst.Unsafe")] [assembly: IgnoresAccessChecksTo("Unity.Collections")] [assembly: IgnoresAccessChecksTo("Unity.Collections.LowLevel.ILSupport")] [assembly: IgnoresAccessChecksTo("Unity.InputSystem")] [assembly: IgnoresAccessChecksTo("Unity.InputSystem.ForUI")] [assembly: IgnoresAccessChecksTo("Unity.Jobs")] [assembly: IgnoresAccessChecksTo("Unity.Mathematics")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.Common")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.MetricTypes")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStats")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Component")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Configuration")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Implementation")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsReporting")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetworkProfiler.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetworkSolutionInterface")] [assembly: IgnoresAccessChecksTo("Unity.Netcode.Components")] [assembly: IgnoresAccessChecksTo("Unity.Netcode.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.Networking.Transport")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Csg")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder.KdTree")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Poly2Tri")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Stl")] [assembly: IgnoresAccessChecksTo("Unity.Profiling.Core")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.ShaderLibrary")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Config.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.ShaderGraph.ShaderGraphLibrary")] [assembly: IgnoresAccessChecksTo("Unity.Services.Authentication")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Analytics")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Configuration")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Device")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments.Internal")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Internal")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Networking")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Registration")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Scheduler")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Telemetry")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Threading")] [assembly: IgnoresAccessChecksTo("Unity.Services.QoS")] [assembly: IgnoresAccessChecksTo("Unity.Services.Relay")] [assembly: IgnoresAccessChecksTo("Unity.TextMeshPro")] [assembly: IgnoresAccessChecksTo("Unity.Timeline")] [assembly: IgnoresAccessChecksTo("Unity.VisualEffectGraph.Runtime")] [assembly: IgnoresAccessChecksTo("UnityEngine.ARModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.NVIDIAModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.UI")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("KarmyDev.KeepMySuitOn")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.1.0")] [assembly: AssemblyInformationalVersion("1.0.1")] [assembly: AssemblyProduct("KeepMySuitOn")] [assembly: AssemblyTitle("KarmyDev.KeepMySuitOn")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.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.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] [Microsoft.CodeAnalysis.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; } } [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 KeepMySuitOn { [BepInPlugin("KarmyDev.KeepMySuitOn", "KeepMySuitOn", "1.0.1")] public class KeepMySuitOnPlugin : BaseUnityPlugin { public static KeepMySuitOnPlugin? Instance; public static ManualLogSource? Logger; private static Harmony? Harmony; public const int DEFAULT_SUIT_ID = 0; private static ConfigEntry<bool>? CanRestoreLockedSuit; private static ConfigEntry<string>? LastUsedSuitName; public static void SaveLastUsedSuit(string suitName) { LastUsedSuitName.Value = suitName; } public static string GetLastUsedSuit() { return LastUsedSuitName.Value; } public static bool GetCanRestoreLockedSuit() { return CanRestoreLockedSuit.Value; } public static IEnumerator LazyRestoreSuit() { yield return (object)new WaitForEndOfFrame(); yield return (object)new WaitForEndOfFrame(); LoadLastUsedSuit(); } public static void LoadLastUsedSuit() { string lastUsedSuit = GetLastUsedSuit(); if (lastUsedSuit == StartOfRound.Instance.unlockablesList.unlockables[0].unlockableName || string.IsNullOrEmpty(lastUsedSuit) || !(lastUsedSuit != "default")) { return; } UnlockableSuit[] array = Object.FindObjectsOfType<UnlockableSuit>(true); for (int i = 0; i < array.Length; i++) { if (StartOfRound.Instance.unlockablesList.unlockables[array[i].suitID].unlockableName == lastUsedSuit) { if (GetCanRestoreLockedSuit()) { array[i].SwitchSuitToThis((PlayerControllerB)null); break; } if (StartOfRound.Instance.unlockablesList.unlockables[array[i].suitID].alreadyUnlocked || StartOfRound.Instance.unlockablesList.unlockables[array[i].suitID].hasBeenUnlockedByPlayer) { array[i].SwitchSuitToThis((PlayerControllerB)null); break; } } } } public void Awake() { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Expected O, but got Unknown Logger = ((BaseUnityPlugin)this).Logger; Instance = this; CanRestoreLockedSuit = ((BaseUnityPlugin)this).Config.Bind<bool>("KeepMySuitOnConfig", "CanRestoreLockedSuit", false, "Determines whether suits that are not unlocked should be restored, unless they have already been purchased in this game."); LastUsedSuitName = ((BaseUnityPlugin)this).Config.Bind<string>("KeepMySuitOnConfig", "LastUsedSuitName", string.Empty, "A suit's name used to find and restore suit, leaving it empty or setting to \"default\" will restore default suit."); Harmony = new Harmony("KarmyDev.KeepMySuitOn"); Logger.LogDebug((object)"Patching..."); Harmony.PatchAll(); Logger.LogDebug((object)"Finished patching!"); Logger.LogInfo((object)"KarmyDev.KeepMySuitOn v1.0.1 has loaded!"); } } public static class MyPluginInfo { public const string PLUGIN_GUID = "KarmyDev.KeepMySuitOn"; public const string PLUGIN_NAME = "KeepMySuitOn"; public const string PLUGIN_VERSION = "1.0.1"; } } namespace KeepMySuitOn.Patches { [HarmonyPatch(typeof(PlayerControllerB))] public class PlayerControllerBPatch { [HarmonyPatch("ConnectClientToPlayerObject")] [HarmonyPostfix] public static void PostConnectClientToPlayerObject(ref PlayerControllerB __instance) { ((MonoBehaviour)__instance).StartCoroutine(KeepMySuitOnPlugin.LazyRestoreSuit()); ManualLogSource? logger = KeepMySuitOnPlugin.Logger; if (logger != null) { logger.LogMessage((object)"Restored last used suit for client."); } } } [HarmonyPatch(typeof(StartOfRound))] public class StartOfRoundPatch { [HarmonyPatch("Start")] [HarmonyPostfix] public static void PostStart(ref StartOfRound __instance) { ((MonoBehaviour)__instance).StartCoroutine(RestoreHostSuit(__instance)); } private static IEnumerator RestoreHostSuit(StartOfRound __instance) { yield return (object)new WaitForEndOfFrame(); yield return (object)new WaitForEndOfFrame(); yield return (object)new WaitForSeconds(0.45f); if (((NetworkBehaviour)__instance).IsServer || ((NetworkBehaviour)__instance).IsHost) { KeepMySuitOnPlugin.LoadLastUsedSuit(); ManualLogSource? logger = KeepMySuitOnPlugin.Logger; if (logger != null) { logger.LogMessage((object)"Restored last used suit for host."); } } } } [HarmonyPatch(typeof(UnlockableSuit))] public class UnlockableSuitPatch { [HarmonyPatch("SwitchSuitToThis")] [HarmonyPrefix] public static void PreSwitchSuitToThis(ref UnlockableSuit __instance, PlayerControllerB playerWhoTriggered) { if (((Object)(object)playerWhoTriggered == (Object)null || (Object)(object)playerWhoTriggered == (Object)(object)GameNetworkManager.Instance.localPlayerController) && GameNetworkManager.Instance.localPlayerController.currentSuitID != __instance.suitID) { ManualLogSource? logger = KeepMySuitOnPlugin.Logger; if (logger != null) { logger.LogMessage((object)("Saving new suit for later restore, id: " + __instance.suitID + ", name: " + StartOfRound.Instance.unlockablesList.unlockables[__instance.suitID].unlockableName)); } KeepMySuitOnPlugin.SaveLastUsedSuit(StartOfRound.Instance.unlockablesList.unlockables[__instance.suitID].unlockableName); } } [HarmonyPatch("SwitchSuitForPlayer")] [HarmonyPostfix] public static void PostSwitchSuitForPlayer(PlayerControllerB player, int suitID) { if (suitID == 0 && (Object)(object)player == (Object)(object)GameNetworkManager.Instance.localPlayerController) { ((MonoBehaviour)player).StartCoroutine(KeepMySuitOnPlugin.LazyRestoreSuit()); ManualLogSource? logger = KeepMySuitOnPlugin.Logger; if (logger != null) { logger.LogMessage((object)"Restored last used suit. (Fallback)"); } } } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }