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 REPOUpgradeAPI v1.0.0
REPOUpgradeAPI.dll
Decompiled 4 months agousing System; using System.Collections; using System.Collections.Generic; 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.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using Photon.Pun; using REPOUpgradeAPI.Runtime; using SingularityGroup.HotReload; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: IgnoresAccessChecksTo("")] [assembly: AssemblyCompany("Kai")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("REPOUpgradeAPI")] [assembly: AssemblyTitle("REPOUpgradeAPI")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.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 REPOUpgradeAPI { [BepInPlugin("Kai.REPOUpgradeAPI", "REPOUpgradeAPI", "3.1")] public class REPOUpgradeAPI : BaseUnityPlugin { internal static REPOUpgradeAPI Instance { get; private set; } internal static ManualLogSource Logger => Instance._logger; private ManualLogSource _logger => ((BaseUnityPlugin)this).Logger; internal Harmony? Harmony { get; set; } private void Awake() { Instance = this; ((Component)this).gameObject.transform.parent = null; ((Object)((Component)this).gameObject).hideFlags = (HideFlags)61; Patch(); Logger.LogInfo((object)$"{((BaseUnityPlugin)this).Info.Metadata.GUID} v{((BaseUnityPlugin)this).Info.Metadata.Version} has loaded!"); } internal void Patch() { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown //IL_0025: Expected O, but got Unknown if (Harmony == null) { Harmony val = new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID); Harmony val2 = val; Harmony = val; } Harmony.PatchAll(); } internal void Unpatch() { Harmony? harmony = Harmony; if (harmony != null) { harmony.UnpatchSelf(); } } private void Update() { } } internal static class UpgradeTypeExtensions { public static string ToInternalString(this UpgradeAPI.UpgradeType type) { return type switch { UpgradeAPI.UpgradeType.Energy => "energy", UpgradeAPI.UpgradeType.Health => "health", UpgradeAPI.UpgradeType.Wings => "wings", UpgradeAPI.UpgradeType.Launch => "launch", UpgradeAPI.UpgradeType.Crouch => "crouch", UpgradeAPI.UpgradeType.Sprint => "sprint", UpgradeAPI.UpgradeType.Strength => "strength", UpgradeAPI.UpgradeType.Range => "range", UpgradeAPI.UpgradeType.Jump => "jump", UpgradeAPI.UpgradeType.Battery => "battery", UpgradeAPI.UpgradeType.Map => "map", UpgradeAPI.UpgradeType.Climb => "climb", _ => throw new ArgumentOutOfRangeException("type"), }; } } public static class UpgradeAPI { public enum UpgradeType { Energy, Health, Wings, Launch, Crouch, Sprint, Strength, Range, Jump, Battery, Map, Climb } internal static readonly HashSet<string> CustomKeys = new HashSet<string>(); internal static bool RpcRegistered { get; private set; } internal static void RegisterRPC(PunManager pun) { if ((Object)(object)pun == (Object)null) { throw new ArgumentNullException("pun"); } GameObject gameObject = ((Component)pun).gameObject; PhotonView val = gameObject.GetComponent<PhotonView>(); if ((Object)(object)val == (Object)null) { val = gameObject.AddComponent<PhotonView>(); } if (val.ViewID == 0 && PhotonNetwork.InRoom && !PhotonNetwork.AllocateRoomViewID(val)) { Logger.CreateLogSource("UpgradeAPI").LogError((object)"[UpgradeAPI] Failed to allocate ViewID for UpgradeNet PhotonView."); } UpgradeNet upgradeNet = default(UpgradeNet); if (!gameObject.TryGetComponent<UpgradeNet>(ref upgradeNet)) { gameObject.AddComponent<UpgradeNet>(); Logger.CreateLogSource("UpgradeAPI").LogInfo((object)"[UpgradeAPI] UpgradeNet attached to PunManager."); } RpcRegistered = true; } public static void RegisterCustomUpgrade(string key) { if (!string.IsNullOrWhiteSpace(key)) { CustomKeys.Add(key.ToLowerInvariant()); } } public static void LogAllUpgradeDictionaries() { UpgradeManager.LogAllUpgradeDictionaries(); } public static void GetUpgradeKeys() { foreach (string upgradeKey in UpgradeManager.GetUpgradeKeys()) { REPOUpgradeAPI.Logger.LogInfo((object)("Key: " + upgradeKey)); } } public static IEnumerable<string> ListUpgradeKeys() { return UpgradeManager.GetUpgradeKeys(); } public static void Add(string type, int delta, string? steamID = null) { UpgradeManager.ApplyDelta(type, delta, steamID); } public static void Add(UpgradeType type, int delta, string? steamID = null) { Add(type.ToInternalString(), delta, steamID); } public static void Set(string type, int level, string? steamID = null) { UpgradeManager.ApplyAbsolute(type, level, steamID); } public static void Set(UpgradeType type, int level, string? steamID = null) { Set(type.ToInternalString(), level, steamID); } } } namespace REPOUpgradeAPI.Runtime { internal static class UpgradeManager { [CompilerGenerated] private sealed class <GetUpgradeKeys>d__9 : IEnumerable<string>, IEnumerable, IEnumerator<string>, IEnumerator, IDisposable { private int <>1__state; private string <>2__current; private int <>l__initialThreadId; private Dictionary<string, Dictionary<string, int>>.Enumerator <>7__wrap1; string IEnumerator<string>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <GetUpgradeKeys>d__9(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 1) { try { } finally { <>m__Finally1(); } } <>7__wrap1 = default(Dictionary<string, Dictionary<string, int>>.Enumerator); <>1__state = -2; } private bool MoveNext() { try { switch (<>1__state) { default: return false; case 0: { <>1__state = -1; StatsManager instance = StatsManager.instance; if ((Object)(object)instance == (Object)null) { return false; } <>7__wrap1 = instance.dictionaryOfDictionaries.GetEnumerator(); <>1__state = -3; break; } case 1: <>1__state = -3; break; } while (<>7__wrap1.MoveNext()) { KeyValuePair<string, Dictionary<string, int>> current = <>7__wrap1.Current; if (current.Key.StartsWith("playerUpgrade")) { <>2__current = current.Key; <>1__state = 1; return true; } } <>m__Finally1(); <>7__wrap1 = default(Dictionary<string, Dictionary<string, int>>.Enumerator); return false; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; ((IDisposable)<>7__wrap1).Dispose(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator<string> IEnumerable<string>.GetEnumerator() { if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; return this; } return new <GetUpgradeKeys>d__9(0); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<string>)this).GetEnumerator(); } } private static string GetLocalSteamID() { PlayerAvatar val = SemiFunc.PlayerAvatarLocal(); return SemiFunc.PlayerGetSteamID(val); } private static bool IsMultiplayer() { if (SemiFunc.IsMultiplayer() && PhotonNetwork.IsConnected) { return PhotonNetwork.InRoom; } return false; } public static void ApplyDelta(string type, int delta, string? targetSteamID = null) { string text = targetSteamID ?? GetLocalSteamID(); if (!string.IsNullOrEmpty(text)) { if (!IsMultiplayer()) { ApplyDeltaLocal(type, text, delta); RefreshUIIfLocal(text); return; } if (!UpgradeAPI.RpcRegistered) { Logger.CreateLogSource("UpgradeAPI").LogError((object)"[UpgradeAPI] RPC not registered. Call UpgradeAPI.RegisterRPC(PunManager.instance) before using ApplyDelta in multiplayer."); return; } PunManager instance = PunManager.instance; instance.photonView.RPC("QC_ApplyUpgradeRPC", (RpcTarget)0, new object[4] { text, type, delta, false }); } } public static void ApplyAbsolute(string type, int targetLevel, string? targetSteamID = null) { string text = targetSteamID ?? GetLocalSteamID(); if (!string.IsNullOrEmpty(text)) { if (!IsMultiplayer()) { ApplyAbsoluteLocal(type, text, targetLevel); RefreshUIIfLocal(text); return; } if (!UpgradeAPI.RpcRegistered) { Logger.CreateLogSource("UpgradeAPI").LogError((object)"[UpgradeAPI] RPC not registered. Call UpgradeAPI.RegisterRPC(PunManager.instance) before using ApplyAbsolute in multiplayer."); return; } PunManager instance = PunManager.instance; instance.photonView.RPC("QC_ApplyUpgradeRPC", (RpcTarget)0, new object[4] { text, type, targetLevel, true }); } } internal static void ApplyDeltaLocal(string type, string steamID, int delta) { StatsManager instance = StatsManager.instance; PunManager instance2 = PunManager.instance; string text = type.ToLowerInvariant(); if ((Object)(object)instance != (Object)null && instance.dictionaryOfDictionaries.TryGetValue(type, out var value) && value != null) { Dictionary<string, int> dictionary = value; dictionary.TryGetValue(steamID, out var value2); dictionary[steamID] = value2 + delta; REPOUpgradeAPI.Logger.LogInfo((object)$"[UpgradeAPI] Applied by direct dict name: {type} += {delta}"); return; } switch (text) { case "energy": instance2.UpgradePlayerEnergy(steamID, delta); return; case "health": instance2.UpgradePlayerHealth(steamID, delta); return; case "sprint": instance2.UpgradePlayerSprintSpeed(steamID, delta); return; case "crouch": instance2.UpgradePlayerCrouchRest(steamID, delta); return; case "launch": instance2.UpgradePlayerTumbleLaunch(steamID, delta); return; case "climb": instance2.UpgradePlayerTumbleClimb(steamID, delta); return; case "throw": instance2.UpgradePlayerThrowStrength(steamID, delta); return; case "mapcount": instance2.UpgradeMapPlayerCount(steamID, delta); return; case "wings": instance2.UpgradePlayerTumbleWings(steamID, delta); return; case "grabrange": instance2.UpgradePlayerGrabRange(steamID, delta); return; case "grabstr": instance2.UpgradePlayerGrabStrength(steamID, delta); return; case "jump": instance2.UpgradePlayerExtraJump(steamID, delta); return; case "battery": instance2.UpgradeDeathHeadBattery(steamID, delta); return; } if (UpgradeAPI.CustomKeys.Contains(text) && TryApplyDynamicByDictName(text, steamID, delta)) { REPOUpgradeAPI.Logger.LogInfo((object)("[UpgradeAPI] Custom upgrade applied: " + text)); } else if (TryApplyDynamicByScan(text, steamID, delta)) { REPOUpgradeAPI.Logger.LogInfo((object)("[UpgradeAPI] Dynamic upgrade applied: " + text)); } else { REPOUpgradeAPI.Logger.LogWarning((object)("[UpgradeAPI] Unknown upgrade key: " + type)); } } private static bool TryApplyDynamic(string type, string steamID, int delta) { StatsManager instance = StatsManager.instance; if ((Object)(object)instance == (Object)null) { return false; } if (!TryGetStatsDict(type, instance, out Dictionary<string, int> dict)) { return false; } dict.TryGetValue(steamID, out var value); dict[steamID] = value + delta; return true; } private static bool TryGetStatsDict(string type, StatsManager sm, out Dictionary<string, int> dict) { dict = null; if (string.IsNullOrEmpty(type)) { return false; } string text = char.ToUpper(type[0]) + ((type.Length > 1) ? type.Substring(1) : ""); string key = "playerUpgrade" + text; if (sm.dictionaryOfDictionaries.TryGetValue(key, out var value) && value != null) { Dictionary<string, int> dictionary = value; dict = dictionary; return true; } string text2 = type switch { "energy" => "playerUpgradeStamina", "health" => "playerUpgradeHealth", "sprint" => "playerUpgradeSpeed", "crouch" => "playerUpgradeCrouchRest", "launch" => "playerUpgradeLaunch", "climb" => "playerUpgradeTumbleClimb", "throw" => "playerUpgradeThrowStrength", "mapcount" => "playerUpgradeMapPlayerCount", "wings" => "playerUpgradeTumbleWings", "grabrange" => "playerUpgradeRange", "grabstr" => "playerUpgradeStrength", "jump" => "playerUpgradeExtraJump", "battery" => "playerUpgradeDeathHeadBattery", _ => null, }; if (text2 != null && sm.dictionaryOfDictionaries.TryGetValue(text2, out var value2) && value2 != null) { Dictionary<string, int> dictionary2 = value2; dict = dictionary2; return true; } return false; } internal static void ApplyAbsoluteLocal(string type, string steamID, int targetLevel) { StatsManager instance = StatsManager.instance; if (!((Object)(object)instance == (Object)null) && TryGetStatsDict(type, instance, out Dictionary<string, int> dict)) { if (!dict.TryGetValue(steamID, out var value)) { value = 0; } int num = targetLevel - value; if (num != 0) { ApplyDeltaLocal(type, steamID, num); } } } internal static void RefreshUIIfLocal(string steamID) { PlayerAvatar val = SemiFunc.PlayerAvatarLocal(); if (!((Object)(object)val == (Object)null) && !(SemiFunc.PlayerGetSteamID(val) != steamID) && (Object)(object)StatsUI.instance != (Object)null) { StatsUI.instance.Fetch(); StatsUI.instance.ShowStats(); } } [IteratorStateMachine(typeof(<GetUpgradeKeys>d__9))] internal static IEnumerable<string> GetUpgradeKeys() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <GetUpgradeKeys>d__9(-2); } internal static void LogAllUpgradeDictionaries() { StatsManager instance = StatsManager.instance; if ((Object)(object)instance == (Object)null) { REPOUpgradeAPI.Logger.LogError((object)"[UpgradeAPI] StatsManager.instance is null."); return; } REPOUpgradeAPI.Logger.LogInfo((object)"==== StatsManager Upgrade Dictionaries ===="); foreach (KeyValuePair<string, Dictionary<string, int>> dictionaryOfDictionary in instance.dictionaryOfDictionaries) { string key = dictionaryOfDictionary.Key; if (key.StartsWith("playerUpgrade")) { Dictionary<string, int> value = dictionaryOfDictionary.Value; if (value != null) { REPOUpgradeAPI.Logger.LogInfo((object)$"- {key} (count={value.Count})"); } else { REPOUpgradeAPI.Logger.LogInfo((object)("- " + key + " (Not a <string,int> dictionary)")); } } } } internal static bool TryApplyDynamicByScan(string type, string steamID, int delta) { StatsManager instance = StatsManager.instance; if ((Object)(object)instance == (Object)null) { return false; } string value = type.ToLowerInvariant(); foreach (KeyValuePair<string, Dictionary<string, int>> dictionaryOfDictionary in instance.dictionaryOfDictionaries) { string text = dictionaryOfDictionary.Key.ToLowerInvariant(); if (text.Contains("upgrade") && text.Contains(value)) { Dictionary<string, int> value2 = dictionaryOfDictionary.Value; if (value2 != null) { value2.TryGetValue(steamID, out var value3); value2[steamID] = value3 + delta; return true; } } } return false; } private static bool TryApplyDynamicByDictName(string type, string steamID, int delta) { StatsManager instance = StatsManager.instance; if ((Object)(object)instance == (Object)null) { return false; } string key = "playerUpgrade_" + type; if (!instance.dictionaryOfDictionaries.TryGetValue(key, out var value)) { return false; } if (value != null) { Dictionary<string, int> dictionary = value; dictionary.TryGetValue(steamID, out var value2); dictionary[steamID] = value2 + delta; return true; } return false; } } public class UpgradeNet : MonoBehaviourPun { [PunRPC] public void QC_ApplyUpgradeRPC(string steamID, string type, int value, bool isAbsolute, PhotonMessageInfo info) { Log.Debug($"[UpgradeFrameworkNet] RPC ApplyUpgrade steamID={steamID}, type={type}, value={value}, abs={isAbsolute}"); if (!string.IsNullOrEmpty(steamID)) { if (isAbsolute) { UpgradeManager.ApplyAbsoluteLocal(type, steamID, value); } else { UpgradeManager.ApplyDeltaLocal(type, steamID, value); } UpgradeManager.RefreshUIIfLocal(steamID); } } } } namespace REPOUpgradeAPI.Patches { [HarmonyPatch(typeof(PunManager), "Start")] internal class PunManagerStartPatch { private static void Postfix(PunManager __instance) { UpgradeAPI.RegisterRPC(__instance); } } }