using 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+3083ba7252749383238904a42c0162c5ca51283d")] [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 CustomKeys = new HashSet(); 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(); if ((Object)(object)val == (Object)null) { val = gameObject.AddComponent(); } 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(ref upgradeNet)) { gameObject.AddComponent(); 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 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 d__9 : IEnumerable, IEnumerable, IEnumerator, IEnumerator, IDisposable { private int <>1__state; private string <>2__current; private int <>l__initialThreadId; private SortedDictionary>.Enumerator <>7__wrap1; string IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public 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(SortedDictionary>.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> current = <>7__wrap1.Current; if (current.Key.StartsWith("playerUpgrade")) { <>2__current = current.Key; <>1__state = 1; return true; } } <>m__Finally1(); <>7__wrap1 = default(SortedDictionary>.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 IEnumerable.GetEnumerator() { if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; return this; } return new d__9(0); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)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 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 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 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 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 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 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(d__9))] internal static IEnumerable GetUpgradeKeys() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new 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> dictionaryOfDictionary in instance.dictionaryOfDictionaries) { string key = dictionaryOfDictionary.Key; if (key.StartsWith("playerUpgrade")) { Dictionary value = dictionaryOfDictionary.Value; if (value != null) { REPOUpgradeAPI.Logger.LogInfo((object)$"- {key} (count={value.Count})"); } else { REPOUpgradeAPI.Logger.LogInfo((object)("- " + key + " (Not a 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> dictionaryOfDictionary in instance.dictionaryOfDictionaries) { string text = dictionaryOfDictionary.Key.ToLowerInvariant(); if (text.Contains("upgrade") && text.Contains(value)) { Dictionary 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 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); } } }