Decompiled source of ResellYourUpgrades v1.1.0
ResellUpgrades.dll
Decompiled 3 weeks ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Logging; using ExitGames.Client.Photon; using HarmonyLib; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using Photon.Pun; using Photon.Realtime; using ResellUpgrades.Compatibility; using ResellUpgrades.MoreUpgrades; 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: AssemblyTitle("ResellUpgrades")] [assembly: AssemblyDescription("Resell Your Upgrades mod for R.E.P.O.! Developed by Jettcodey.")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Jettcodey")] [assembly: AssemblyProduct("ResellUpgrades")] [assembly: AssemblyCopyright("")] [assembly: ComVisible(false)] [assembly: Guid("c554f22b-0363-47e2-91a8-48d4cf18f033")] [assembly: AssemblyFileVersion("1.1.0")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.1.0.0")] [module: UnverifiableCode] 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; } } } namespace ResellUpgrades { [HarmonyPatch(typeof(DebugCommandHandler))] public static class DebugCommandPatches { [HarmonyPatch("Start")] [HarmonyPostfix] private static void DebugCommandHandler_Start_Postfix(DebugCommandHandler __instance) { //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Expected O, but got Unknown //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Expected O, but got Unknown //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Expected O, but got Unknown //IL_018a: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Expected O, but got Unknown //IL_01e0: Unknown result type (might be due to invalid IL or missing references) //IL_01ea: Expected O, but got Unknown //IL_0236: Unknown result type (might be due to invalid IL or missing references) //IL_0240: Expected O, but got Unknown //IL_028c: Unknown result type (might be due to invalid IL or missing references) //IL_0296: Expected O, but got Unknown //IL_02e2: Unknown result type (might be due to invalid IL or missing references) //IL_02ec: Expected O, but got Unknown //IL_0338: Unknown result type (might be due to invalid IL or missing references) //IL_0342: Expected O, but got Unknown __instance.Register(new ChatCommand("resell", "Resell an upgrade for 50% refund", (Action<bool, string[]>)delegate(bool isDebugConsole, string[] args) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) if (args.Length == 0) { DebugCommandHandler.instance.CommandFailedEffect(); DebugConsoleUI instance17 = DebugConsoleUI.instance; if (instance17 != null) { instance17.SetResponseText("Usage: /resell <upgradeName>", Color.red, 2f); } } else { string text7 = string.Join(' ', args); string playerSteamID2 = PlayerController.instance.playerSteamID; if (ResellManager.ResellUpgrade(text7, playerSteamID2)) { DebugCommandHandler.instance.CommandSuccessEffect(); DebugConsoleUI instance18 = DebugConsoleUI.instance; if (instance18 != null) { instance18.SetResponseText("Resold " + text7 + " successfully!", Color.green, 2f); } } else { DebugCommandHandler.instance.CommandFailedEffect(); DebugConsoleUI instance19 = DebugConsoleUI.instance; if (instance19 != null) { instance19.SetResponseText("Failed to resell " + text7 + ". Check if you have it and are in a shop.", Color.red, 2f); } } } }, (Func<bool, string, string[], List<string>>)delegate(bool isDebugConsole, string partial, string[] args) { if (args.Length > 1) { return new List<string>(); } Dictionary<string, int> availableUpgradesForResell3 = ResellManager.GetAvailableUpgradesForResell(PlayerController.instance.playerSteamID); return (from upgrade in availableUpgradesForResell3 select upgrade.Key into name where args.Length == 0 || name.ToLower().StartsWith(args[0].ToLower()) select name).ToList(); }, (Func<bool>)(() => ResellManager.CanResellUpgrades && (SemiFunc.IsMasterClientOrSingleplayer() || !MultiplayerUpgradesCompatibility.AnySyncedUpgradesModDetected)), false)); __instance.Register(new ChatCommand("resellclienttest", "Test client upgrade removal", (Action<bool, string[]>)delegate(bool isDebugConsole, string[] args) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) if (!PhotonNetwork.IsMasterClient) { DebugConsoleUI instance15 = DebugConsoleUI.instance; if (instance15 != null) { instance15.SetResponseText("This command only works for the host", Color.red, 2f); } DebugCommandHandler.instance.CommandFailedEffect(); } else { string text6 = ((args.Length != 0) ? args[0] : "Health"); UpgradeSyncManager.RemoveUpgradeFromAllPlayers(text6, 100); DebugConsoleUI instance16 = DebugConsoleUI.instance; if (instance16 != null) { instance16.SetResponseText("Tested client removal of " + text6, Color.green, 2f); } DebugCommandHandler.instance.CommandSuccessEffect(); } }, (Func<bool, string, string[], List<string>>)((bool isDebugConsole, string partial, string[] args) => new List<string> { "Health", "Stamina", "Extra Jump", "Speed", "Strength", "Throw", "Range" }), (Func<bool>)(() => MultiplayerUpgradesCompatibility.AnySyncedUpgradesModDetected && PhotonNetwork.IsMasterClient), false)); __instance.Register(new ChatCommand("moddetection", "Show detailed mod detection information", (Action<bool, string[]>)delegate { //IL_0090: Unknown result type (might be due to invalid IL or missing references) string text5 = "Mod Detection Info:\n"; text5 = text5 + MultiplayerUpgradesCompatibility.GetModDetectionInfo() + "\n"; text5 += $"Any Synced Mods: {MultiplayerUpgradesCompatibility.AnySyncedUpgradesModDetected}\n"; text5 += $"Multiplayer: {SemiFunc.IsMultiplayer()}\n"; text5 += $"Is Master Client: {PhotonNetwork.IsMasterClient}\n"; text5 += $"Can Resell: {ResellManager.CanResellUpgrades}\n"; DebugConsoleUI instance14 = DebugConsoleUI.instance; if (instance14 != null) { instance14.SetResponseText(text5, Color.white, 2f); } DebugCommandHandler.instance.CommandSuccessEffect(); }, (Func<bool, string, string[], List<string>>)null, (Func<bool>)(() => true), false)); __instance.Register(new ChatCommand("forcedetect", "Force re-run mod detection", (Action<bool, string[]>)delegate { //IL_005c: Unknown result type (might be due to invalid IL or missing references) FieldInfo field = typeof(MultiplayerUpgradesCompatibility).GetField("_initialized", BindingFlags.Static | BindingFlags.NonPublic); if (field != null) { field.SetValue(null, false); } MultiplayerUpgradesCompatibility.Initialize(); string text4 = "Forced detection complete:\n"; text4 = text4 + MultiplayerUpgradesCompatibility.GetModDetectionInfo() + "\n"; DebugConsoleUI instance13 = DebugConsoleUI.instance; if (instance13 != null) { instance13.SetResponseText(text4, Color.green, 2f); } DebugCommandHandler.instance.CommandSuccessEffect(); }, (Func<bool, string, string[], List<string>>)null, (Func<bool>)(() => true), false)); __instance.Register(new ChatCommand("reselllist", "List available upgrades to resell", (Action<bool, string[]>)delegate { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) Dictionary<string, int> availableUpgradesForResell2 = ResellManager.GetAvailableUpgradesForResell(PlayerController.instance.playerSteamID); if (availableUpgradesForResell2.Count == 0) { DebugConsoleUI instance11 = DebugConsoleUI.instance; if (instance11 != null) { instance11.SetResponseText("No upgrades available to resell", Color.white, 2f); } DebugCommandHandler.instance.CommandFailedEffect(); } else { string text3 = "Available upgrades to resell:\n"; foreach (KeyValuePair<string, int> item in availableUpgradesForResell2) { text3 += $"{item.Key} Resell: {item.Value}\n"; } DebugConsoleUI instance12 = DebugConsoleUI.instance; if (instance12 != null) { instance12.SetResponseText(text3, Color.white, 2f); } DebugCommandHandler.instance.CommandSuccessEffect(); } }, (Func<bool, string, string[], List<string>>)null, (Func<bool>)(() => ResellManager.CanResellUpgrades), false)); __instance.Register(new ChatCommand("moreupgradestest", "Test MoreUpgrades detection and list", (Action<bool, string[]>)delegate { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_01dd: Unknown result type (might be due to invalid IL or missing references) if (!MultiplayerUpgradesCompatibility.MoreUpgradesDetected) { DebugConsoleUI instance9 = DebugConsoleUI.instance; if (instance9 != null) { instance9.SetResponseText("MoreUpgrades not detected", Color.red, 2f); } DebugCommandHandler.instance.CommandFailedEffect(); } else { ResellManager.DetectMoreUpgradesItems(); Dictionary<string, int> availableUpgradesForResell = ResellManager.GetAvailableUpgradesForResell(PlayerController.instance.playerSteamID); string text2 = "MoreUpgrades Detected!\nAvailable upgrades:\n"; int num = 0; foreach (KeyValuePair<string, int> item2 in availableUpgradesForResell) { if (!item2.Key.Contains("Health") && !item2.Key.Contains("Stamina") && !item2.Key.Contains("Speed") && !item2.Key.Contains("Extra Jump") && !item2.Key.Contains("Strength") && !item2.Key.Contains("Throw") && !item2.Key.Contains("Range") && !item2.Key.Contains("Launch") && !item2.Key.Contains("Tumble") && !item2.Key.Contains("Death Head") && !item2.Key.Contains("Map Player Count") && !item2.Key.Contains("Crouch Rest")) { text2 += $"{item2.Key}: Resell: {item2.Value}\n"; num++; } } if (num == 0) { text2 += "No MoreUpgrades items found in your inventory"; } DebugConsoleUI instance10 = DebugConsoleUI.instance; if (instance10 != null) { instance10.SetResponseText(text2, Color.green, 2f); } DebugCommandHandler.instance.CommandSuccessEffect(); } }, (Func<bool, string, string[], List<string>>)null, (Func<bool>)(() => true), false)); __instance.Register(new ChatCommand("debugupgrades", "Debug upgrade detection and mappings", (Action<bool, string[]>)delegate { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0221: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)StatsManager.instance == (Object)null) { DebugConsoleUI instance7 = DebugConsoleUI.instance; if (instance7 != null) { instance7.SetResponseText("StatsManager not available", Color.red, 2f); } } else { string playerSteamID = PlayerController.instance.playerSteamID; Dictionary<string, int> dictionary = StatsManager.instance.FetchPlayerUpgrades(playerSteamID); string text = "Upgrade Debug Info for " + playerSteamID + ":\n\n"; text += $"MoreUpgrades detected: {MultiplayerUpgradesCompatibility.MoreUpgradesDetected}\n"; if (dictionary != null) { text += $"Player upgrades ({dictionary.Count}):\n"; foreach (KeyValuePair<string, int> item3 in dictionary) { text += $" '{item3.Key}': {item3.Value}\n"; } } text += $"\nCommandNameToDisplayName mappings ({ResellManager.CommandNameToDisplayName.Count}):\n"; foreach (KeyValuePair<string, string> item4 in ResellManager.CommandNameToDisplayName) { text = text + " '" + item4.Key + "' -> '" + item4.Value + "'\n"; } text += $"\nUpgradeDisplayNameToInternalName mappings ({ResellManager.UpgradeDisplayNameToInternalName.Count}):\n"; foreach (KeyValuePair<string, string> item5 in ResellManager.UpgradeDisplayNameToInternalName) { text = text + " '" + item5.Key + "' -> '" + item5.Value + "'\n"; } DebugConsoleUI instance8 = DebugConsoleUI.instance; if (instance8 != null) { instance8.SetResponseText(text, Color.white, 2f); } Plugin.Logger.LogInfo((object)text); DebugCommandHandler.instance.CommandSuccessEffect(); } }, (Func<bool, string, string[], List<string>>)null, (Func<bool>)(() => true), false)); __instance.Register(new ChatCommand("forcesyncprices", "Force sync price tracking data (host sends, client requests)", (Action<bool, string[]>)delegate { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) if (PhotonNetwork.IsMasterClient && (Object)(object)ResellPhotonManager.Instance != (Object)null) { ResellPhotonManager.Instance.SyncPriceTrackingData(); DebugConsoleUI instance4 = DebugConsoleUI.instance; if (instance4 != null) { instance4.SetResponseText("Sent price tracking data to all clients", Color.green, 2f); } } else if (!PhotonNetwork.IsMasterClient && (Object)(object)ResellPhotonManager.Instance != (Object)null) { PriceTrackingSync.RequestPriceTrackingData(); DebugConsoleUI instance5 = DebugConsoleUI.instance; if (instance5 != null) { instance5.SetResponseText("Requested price tracking data from host", Color.yellow, 2f); } } else { DebugConsoleUI instance6 = DebugConsoleUI.instance; if (instance6 != null) { instance6.SetResponseText("Not in multiplayer or ResellPhotonManager not available", Color.red, 2f); } } DebugCommandHandler.instance.CommandSuccessEffect(); }, (Func<bool, string, string[], List<string>>)null, (Func<bool>)(() => true), false)); __instance.Register(new ChatCommand("resellgui", "Toggle the resell GUI", (Action<bool, string[]>)delegate { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ResellGUI.Instance == (Object)null) { DebugConsoleUI instance = DebugConsoleUI.instance; if (instance != null) { instance.SetResponseText("Resell GUI not initialized yet", Color.red, 2f); } DebugCommandHandler.instance.CommandFailedEffect(); } else { if (ResellGUI.Instance.IsVisible()) { ResellGUI.Instance.Hide(); DebugConsoleUI instance2 = DebugConsoleUI.instance; if (instance2 != null) { instance2.SetResponseText("Resell GUI hidden", Color.white, 2f); } } else { ResellGUI.Instance.Show(); DebugConsoleUI instance3 = DebugConsoleUI.instance; if (instance3 != null) { instance3.SetResponseText("Resell GUI shown", Color.white, 2f); } } DebugCommandHandler.instance.CommandSuccessEffect(); } }, (Func<bool, string, string[], List<string>>)null, (Func<bool>)(() => true), false)); } } public static class MyPluginInfo { public const string PLUGIN_GUID = "Jettcodey.ResellUpgrades"; public const string PLUGIN_NAME = "Resell Your Upgrades"; public const string PLUGIN_VERSION = "1.1.0"; } public class ResellGUI : MonoBehaviour { [CompilerGenerated] private sealed class <InitializeGUI>d__16 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public ResellGUI <>4__this; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <InitializeGUI>d__16(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Expected O, but got Unknown //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitUntil((Func<bool>)(() => (Object)(object)PlayerController.instance != (Object)null && (Object)(object)StatsManager.instance != (Object)null)); <>1__state = 1; return true; case 1: <>1__state = -1; <>2__current = (object)new WaitForSeconds(0.05f); <>1__state = 2; return true; case 2: <>1__state = -1; <>4__this.CreatePanel(); <>4__this.isInitialized = true; return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private GameObject panel; private bool isVisible = false; private Dictionary<string, GameObject> upgradeButtons = new Dictionary<string, GameObject>(); private Dictionary<string, bool> pendingUpgrades = new Dictionary<string, bool>(); private float lastUpdateTime = 0f; private const float UPDATE_INTERVAL = 2f; private bool isInitialized = false; private GameObject noUpgradesText; private bool updateInProgress = false; private RectTransform contentRect; private RectTransform viewportRect; public static ResellGUI Instance { get; private set; } private void Awake() { if ((Object)(object)Instance != (Object)null && (Object)(object)Instance != (Object)(object)this) { Object.Destroy((Object)(object)((Component)this).gameObject); return; } Instance = this; Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject); ((MonoBehaviour)this).StartCoroutine(InitializeGUI()); } [IteratorStateMachine(typeof(<InitializeGUI>d__16))] private IEnumerator InitializeGUI() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <InitializeGUI>d__16(0) { <>4__this = this }; } private void CreateCompatibilityWarning() { //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) if (!MultiplayerUpgradesCompatibility.AnySyncedUpgradesModDetected) { return; } string resellRestrictionMessage = MultiplayerUpgradesCompatibility.GetResellRestrictionMessage(); if (!string.IsNullOrEmpty(resellRestrictionMessage)) { Transform val = panel.transform.Find("CompatibilityWarning"); if ((Object)(object)val != (Object)null) { Object.Destroy((Object)(object)((Component)val).gameObject); } GameObject val2 = CreateHeaderText(panel.transform, resellRestrictionMessage, 14, new Vector2(0f, 0.85f), Color.yellow); ((Object)val2).name = "CompatibilityWarning"; TextMeshProUGUI component = val2.GetComponent<TextMeshProUGUI>(); if ((Object)(object)component != (Object)null) { ((TMP_Text)component).fontStyle = (FontStyles)1; ((TMP_Text)component).alignment = (TextAlignmentOptions)514; ((Graphic)component).color = new Color(1f, 0.8f, 0f, 1f); } } } private void CreatePanel() { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Expected O, but got Unknown //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: Unknown result type (might be due to invalid IL or missing references) //IL_01e3: Unknown result type (might be due to invalid IL or missing references) //IL_01e8: Unknown result type (might be due to invalid IL or missing references) //IL_0225: Unknown result type (might be due to invalid IL or missing references) //IL_022c: Expected O, but got Unknown //IL_025a: Unknown result type (might be due to invalid IL or missing references) //IL_0271: Unknown result type (might be due to invalid IL or missing references) //IL_027e: Unknown result type (might be due to invalid IL or missing references) //IL_028b: Unknown result type (might be due to invalid IL or missing references) //IL_0298: Unknown result type (might be due to invalid IL or missing references) //IL_02c2: Unknown result type (might be due to invalid IL or missing references) //IL_032c: Unknown result type (might be due to invalid IL or missing references) //IL_0333: Expected O, but got Unknown //IL_035b: Unknown result type (might be due to invalid IL or missing references) //IL_0376: Unknown result type (might be due to invalid IL or missing references) //IL_0387: Unknown result type (might be due to invalid IL or missing references) //IL_0398: Unknown result type (might be due to invalid IL or missing references) //IL_03a9: Unknown result type (might be due to invalid IL or missing references) //IL_03cc: Unknown result type (might be due to invalid IL or missing references) //IL_03d3: Expected O, but got Unknown //IL_0405: Unknown result type (might be due to invalid IL or missing references) //IL_0420: Unknown result type (might be due to invalid IL or missing references) //IL_043b: Unknown result type (might be due to invalid IL or missing references) //IL_044c: Unknown result type (might be due to invalid IL or missing references) //IL_0467: Unknown result type (might be due to invalid IL or missing references) //IL_0478: Unknown result type (might be due to invalid IL or missing references) //IL_04c3: Unknown result type (might be due to invalid IL or missing references) //IL_04cd: Expected O, but got Unknown //IL_050e: Unknown result type (might be due to invalid IL or missing references) //IL_0515: Expected O, but got Unknown //IL_053f: Unknown result type (might be due to invalid IL or missing references) //IL_0556: Unknown result type (might be due to invalid IL or missing references) //IL_056d: Unknown result type (might be due to invalid IL or missing references) //IL_0584: Unknown result type (might be due to invalid IL or missing references) //IL_0591: Unknown result type (might be due to invalid IL or missing references) //IL_05bb: Unknown result type (might be due to invalid IL or missing references) //IL_05f0: Unknown result type (might be due to invalid IL or missing references) //IL_05f7: Expected O, but got Unknown //IL_0617: Unknown result type (might be due to invalid IL or missing references) //IL_0624: Unknown result type (might be due to invalid IL or missing references) //IL_0631: Unknown result type (might be due to invalid IL or missing references) //IL_063e: Unknown result type (might be due to invalid IL or missing references) //IL_0668: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("ResellCanvas", new Type[3] { typeof(Canvas), typeof(CanvasScaler), typeof(GraphicRaycaster) }); val.transform.SetParent(((Component)this).transform, false); Canvas component = val.GetComponent<Canvas>(); component.renderMode = (RenderMode)0; component.sortingOrder = 9999; CanvasScaler component2 = val.GetComponent<CanvasScaler>(); component2.uiScaleMode = (ScaleMode)1; component2.referenceResolution = new Vector2(1920f, 1080f); component2.matchWidthOrHeight = 0.5f; panel = new GameObject("ResellPanel", new Type[2] { typeof(Image), typeof(RectTransform) }); panel.transform.SetParent(val.transform, false); Image component3 = panel.GetComponent<Image>(); ((Graphic)component3).color = new Color(0.08f, 0.08f, 0.08f, 0.85f); RectTransform component4 = panel.GetComponent<RectTransform>(); component4.anchorMin = new Vector2(0f, 0.15f); component4.anchorMax = new Vector2(0f, 0.75f); component4.pivot = new Vector2(0f, 0.5f); component4.sizeDelta = new Vector2(420f, 0f); component4.anchoredPosition = new Vector2(16f, 0f); ((Transform)component4).localScale = Vector3.one; CreateHeaderText(panel.transform, "RESELL UPGRADES", 26, new Vector2(0f, 0.94f), Color.white); CreateHeaderText(panel.transform, "Press F6 to toggle Click to resell for 50% refund", 12, new Vector2(0f, 0.88f), Color.yellow); GameObject val2 = new GameObject("UpgradesScroll", new Type[3] { typeof(RectTransform), typeof(Image), typeof(ScrollRect) }); val2.transform.SetParent(panel.transform, false); RectTransform component5 = val2.GetComponent<RectTransform>(); component5.anchorMin = new Vector2(0.03f, 0.06f); component5.anchorMax = new Vector2(0.97f, 0.82f); component5.offsetMin = Vector2.zero; component5.offsetMax = Vector2.zero; ((Transform)component5).localScale = Vector3.one; Image component6 = val2.GetComponent<Image>(); ((Graphic)component6).color = new Color(0.05f, 0.05f, 0.05f, 0f); ScrollRect component7 = val2.GetComponent<ScrollRect>(); component7.horizontal = false; component7.vertical = true; component7.scrollSensitivity = 20f; component7.movementType = (MovementType)2; component7.inertia = true; GameObject val3 = new GameObject("Viewport", new Type[2] { typeof(RectTransform), typeof(RectMask2D) }); val3.transform.SetParent(val2.transform, false); viewportRect = val3.GetComponent<RectTransform>(); viewportRect.anchorMin = Vector2.zero; viewportRect.anchorMax = new Vector2(0.95f, 1f); viewportRect.offsetMin = Vector2.zero; viewportRect.offsetMax = Vector2.zero; ((Transform)viewportRect).localScale = Vector3.one; GameObject val4 = new GameObject("Content", new Type[1] { typeof(RectTransform) }); val4.transform.SetParent(val3.transform, false); contentRect = val4.GetComponent<RectTransform>(); contentRect.anchorMin = new Vector2(0f, 1f); contentRect.anchorMax = new Vector2(1f, 1f); contentRect.pivot = new Vector2(0.5f, 1f); contentRect.anchoredPosition = Vector2.zero; contentRect.sizeDelta = new Vector2(0f, 100f); ((Transform)contentRect).localScale = Vector3.one; VerticalLayoutGroup val5 = val4.AddComponent<VerticalLayoutGroup>(); ((HorizontalOrVerticalLayoutGroup)val5).childForceExpandHeight = false; ((HorizontalOrVerticalLayoutGroup)val5).childControlHeight = true; ((HorizontalOrVerticalLayoutGroup)val5).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)val5).childForceExpandWidth = true; ((HorizontalOrVerticalLayoutGroup)val5).spacing = 8f; ((LayoutGroup)val5).padding = new RectOffset(8, 8, 8, 8); ContentSizeFitter val6 = val4.AddComponent<ContentSizeFitter>(); val6.verticalFit = (FitMode)2; val6.horizontalFit = (FitMode)0; GameObject val7 = new GameObject("Scrollbar", new Type[2] { typeof(Image), typeof(Scrollbar) }); val7.transform.SetParent(val2.transform, false); RectTransform component8 = val7.GetComponent<RectTransform>(); component8.anchorMin = new Vector2(0.95f, 0f); component8.anchorMax = new Vector2(1f, 1f); component8.pivot = new Vector2(1f, 0.5f); component8.sizeDelta = new Vector2(2f, 0f); component8.anchoredPosition = Vector2.zero; Image component9 = val7.GetComponent<Image>(); ((Graphic)component9).color = new Color(0.2f, 0.2f, 0.2f, 0.8f); Scrollbar component10 = val7.GetComponent<Scrollbar>(); component10.direction = (Direction)2; GameObject val8 = new GameObject("Handle", new Type[1] { typeof(Image) }); val8.transform.SetParent(val7.transform, false); RectTransform component11 = val8.GetComponent<RectTransform>(); component11.anchorMin = Vector2.zero; component11.anchorMax = Vector2.one; component11.sizeDelta = Vector2.zero; component11.anchoredPosition = Vector2.zero; Image component12 = val8.GetComponent<Image>(); ((Graphic)component12).color = new Color(0.5f, 0.5f, 0.5f, 0.8f); component10.handleRect = component11; ((Selectable)component10).targetGraphic = (Graphic)(object)component12; component7.viewport = viewportRect; component7.content = contentRect; component7.verticalScrollbar = component10; component7.verticalScrollbarVisibility = (ScrollbarVisibility)0; noUpgradesText = CreateCenteredText(panel.transform, "No upgrades available to resell", 14); noUpgradesText.SetActive(false); panel.SetActive(false); } private GameObject CreateHeaderText(Transform parent, string text, int fontSize, Vector2 anchoredPos, Color color) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Header_" + text, new Type[1] { typeof(RectTransform) }); val.transform.SetParent(parent, false); RectTransform component = val.GetComponent<RectTransform>(); component.anchorMin = new Vector2(0.03f, anchoredPos.y - 0.02f); component.anchorMax = new Vector2(0.97f, anchoredPos.y + 0.02f); component.offsetMin = Vector2.zero; component.offsetMax = Vector2.zero; ((Transform)component).localScale = Vector3.one; TextMeshProUGUI val2 = val.AddComponent<TextMeshProUGUI>(); ((TMP_Text)val2).text = text; ((TMP_Text)val2).fontSize = fontSize; ((Graphic)val2).color = color; ((TMP_Text)val2).alignment = (TextAlignmentOptions)514; ((TMP_Text)val2).enableAutoSizing = true; ((TMP_Text)val2).fontSizeMin = Mathf.Max(10, fontSize / 2); ((TMP_Text)val2).fontSizeMax = fontSize; return val; } private GameObject CreateCenteredText(Transform parent, string text, int fontSize) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("CenteredText", new Type[1] { typeof(RectTransform) }); val.transform.SetParent(parent, false); RectTransform component = val.GetComponent<RectTransform>(); component.anchorMin = new Vector2(0.05f, 0.02f); component.anchorMax = new Vector2(0.95f, 0.06f); component.offsetMin = Vector2.zero; component.offsetMax = Vector2.zero; ((Transform)component).localScale = Vector3.one; TextMeshProUGUI val2 = val.AddComponent<TextMeshProUGUI>(); ((TMP_Text)val2).text = text; ((TMP_Text)val2).fontSize = fontSize; ((Graphic)val2).color = Color.gray; ((TMP_Text)val2).alignment = (TextAlignmentOptions)514; ((TMP_Text)val2).enableAutoSizing = true; return val; } private void ClearUpgradeButtons() { foreach (KeyValuePair<string, GameObject> upgradeButton in upgradeButtons) { if ((Object)(object)upgradeButton.Value != (Object)null) { Object.Destroy((Object)(object)upgradeButton.Value); } } upgradeButtons.Clear(); } private void UpdateUpgradeList() { if (!IsVisible() || updateInProgress) { return; } updateInProgress = true; Plugin.Logger.LogInfo((object)$"UpdateUpgradeList: AnySyncedUpgradesModDetected = {MultiplayerUpgradesCompatibility.AnySyncedUpgradesModDetected}"); Plugin.Logger.LogInfo((object)$"UpdateUpgradeList: IsMasterClient = {PhotonNetwork.IsMasterClient}"); CreateCompatibilityWarning(); string text = PlayerController.instance?.playerSteamID; if (string.IsNullOrEmpty(text)) { updateInProgress = false; return; } Dictionary<string, int> availableUpgradesForResell = ResellManager.GetAvailableUpgradesForResell(text); ClearUpgradeButtons(); if ((Object)(object)contentRect == (Object)null) { updateInProgress = false; return; } int num = 0; foreach (KeyValuePair<string, int> item in availableUpgradesForResell) { CreateUpgradeButton(item.Key, item.Value, num); num++; } noUpgradesText.SetActive(availableUpgradesForResell.Count == 0); updateInProgress = false; } private void CreateUpgradeButton(string upgradeName, int resellValue, int index) { //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Expected O, but got Unknown //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Expected O, but got Unknown //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Expected O, but got Unknown //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_01ce: Unknown result type (might be due to invalid IL or missing references) //IL_01db: Unknown result type (might be due to invalid IL or missing references) //IL_023d: Unknown result type (might be due to invalid IL or missing references) //IL_0260: Unknown result type (might be due to invalid IL or missing references) //IL_0267: Expected O, but got Unknown //IL_0290: Unknown result type (might be due to invalid IL or missing references) //IL_02a7: Unknown result type (might be due to invalid IL or missing references) //IL_02be: Unknown result type (might be due to invalid IL or missing references) //IL_02d5: Unknown result type (might be due to invalid IL or missing references) //IL_02e2: Unknown result type (might be due to invalid IL or missing references) //IL_0333: Unknown result type (might be due to invalid IL or missing references) //IL_0370: Unknown result type (might be due to invalid IL or missing references) //IL_0377: Expected O, but got Unknown //IL_03a0: Unknown result type (might be due to invalid IL or missing references) //IL_03b7: Unknown result type (might be due to invalid IL or missing references) //IL_03ce: Unknown result type (might be due to invalid IL or missing references) //IL_03e5: Unknown result type (might be due to invalid IL or missing references) //IL_03fc: Unknown result type (might be due to invalid IL or missing references) //IL_0409: Unknown result type (might be due to invalid IL or missing references) //IL_0433: Unknown result type (might be due to invalid IL or missing references) //IL_0455: Unknown result type (might be due to invalid IL or missing references) //IL_045f: Expected O, but got Unknown //IL_0478: Unknown result type (might be due to invalid IL or missing references) //IL_047f: Expected O, but got Unknown //IL_049f: Unknown result type (might be due to invalid IL or missing references) //IL_04ac: Unknown result type (might be due to invalid IL or missing references) //IL_04b9: Unknown result type (might be due to invalid IL or missing references) //IL_04c6: Unknown result type (might be due to invalid IL or missing references) //IL_04d3: Unknown result type (might be due to invalid IL or missing references) //IL_0519: Unknown result type (might be due to invalid IL or missing references) string upgradeName2 = upgradeName; if (!((Object)(object)contentRect == (Object)null)) { GameObject val = new GameObject("Button_" + upgradeName2, new Type[2] { typeof(RectTransform), typeof(Image) }); val.transform.SetParent((Transform)(object)contentRect, false); RectTransform component = val.GetComponent<RectTransform>(); component.anchorMin = new Vector2(0f, 1f); component.anchorMax = new Vector2(1f, 1f); component.pivot = new Vector2(0.5f, 1f); ((Transform)component).localScale = Vector3.one; Image component2 = val.GetComponent<Image>(); ((Graphic)component2).color = new Color(0.18f, 0.18f, 0.18f, 0.95f); LayoutElement val2 = val.AddComponent<LayoutElement>(); val2.minHeight = 44f; val2.preferredHeight = 44f; val2.flexibleWidth = 1f; Button val3 = val.AddComponent<Button>(); ((UnityEvent)val3.onClick).AddListener((UnityAction)delegate { OnUpgradeClicked(upgradeName2); }); GameObject val4 = new GameObject("Name", new Type[1] { typeof(RectTransform) }); val4.transform.SetParent(val.transform, false); RectTransform component3 = val4.GetComponent<RectTransform>(); component3.anchorMin = new Vector2(0f, 0f); component3.anchorMax = new Vector2(0.62f, 1f); component3.offsetMin = new Vector2(8f, 6f); component3.offsetMax = new Vector2(-4f, -6f); ((Transform)component3).localScale = Vector3.one; TextMeshProUGUI val5 = val4.AddComponent<TextMeshProUGUI>(); ((TMP_Text)val5).text = $"{upgradeName2} (Level {GetPlayerUpgradeLevel(upgradeName2)})"; ((TMP_Text)val5).enableAutoSizing = true; ((TMP_Text)val5).fontSizeMax = 16f; ((TMP_Text)val5).alignment = (TextAlignmentOptions)513; ((Graphic)val5).color = Color.white; GameObject val6 = new GameObject("Value", new Type[1] { typeof(RectTransform) }); val6.transform.SetParent(val.transform, false); RectTransform component4 = val6.GetComponent<RectTransform>(); component4.anchorMin = new Vector2(0.62f, 0f); component4.anchorMax = new Vector2(0.86f, 1f); component4.offsetMin = new Vector2(4f, 6f); component4.offsetMax = new Vector2(-4f, -6f); ((Transform)component4).localScale = Vector3.one; TextMeshProUGUI val7 = val6.AddComponent<TextMeshProUGUI>(); ((TMP_Text)val7).text = $"+{resellValue}K $"; ((TMP_Text)val7).enableAutoSizing = true; ((TMP_Text)val7).fontSizeMax = 16f; ((TMP_Text)val7).alignment = (TextAlignmentOptions)514; ((Graphic)val7).color = Color.green; GameObject val8 = new GameObject("SellButton", new Type[3] { typeof(RectTransform), typeof(Image), typeof(Button) }); val8.transform.SetParent(val.transform, false); RectTransform component5 = val8.GetComponent<RectTransform>(); component5.anchorMin = new Vector2(0.86f, 0f); component5.anchorMax = new Vector2(1f, 1f); component5.offsetMin = new Vector2(4f, 6f); component5.offsetMax = new Vector2(-8f, -6f); component5.sizeDelta = new Vector2(4f, 0.8f); ((Transform)component5).localScale = Vector3.one; Image component6 = val8.GetComponent<Image>(); ((Graphic)component6).color = new Color(0.78f, 0.22f, 0.22f, 0.95f); Button component7 = val8.GetComponent<Button>(); ((UnityEvent)component7.onClick).AddListener((UnityAction)delegate { OnUpgradeClicked(upgradeName2); }); GameObject val9 = new GameObject("SellText", new Type[1] { typeof(RectTransform) }); val9.transform.SetParent(val8.transform, false); RectTransform component8 = val9.GetComponent<RectTransform>(); component8.anchorMin = Vector2.zero; component8.anchorMax = Vector2.one; component8.offsetMin = Vector2.zero; component8.offsetMax = Vector2.zero; ((Transform)component8).localScale = Vector3.one; TextMeshProUGUI val10 = val9.AddComponent<TextMeshProUGUI>(); ((TMP_Text)val10).text = "SELL"; ((TMP_Text)val10).enableAutoSizing = true; ((TMP_Text)val10).fontSizeMax = 14f; ((TMP_Text)val10).alignment = (TextAlignmentOptions)514; ((Graphic)val10).color = Color.white; upgradeButtons[upgradeName2] = val; } } private int GetPlayerUpgradeLevel(string displayCommandName) { string text = ResellManager.ConvertCommandToUpgradeKey(displayCommandName); Dictionary<string, int> dictionary = StatsManager.instance.FetchPlayerUpgrades(PlayerController.instance.playerSteamID); if (dictionary == null) { return 0; } if (dictionary.TryGetValue(text, out var value)) { return value; } string b = ResellManager.NormalizeSpaces(text); foreach (KeyValuePair<string, int> item in dictionary) { string a = ResellManager.NormalizeSpaces(item.Key); if (string.Equals(a, b, StringComparison.OrdinalIgnoreCase)) { return item.Value; } } return 0; } private void OnUpgradeClicked(string upgradeName) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) string playerSteamID = PlayerController.instance.playerSteamID; if (pendingUpgrades.ContainsKey(upgradeName) && pendingUpgrades[upgradeName]) { DebugConsoleUI instance = DebugConsoleUI.instance; if (instance != null) { instance.SetResponseText("Resell of " + upgradeName + " already pending...", Color.yellow, 2f); } return; } if (SemiFunc.IsMultiplayer() && !PhotonNetwork.IsMasterClient && !MultiplayerUpgradesCompatibility.AnySyncedUpgradesModDetected) { pendingUpgrades[upgradeName] = true; if (upgradeButtons.ContainsKey(upgradeName) && (Object)(object)upgradeButtons[upgradeName] != (Object)null) { Button component = upgradeButtons[upgradeName].GetComponent<Button>(); if ((Object)(object)component != (Object)null) { Image component2 = ((Component)component).GetComponent<Image>(); if ((Object)(object)component2 != (Object)null) { ((Graphic)component2).color = new Color(0.3f, 0.3f, 0.3f, 0.7f); } Transform obj = ((Component)component).transform.Find("Name"); TextMeshProUGUI val = ((obj != null) ? ((Component)obj).GetComponent<TextMeshProUGUI>() : null); if ((Object)(object)val != (Object)null) { ((TMP_Text)val).text = upgradeName + " (Pending...)"; } } } } if (ResellManager.ResellUpgrade(upgradeName, playerSteamID)) { if (PhotonNetwork.IsMasterClient || !SemiFunc.IsMultiplayer()) { UpdateUpgradeList(); } } else { pendingUpgrades[upgradeName] = false; UpdateUpgradeList(); } } public void ClearPendingState(string upgradeName) { if (string.IsNullOrEmpty(upgradeName)) { List<string> list = new List<string>(); foreach (KeyValuePair<string, bool> pendingUpgrade in pendingUpgrades) { if (pendingUpgrade.Value) { list.Add(pendingUpgrade.Key); } } foreach (string item in list) { pendingUpgrades[item] = false; } } else if (pendingUpgrades.ContainsKey(upgradeName)) { pendingUpgrades[upgradeName] = false; } UpdateUpgradeList(); } public void Show() { if (isInitialized && !((Object)(object)panel == (Object)null)) { panel.SetActive(true); isVisible = true; UpdateUpgradeList(); Cursor.visible = true; Cursor.lockState = (CursorLockMode)0; } } public void Hide() { if (isInitialized && !((Object)(object)panel == (Object)null)) { panel.SetActive(false); isVisible = false; Cursor.visible = false; Cursor.lockState = (CursorLockMode)1; } } public bool IsVisible() { return isInitialized && isVisible && (Object)(object)panel != (Object)null && panel.activeSelf; } private void Update() { if (!isInitialized) { return; } if (IsVisible() && ResellManager.CanResellUpgrades) { if (Time.time - lastUpdateTime >= 2f) { UpdateUpgradeList(); lastUpdateTime = Time.time; } } else if (IsVisible() && !ResellManager.CanResellUpgrades) { Hide(); } if (IsVisible() && Input.GetKeyDown((KeyCode)27)) { Hide(); } if (ResellManager.CanResellUpgrades && Input.GetKeyDown((KeyCode)287)) { if (IsVisible()) { Hide(); } else { Show(); } } } } public static class ResellManager { public static float ResellRatio = 0.5f; public static Dictionary<string, string> UpgradeDisplayNameToInternalName = new Dictionary<string, string> { { "Health Upgrade", "Item Upgrade Player Health" }, { "Stamina Upgrade", "Item Upgrade Player Energy" }, { "Extra Jump Upgrade", "Item Upgrade Player Extra Jump" }, { "Tumble Launch Upgrade", "Item Upgrade Player Tumble Launch" }, { "Tumble Climb Upgrade", "Item Upgrade Player Tumble Climb" }, { "Death Head Battery Upgrade", "Item Upgrade Death Head Battery" }, { "Map Player Count Upgrade", "Item Upgrade Map Player Count" }, { "Sprint Speed Upgrade", "Item Upgrade Player Sprint Speed" }, { "Strength Upgrade", "Item Upgrade Player Grab Strength" }, { "Throw Strength Upgrade", "Item Upgrade Player Throw Strength" }, { "Range Upgrade", "Item Upgrade Player Grab Range" }, { "Crouch Rest Upgrade", "Item Upgrade Player Crouch Rest" }, { "Tumble Wings Upgrade", "Item Upgrade Player Tumble Wings" }, { "Sprint Usage Upgrade", "Modded Item Upgrade Player Sprint Usage" }, { "Valuable Count Upgrade", "Modded Item Upgrade Player Valuable Count" }, { "Map Enemy Tracker Upgrade", "Modded Item Upgrade Player Map Enemy Tracker" }, { "Map Player Tracker Upgrade", "Modded Item Upgrade Player Map Player Tracker" }, { "Item Resist Upgrade", "Modded Item Upgrade Player Item Resist" }, { "Map Zoom Upgrade", "Modded Item Upgrade Player Map Zoom" }, { "Autoscan Upgrade", "Modded Item Upgrade Player Autoscan" }, { "Item Value Upgrade", "Modded Item Upgrade Player Item Value" }, { "Extra Life Upgrade", "Modded Item Upgrade Player Extra Life" } }; public static Dictionary<string, string> CommandNameToDisplayName = new Dictionary<string, string> { { "Health", "Health Upgrade" }, { "Stamina", "Stamina Upgrade" }, { "Extra Jump", "Extra Jump Upgrade" }, { "Launch", "Tumble Launch Upgrade" }, { "Tumble Climb", "Tumble Climb Upgrade" }, { "Death Head Battery", "Death Head Battery Upgrade" }, { "Map Player Count", "Map Player Count Upgrade" }, { "Speed", "Sprint Speed Upgrade" }, { "Strength", "Strength Upgrade" }, { "Throw", "Throw Strength Upgrade" }, { "Range", "Range Upgrade" }, { "Crouch Rest", "Crouch Rest Upgrade" }, { "Tumble Wings", "Tumble Wings Upgrade" }, { "Sprint Usage", "Sprint Usage Upgrade" }, { "Valuable Count", "Valuable Count Upgrade" }, { "Map Enemy Tracker", "Map Enemy Tracker Upgrade" }, { "Map Player Tracker", "Map Player Tracker Upgrade" }, { "Item Resist", "Item Resist Upgrade" }, { "Map Zoom", "Map Zoom Upgrade" }, { "Autoscan", "Autoscan Upgrade" }, { "Item Value", "Item Value Upgrade" }, { "Extra Life", "Extra Life Upgrade" } }; private static bool _compatibilityInitialized = false; private static bool _moreUpgradesDetected = false; public static bool CanResellUpgrades => (SemiFunc.RunIsShop() && SemiFunc.RunIsLobby()) || ((Object)(object)RunManager.instance != (Object)null && RunManager.instance.levelIsShop && Object.op_Implicit((Object)(object)RunManager.instance.levelLobby)); public static bool TryGetUpgradeInternalName(string name, out string internalName) { internalName = null; string key = ConvertCommandToUpgradeKey(name); if (CommandNameToDisplayName.TryGetValue(key, out string value)) { return UpgradeDisplayNameToInternalName.TryGetValue(value, out internalName); } return false; } public static int CalculateResellValue(string internalName, int currentUpgradeLevel) { try { if (string.IsNullOrEmpty(internalName) || (Object)(object)StatsManager.instance == (Object)null) { return 0; } if (StatsManager.instance.itemDictionary.TryGetValue(internalName, out var value)) { float baseItemValue = GetBaseItemValue(value); float num = CalculateCurrentUpgradeValue(value, baseItemValue, Mathf.Max(0, currentUpgradeLevel - 1)); return Mathf.RoundToInt(num * ResellRatio); } } catch (Exception ex) { Plugin.Logger.LogError((object)("Error calculating resell value: " + ex.Message)); } return 0; } private static float GetBaseItemValue(Item item) { if ((Object)(object)item == (Object)null || (Object)(object)ShopManager.instance == (Object)null) { return 0f; } return item.value.valueMax / 1000f * ShopManager.instance.itemValueMultiplier; } private static float CalculateCurrentUpgradeValue(Item item, float baseValue, int upgradeLevel) { if ((Object)(object)item == (Object)null || (Object)(object)ShopManager.instance == (Object)null || (Object)(object)GameDirector.instance == (Object)null) { return 0f; } float num = baseValue; int num2 = GameDirector.instance.PlayerList?.Count ?? 1; num -= num * 0.1f * (float)(num2 - 1); num += num * ShopManager.instance.upgradeValueIncrease * (float)upgradeLevel; return Mathf.Ceil(num); } public static bool CanResellUpgrade(string commandName, string steamID) { if (!CanResellUpgrades) { return false; } if (!_compatibilityInitialized) { MultiplayerUpgradesCompatibility.Initialize(); _compatibilityInitialized = true; } if (!MultiplayerUpgradesCompatibility.CanPlayerResell(steamID)) { Plugin.Logger.LogWarning((object)("Player " + steamID + " cannot resell due to compatibility restrictions")); return false; } if (string.IsNullOrEmpty(commandName) || (Object)(object)StatsManager.instance == (Object)null) { return false; } string text = ConvertCommandToUpgradeKey(commandName); if (!CommandNameToDisplayName.ContainsKey(text)) { Plugin.Logger.LogWarning((object)("Cannot resell: No mapping for command " + commandName + " (converted to " + text + ")")); return false; } Dictionary<string, int> dictionary = StatsManager.instance.FetchPlayerUpgrades(steamID); if (dictionary == null) { return false; } bool flag = false; if (dictionary.ContainsKey(text)) { flag = dictionary[text] > 0; } if (!flag) { string b = NormalizeSpaces(text); foreach (KeyValuePair<string, int> item in dictionary) { string a = NormalizeSpaces(item.Key); if (string.Equals(a, b, StringComparison.OrdinalIgnoreCase)) { flag = item.Value > 0; break; } } } return flag; } public static bool ResellUpgrade(string commandName, string steamID) { //IL_0463: Unknown result type (might be due to invalid IL or missing references) if (!_compatibilityInitialized) { MultiplayerUpgradesCompatibility.Initialize(); _compatibilityInitialized = true; } if (SemiFunc.IsMultiplayer() && !MultiplayerUpgradesCompatibility.AnySyncedUpgradesModDetected) { ResellPhotonManager.Ensure(); } if (!MultiplayerUpgradesCompatibility.CanPlayerResell(steamID)) { string resellRestrictionMessage = MultiplayerUpgradesCompatibility.GetResellRestrictionMessage(); if (!string.IsNullOrEmpty(resellRestrictionMessage)) { Plugin.Logger.LogWarning((object)resellRestrictionMessage); } return false; } Plugin.Logger.LogInfo((object)("Attempting to resell " + commandName + " for player " + steamID)); if (!CanResellUpgrade(commandName, steamID)) { Plugin.Logger.LogWarning((object)("Cannot resell upgrade " + commandName)); return false; } if (!TryGetUpgradeInternalName(commandName, out string internalName)) { Plugin.Logger.LogWarning((object)("No internal name mapping for command " + commandName)); return false; } Dictionary<string, int> dictionary = StatsManager.instance.FetchPlayerUpgrades(steamID); string text = ConvertCommandToUpgradeKey(commandName); string upgradeKey = text; int num = 0; if (dictionary.ContainsKey(text)) { num = dictionary[text]; } else { string b = NormalizeSpaces(text); foreach (KeyValuePair<string, int> item in dictionary) { string a = NormalizeSpaces(item.Key); if (string.Equals(a, b, StringComparison.OrdinalIgnoreCase)) { upgradeKey = item.Key; num = item.Value; break; } } } if (num <= 0) { Plugin.Logger.LogWarning((object)("Player has level 0 for " + commandName + ", cannot resell")); return false; } if (num <= 0) { Plugin.Logger.LogWarning((object)("Player has level 0 for " + commandName + ", cannot resell")); return false; } int num2 = CalculateResellValue(internalName, num); string upgradeDictionaryName = GetUpgradeDictionaryName(text); if (string.IsNullOrEmpty(upgradeDictionaryName) || !StatsManager.instance.dictionaryOfDictionaries.ContainsKey(upgradeDictionaryName)) { upgradeDictionaryName = GetUpgradeDictionaryName(upgradeKey); if (string.IsNullOrEmpty(upgradeDictionaryName) || !StatsManager.instance.dictionaryOfDictionaries.ContainsKey(upgradeDictionaryName)) { Plugin.Logger.LogWarning((object)("No dictionary found for upgrade " + commandName + " (" + text + ")")); return false; } } Plugin.Logger.LogInfo((object)$"Reselling {commandName}: Level {num} -> {num - 1}, Value: {num2}"); if (SemiFunc.IsMultiplayer()) { if (MultiplayerUpgradesCompatibility.AnySyncedUpgradesModDetected) { if (!PhotonNetwork.IsMasterClient) { Plugin.Logger.LogWarning((object)"Only host can resell when using multiplayer upgrade sync mods"); return false; } UpgradeSyncManager.RemoveUpgradeFromAllPlayers(text, num2); } else { if (!PhotonNetwork.IsMasterClient) { if ((Object)(object)ResellPhotonManager.Instance != (Object)null) { ResellPhotonManager.Instance.SendResellRequest(text, steamID, num, num2); if ((Object)(object)DebugConsoleUI.instance != (Object)null) { DebugConsoleUI.instance.SetResponseText("Requesting resell of " + commandName + "...", Color.yellow, 2f); } return true; } Plugin.Logger.LogError((object)"ResellPhotonManager not available"); return false; } int num3 = StatsManager.instance.runStats["currency"]; StatsManager.instance.dictionaryOfDictionaries[upgradeDictionaryName][steamID] = num - 1; StatsManager.instance.runStats["currency"] += num2; Plugin.Logger.LogInfo((object)string.Format("Host resell - Currency: {0} -> {1} (+{2})", num3, StatsManager.instance.runStats["currency"], num2)); PunManager.instance.UpdateStat(upgradeDictionaryName, steamID, num - 1); PunManager.instance.SetRunStatSet("currency", StatsManager.instance.runStats["currency"]); ApplyImmediateStatChanges(commandName, steamID, -1); } } else { int num4 = StatsManager.instance.runStats["currency"]; StatsManager.instance.dictionaryOfDictionaries[upgradeDictionaryName][steamID] = num - 1; StatsManager.instance.runStats["currency"] += num2; Plugin.Logger.LogInfo((object)string.Format("Currency: {0} -> {1} (+{2})", num4, StatsManager.instance.runStats["currency"], num2)); ApplyImmediateStatChanges(commandName, steamID, -1); } if ((Object)(object)StatsUI.instance != (Object)null) { StatsUI.instance.Fetch(); } return true; } public static void RequestCurrencyUpdate(int amount) { if (SemiFunc.IsMultiplayer() && !PhotonNetwork.IsMasterClient) { Plugin.Logger.LogInfo((object)$"Client requesting currency update: +{amount}"); } } public static string ConvertCommandToUpgradeKey(string commandName) { if (string.IsNullOrEmpty(commandName)) { return commandName; } switch (commandName) { case "Launch": case "Tumble Launch": return "Launch"; case "Speed": case "Sprint Speed": return "Speed"; case "Throw": case "Throw Strength": return "Throw"; default: return commandName; } } public static string GetUpgradeDictionaryName(string upgradeKey) { if (string.IsNullOrEmpty(upgradeKey)) { return null; } switch (upgradeKey.Trim()) { case "Health": return "playerUpgradeHealth"; case "Stamina": return "playerUpgradeStamina"; case "Extra Jump": return "playerUpgradeExtraJump"; case "Launch": case "Tumble Launch": return "playerUpgradeLaunch"; case "Tumble Climb": return "playerUpgradeTumbleClimb"; case "Death Head Battery": return "playerUpgradeDeathHeadBattery"; case "Map Player Count": return "playerUpgradeMapPlayerCount"; case "Speed": case "Sprint Speed": return "playerUpgradeSpeed"; case "Strength": return "playerUpgradeStrength"; case "Throw": case "Throw Strength": return "playerUpgradeThrow"; case "Range": return "playerUpgradeRange"; case "Crouch Rest": return "playerUpgradeCrouchRest"; case "Tumble Wings": return "playerUpgradeTumbleWings"; case "Sprint Usage": return "playerUpgradeSprint Usage"; case "Valuable Count": return "playerUpgradeValuable Count"; case "Map Enemy Tracker": return "playerUpgradeMap Enemy Tracker"; case "Map Player Tracker": return "playerUpgradeMap Player Tracker"; case "Item Resist": return "playerUpgradeItem Resist"; case "Map Zoom": return "playerUpgradeMap Zoom"; case "Autoscan": return "playerUpgradeAutoscan"; case "Item Value": return "playerUpgradeItem Value"; case "Extra Life": return "playerUpgradeExtra Life"; default: Plugin.Logger.LogWarning((object)("Unknown upgrade key: " + upgradeKey)); return null; } } public static void DetectMoreUpgradesItems() { if (!MultiplayerUpgradesCompatibility.MoreUpgradesDetected || (Object)(object)StatsManager.instance == (Object)null) { return; } try { if (SemiFunc.RunIsShop()) { Plugin.Logger.LogInfo((object)"Scanning for MoreUpgrades items..."); } int num = 0; foreach (KeyValuePair<string, Item> item in StatsManager.instance.itemDictionary) { string key = item.Key; Item value = item.Value; if ((Object)(object)value == (Object)null || string.IsNullOrEmpty(value.itemName)) { continue; } string itemName = value.itemName; string text = itemName.Replace(" Upgrade", ""); string[] array = new string[9] { "Sprint Usage Upgrade", "Valuable Count Upgrade", "Map Enemy Tracker Upgrade", "Map Player Tracker Upgrade", "Item Resist Upgrade", "Map Zoom Upgrade", "Autoscan Upgrade", "Item Value Upgrade", "Extra Life Upgrade" }; bool flag = false; string[] array2 = array; foreach (string text2 in array2) { if (itemName == text2) { flag = true; break; } } if (!flag && itemName.Contains("Upgrade") && !UpgradeDisplayNameToInternalName.ContainsKey(itemName) && !IsVanillaUpgrade(itemName)) { flag = true; } if (flag) { if (!string.IsNullOrEmpty(itemName) && !UpgradeDisplayNameToInternalName.ContainsKey(itemName)) { UpgradeDisplayNameToInternalName[itemName] = key; Plugin.Logger.LogInfo((object)("Added MoreUpgrades item: " + itemName + " -> " + key)); } if (!string.IsNullOrEmpty(text) && !CommandNameToDisplayName.ContainsKey(text)) { CommandNameToDisplayName[text] = itemName; Plugin.Logger.LogInfo((object)("Added MoreUpgrades command: " + text + " -> " + itemName)); num++; } } } if (SemiFunc.RunIsShop()) { Plugin.Logger.LogInfo((object)"MoreUpgrades items detected."); } _moreUpgradesDetected = true; } catch (Exception ex) { Plugin.Logger.LogError((object)("Error detecting MoreUpgrades items: " + ex.Message)); } } private static bool IsVanillaUpgrade(string displayName) { string[] array = new string[13] { "Health Upgrade", "Stamina Upgrade", "Extra Jump Upgrade", "Tumble Launch Upgrade", "Tumble Climb Upgrade", "Death Head Battery Upgrade", "Map Player Count Upgrade", "Sprint Speed Upgrade", "Strength Upgrade", "Throw Strength Upgrade", "Range Upgrade", "Crouch Rest Upgrade", "Tumble Wings Upgrade" }; string[] array2 = array; foreach (string text in array2) { if (displayName == text) { return true; } } return false; } public static void ApplyImmediateStatChanges(string commandName, string steamID, int change) { if (steamID != PlayerController.instance?.playerSteamID) { return; } PlayerAvatar val = SemiFunc.PlayerAvatarGetFromSteamID(steamID); if ((Object)(object)val == (Object)null) { Plugin.Logger.LogWarning((object)("Player not found for steamID: " + steamID)); return; } Dictionary<string, int> dictionary = StatsManager.instance.FetchPlayerUpgrades(steamID); string key = ConvertCommandToUpgradeKey(commandName); int num = (dictionary.ContainsKey(key) ? dictionary[key] : 0); Plugin.Logger.LogInfo((object)$"Applying immediate stat changes for {commandName}, level: {num}, change: {change}"); switch (commandName) { case "Health": if (val.isLocal) { val.playerHealth.maxHealth = 100 + num * 20; if (change < 0 && val.playerHealth.health > val.playerHealth.maxHealth) { val.playerHealth.health = val.playerHealth.maxHealth; } Plugin.Logger.LogInfo((object)$"Health updated: max={val.playerHealth.maxHealth}, current={val.playerHealth.health}"); } break; case "Stamina": if (val.isLocal && (Object)(object)PlayerController.instance != (Object)null) { PlayerController.instance.EnergyStart = 40f + (float)num * 10f; PlayerController.instance.EnergyCurrent = Mathf.Min(PlayerController.instance.EnergyCurrent, PlayerController.instance.EnergyStart); Plugin.Logger.LogInfo((object)$"Stamina updated: EnergyStart={PlayerController.instance.EnergyStart}"); } break; case "Extra Jump": if (val.isLocal && (Object)(object)PlayerController.instance != (Object)null) { PlayerController.instance.JumpExtra = num; Plugin.Logger.LogInfo((object)$"Extra jumps updated: {PlayerController.instance.JumpExtra}"); } break; case "Sprint Speed": if (val.isLocal && (Object)(object)PlayerController.instance != (Object)null) { PlayerController.instance.SprintSpeed = 7f + (float)num; PlayerController.instance.SprintSpeedUpgrades = num; PlayerController.instance.playerOriginalSprintSpeed = 7f + (float)num; Plugin.Logger.LogInfo((object)$"Speed updated: SprintSpeed={PlayerController.instance.SprintSpeed}"); } break; case "Strength": if ((Object)(object)val.physGrabber != (Object)null) { val.physGrabber.grabStrength = 1f + (float)num * 0.2f; Plugin.Logger.LogInfo((object)$"Strength updated: grabStrength={val.physGrabber.grabStrength}"); } break; case "Throw Strength": if ((Object)(object)val.physGrabber != (Object)null) { val.physGrabber.throwStrength = 1f + (float)num * 0.3f; Plugin.Logger.LogInfo((object)$"Throw strength updated: throwStrength={val.physGrabber.throwStrength}"); } break; case "Range": if ((Object)(object)val.physGrabber != (Object)null) { val.physGrabber.grabRange = 3f + (float)num; Plugin.Logger.LogInfo((object)$"Range updated: grabRange={val.physGrabber.grabRange}"); } break; case "Sprint Usage": if (val.isLocal && (Object)(object)PlayerController.instance != (Object)null) { Plugin.Logger.LogInfo((object)$"Sprint Usage updated to level {num}"); } break; case "Map Zoom": if (val.isLocal) { Plugin.Logger.LogInfo((object)$"Map Zoom updated to level {num}"); } break; case "Autoscan": if (val.isLocal) { Plugin.Logger.LogInfo((object)$"Autoscan updated to level {num}"); } break; case "Extra Life": Plugin.Logger.LogInfo((object)$"Extra Life count: {num}"); break; case "Item Value": Plugin.Logger.LogInfo((object)$"Item Value multiplier: {num}"); break; case "Item Resist": Plugin.Logger.LogInfo((object)$"Item Resist level: {num}"); break; default: Plugin.Logger.LogInfo((object)("No immediate stat changes defined for " + commandName)); break; } } public static Dictionary<string, int> GetAvailableUpgradesForResell(string steamID) { Dictionary<string, int> dictionary = new Dictionary<string, int>(); try { if ((Object)(object)StatsManager.instance == (Object)null || string.IsNullOrEmpty(steamID)) { return dictionary; } if (MultiplayerUpgradesCompatibility.MoreUpgradesDetected && !_moreUpgradesDetected) { DetectMoreUpgradesItems(); } Dictionary<string, int> dictionary2 = StatsManager.instance.FetchPlayerUpgrades(steamID); if (dictionary2 == null || dictionary2.Count == 0) { return dictionary; } foreach (KeyValuePair<string, string> item in CommandNameToDisplayName) { string key = item.Key; string value = item.Value; string text = value.Replace(" Upgrade", "").Trim(); int value2 = 0; bool flag = false; if (dictionary2.TryGetValue(key, out value2)) { flag = true; } if (!flag && dictionary2.TryGetValue(text, out value2)) { flag = true; } if (!flag) { string text2 = NormalizeSpaces(key); string text3 = NormalizeSpaces(text); foreach (KeyValuePair<string, int> item2 in dictionary2) { string text4 = NormalizeSpaces(item2.Key); if (text4 == text2 || text4 == text3) { value2 = item2.Value; flag = true; Plugin.Logger.LogDebug((object)("Found " + key + " via normalized spaces: " + item2.Key + " -> " + text4)); break; } } } if (!flag) { foreach (KeyValuePair<string, int> item3 in dictionary2) { string a = NormalizeSpaces(item3.Key); string b = NormalizeSpaces(key); string b2 = NormalizeSpaces(text); if (string.Equals(a, b, StringComparison.OrdinalIgnoreCase) || string.Equals(a, b2, StringComparison.OrdinalIgnoreCase)) { value2 = item3.Value; flag = true; Plugin.Logger.LogDebug((object)("Found " + key + " via case-insensitive normalized match: " + item3.Key)); break; } } } if (flag && value2 > 0) { if (TryGetUpgradeInternalName(key, out string internalName)) { int value3 = CalculateResellValue(internalName, value2); dictionary.Add(text, value3); } else { dictionary.Add(text, 0); } } } } catch (Exception ex) { Plugin.Logger.LogError((object)("Error in GetAvailableUpgradesForResell: " + ex.Message)); } return dictionary; } public static string NormalizeSpaces(string input) { if (string.IsNullOrEmpty(input)) { return input; } return Regex.Replace(input.Trim(), "\\s+", " "); } } public class ResellPhotonManager : MonoBehaviourPunCallbacks, IOnEventCallback { [CompilerGenerated] private sealed class <SyncPriceTrackingWithDelay>d__28 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public ResellPhotonManager <>4__this; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <SyncPriceTrackingWithDelay>d__28(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(0.5f); <>1__state = 1; return true; case 1: <>1__state = -1; <>4__this.SyncPriceTrackingData(); return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private static bool _created; public const byte EV_RESELL_REQUEST = 161; public const byte EV_RESELL_APPROVED = 162; public const byte EV_RESELL_DENIED = 163; public const byte EV_PRICE_TRACKING_SYNC = 164; public const byte EV_PRICE_TRACKING_REQUEST = 165; public static ResellPhotonManager Instance { get; private set; } public static void Ensure() { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown if (!_created) { _created = true; if ((Object)(object)Instance == (Object)null) { GameObject val = new GameObject("ResellUpgrades_ResellPhotonManager"); Object.DontDestroyOnLoad((Object)(object)val); Instance = val.AddComponent<ResellPhotonManager>(); Plugin.Logger.LogInfo((object)"ResellPhotonManager created and ensured!"); } } } private void Start() { Plugin.Logger.LogInfo((object)"ResellPhotonManager Start() called"); } private void OnEnable() { Plugin.Logger.LogInfo((object)"ResellPhotonManager OnEnable() - Adding callback target"); PhotonNetwork.AddCallbackTarget((object)this); } private void OnDisable() { Plugin.Logger.LogInfo((object)"ResellPhotonManager OnDisable() - Removing callback target"); PhotonNetwork.RemoveCallbackTarget((object)this); } public override void OnJoinedRoom() { Plugin.Logger.LogInfo((object)"ResellPhotonManager: Joined room successfully"); } public override void OnLeftRoom() { Plugin.Logger.LogInfo((object)"ResellPhotonManager: Left room"); } public void SendResellRequest(string upgradeKey, string steamID, int currentLevel, int calculatedValue) { //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Expected O, but got Unknown //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) if (!PhotonNetwork.IsConnected || !PhotonNetwork.InRoom) { Plugin.Logger.LogWarning((object)"SendResellRequest: Not connected or not in room"); return; } if (PhotonNetwork.IsMasterClient) { Plugin.Logger.LogInfo((object)"SendResellRequest: Master client doesn't need to send requests"); return; } object[] array = new object[5] { upgradeKey ?? string.Empty, steamID ?? string.Empty, currentLevel, calculatedValue, PhotonNetwork.LocalPlayer.ActorNumber }; RaiseEventOptions val = new RaiseEventOptions { Receivers = (ReceiverGroup)2 }; SendOptions val2 = default(SendOptions); ((SendOptions)(ref val2)).Reliability = true; SendOptions val3 = val2; PhotonNetwork.RaiseEvent((byte)161, (object)array, val, val3); Plugin.Logger.LogInfo((object)$"Sent resell request to host: {upgradeKey}, Level: {currentLevel}, Value: {calculatedValue}"); } private void SendResellApproval(string upgradeKey, string steamID, int newLevel, int currencyAdded, int requestorActorNumber) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected O, but got Unknown //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) if (PhotonNetwork.IsMasterClient && PhotonNetwork.IsConnected) { object[] array = new object[4] { upgradeKey ?? string.Empty, steamID ?? string.Empty, newLevel, currencyAdded }; RaiseEventOptions val = new RaiseEventOptions(); val.TargetActors = new int[1] { requestorActorNumber }; RaiseEventOptions val2 = val; SendOptions val3 = default(SendOptions); ((SendOptions)(ref val3)).Reliability = true; SendOptions val4 = val3; PhotonNetwork.RaiseEvent((byte)162, (object)array, val2, val4); Plugin.Logger.LogInfo((object)$"Sent resell approval to client {requestorActorNumber}: {upgradeKey} -> Level {newLevel}"); } } private void SendResellDenial(string reason, int requestorActorNumber) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) if (PhotonNetwork.IsMasterClient && PhotonNetwork.IsConnected) { RaiseEventOptions val = new RaiseEventOptions(); val.TargetActors = new int[1] { requestorActorNumber }; RaiseEventOptions val2 = val; SendOptions val3 = default(SendOptions); ((SendOptions)(ref val3)).Reliability = true; SendOptions val4 = val3; PhotonNetwork.RaiseEvent((byte)163, (object)(reason ?? string.Empty), val2, val4); Plugin.Logger.LogInfo((object)$"Sent resell denial to client {requestorActorNumber}: {reason}"); } } public void OnEvent(EventData photonEvent) { switch (photonEvent.Code) { case 161: Plugin.Logger.LogInfo((object)"Processing RESELL_REQUEST event"); if (PhotonNetwork.IsMasterClient) { HandleResellRequest(photonEvent); } break; case 162: Plugin.Logger.LogInfo((object)"Processing RESELL_APPROVED event"); if (!PhotonNetwork.IsMasterClient) { HandleResellApproval(photonEvent); } break; case 163: Plugin.Logger.LogInfo((object)"Processing RESELL_DENIED event"); if (!PhotonNetwork.IsMasterClient) { HandleResellDenial(photonEvent); } break; case 165: Plugin.Logger.LogInfo((object)"Processing PRICE_TRACKING_REQUEST event"); if (PhotonNetwork.IsMasterClient) { HandlePriceTrackingRequest(photonEvent); } break; case 164: Plugin.Logger.LogInfo((object)"Processing PRICE_TRACKING_SYNC event"); if (!PhotonNetwork.IsMasterClient) { HandlePriceTrackingSync(photonEvent); } break; } } private void HandleResellRequest(EventData photonEvent) { try { if (!(photonEvent.CustomData is object[] array) || array.Length < 5) { Plugin.Logger.LogError((object)"Invalid resell request data"); return; } string text = (array[0] as string) ?? string.Empty; string steamID = (array[1] as string) ?? string.Empty; int num = (int)array[2]; int calculatedValue = (int)array[3]; int num2 = (int)array[4]; Plugin.Logger.LogInfo((object)$"Host received resell request from actor {num2}: {text}, Level: {num}"); if (!ValidateResellRequest(text, steamID, num, calculatedValue, out string denialReason)) { SendResellDenial(denialReason, num2); } else { ApplyResellAsHost(text, steamID, num, calculatedValue, num2); } } catch (Exception arg) { Plugin.Logger.LogError((object)$"Error handling resell request: {arg}"); } } private bool ValidateResellRequest(string upgradeKey, string steamID, int currentLevel, int calculatedValue, out string denialReason) { denialReason = null; if (!ResellManager.CanResellUpgrades) { denialReason = "Not in shop area"; return false; } StatsManager instance = StatsManager.instance; Dictionary<string, int> dictionary = ((instance != null) ? instance.FetchPlayerUpgrades(steamID) : null); if (dictionary == null) { denialReason = "Player upgrades not found"; return false; } bool flag = false; int num = 0; string b = ResellManager.NormalizeSpaces(upgradeKey); foreach (KeyValuePair<string, int> item in dictionary) { string a = ResellManager.NormalizeSpaces(item.Key); if (string.Equals(a, b, StringComparison.OrdinalIgnoreCase)) { flag = true; num = item.Value; break; } } if (!flag) { denialReason = "Upgrade '" + upgradeKey + "' not found for player"; return false; } if (num != currentLevel) { Plugin.Logger.LogWarning((object)$"Upgrade level mismatch: Client claims {currentLevel}, host has {num} for {upgradeKey}"); if (Mathf.Abs(num - currentLevel) <= 1) { Plugin.Logger.LogInfo((object)$"Accepting close level match for {upgradeKey}: client={currentLevel}, host={num}"); return true; } denialReason = $"Upgrade level mismatch: You have level {num}, not {currentLevel}"; return false; } return true; } private void ApplyResellAsHost(string upgradeKey, string steamID, int claimedLevel, int calculatedValue, int requestorActorNumber) { StatsManager instance = StatsManager.instance; Dictionary<string, int> dictionary = ((instance != null) ? instance.FetchPlayerUpgrades(steamID) : null); if (dictionary == null) { SendResellDenial("Could not fetch player upgrades", requestorActorNumber); return; } int num = 0; string b = ResellManager.NormalizeSpaces(upgradeKey); foreach (KeyValuePair<string, int> item in dictionary) { string a = ResellManager.NormalizeSpaces(item.Key); if (string.Equals(a, b, StringComparison.OrdinalIgnoreCase)) { num = item.Value; break; } } if (num <= 0) { SendResellDenial("Player does not have " + upgradeKey + " or has level 0", requestorActorNumber); return; } int num2 = num - 1; if (!ResellManager.TryGetUpgradeInternalName(upgradeKey, out string internalName)) { SendResellDenial("Invalid upgrade type", requestorActorNumber); return; } int num3 = ResellManager.CalculateResellValue(internalName, num); Plugin.Logger.LogInfo((object)$"Host processing resell: {upgradeKey} from level {num} -> {num2}, Value: {num3}"); string upgradeDictionaryName = ResellManager.GetUpgradeDictionaryName(upgradeKey); if (string.IsNullOrEmpty(upgradeDictionaryName)) { SendResellDenial("Invalid upgrade type", requestorActorNumber); return; } if (StatsManager.instance.dictionaryOfDictionaries.ContainsKey(upgradeDictionaryName)) { StatsManager.instance.dictionaryOfDictionaries[upgradeDictionaryName][steamID] = num2; } int num4 = StatsManager.instance.runStats["currency"]; StatsManager.instance.runStats["currency"] += num3; PunManager.instance.UpdateStat(upgradeDictionaryName, steamID, num2); PunManager.instance.SetRunStatSet("currency", StatsManager.instance.runStats["currency"]); Plugin.Logger.LogInfo((object)string.Format("Host applied resell: {0} for {1}, Currency: {2} -> {3} (+{4})", upgradeKey, steamID, num4, StatsManager.instance.runStats["currency"], num3)); SendResellApproval(upgradeKey, steamID, num2, num3, requestorActorNumber); if ((Object)(object)StatsUI.instance != (Object)null) { StatsUI.instance.Fetch(); } MoreUpgradesPriceTracker.TrackUpgradeResell(internalName, ResellManager.CommandNameToDisplayName[upgradeKey], num); } private void HandleResellApproval(EventData photonEvent) { //IL_0134: Unknown result type (might be due to invalid IL or missing references) try { if (photonEvent.CustomData is object[] array && array.Length >= 4) { string text = (array[0] as string) ?? string.Empty; string text2 = (array[1] as string) ?? string.Empty; int num = (int)array[2]; int num2 = (int)array[3]; Plugin.Logger.LogInfo((object)$"Client received resell approval: {text} -> Level {num}, +{num2} currency"); string upgradeDictionaryName = ResellManager.GetUpgradeDictionaryName(text); if (!string.IsNullOrEmpty(upgradeDictionaryName) && StatsManager.instance.dictionaryOfDictionaries.ContainsKey(upgradeDictionaryName)) { StatsManager.instance.dictionaryOfDictionaries[upgradeDictionaryName][text2] = num; } ResellManager.ApplyImmediateStatChanges(text, text2, -1); if ((Object)(object)StatsUI.instance != (Object)null) { StatsUI.instance.Fetch(); } if ((Object)(object)ResellGUI.Instance != (Object)null) { ResellGUI.Instance.ClearPendingState(text); } if ((Object)(object)DebugConsoleUI.instance != (Object)null) { DebugConsoleUI.instance.SetResponseText($"Resold {text} successfully! +{num2}K $", Color.green, 2f); } } } catch (Exception arg) { Plugin.Logger.LogError((object)$"Error handling resell approval: {arg}"); } } private void HandleResellDenial(EventData photonEvent) { //IL_006e: Unknown result type (might be due to invalid IL or missing references) try { string text = (photonEvent.CustomData as string) ?? "Unknown reason"; Plugin.Logger.LogWarning((object)("Client received resell denial: " + text)); if ((Object)(object)ResellGUI.Instance != (Object)null) { ResellGUI.Instance.ClearPendingState(""); } if ((Object)(object)DebugConsoleUI.instance != (Object)null) { DebugConsoleUI.instance.SetResponseText("Resell denied: " + text, Color.red, 2f); } } catch (Exception arg) { Plugin.Logger.LogError((object)$"Error handling resell denial: {arg}"); } } public void RequestPriceTrackingData() { //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected O, but got Unknown //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) if (!PhotonNetwork.IsConnected || !PhotonNetwork.InRoom) { Plugin.Logger.LogWarning((object)"RequestPriceTrackingData: Not connected or not in room"); return; } if (PhotonNetwork.IsMasterClient) { Plugin.Logger.LogInfo((object)"RequestPriceTrackingData: Master client doesn't need to request"); return; } Plugin.Logger.LogInfo((object)"Sending price tracking request to host"); RaiseEventOptions val = new RaiseEventOptions { Receivers = (ReceiverGroup)2 }; SendOptions val2 = default(SendOptions); ((SendOptions)(ref val2)).Reliability = true; SendOptions val3 = val2; PhotonNetwork.RaiseEvent((byte)165, (object)"REQUEST_PRICE_DATA", val, val3); } private void HandlePriceTrackingRequest(EventData photonEvent) { try { string text = photonEvent.CustomData as string; Plugin.Logger.LogInfo((object)("Host received price tracking data request: " + text)); SyncPriceTrackingData(); } catch (Exception ex) { Plugin.Logger.LogError((object)("Error handling price tracking request: " + ex.Message)); } } private void HandlePriceTrackingSync(EventData photonEvent) { try { string text = photonEvent.CustomData as string; if (string.IsNullOrEmpty(text)) { Plugin.Logger.LogWarning((object)"Received empty price tracking data"); return; } Plugin.Logger.LogInfo((object)"Client received price tracking data"); PriceTrackingSync.ReceivePriceTrackingData(text); } catch (Exception ex) { Plugin.Logger.LogError((object)("Error handling price tracking sync: " + ex.Message)); } } [IteratorStateMachine(typeof(<SyncPriceTrackingWithDelay>d__28))] private IEnumerator SyncPriceTrackingWithDelay() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <SyncPriceTrackingWithDelay>d__28(0) { <>4__this = this }; } public void SyncPriceTrackingData() { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Expected O, but got Unknown //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) if (!PhotonNetwork.IsMasterClient || !PhotonNetwork.IsConnected || !PhotonNetwork.InRoom) { Plugin.Logger.LogWarning((object)$"Cannot sync price data: IsMaster={PhotonNetwork.IsMasterClient}"); return; } try { List<UpgradePriceData> allTrackedData = MoreUpgradesPriceTracker.GetAllTrackedData(); string text = JsonConvert.SerializeObject((object)allTrackedData); RaiseEventOptions val = new RaiseEventOptions { Receivers = (ReceiverGroup)0 }; SendOptions val2 = default(SendOptions); ((SendOptions)(ref val2)).Reliability = true; SendOptions val3 = val2; PhotonNetwork.RaiseEvent((byte)164, (object)text, val, val3); Plugin.Logger.LogInfo((object)$"Sent price tracking data to clients ({allTrackedData.Count} items)"); } catch (Exception ex) { Plugin.Logger.LogError((object)("Failed to sync price tracking data: " + ex.Message)); } } } [HarmonyPatch] public static class ResellUIPatches { [CompilerGenerated] private sealed class <RequestPriceTrackingWithDelay>d__3 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <RequestPriceTrackingWithDelay>d__3(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(2f); <>1__state = 1; return true; case 1: <>1__state = -1; if ((Object)(object)RunManager.instance != (Object)null && RunManager.instance.levelIsShop && !PhotonNetwork.IsMasterClient && (Object)(object)ResellPhotonManager.Instance != (Object)null) { Plugin.Logger.LogInfo((object)"Sending price tracking request..."); PriceTrackingSync.RequestPriceTrackingData(); } else { Plugin.Logger.LogWarning((object)"Not in shop or host, skipping price request"); } return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <SyncPriceTrackingWithDelay>d__4 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <SyncPriceTrackingWithDelay>d__4(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(1.5f); <>1__state = 1; return true; case 1: <>1__state = -1; ResellPhotonManager.Instance?.SyncPriceTrackingData(); return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private static bool guiCreated; [HarmonyPatch(typeof(StatsUI), "Start")] [HarmonyPostfix] private static void StatsUI_Start_Postfix(StatsUI __instance) { if (!guiCreated) { CreateResellGUI(); guiCreated = true; } if (SemiFunc.IsMultiplayer()) { ResellPhotonManager.Ensure(); } if (MultiplayerUpgradesCompatibility.MoreUpgradesDetected) { ResellManager.DetectMoreUpgradesItems(); } } [HarmonyPatch(typeof(ShopManager), "ShopInitialize")] [HarmonyPostfix] private static void ShopManager_ShopInitialize_SyncPostfix() { try { if (SemiFunc.RunIsShop()) { Plugin.Logger.LogInfo((object)"ShopInitialize - Initializing price tracking sync"); } if (SemiFunc.IsMultiplayer()) { ResellPhotonManager.Ensure(); } if (SemiFunc.RunIsShop()) { PriceTrackingSync.Initialize(); } if (PhotonNetwork.IsMasterClient && PhotonNetwork.IsConnected && SemiFunc.RunIsShop()) { Plugin.Logger.LogInfo((object)"Host: Price tracking system ready"); } else if (!PhotonNetwork.IsMasterClient && PhotonNetwork.IsConnected) { Plugin.Logger.LogInfo((object)"Client: Requesting price tracking data"); ResellPhotonManager instance = ResellPhotonManager.Instance; if (instance != null) { ((MonoBehaviour)instance).StartCoroutine(RequestPriceTrackingWithDelay()); } } } catch (Exception ex) { Plugin.Logger.LogError((object)("Error in shop sync: " + ex.Message)); } } [IteratorStateMachine(typeof(<RequestPriceTrackingWithDelay>d__3))] private static IEnumerator RequestPriceTrackingWithDelay() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <RequestPriceTrackingWithDelay>d__3(0); } [IteratorStateMachine(typeof(<SyncPriceTrackingWithDelay>d__4))] private static IEnumerator SyncPriceTrackingWithDelay() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <SyncPriceTrackingWithDelay>d__4(0); } private static void CreateResellGUI() { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown if (!((Object)(object)ResellGUI.Instance != (Object)null)) { Plugin.Logger.LogInfo((object)"Creating ResellGUI from StatsUI Start..."); GameObject val = new GameObject("ResellGUI"); val.AddComponent<ResellGUI>(); Object.DontDestroyOnLoad((Object)(object)val); } } } [BepInPlugin("Jettcodey.ResellUpgrades", "Resell Your Upgrades", "1.1.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { [CompilerGenerated] private sealed class <InitializePriceTracking>d__13 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public Plugin <>4__this; object? IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object? IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <InitializePriceTracking>d__13(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitUntil((Func<bool>)(() => (Object)(object)StatsManager.instance != (Object)null)); <>1__state = 1; return true; case 1: <>1__state = -1; MoreUpgradesPriceTracker.Initialize(); return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } internal static Plugin? Instance { get; private set; } internal static ManualLogSource Logger => Instance._logger; public ManualLogSource _logger => ((BaseUnityPlugin)this).Logger; internal Harmony? Harmony { get; set; } private void Awake() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown Instance = this; MultiplayerUpgradesCompatibility.Initialize(); Harmony = new Harmony("Jettcodey.ResellUpgrades"); Harmony.PatchAll(); Logger.LogInfo((object)"Plugin Resell Your Upgrades v1.1.0 loaded successfully."); ((MonoBehaviour)this).StartCoroutine(InitializePriceTracking()); if (MultiplayerUpgradesCompatibility.AnySyncedUpgradesModDetected) { Logger.LogInfo((object)"Multiplayer upgrade Sync mods detected - compatibility mode active"); Logger.LogInfo((object)("Detected mods: " + MultiplayerUpgradesCompatibility.GetModDetectionInfo())); } else { Logger.LogInfo((object)"No multiplayer upgrade mods detected - normal resell mode"); } if (MultiplayerUpgradesCompatibility.MoreUpgradesDetected) { Logger.LogInfo((object)"MoreUpgrades mod detected - adding support for modded upgrades"); } } [IteratorStateMachine(typeof(<InitializePriceTracking>d__13))] private IEnumerator InitializePriceTracking() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <InitializePriceTracking>d__13(0) { <>4__this = this }; } } } namespace ResellUpgrades.MoreUpgrades { public static class PriceTrackingSync { private static bool _synced = false; private static Dictionary<string, UpgradePriceData> _cachedData = new Dictionary<string, UpgradePriceData>(); public static bool HasSyncedData => _synced; public static void Initialize() { Plugin.Logger.LogInfo((object)"Price tracking sync system initialized"); _synced = false; _cachedData.Clear(); } public static void RequestPriceTrackingData() { if (PhotonNetwork.IsMasterClient || !PhotonNetwork.IsConnected || !PhotonNetwork.InRoom) { Plugin.Logger.LogWarning((object)$"Cannot request price data: Connected={PhotonNetwork.IsConnected}, InRoom={PhotonNetwork.InRoom}, IsMaster={PhotonNetwork.IsMasterClient}"); return; } Plugin.Logger.LogInfo((object)"Requesting price tracking data from host"); if ((Object)(object)ResellPhotonManager.Instance != (Object)null) { ResellPhotonManager.Instance.RequestPriceTrackingData(); } else { Plugin.Logger.LogError((object)"ResellPhotonManager not available!"); } } public static void ReceivePriceTrackingData(string jsonData) { try { List<UpgradePriceData> list = JsonConvert.DeserializeObject<List<UpgradePriceData>>(jsonData); _cachedData.Clear(); foreach (UpgradePriceData item in list) { if (!string.IsNullOrEmpty(item.InternalName)) { _cachedData[item.InternalName] = item; Plugin.Logger.LogInfo((object)("Received tracking for: " + item.UpgradeName)); } } _synced = true; Plugin.Logger.LogInfo((object)$"Received price tracking data ({_cachedData.Count} items)"); } catch (Exception ex) { Plugin.Logger.LogError((object)("Failed to receive price tracking data: " + ex.Message)); } } public static int GetTrackedPrice(string internalName, int level) { if (_cachedData.TryGetValue(internalName, out UpgradePriceData value) && value.LevelPrices.T