Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of UpgradeEveryRoundUpdated v3.0.0
plugins/UpgradeEveryRound.dll
Decompiled 7 hours agousing 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.Serialization.Formatters.Binary; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using ExitGames.Client.Photon; using HarmonyLib; using MenuLib; using MenuLib.MonoBehaviors; using Microsoft.CodeAnalysis; using Photon.Pun; using Photon.Realtime; using REPOLib.Modules; using Steamworks; using TMPro; using UnityEngine; using UnityEngine.Events; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("UpgradeEveryRound")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("2.0.3")] [assembly: AssemblyInformationalVersion("2.0.3+5afcb5a3443f338f580af04e2dbfb911a7c75e80")] [assembly: AssemblyProduct("Upgrade Every Round")] [assembly: AssemblyTitle("UpgradeEveryRound")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("2.0.3.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [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] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace UpgradeEveryRound { [HarmonyPatch(typeof(StatsUI), "Update")] public static class StatsUIPatch { private static void Prefix(ref float ___showStatsTimer) { if (UpgradeMenu.isOpen) { ___showStatsTimer = 5f; } } } [HarmonyPatch(typeof(StatsManager))] [HarmonyPatch("Start")] public static class StatsManagerStartPatch { private static void Prefix(StatsManager __instance) { UpgradeUsageData.Initialize(__instance); } private static void Postfix(StatsManager __instance) { ModUpgradeHandler.BuildExtraUpgradeList(); } } [HarmonyPatch(typeof(StatsManager), "LoadGame")] public static class StatsManagerLoadGamePatch { private static void Postfix(StatsManager __instance) { UpgradeUsageData.Initialize(__instance); } } [HarmonyPatch(typeof(RunManager))] [HarmonyPatch("LeaveToMainMenu")] public static class RunManagerMainMenuPatch { private static void Prefix() { UpgradeMenu.isOpen = false; Plugin.remoteNetworkData = null; } } internal static class ModUpgradeHandler { private static bool initialized = false; public static Dictionary<int, ConfigEntry<bool>> AllowExtras = new Dictionary<int, ConfigEntry<bool>>(); public static Dictionary<int, string> ExtraLabels = new Dictionary<int, string>(); public static Dictionary<int, string> ExtraKeys = new Dictionary<int, string>(); public static Dictionary<string, GameObject> ExtraUpgrades = new Dictionary<string, GameObject>(); public static Dictionary<string, string> ExtraUpgradeIds = new Dictionary<string, string>(); public static Dictionary<string, GameObject> ExtraUpgradePrefabs = new Dictionary<string, GameObject>(); internal static bool DoUpgrade(string upgradeKey, string _steamID) { if (ExtraUpgradeIds.TryGetValue(upgradeKey, out var value)) { PlayerUpgrade upgrade = Upgrades.GetUpgrade(value); if (upgrade == null) { Plugin.Logger.LogError((object)("Registered upgrade '" + value + "' is no longer available.")); return false; } upgrade.AddLevel(_steamID, 1); return true; } if (!ExtraUpgradePrefabs.TryGetValue(upgradeKey, out var value2) || (Object)(object)value2 == (Object)null) { Plugin.Logger.LogError((object)("No registered upgrade ID or item prefab found for key '" + upgradeKey + "'.")); return false; } GameObject val = Object.Instantiate<GameObject>(value2); MonoBehaviour[] components = val.GetComponents<MonoBehaviour>(); for (int i = 0; i < components.Length; i++) { Traverse val2 = Traverse.Create((object)components[i]).Method("Start", Array.Empty<Type>(), (object[])null); if (val2.MethodExists()) { val2.GetValue(Array.Empty<object>()); } } ItemToggle component = val.GetComponent<ItemToggle>(); ItemUpgrade component2 = val.GetComponent<ItemUpgrade>(); Traverse.Create((object)component).Field<int>("playerTogglePhotonID").Value = SemiFunc.PlayerGetFromSteamID(_steamID).photonView.ViewID; Traverse obj = Traverse.Create((object)component2); obj.Field<PhysGrabObjectImpactDetector>("impactDetector").Value.destroyDisable = true; obj.Method("PlayerUpgrade", Array.Empty<Type>(), (object[])null).GetValue(Array.Empty<object>()); Object.Destroy((Object)(object)val); return true; } public static void BuildExtraUpgradeList() { //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Expected O, but got Unknown //IL_0342: Unknown result type (might be due to invalid IL or missing references) //IL_034c: Expected O, but got Unknown if (initialized) { return; } Plugin.Logger.LogMessage((object)"Building extra upgrades list"); int num = 0; Regex regex = new Regex("(?<!^)(?=[A-Z])"); AllowExtras.Clear(); ExtraLabels.Clear(); ExtraKeys.Clear(); ExtraUpgrades.Clear(); ExtraUpgradeIds.Clear(); ExtraUpgradePrefabs.Clear(); foreach (PlayerUpgrade item in Upgrades.PlayerUpgrades.OrderBy<PlayerUpgrade, string>((PlayerUpgrade x) => x.UpgradeId, StringComparer.Ordinal)) { string text = string.Join(" ", regex.Split(item.UpgradeId)); ConfigEntry<bool> val = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>("Enabled upgrades", "Enable " + text, true, new ConfigDescription("Allows " + text + " Upgrade to be chosen", (AcceptableValueBase)null, Array.Empty<object>())); AllowExtras.Add(num, val); ExtraLabels.Add(num, text); string text2 = "upgrade:" + item.UpgradeId; ExtraKeys.Add(num, text2); ExtraUpgrades.Add(text, null); ExtraUpgradeIds.Add(text2, item.UpgradeId); BindExtraConfig(val); num++; } string[] source = new string[12] { "Map Player Count", "Stamina", "Extra Jump", "Range", "Strength", "Health", "Sprint Speed", "Tumble Launch", "Tumble Climb", "Death Head Battery", "Tumble Wings", "Crouch Rest" }; string[] source2 = new string[1] { "Throw Strength" }; foreach (Item item2 in Items.AllItems.Where((Item x) => (int)x.itemType == 3).OrderBy<Item, string>((Item x) => x.itemName, StringComparer.Ordinal).ThenBy<Item, string>((Item x) => ((Object)x).name, StringComparer.Ordinal)) { string itemName = item2.itemName; string text3 = itemName.Substring(0, itemName.Length - 8).Trim(); if (!ExtraUpgrades.ContainsKey(text3) && !source.Contains(text3) && !source2.Contains(text3)) { GameObject prefab = ((PrefabRef<GameObject>)(object)item2.prefab).Prefab; if ((Object)(object)prefab == (Object)null) { Plugin.Logger.LogWarning((object)("Ignoring item upgrade '" + item2.itemName + "' because it has no prefab.")); continue; } ConfigEntry<bool> val2 = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>("Enabled upgrades", "Enable " + text3, true, new ConfigDescription("Allows " + text3 + " Upgrade to be chosen", (AcceptableValueBase)null, Array.Empty<object>())); AllowExtras.Add(num, val2); ExtraLabels.Add(num, text3); string text4 = "item:" + ((Object)item2).name; ExtraKeys.Add(num, text4); ExtraUpgrades.Add(text3, prefab); ExtraUpgradePrefabs.Add(text4, prefab); BindExtraConfig(val2); num++; } } Plugin.ConfigUpdated(null, EventArgs.Empty); initialized = true; } private static void BindExtraConfig(ConfigEntry<bool> allowCustomUpgrade) { allowCustomUpgrade.SettingChanged += Plugin.ConfigUpdated; } public static bool AllowCustomUpgradeByIndex(int configIndex) { NetworkData currentNetworkData = Plugin.CurrentNetworkData; if (currentNetworkData?.extraData == null || currentNetworkData.extraConfigHash != GetExtraConfigSchemaHash()) { return false; } int num = configIndex / 32; if (num >= currentNetworkData.extraData.Length) { return false; } int num2 = 1 << configIndex % 32; return (currentNetworkData.extraData[num] & num2) != 0; } internal static int[] GetExtraConfigBits() { int[] array = new int[(AllowExtras.Count + 31) / 32]; foreach (KeyValuePair<int, ConfigEntry<bool>> allowExtra in AllowExtras) { if (allowExtra.Value.Value) { int num = allowExtra.Key / 32; int num2 = 1 << allowExtra.Key % 32; array[num] |= num2; } } return array; } internal static int GetExtraConfigSchemaHash() { uint num = 2166136261u; foreach (KeyValuePair<int, string> item in ExtraKeys.OrderBy((KeyValuePair<int, string> x) => x.Key)) { string value = item.Value; foreach (char c in value) { num = (num ^ c) * 16777619; } num = (num ^ 0xFF) * 16777619; } return (int)num; } } [Serializable] public record NetworkData { public int upgradesPerRound; public bool limitedChoices; public int numChoices; public bool allowMapCount; public bool allowEnergy; public bool allowExtraJump; public bool allowRange; public bool allowStrength; public bool allowHealth; public bool allowSpeed; public bool allowTumbleLaunch; public bool allowTumbleClimb; public bool allowDeathHeadBattery; public bool allowTumbleWings; public bool allowCrouchRest; public int extraConfigHash; public int[] extraData; public NetworkData() { upgradesPerRound = Plugin.upgradesPerRound.Value; limitedChoices = Plugin.limitedChoices.Value; numChoices = Plugin.numChoices.Value; allowMapCount = Plugin.allowMapCount.Value; allowEnergy = Plugin.allowEnergy.Value; allowExtraJump = Plugin.allowExtraJump.Value; allowRange = Plugin.allowRange.Value; allowStrength = Plugin.allowStrength.Value; allowHealth = Plugin.allowHealth.Value; allowSpeed = Plugin.allowSpeed.Value; allowTumbleLaunch = Plugin.allowTumbleLaunch.Value; allowTumbleClimb = Plugin.allowTumbleClimb.Value; allowDeathHeadBattery = Plugin.allowDeathHeadBattery.Value; allowTumbleWings = Plugin.allowTumbleWings.Value; allowCrouchRest = Plugin.allowCrouchRest.Value; extraConfigHash = ModUpgradeHandler.GetExtraConfigSchemaHash(); extraData = ModUpgradeHandler.GetExtraConfigBits(); } public static byte[] Serealize(object data) { BinaryFormatter binaryFormatter = new BinaryFormatter(); using MemoryStream memoryStream = new MemoryStream(); binaryFormatter.Serialize(memoryStream, data); return memoryStream.ToArray(); } public static NetworkData Deserialize(byte[] arrBytes) { using MemoryStream memoryStream = new MemoryStream(); BinaryFormatter binaryFormatter = new BinaryFormatter(); memoryStream.Write(arrBytes, 0, arrBytes.Length); memoryStream.Seek(0L, SeekOrigin.Begin); return (NetworkData)binaryFormatter.Deserialize(memoryStream); } } [HarmonyPatch(typeof(SemiFunc))] [HarmonyPatch("OnLevelGenDone")] internal static class OnLevelGenDonePatch { internal static void Postfix() { UERNetworkManager.levelLoaded = true; if (SemiFunc.IsMasterClientOrSingleplayer()) { UpgradeMenu.OpenMenu(); } } } [BepInPlugin("dev.redfops.repo.upgradeeveryround", "Upgrade Every Round Updated", "3.0.0")] [BepInDependency("nickklmao.menulib", "2.1.3")] [BepInDependency("REPOLib", "4.2.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { [CompilerGenerated] private static class <>O { public static EventHandler <0>__ConfigUpdated; public static Action<EventData> <1>__HandleConfigUpdateEvent; public static Action<EventData> <2>__HandleClientUpgradeEvent; public static DeserializeMethod <3>__Deserialize; } [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static SerializeMethod <>9__29_0; internal byte[] <Awake>b__29_0(object x) { return NetworkData.Serealize(x); } } public const string modGUID = "dev.redfops.repo.upgradeeveryround"; public const string modName = "Upgrade Every Round Updated"; public const string modVersion = "3.0.0"; public static ConfigEntry<int> upgradesPerRound; public static ConfigEntry<bool> limitedChoices; public static ConfigEntry<int> numChoices; public static Plugin Instance; public static ConfigEntry<bool> allowMapCount; public static ConfigEntry<bool> allowEnergy; public static ConfigEntry<bool> allowExtraJump; public static ConfigEntry<bool> allowRange; public static ConfigEntry<bool> allowStrength; public static ConfigEntry<bool> allowHealth; public static ConfigEntry<bool> allowSpeed; public static ConfigEntry<bool> allowTumbleLaunch; public static ConfigEntry<bool> allowTumbleClimb; public static ConfigEntry<bool> allowDeathHeadBattery; public static ConfigEntry<bool> allowTumbleWings; public static ConfigEntry<bool> allowCrouchRest; public static NetworkData localNetworkData; public static NetworkData remoteNetworkData; public static NetworkedEvent ConfigUpdateEvent; public static NetworkedEvent ClientUpgradeEvent; public static RaiseEventOptions ConfigUpdateEventOptions = new RaiseEventOptions { CachingOption = (EventCaching)4, Receivers = (ReceiverGroup)0 }; public static RaiseEventOptions ClientUpgradeEventOptions = new RaiseEventOptions { Receivers = (ReceiverGroup)2 }; internal static ManualLogSource Logger; private readonly Harmony harmony = new Harmony("dev.redfops.repo.upgradeeveryround"); public static NetworkData CurrentNetworkData { get { if (!Object.op_Implicit((Object)(object)GameManager.instance) || SemiFunc.IsMasterClientOrSingleplayer()) { return localNetworkData; } if (remoteNetworkData == null) { Logger.LogError((object)"Missing remote data"); return localNetworkData; } return remoteNetworkData; } } public static int UpgradesPerRound => CurrentNetworkData.upgradesPerRound; public static bool LimitedChoices => CurrentNetworkData.limitedChoices; public static int NumChoices => CurrentNetworkData.numChoices; public static bool AllowMapCount => CurrentNetworkData.allowMapCount; public static bool AllowEnergy => CurrentNetworkData.allowEnergy; public static bool AllowExtraJump => CurrentNetworkData.allowExtraJump; public static bool AllowRange => CurrentNetworkData.allowRange; public static bool AllowStrength => CurrentNetworkData.allowStrength; public static bool AllowHealth => CurrentNetworkData.allowHealth; public static bool AllowSpeed => CurrentNetworkData.allowSpeed; public static bool AllowTumbleLaunch => CurrentNetworkData.allowTumbleLaunch; public static bool AllowTumbleClimb => CurrentNetworkData.allowTumbleClimb; public static bool AllowDeathHeadBattery => CurrentNetworkData.allowDeathHeadBattery; public static bool AllowTumbleWings => CurrentNetworkData.allowTumbleWings; public static bool AllowCrouchRest => CurrentNetworkData.allowCrouchRest; private void Awake() { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Expected O, but got Unknown //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Expected O, but got Unknown //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Expected O, but got Unknown //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Expected O, but got Unknown //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Expected O, but got Unknown //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Expected O, but got Unknown //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Expected O, but got Unknown //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Expected O, but got Unknown //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Expected O, but got Unknown //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Expected O, but got Unknown //IL_01e8: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Expected O, but got Unknown //IL_0213: Unknown result type (might be due to invalid IL or missing references) //IL_021d: Expected O, but got Unknown //IL_023e: Unknown result type (might be due to invalid IL or missing references) //IL_0248: Expected O, but got Unknown //IL_0269: Unknown result type (might be due to invalid IL or missing references) //IL_0273: Expected O, but got Unknown //IL_0294: Unknown result type (might be due to invalid IL or missing references) //IL_029e: Expected O, but got Unknown //IL_04ee: Unknown result type (might be due to invalid IL or missing references) //IL_04f8: Expected O, but got Unknown //IL_0518: Unknown result type (might be due to invalid IL or missing references) //IL_0522: Expected O, but got Unknown //IL_05e4: Unknown result type (might be due to invalid IL or missing references) //IL_05e9: Unknown result type (might be due to invalid IL or missing references) //IL_05ef: Expected O, but got Unknown //IL_05ff: Unknown result type (might be due to invalid IL or missing references) //IL_0604: Unknown result type (might be due to invalid IL or missing references) //IL_060a: Expected O, but got Unknown Logger = ((BaseUnityPlugin)this).Logger; Instance = this; upgradesPerRound = ((BaseUnityPlugin)this).Config.Bind<int>("Upgrades", "Upgrades Per Round", 1, new ConfigDescription("Number of upgrades per round", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 7), Array.Empty<object>())); limitedChoices = ((BaseUnityPlugin)this).Config.Bind<bool>("Upgrades", "Limited random choices", false, new ConfigDescription("Only presents a fixed number of random options", (AcceptableValueBase)null, Array.Empty<object>())); numChoices = ((BaseUnityPlugin)this).Config.Bind<int>("Upgrades", "Number of choices", 3, new ConfigDescription("Number of options to choose from per upgrade", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 12), Array.Empty<object>())); allowMapCount = ((BaseUnityPlugin)this).Config.Bind<bool>("Enabled upgrades", "Enable Map Player Count", true, new ConfigDescription("Allows Map Player Count Upgrade to be chosen", (AcceptableValueBase)null, Array.Empty<object>())); allowEnergy = ((BaseUnityPlugin)this).Config.Bind<bool>("Enabled upgrades", "Enable Stamina", true, new ConfigDescription("Allows Stamina Upgrade to be chosen", (AcceptableValueBase)null, Array.Empty<object>())); allowExtraJump = ((BaseUnityPlugin)this).Config.Bind<bool>("Enabled upgrades", "Enable Extra Jump", true, new ConfigDescription("Allows Extra Jump Upgrade to be chosen", (AcceptableValueBase)null, Array.Empty<object>())); allowRange = ((BaseUnityPlugin)this).Config.Bind<bool>("Enabled upgrades", "Enable Range", true, new ConfigDescription("Allows Range Upgrade to be chosen", (AcceptableValueBase)null, Array.Empty<object>())); allowStrength = ((BaseUnityPlugin)this).Config.Bind<bool>("Enabled upgrades", "Enable Strength", true, new ConfigDescription("Allows Strength Upgrade to be chosen", (AcceptableValueBase)null, Array.Empty<object>())); allowHealth = ((BaseUnityPlugin)this).Config.Bind<bool>("Enabled upgrades", "Enable Health", true, new ConfigDescription("Allows Health Upgrade to be chosen", (AcceptableValueBase)null, Array.Empty<object>())); allowSpeed = ((BaseUnityPlugin)this).Config.Bind<bool>("Enabled upgrades", "Enable Speed", true, new ConfigDescription("Allows Speed Upgrade to be chosen", (AcceptableValueBase)null, Array.Empty<object>())); allowTumbleLaunch = ((BaseUnityPlugin)this).Config.Bind<bool>("Enabled upgrades", "Enable Tumble Launch", true, new ConfigDescription("Allows Tumble Launch Upgrade to be chosen", (AcceptableValueBase)null, Array.Empty<object>())); allowTumbleClimb = ((BaseUnityPlugin)this).Config.Bind<bool>("Enabled upgrades", "Enable Tumble Climb", true, new ConfigDescription("Allows Tumble Climb Upgrade to be chosen", (AcceptableValueBase)null, Array.Empty<object>())); allowDeathHeadBattery = ((BaseUnityPlugin)this).Config.Bind<bool>("Enabled upgrades", "Enable Death Head Battery", true, new ConfigDescription("Allows Death Head Battery Upgrade to be chosen", (AcceptableValueBase)null, Array.Empty<object>())); allowTumbleWings = ((BaseUnityPlugin)this).Config.Bind<bool>("Enabled upgrades", "Enable Tumble Wings", true, new ConfigDescription("Allows Tumble Wings Upgrade to be chosen", (AcceptableValueBase)null, Array.Empty<object>())); allowCrouchRest = ((BaseUnityPlugin)this).Config.Bind<bool>("Enabled upgrades", "Enable Crouch Rest", true, new ConfigDescription("Allows Crouch Rest Upgrade to be chosen", (AcceptableValueBase)null, Array.Empty<object>())); upgradesPerRound.SettingChanged += ConfigUpdated; limitedChoices.SettingChanged += ConfigUpdated; numChoices.SettingChanged += ConfigUpdated; allowMapCount.SettingChanged += ConfigUpdated; allowEnergy.SettingChanged += ConfigUpdated; allowExtraJump.SettingChanged += ConfigUpdated; allowRange.SettingChanged += ConfigUpdated; allowStrength.SettingChanged += ConfigUpdated; allowHealth.SettingChanged += ConfigUpdated; allowSpeed.SettingChanged += ConfigUpdated; allowTumbleLaunch.SettingChanged += ConfigUpdated; allowTumbleClimb.SettingChanged += ConfigUpdated; allowDeathHeadBattery.SettingChanged += ConfigUpdated; allowTumbleWings.SettingChanged += ConfigUpdated; allowCrouchRest.SettingChanged += ConfigUpdated; ConfigUpdateEvent = new NetworkedEvent("ConfigUpdate", (Action<EventData>)HandleConfigUpdateEvent); ClientUpgradeEvent = new NetworkedEvent("ClientUpgrade", (Action<EventData>)HandleClientUpgradeEvent); ((Component)this).gameObject.AddComponent<UpgradeEveryRoundPhotonCallbacks>(); harmony.PatchAll(typeof(SceneSwitchPatch)); harmony.PatchAll(typeof(OnLevelGenDonePatch)); harmony.PatchAll(typeof(SteamManagerPatch)); harmony.PatchAll(typeof(RunManagerMainMenuPatch)); harmony.PatchAll(typeof(StatsManagerStartPatch)); harmony.PatchAll(typeof(StatsManagerLoadGamePatch)); harmony.PatchAll(typeof(StatsUIPatch)); Type? typeFromHandle = typeof(NetworkData); object obj = <>c.<>9__29_0; if (obj == null) { SerializeMethod val = (object x) => NetworkData.Serealize(x); <>c.<>9__29_0 = val; obj = (object)val; } object obj2 = <>O.<3>__Deserialize; if (obj2 == null) { DeserializeMethod val2 = NetworkData.Deserialize; <>O.<3>__Deserialize = val2; obj2 = (object)val2; } PhotonPeer.RegisterType(typeFromHandle, (byte)248, (SerializeMethod)obj, (DeserializeMethod)obj2); ((MonoBehaviour)this).StartCoroutine(UERNetworkManager.Go()); Logger.LogInfo((object)"Plugin UpgradeEveryRound is loaded!"); } internal static void ConfigUpdated(object sender, EventArgs args) { localNetworkData = new NetworkData(); if (SemiFunc.IsMultiplayer() && PhotonNetwork.IsMasterClient) { SendConfig(); } } public static void SendConfig() { //IL_002f: Unknown result type (might be due to invalid IL or missing references) if (!PhotonNetwork.InRoom || PhotonNetwork.IsMasterClient) { if ((object)localNetworkData == null) { localNetworkData = new NetworkData(); } ConfigUpdateEvent.RaiseEvent((object)localNetworkData, ConfigUpdateEventOptions, SendOptions.SendReliable); } } private static void HandleConfigUpdateEvent(EventData eventData) { if (PhotonNetwork.MasterClient == null || eventData.Sender != PhotonNetwork.MasterClient.ActorNumber) { Logger.LogWarning((object)"Ignoring upgrade configuration sent by a non-master client."); } else if (!(eventData.CustomData is NetworkData networkData)) { Logger.LogWarning((object)"Ignoring invalid upgrade configuration data."); } else { remoteNetworkData = networkData; } } public static void DoUpgradeClient(string upgradeId, string _steamID) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown //IL_001e: Expected O, but got Unknown //IL_0029: Unknown result type (might be due to invalid IL or missing references) Hashtable val = new Hashtable(); ((Dictionary<object, object>)val).Add((object)"upgrade", (object)upgradeId); ((Dictionary<object, object>)val).Add((object)"steamID", (object)_steamID); Hashtable val2 = val; ClientUpgradeEvent.RaiseEvent((object)val2, ClientUpgradeEventOptions, SendOptions.SendReliable); } private static void HandleClientUpgradeEvent(EventData eventData) { object customData = eventData.CustomData; Hashtable val = (Hashtable)((customData is Hashtable) ? customData : null); if (val == null || !(val[(object)"upgrade"] is string text) || !(val[(object)"steamID"] is string text2)) { Logger.LogWarning((object)"Ignoring invalid upgrade request data."); return; } switch (text) { case "Stamina": PunManager.instance.UpgradePlayerEnergy(text2, 1); break; case "Extra Jump": PunManager.instance.UpgradePlayerExtraJump(text2, 1); break; case "Range": PunManager.instance.UpgradePlayerGrabRange(text2, 1); break; case "Strength": PunManager.instance.UpgradePlayerGrabStrength(text2, 1); break; case "Health": PunManager.instance.UpgradePlayerHealth(text2, 1); break; case "Sprint Speed": PunManager.instance.UpgradePlayerSprintSpeed(text2, 1); break; case "Tumble Launch": PunManager.instance.UpgradePlayerTumbleLaunch(text2, 1); break; case "Map Player Count": PunManager.instance.UpgradeMapPlayerCount(text2, 1); break; case "Tumble Climb": PunManager.instance.UpgradePlayerTumbleClimb(text2, 1); break; case "Death Head Battery": PunManager.instance.UpgradeDeathHeadBattery(text2, 1); break; case "Tumble Wings": PunManager.instance.UpgradePlayerTumbleWings(text2, 1); break; case "Crouch Rest": PunManager.instance.UpgradePlayerCrouchRest(text2, 1); break; default: if (!ModUpgradeHandler.DoUpgrade(text, text2)) { return; } break; } int num = UpgradeUsageData.GetCount(StatsManager.instance, text2) + 1; PunManager.instance.UpdateStat("upgradeEveryRoundUsage", text2, num); } public static void ApplyUpgrade(string _steamID, REPOPopupPage popupPage) { StatsUI.instance.Fetch(); StatsUI.instance.ShowStats(); CameraGlitch.Instance.PlayUpgrade(); int num = (UERNetworkManager.upgradesUsedLocal = NumUpgradesUsed(_steamID) + 1); if (SemiFunc.IsMasterClientOrSingleplayer()) { PunManager.instance.UpdateStat("upgradeEveryRoundUsage", _steamID, num); } UpgradeMenu.isOpen = false; popupPage.ClosePage(true); if (RunManager.instance.levelsCompleted * UpgradesPerRound > num) { UpgradeMenu.createMenu(_steamID).OpenPage(false); UpgradeMenu.isOpen = true; } } public static int NumUpgradesUsed(string _steamID) { if (!SemiFunc.IsMasterClientOrSingleplayer()) { return UERNetworkManager.upgradesUsedLocal; } return UpgradeUsageData.GetCount(StatsManager.instance, _steamID); } } internal sealed class UpgradeEveryRoundPhotonCallbacks : MonoBehaviourPunCallbacks { public override void OnMasterClientSwitched(Player newMasterClient) { if (PhotonNetwork.IsMasterClient) { Plugin.SendConfig(); } } } [HarmonyPatch(typeof(SemiFunc))] [HarmonyPatch("OnSceneSwitch")] internal static class SceneSwitchPatch { private static void Prefix() { UERNetworkManager.LevelChange(); } } [HarmonyPatch(typeof(SteamManager))] internal static class SteamManagerPatch { [HarmonyPatch("UnlockLobby")] [HarmonyPostfix] internal static void UnlockLobbyPostfix() { Plugin.SendConfig(); } } public static class UERNetworkManager { public static bool synced = false; public static bool levelLoaded = false; public static bool menuOpened = false; private static bool joinedGame = false; public static int upgradesUsedLocal = -1; public static IEnumerator Go() { while (true) { yield return (object)new WaitForFixedUpdate(); if (!Object.op_Implicit((Object)(object)GameManager.instance) || SemiFunc.IsMasterClientOrSingleplayer()) { synced = false; levelLoaded = false; menuOpened = false; upgradesUsedLocal = -1; continue; } if (!joinedGame) { UpgradeUsageData.SetCount(StatsManager.instance, SteamClient.SteamId.Value.ToString(), -1); joinedGame = true; } if (!levelLoaded) { continue; } synced = StatsManager.instance.statsSynced; if (!synced || !levelLoaded || menuOpened || Plugin.remoteNetworkData == null) { continue; } int count = UpgradeUsageData.GetCount(StatsManager.instance, SteamClient.SteamId.Value.ToString()); if (count != -1) { if (upgradesUsedLocal == -1) { upgradesUsedLocal = count; } UpgradeMenu.OpenMenu(); menuOpened = true; } } } public static void LevelChange() { synced = false; levelLoaded = false; menuOpened = false; } } public static class UpgradeMenu { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static UnityAction <>9__3_0; internal void <createMenu>b__3_0() { isOpen = false; } } public static bool isOpen; public static bool choseUpgrade; public static void OpenMenu() { //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) if (!isOpen && !((IEnumerable<Level>)(object)new Level[3] { RunManager.instance.levelMainMenu, RunManager.instance.levelLobbyMenu, RunManager.instance.levelTutorial }).Contains(RunManager.instance.levelCurrent)) { string steamID = SteamClient.SteamId.Value.ToString(); int num = RunManager.instance.levelsCompleted * Plugin.UpgradesPerRound; if (Plugin.NumUpgradesUsed(steamID) < num) { MenuManager.instance.PageCloseAll(); REPOPopupPage obj = createMenu(steamID); isOpen = true; obj.OpenPage(false); } } } public static REPOPopupPage createMenu(string _steamID) { //IL_0063: 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) //IL_006e: Expected O, but got Unknown //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_0227: Unknown result type (might be due to invalid IL or missing references) //IL_0238: 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_024e: Unknown result type (might be due to invalid IL or missing references) //IL_0253: Unknown result type (might be due to invalid IL or missing references) //IL_0264: Unknown result type (might be due to invalid IL or missing references) //IL_0269: Unknown result type (might be due to invalid IL or missing references) //IL_027a: Unknown result type (might be due to invalid IL or missing references) //IL_027f: Unknown result type (might be due to invalid IL or missing references) //IL_0290: Unknown result type (might be due to invalid IL or missing references) //IL_0295: Unknown result type (might be due to invalid IL or missing references) //IL_02a6: Unknown result type (might be due to invalid IL or missing references) //IL_02ab: Unknown result type (might be due to invalid IL or missing references) //IL_02bc: Unknown result type (might be due to invalid IL or missing references) //IL_02c1: Unknown result type (might be due to invalid IL or missing references) //IL_037f: Unknown result type (might be due to invalid IL or missing references) //IL_0389: Expected O, but got Unknown //IL_03ac: Unknown result type (might be due to invalid IL or missing references) //IL_03b6: Expected O, but got Unknown //IL_03d9: Unknown result type (might be due to invalid IL or missing references) //IL_03e3: Expected O, but got Unknown //IL_0406: Unknown result type (might be due to invalid IL or missing references) //IL_0410: Expected O, but got Unknown //IL_0433: Unknown result type (might be due to invalid IL or missing references) //IL_043d: Expected O, but got Unknown //IL_0460: Unknown result type (might be due to invalid IL or missing references) //IL_046a: Expected O, but got Unknown //IL_048d: Unknown result type (might be due to invalid IL or missing references) //IL_0497: Expected O, but got Unknown //IL_04ba: Unknown result type (might be due to invalid IL or missing references) //IL_04c4: Expected O, but got Unknown //IL_04e7: Unknown result type (might be due to invalid IL or missing references) //IL_04f1: Expected O, but got Unknown //IL_0514: Unknown result type (might be due to invalid IL or missing references) //IL_051e: Expected O, but got Unknown //IL_0541: Unknown result type (might be due to invalid IL or missing references) //IL_054b: Expected O, but got Unknown //IL_056b: Unknown result type (might be due to invalid IL or missing references) //IL_0575: Expected O, but got Unknown //IL_05bd: Unknown result type (might be due to invalid IL or missing references) //IL_05c7: Expected O, but got Unknown choseUpgrade = false; StatsUI.instance.Fetch(); StatsUI.instance.ShowStats(); REPOPopupPage repoPopupPage = MenuAPI.CreateREPOPopupPage("Choose an upgrade", (PresetSide)1, false, true, 1.5f); UnityEvent onPageEnd = repoPopupPage.menuPage.onPageEnd; object obj = <>c.<>9__3_0; if (obj == null) { UnityAction val = delegate { isOpen = false; }; <>c.<>9__3_0 = val; obj = (object)val; } onPageEnd.AddListener((UnityAction)obj); List<int> list = new List<int>(12) { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; List<bool> list2 = new List<bool>(12) { Plugin.AllowEnergy, Plugin.AllowExtraJump, Plugin.AllowRange, Plugin.AllowStrength, Plugin.AllowHealth, Plugin.AllowSpeed, Plugin.AllowTumbleLaunch, Plugin.AllowMapCount, Plugin.AllowTumbleClimb, Plugin.AllowDeathHeadBattery, Plugin.AllowTumbleWings, Plugin.AllowCrouchRest }; foreach (KeyValuePair<int, ConfigEntry<bool>> allowExtra in ModUpgradeHandler.AllowExtras) { int key = allowExtra.Key; list.Add(list.Count); list2.Add(ModUpgradeHandler.AllowCustomUpgradeByIndex(key)); } int numChoices = (Plugin.LimitedChoices ? Plugin.NumChoices : list.Count); int num = 0; for (int num2 = 0; num2 < list.Count; num2++) { if (!list2[num2]) { list.RemoveAt(num2 - num); num++; } } numChoices = Mathf.Min(numChoices, list.Count); _ = new Vector2[8] { new Vector2(390f, 18f), new Vector2(530f, 18f), new Vector2(390f, 60f), new Vector2(530f, 60f), new Vector2(390f, 102f), new Vector2(530f, 102f), new Vector2(390f, 144f), new Vector2(530f, 144f) }; for (int i = 0; i < numChoices; i++) { int index = (Plugin.LimitedChoices ? Random.Range(0, list.Count) : 0); int num3 = list[index]; list.RemoveAt(index); _ = i; switch (num3) { case 0: repoPopupPage.AddElement((BuilderDelegate)delegate(Transform parent) { CreateButton(parent, "Stamina", delegate { if (SemiFunc.IsMasterClientOrSingleplayer()) { PunManager.instance.UpgradePlayerEnergy(_steamID, 1); } else { Plugin.DoUpgradeClient("Stamina", _steamID); } }, i, numChoices, _steamID, repoPopupPage); }); continue; case 1: repoPopupPage.AddElement((BuilderDelegate)delegate(Transform parent) { CreateButton(parent, "Extra Jump", delegate { if (SemiFunc.IsMasterClientOrSingleplayer()) { PunManager.instance.UpgradePlayerExtraJump(_steamID, 1); } else { Plugin.DoUpgradeClient("Extra Jump", _steamID); } }, i, numChoices, _steamID, repoPopupPage); }); continue; case 2: repoPopupPage.AddElement((BuilderDelegate)delegate(Transform parent) { CreateButton(parent, "Range", delegate { if (SemiFunc.IsMasterClientOrSingleplayer()) { PunManager.instance.UpgradePlayerGrabRange(_steamID, 1); } else { Plugin.DoUpgradeClient("Range", _steamID); } }, i, numChoices, _steamID, repoPopupPage); }); continue; case 3: repoPopupPage.AddElement((BuilderDelegate)delegate(Transform parent) { CreateButton(parent, "Strength", delegate { if (SemiFunc.IsMasterClientOrSingleplayer()) { PunManager.instance.UpgradePlayerGrabStrength(_steamID, 1); } else { Plugin.DoUpgradeClient("Strength", _steamID); } }, i, numChoices, _steamID, repoPopupPage); }); continue; case 4: repoPopupPage.AddElement((BuilderDelegate)delegate(Transform parent) { CreateButton(parent, "Health", delegate { if (SemiFunc.IsMasterClientOrSingleplayer()) { PunManager.instance.UpgradePlayerHealth(_steamID, 1); } else { Plugin.DoUpgradeClient("Health", _steamID); } }, i, numChoices, _steamID, repoPopupPage); }); continue; case 5: repoPopupPage.AddElement((BuilderDelegate)delegate(Transform parent) { CreateButton(parent, "Sprint Speed", delegate { if (SemiFunc.IsMasterClientOrSingleplayer()) { PunManager.instance.UpgradePlayerSprintSpeed(_steamID, 1); } else { Plugin.DoUpgradeClient("Sprint Speed", _steamID); } }, i, numChoices, _steamID, repoPopupPage); }); continue; case 6: repoPopupPage.AddElement((BuilderDelegate)delegate(Transform parent) { CreateButton(parent, "Tumble Launch", delegate { if (SemiFunc.IsMasterClientOrSingleplayer()) { PunManager.instance.UpgradePlayerTumbleLaunch(_steamID, 1); } else { Plugin.DoUpgradeClient("Tumble Launch", _steamID); } }, i, numChoices, _steamID, repoPopupPage); }); continue; case 7: repoPopupPage.AddElement((BuilderDelegate)delegate(Transform parent) { CreateButton(parent, "Map Player Count", delegate { if (SemiFunc.IsMasterClientOrSingleplayer()) { PunManager.instance.UpgradeMapPlayerCount(_steamID, 1); } else { Plugin.DoUpgradeClient("Map Player Count", _steamID); } }, i, numChoices, _steamID, repoPopupPage); }); continue; case 8: repoPopupPage.AddElement((BuilderDelegate)delegate(Transform parent) { CreateButton(parent, "Tumble Climb", delegate { if (SemiFunc.IsMasterClientOrSingleplayer()) { PunManager.instance.UpgradePlayerTumbleClimb(_steamID, 1); } else { Plugin.DoUpgradeClient("Tumble Climb", _steamID); } }, i, numChoices, _steamID, repoPopupPage); }); continue; case 9: repoPopupPage.AddElement((BuilderDelegate)delegate(Transform parent) { CreateButton(parent, "Death Head Battery", delegate { if (SemiFunc.IsMasterClientOrSingleplayer()) { PunManager.instance.UpgradeDeathHeadBattery(_steamID, 1); } else { Plugin.DoUpgradeClient("Death Head Battery", _steamID); } }, i, numChoices, _steamID, repoPopupPage); }); continue; case 10: repoPopupPage.AddElement((BuilderDelegate)delegate(Transform parent) { CreateButton(parent, "Tumble Wings", delegate { if (SemiFunc.IsMasterClientOrSingleplayer()) { PunManager.instance.UpgradePlayerTumbleWings(_steamID, 1); } else { Plugin.DoUpgradeClient("Tumble Wings", _steamID); } }, i, numChoices, _steamID, repoPopupPage); }); continue; case 11: repoPopupPage.AddElement((BuilderDelegate)delegate(Transform parent) { CreateButton(parent, "Crouch Rest", delegate { if (SemiFunc.IsMasterClientOrSingleplayer()) { PunManager.instance.UpgradePlayerCrouchRest(_steamID, 1); } else { Plugin.DoUpgradeClient("Crouch Rest", _steamID); } }, i, numChoices, _steamID, repoPopupPage); }); continue; } int key2 = num3 - 12; string extraLabel = ModUpgradeHandler.ExtraLabels[key2]; string extraKey = ModUpgradeHandler.ExtraKeys[key2]; repoPopupPage.AddElement((BuilderDelegate)delegate(Transform parent) { CreateButton(parent, extraLabel, delegate { if (SemiFunc.IsMasterClientOrSingleplayer()) { ModUpgradeHandler.DoUpgrade(extraKey, _steamID); } else { Plugin.DoUpgradeClient(extraKey, _steamID); } }, i, numChoices, _steamID, repoPopupPage); }); } return repoPopupPage; } private static REPOButton CreateButton(Transform parent, string buttonText, Action upgradeStat, int buttonNumber, int totalButtons, string _steamID, REPOPopupPage page) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) (Vector2, float) buttonPos = GetButtonPos(buttonNumber, totalButtons); Vector2 item = buttonPos.Item1; float item2 = buttonPos.Item2; REPOButton obj = MenuAPI.CreateREPOButton(buttonText, (Action)delegate { if (!choseUpgrade) { choseUpgrade = true; upgradeStat(); Plugin.ApplyUpgrade(_steamID, page); } }, parent, item); TextMeshProUGUI labelTMP = obj.labelTMP; ((TMP_Text)labelTMP).fontSize = ((TMP_Text)labelTMP).fontSize * item2; return obj; } private static (Vector2, float) GetButtonPos(int buttonNumber, int totalButtons) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) if (totalButtons <= 8) { return (new Vector2(370f + (float)(140 * (buttonNumber % 2)), 270f - 52f * (float)(buttonNumber / 2)), 0.9f); } float num = 252f; int num2 = 8; float num3 = num / (42f * (float)(totalButtons / num2)); float num4 = num3 * 42f; float num5 = num3 * 180f; num2 = Math.Max((int)(370f / num5), 2); while (num2 != 1) { num2--; num3 = Math.Min(num / (42f * (float)(totalButtons / num2)), 2f / (float)num2); num4 = num3 * 42f; num5 = num3 * 180f; if (!((float)(totalButtons / num2) * num4 < num)) { break; } } num2++; num3 = Math.Min(num / (42f * (float)(totalButtons / num2)), 2f / (float)num2); num4 = num3 * 42f; num5 = num3 * 180f; return (new Vector2(370f + (float)(buttonNumber % num2) * num5, 270f - (float)(buttonNumber / num2) * num4), num3 * 0.9f); } } internal static class UpgradeUsageData { internal const string DictionaryName = "upgradeEveryRoundUsage"; private const string LegacyDictionaryName = "playerUpgradesUsed"; internal static void Initialize(StatsManager statsManager) { IDictionary<string, Dictionary<string, int>> dictionaries = GetDictionaries(statsManager); if (!dictionaries.TryGetValue("upgradeEveryRoundUsage", out var value)) { value = new Dictionary<string, int>(); dictionaries.Add("upgradeEveryRoundUsage", value); } if (!dictionaries.TryGetValue("playerUpgradesUsed", out var value2)) { return; } foreach (KeyValuePair<string, int> item in value2) { if (!value.ContainsKey(item.Key)) { value[item.Key] = item.Value; } } dictionaries.Remove("playerUpgradesUsed"); } internal static int GetCount(StatsManager statsManager, string steamId) { if (!GetCounts(statsManager).TryGetValue(steamId, out var value)) { return 0; } return value; } internal static void SetCount(StatsManager statsManager, string steamId, int count) { GetCounts(statsManager)[steamId] = count; } private static Dictionary<string, int> GetCounts(StatsManager statsManager) { IDictionary<string, Dictionary<string, int>> dictionaries = GetDictionaries(statsManager); if (!dictionaries.TryGetValue("upgradeEveryRoundUsage", out var value)) { value = new Dictionary<string, int>(); dictionaries.Add("upgradeEveryRoundUsage", value); } return value; } private static IDictionary<string, Dictionary<string, int>> GetDictionaries(StatsManager statsManager) { if ((Object)(object)statsManager == (Object)null) { throw new ArgumentNullException("statsManager"); } return (Traverse.Create((object)statsManager).Field("dictionaryOfDictionaries").GetValue() as IDictionary<string, Dictionary<string, int>>) ?? throw new MissingFieldException(typeof(StatsManager).FullName, "dictionaryOfDictionaries"); } } public static class MyPluginInfo { public const string PLUGIN_GUID = "UpgradeEveryRound"; public const string PLUGIN_NAME = "Upgrade Every Round"; public const string PLUGIN_VERSION = "2.0.3"; } }