using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Net; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Logging; using CubeX.Core; using CubeX.Features.Actions; using CubeX.Features.Game; using CubeX.Features.Host; using CubeX.Features.Inventory; using CubeX.Features.Misc; using CubeX.Features.Misc.PauseMenuFeatures; using CubeX.Features.Network; using CubeX.Features.Player; using CubeX.Features.Player.PlayerActions; using CubeX.Features.Search; using CubeX.Features.Self; using CubeX.Features.Settings; using CubeX.Features.Spawn; using CubeX.Features.Teleport; using CubeX.Features.Visuals; using CubeX.Features.World; using CubeX.Runtime.Diagnostics; using CubeX.Runtime.Network; using CubeX.Runtime.Player; using CubeX.UI; using CubeX.UI.Features; using ExitGames.Client.Photon; using HarmonyLib; using JetBrains.Annotations; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Peak.Network; using Photon.Pun; using Photon.Realtime; using Photon.Voice; using Photon.Voice.PUN; using Photon.Voice.Unity; using TMPro; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.Playables; using UnityEngine.Rendering; using UnityEngine.SceneManagement; using UnityEngine.Serialization; using UnityEngine.UI; using Zorro.Core; using Zorro.Core.Serizalization; [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("CubeX")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.3.2.0")] [assembly: AssemblyInformationalVersion("1.3.2+0b937d626c053269000f652cd3c66364b965afb2")] [assembly: AssemblyProduct("Cube-X mod menu for PEAK")] [assembly: AssemblyTitle("CubeX")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.3.2.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] [CompilerGenerated] internal sealed class <>z__ReadOnlyArray : IEnumerable, ICollection, IList, IEnumerable, IReadOnlyCollection, IReadOnlyList, ICollection, IList { int ICollection.Count => _items.Length; bool ICollection.IsSynchronized => false; object ICollection.SyncRoot => this; object IList.this[int index] { get { return _items[index]; } set { throw new NotSupportedException(); } } bool IList.IsFixedSize => true; bool IList.IsReadOnly => true; int IReadOnlyCollection.Count => _items.Length; T IReadOnlyList.this[int index] => _items[index]; int ICollection.Count => _items.Length; bool ICollection.IsReadOnly => true; T IList.this[int index] { get { return _items[index]; } set { throw new NotSupportedException(); } } public <>z__ReadOnlyArray(T[] items) { _items = items; } IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)_items).GetEnumerator(); } void ICollection.CopyTo(Array array, int index) { ((ICollection)_items).CopyTo(array, index); } int IList.Add(object value) { throw new NotSupportedException(); } void IList.Clear() { throw new NotSupportedException(); } bool IList.Contains(object value) { return ((IList)_items).Contains(value); } int IList.IndexOf(object value) { return ((IList)_items).IndexOf(value); } void IList.Insert(int index, object value) { throw new NotSupportedException(); } void IList.Remove(object value) { throw new NotSupportedException(); } void IList.RemoveAt(int index) { throw new NotSupportedException(); } IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)_items).GetEnumerator(); } void ICollection.Add(T item) { throw new NotSupportedException(); } void ICollection.Clear() { throw new NotSupportedException(); } bool ICollection.Contains(T item) { return ((ICollection)_items).Contains(item); } void ICollection.CopyTo(T[] array, int arrayIndex) { ((ICollection)_items).CopyTo(array, arrayIndex); } bool ICollection.Remove(T item) { throw new NotSupportedException(); } int IList.IndexOf(T item) { return ((IList)_items).IndexOf(item); } void IList.Insert(int index, T item) { throw new NotSupportedException(); } void IList.RemoveAt(int index) { throw new NotSupportedException(); } } [CompilerGenerated] internal sealed class <>z__ReadOnlySingleElementList : IEnumerable, ICollection, IList, IEnumerable, IReadOnlyCollection, IReadOnlyList, ICollection, IList { private sealed class Enumerator : IDisposable, IEnumerator, IEnumerator { object IEnumerator.Current => _item; T IEnumerator.Current => _item; public Enumerator(T item) { _item = item; } bool IEnumerator.MoveNext() { if (!_moveNextCalled) { return _moveNextCalled = true; } return false; } void IEnumerator.Reset() { _moveNextCalled = false; } void IDisposable.Dispose() { } } int ICollection.Count => 1; bool ICollection.IsSynchronized => false; object ICollection.SyncRoot => this; object IList.this[int index] { get { if (index != 0) { throw new IndexOutOfRangeException(); } return _item; } set { throw new NotSupportedException(); } } bool IList.IsFixedSize => true; bool IList.IsReadOnly => true; int IReadOnlyCollection.Count => 1; T IReadOnlyList.this[int index] { get { if (index != 0) { throw new IndexOutOfRangeException(); } return _item; } } int ICollection.Count => 1; bool ICollection.IsReadOnly => true; T IList.this[int index] { get { if (index != 0) { throw new IndexOutOfRangeException(); } return _item; } set { throw new NotSupportedException(); } } public <>z__ReadOnlySingleElementList(T item) { _item = item; } IEnumerator IEnumerable.GetEnumerator() { return new Enumerator(_item); } void ICollection.CopyTo(Array array, int index) { array.SetValue(_item, index); } int IList.Add(object value) { throw new NotSupportedException(); } void IList.Clear() { throw new NotSupportedException(); } bool IList.Contains(object value) { return EqualityComparer.Default.Equals(_item, (T)value); } int IList.IndexOf(object value) { if (!EqualityComparer.Default.Equals(_item, (T)value)) { return -1; } return 0; } void IList.Insert(int index, object value) { throw new NotSupportedException(); } void IList.Remove(object value) { throw new NotSupportedException(); } void IList.RemoveAt(int index) { throw new NotSupportedException(); } IEnumerator IEnumerable.GetEnumerator() { return new Enumerator(_item); } void ICollection.Add(T item) { throw new NotSupportedException(); } void ICollection.Clear() { throw new NotSupportedException(); } bool ICollection.Contains(T item) { return EqualityComparer.Default.Equals(_item, item); } void ICollection.CopyTo(T[] array, int arrayIndex) { array[arrayIndex] = _item; } bool ICollection.Remove(T item) { throw new NotSupportedException(); } int IList.IndexOf(T item) { if (!EqualityComparer.Default.Equals(_item, item)) { return -1; } return 0; } void IList.Insert(int index, T item) { throw new NotSupportedException(); } void IList.RemoveAt(int index) { throw new NotSupportedException(); } } namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace CubeX { [BepInPlugin("com.mister9982.cubex", "Cube-X", "1.3.2")] public class Plugin : BaseUnityPlugin { private Harmony _harmony; private bool _updateFailureLogged; private const string ModGuid = "com.mister9982.cubex"; private const string ModName = "Cube-X"; public const string ModVersion = "1.3.2"; public static Plugin Instance { get; private set; } public static ManualLogSource Log { get; private set; } private static FeatureManager FeatureManager { get; set; } private static MenuUI Menu { get; set; } private void Awake() { //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Expected O, but got Unknown //IL_008a: 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) Instance = this; Log = ((BaseUnityPlugin)this).Logger; try { FeatureManager = new FeatureManager(); FeatureManager.RegisterAllFromAssembly(); ConfigService.Initialize(FeatureManager); Menu = ((Component)this).gameObject.AddComponent(); Menu.Bind(FeatureManager); ((Component)this).gameObject.AddComponent(); NotificationSystem.MarkReady(); _harmony = new Harmony("com.mister9982.cubex"); PatchAllSafely(); Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject); KeyCode menuBind = RuntimeKeybinds.MenuBind; CubeXDiagnostics.Info("Cube-X", "v1.3.2 loaded - press " + ((object)(KeyCode)(ref menuBind)).ToString() + " to open.", notify: true); } catch (Exception exception) { CubeXDiagnostics.Error("Cube-X", "Startup failed.", exception); } } private void PatchAllSafely() { int num = 0; int num2 = 0; Type[] typesSafely = GetTypesSafely(Assembly.GetExecutingAssembly()); foreach (Type type in typesSafely) { if (!(type == null) && HasHarmonyPatch(type)) { try { _harmony.CreateClassProcessor(type).Patch(); num++; } catch (Exception ex) { num2++; CubeXDiagnostics.Warning("Harmony", "Skipped patch " + type.FullName + ": " + ex.GetBaseException().Message); } } } CubeXDiagnostics.Info("Harmony", "Patches applied: " + num + ", skipped: " + num2 + ".", num2 > 0); } private static Type[] GetTypesSafely(Assembly assembly) { try { return assembly.GetTypes(); } catch (ReflectionTypeLoadException ex) { return ex.Types.Where((Type t) => t != null).ToArray(); } } private static bool HasHarmonyPatch(Type type) { if (type.GetCustomAttributes(typeof(HarmonyPatch), inherit: false).Length != 0) { return true; } return type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).Any((MethodInfo t) => t.GetCustomAttributes(typeof(HarmonyPatch), inherit: false).Length != 0); } private void Update() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) try { if (!RuntimeKeybinds.IsCapturing && (Object)(object)Menu != (Object)null) { bool keyDown = Input.GetKeyDown(RuntimeKeybinds.MenuBind); bool flag = MenuControllerInput.ToggleMenuPressed(); if (keyDown || flag) { Menu.IsOpen = !Menu.IsOpen; } } RuntimeKeybinds.TickFeatureBinds(FeatureManager); FeatureManager?.Tick(); ConfigService.Tick(); } catch (Exception exception) { if (!_updateFailureLogged) { _updateFailureLogged = true; CubeXDiagnostics.Error("Cube-X", "Update loop failed. Further update-loop errors will be logged only.", exception); } else { CubeXDiagnostics.Error("Cube-X", "Update loop failed.", exception, notify: false); } } } private void OnDestroy() { CubeXDiagnostics.Try("Cube-X", "Unpatch Harmony", delegate { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } }, notifyErrors: false); CubeXDiagnostics.Try("Cube-X", "Shutdown config", ConfigService.Shutdown, notifyErrors: false); CubeXDiagnostics.Try("Cube-X", "Disable features", delegate { FeatureManager?.DisableAll(); }, notifyErrors: false); } } public static class MyPluginInfo { public const string PLUGIN_GUID = "CubeX"; public const string PLUGIN_NAME = "Cube-X mod menu for PEAK"; public const string PLUGIN_VERSION = "1.3.2"; } } namespace CubeX.UI { internal static class DiscordCommunityPrompt { private const string InviteUrl = "https://discord.gg/cHmp58MqPf"; private static bool _dismissedThisSession; private static bool? _dismissedPersisted; private static GUIStyle _titleStyle; private static GUIStyle _bodyStyle; private static GUIStyle _buttonStyle; private const string StateFolderName = "State"; private static string StatePath => AppDataPaths.FilePath("State", "discord_prompt_seen"); public static bool ShouldRender { get { if (!_dismissedThisSession) { return !IsDismissedPersisted(); } return false; } } public static void OpenInvite() { Application.OpenURL("https://discord.gg/cHmp58MqPf"); } public static void Render() { //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_020f: Unknown result type (might be due to invalid IL or missing references) if (ShouldRender) { EnsureStyles(); float num = Mathf.Min(420f, Mathf.Max(280f, (float)Screen.width - 36f)); float num2 = 168f; Rect val = default(Rect); ((Rect)(ref val))..ctor(((float)Screen.width - num) * 0.5f, Mathf.Max(24f, (float)Screen.height * 0.18f), num, num2); Theme.Fill(new Rect(0f, 0f, (float)Screen.width, (float)Screen.height), new Color(0f, 0f, 0f, 0.42f)); Theme.Fill(val, new Color(0.035f, 0.035f, 0.04f, 0.96f)); Theme.Fill(new Rect(((Rect)(ref val)).x, ((Rect)(ref val)).y, 4f, ((Rect)(ref val)).height), MenuConfig.AccentColor); DrawOutline(val, new Color(1f, 1f, 1f, 0.14f), 1f); GUI.Label(new Rect(((Rect)(ref val)).x + 20f, ((Rect)(ref val)).y + 18f, ((Rect)(ref val)).width - 40f, 28f), "Join the Cube-X Discord?", _titleStyle); GUI.Label(new Rect(((Rect)(ref val)).x + 20f, ((Rect)(ref val)).y + 52f, ((Rect)(ref val)).width - 40f, 46f), "Get updates, support, and community help from the Discord server.", _bodyStyle); Rect val2 = new Rect(((Rect)(ref val)).x + ((Rect)(ref val)).width - 220f, ((Rect)(ref val)).yMax - 52f, 96f, 32f); Rect val3 = default(Rect); ((Rect)(ref val3))..ctor(((Rect)(ref val)).x + ((Rect)(ref val)).width - 114f, ((Rect)(ref val)).yMax - 52f, 94f, 32f); if (GUI.Button(val2, "Join", _buttonStyle)) { Dismiss(); OpenInvite(); Event.current.Use(); } if (GUI.Button(val3, "Not Now", _buttonStyle)) { Dismiss(); Event.current.Use(); } } } private static void Dismiss() { _dismissedThisSession = true; _dismissedPersisted = true; try { Directory.CreateDirectory(AppDataPaths.DirectoryPath("State")); File.WriteAllText(StatePath, "1"); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Discord Prompt] Failed to persist dismissal: " + ex.Message)); } } } private static bool IsDismissedPersisted() { if (_dismissedPersisted.HasValue) { return _dismissedPersisted.Value; } try { AppDataPaths.MigrateFileToDirectory("discord_prompt_seen", "State"); _dismissedPersisted = File.Exists(StatePath); } catch { _dismissedPersisted = false; } return _dismissedPersisted.Value; } private static void EnsureStyles() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected O, but got Unknown //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: 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_0073: 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_0089: Expected O, but got Unknown //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Expected O, but got Unknown if (_titleStyle == null) { GUIStyle val = new GUIStyle(GUI.skin.label) { fontSize = 18, fontStyle = (FontStyle)1 }; val.normal.textColor = Color.white; val.clipping = (TextClipping)1; _titleStyle = val; GUIStyle val2 = new GUIStyle(GUI.skin.label) { fontSize = 13 }; val2.normal.textColor = new Color(0.9f, 0.9f, 0.9f, 1f); val2.wordWrap = true; _bodyStyle = val2; _buttonStyle = new GUIStyle(GUI.skin.button) { fontSize = 13, fontStyle = (FontStyle)1 }; } } private static void DrawOutline(Rect rect, Color color, float thickness) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: 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_0082: Unknown result type (might be due to invalid IL or missing references) Theme.Fill(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, ((Rect)(ref rect)).width, thickness), color); Theme.Fill(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).yMax - thickness, ((Rect)(ref rect)).width, thickness), color); Theme.Fill(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, thickness, ((Rect)(ref rect)).height), color); Theme.Fill(new Rect(((Rect)(ref rect)).xMax - thickness, ((Rect)(ref rect)).y, thickness, ((Rect)(ref rect)).height), color); } } [HarmonyPatch(typeof(Character), "RPCA_Die")] internal static class CharacterDiedNotificationPatch { private static void Postfix(Character __instance) { CharacterEventNotifications.NotifyDied(__instance); } } internal static class CharacterEventNotifications { private const float Cooldown = 1.2f; private static readonly Dictionary LastEvents = new Dictionary(); public static void NotifyDied(Character character) { NotifyCharacterEvent(character, "Player Died", NotificationKind.Error, "died"); } public static void NotifyPassedOut(Character character) { NotifyCharacterEvent(character, "Player Passed Out", NotificationKind.Warning, "passed-out"); } public static void NotifyRevived(Character character) { NotifyCharacterEvent(character, "Player Revived", NotificationKind.Success, "revived"); } private static void NotifyCharacterEvent(Character character, string title, NotificationKind kind, string key) { if (NotificationSettings.PlayerLife && IsPlayerCharacter(character) && !IsCoolingDown(key + ":" + ((Object)character).GetInstanceID().ToString(CultureInfo.InvariantCulture))) { NotificationSystem.Push(title, GetCharacterNameForNotifications(character), kind); } } private static bool IsCoolingDown(string key) { float unscaledTime = Time.unscaledTime; if (LastEvents.TryGetValue(key, out var value) && unscaledTime - value < 1.2f) { return true; } LastEvents[key] = unscaledTime; return false; } private static bool IsPlayerCharacter(Character character) { if (!Object.op_Implicit((Object)(object)character)) { return false; } if (character.isBot || character.isZombie || character.isScoutmaster) { return false; } PhotonView photonView = GetPhotonView((Component)(object)character); if (Object.op_Implicit((Object)(object)photonView)) { return photonView.Owner != null; } return false; } public static string GetCharacterNameForNotifications(Character character) { PhotonView photonView = GetPhotonView((Component)(object)character); if (Object.op_Implicit((Object)(object)photonView) && photonView.Owner != null) { string nickName = photonView.Owner.NickName; if (!string.IsNullOrWhiteSpace(nickName)) { return nickName + " #" + photonView.Owner.ActorNumber.ToString(CultureInfo.InvariantCulture); } } return "Player " + ((Object)character).GetInstanceID().ToString(CultureInfo.InvariantCulture); } private static PhotonView GetPhotonView(Component component) { if (!Object.op_Implicit((Object)(object)component)) { return null; } return component.GetComponent() ?? component.GetComponentInChildren(); } } [HarmonyPatch(typeof(Character), "RPCA_PassOut")] internal static class CharacterPassedOutNotificationPatch { private static void Postfix(Character __instance) { CharacterEventNotifications.NotifyPassedOut(__instance); } } [HarmonyPatch(typeof(Character), "RPCA_ReviveAtPosition")] internal static class CharacterRevivedAtPositionNotificationPatch { private static void Postfix(Character __instance) { CharacterEventNotifications.NotifyRevived(__instance); } } [HarmonyPatch(typeof(Character), "RPCA_Revive")] internal static class CharacterRevivedNotificationPatch { private static void Postfix(Character __instance) { CharacterEventNotifications.NotifyRevived(__instance); } } public class GameEventNotifier : MonoBehaviour, IInRoomCallbacks { private void OnEnable() { PhotonNetwork.AddCallbackTarget((object)this); } private void OnDisable() { PhotonNetwork.RemoveCallbackTarget((object)this); } public void OnPlayerEnteredRoom(Player newPlayer) { RecentPlayersStore.Record(newPlayer); if (!PlayerBlacklistStore.TryBlock(newPlayer) && NotificationSettings.JoinLeave && newPlayer != null && !newPlayer.IsLocal) { NotificationSystem.Push("Player Joined", GetPlayerName(newPlayer), NotificationKind.Success); } } public void OnPlayerLeftRoom(Player otherPlayer) { RecentPlayersStore.Record(otherPlayer); if (NotificationSettings.JoinLeave && otherPlayer != null && !otherPlayer.IsLocal) { NotificationSystem.Push("Player Left", GetPlayerName(otherPlayer), NotificationKind.Warning); } } public void OnRoomPropertiesUpdate(Hashtable propertiesThatChanged) { } public void OnPlayerPropertiesUpdate(Player targetPlayer, Hashtable changedProps) { } public void OnMasterClientSwitched(Player newMasterClient) { if (newMasterClient != null && newMasterClient.IsLocal) { PlayerBlacklistStore.EnforceCurrentRoomBlacklist(); } } private static string GetPlayerName(Player player) { if (player == null) { return "Unknown"; } return (string.IsNullOrWhiteSpace(player.NickName) ? "Player" : player.NickName) + " #" + player.ActorNumber.ToString(CultureInfo.InvariantCulture); } } public static class NotificationSettings { public static bool JoinLeave = true; public static bool PlayerLife = true; public static bool RpcEvents = true; public static bool KeybindToggles = true; } public static class RpcEventNotifications { private const float Cooldown = 0.7f; private static readonly Dictionary LastEvents = new Dictionary(); public static void NotifyExecuted(string methodName, Player sender, PhotonView view) { if (NotificationSettings.RpcEvents && !string.IsNullOrEmpty(methodName) && !IsCoolingDown("rpc:" + methodName + ":" + GetSenderKey(sender) + ":" + (Object.op_Implicit((Object)(object)view) ? view.ViewID.ToString(CultureInfo.InvariantCulture) : "0"))) { string text = ((sender != null && sender.IsLocal) ? "You" : GetPlayerName(sender)); string targetText = GetTargetText(view); string description = (string.IsNullOrEmpty(targetText) ? text : (text + " -> " + targetText)); NotificationSystem.Push("RPC " + methodName, description); } } public static void NotifyBlocked(string methodName, Player sender) { if (NotificationSettings.RpcEvents && !string.IsNullOrEmpty(methodName) && !IsCoolingDown("blocked:" + methodName + ":" + GetSenderKey(sender))) { NotificationSystem.Push("RPC Blocked", methodName + " from " + GetPlayerName(sender), NotificationKind.Warning); } } public static void NotifyProtectionDetected(string eventName, Player sender, PhotonView view) { if (NotificationSettings.RpcEvents && !string.IsNullOrEmpty(eventName) && !IsCoolingDown("protection:" + eventName + ":" + GetSenderKey(sender) + ":" + (Object.op_Implicit((Object)(object)view) ? view.ViewID.ToString(CultureInfo.InvariantCulture) : "0"))) { string targetText = GetTargetText(view); string text = eventName + " from " + GetPlayerName(sender); if (!string.IsNullOrEmpty(targetText)) { text = text + " -> " + targetText; } NotificationSystem.Push("Modder Detection", text, NotificationKind.Warning); } } public static void NotifyProtectionBlocked(string eventName, Player sender) { if (NotificationSettings.RpcEvents && !string.IsNullOrEmpty(eventName) && !IsCoolingDown("protection-blocked:" + eventName + ":" + GetSenderKey(sender))) { NotificationSystem.Push("Protection Blocked", eventName + " from " + GetPlayerName(sender), NotificationKind.Warning); } } private static bool IsCoolingDown(string key) { float unscaledTime = Time.unscaledTime; if (LastEvents.TryGetValue(key, out var value) && unscaledTime - value < 0.7f) { return true; } LastEvents[key] = unscaledTime; return false; } private static string GetSenderKey(Player sender) { if (sender != null) { return sender.ActorNumber.ToString(CultureInfo.InvariantCulture); } return "unknown"; } private static string GetPlayerName(Player player) { if (player == null) { return "Unknown"; } return (string.IsNullOrWhiteSpace(player.NickName) ? "Player" : player.NickName) + " #" + player.ActorNumber.ToString(CultureInfo.InvariantCulture); } private static string GetTargetText(PhotonView view) { if (!Object.op_Implicit((Object)(object)view)) { return string.Empty; } Character val = ((Component)view).GetComponent() ?? ((Component)view).GetComponentInParent() ?? ((Component)view).GetComponentInChildren(); if (Object.op_Implicit((Object)(object)val)) { return CharacterEventNotifications.GetCharacterNameForNotifications(val); } return "View " + view.ViewID.ToString(CultureInfo.InvariantCulture); } } public struct ColorPreset { public readonly string Name; public readonly Color Color; public ColorPreset(string name, Color color) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) Name = name; Color = color; } } public static class MenuConfig { public static readonly ColorPreset[] Presets = new ColorPreset[8] { new ColorPreset("Teal", new Color(0.243f, 0.706f, 0.537f, 1f)), new ColorPreset("Purple", new Color(0.486f, 0.361f, 1f, 1f)), new ColorPreset("Crimson", new Color(0.937f, 0.267f, 0.267f, 1f)), new ColorPreset("Sky", new Color(0.231f, 0.62f, 0.965f, 1f)), new ColorPreset("Lime", new Color(0.486f, 0.831f, 0.267f, 1f)), new ColorPreset("Amber", new Color(0.976f, 0.69f, 0.086f, 1f)), new ColorPreset("Pink", new Color(0.945f, 0.345f, 0.62f, 1f)), new ColorPreset("Cyan", new Color(0.063f, 0.808f, 0.851f, 1f)) }; public static int PresetIndex = 0; public static Color AccentColor = Presets[0].Color; private const float ReferenceWidth = 1920f; private const float ReferenceHeight = 1080f; private const float MinUIScale = 0.5f; private const float MaxConfiguredUIScale = 4f; private const float DefaultMenuWidth = 480f; private const float DefaultUIScale = 1f; private const float DefaultHighlightLerpSpeed = 18f; private const int DefaultMaxVisibleRows = 12; public static float MenuWidth = 480f; public static float UIScale = 1f; public static float HighlightLerpSpeed = 18f; public static int MaxVisibleRows = 12; public static bool ShowBreadcrumb = true; public static bool ShowDescription = true; public static bool ShowFooter = true; public static bool ShowScrollbar = true; public static bool AutoSave = false; public static bool AutoLoadOnStart = true; public static void ApplyPreset(int index) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) int num = Presets.Length; PresetIndex = (index % num + num) % num; AccentColor = Presets[PresetIndex].Color; } public static void SetAccentColor(Color color) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //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_003f: 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_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0062: 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) AccentColor = new Color(Mathf.Clamp01(color.r), Mathf.Clamp01(color.g), Mathf.Clamp01(color.b), 1f); for (int i = 0; i < Presets.Length; i++) { Color color2 = Presets[i].Color; if (Mathf.Abs(color2.r - AccentColor.r) <= 0.001f && Mathf.Abs(color2.g - AccentColor.g) <= 0.001f && Mathf.Abs(color2.b - AccentColor.b) <= 0.001f) { PresetIndex = i; break; } } } public static float GetMaxUIScale() { if (Screen.width <= 0 || Screen.height <= 0) { return 4f; } float num = (float)Screen.width / 1920f; float num2 = (float)Screen.height / 1080f; return Mathf.Max(1f, Mathf.Min(num, num2)); } public static float GetResolvedUIScale() { return Mathf.Clamp(UIScale, 0.5f, GetMaxUIScale()); } public static void SetUIScale(float scale) { UIScale = Mathf.Clamp(scale, 0.5f, GetMaxUIScale()); } public static void ResetToDefaults() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) PresetIndex = 0; AccentColor = Presets[0].Color; MenuWidth = 480f; UIScale = 1f; HighlightLerpSpeed = 18f; MaxVisibleRows = 12; ShowBreadcrumb = true; ShowDescription = true; ShowFooter = true; ShowScrollbar = true; AutoSave = false; AutoLoadOnStart = true; } } internal static class MenuControllerInput { private sealed class DirectionRepeater { private int _heldDirection; private float _nextRepeatAt; public int Consume(int direction) { if (direction == 0) { Reset(); return 0; } float unscaledTime = Time.unscaledTime; if (direction != _heldDirection) { _heldDirection = direction; _nextRepeatAt = unscaledTime + 0.32f; return direction; } if (unscaledTime < _nextRepeatAt) { return 0; } _nextRepeatAt = unscaledTime + 0.09f; return direction; } public void Reset() { _heldDirection = 0; _nextRepeatAt = 0f; } } private const float RepeatDelay = 0.32f; private const float RepeatInterval = 0.09f; private static readonly DirectionRepeater VerticalRepeat = new DirectionRepeater(); private static readonly DirectionRepeater HorizontalRepeat = new DirectionRepeater(); private static bool _confirmHeld; private static bool _backHeld; private static bool _toggleChordHeld; public static bool ToggleMenuPressed() { bool flag = ToggleMenuChordHeld(); bool result = flag && !_toggleChordHeld; _toggleChordHeld = flag; return result; } public static bool ToggleMenuChordHeld() { Gamepad val = CurrentGamepad(); if (val != null && val.dpad.right.isPressed) { return val.rightShoulder.isPressed; } return false; } public static bool ConfirmPressed() { Gamepad obj = CurrentGamepad(); return ConsumePress(obj != null && obj.buttonSouth.isPressed, ref _confirmHeld); } public static bool BackPressed() { Gamepad obj = CurrentGamepad(); return ConsumePress(obj != null && obj.buttonEast.isPressed, ref _backHeld); } public static int ConsumeVerticalDirection() { Gamepad val = CurrentGamepad(); int direction = 0; if (val != null) { if (val.dpad.up.isPressed) { direction = -1; } else if (val.dpad.down.isPressed) { direction = 1; } } return VerticalRepeat.Consume(direction); } public static int ConsumeHorizontalDirection() { Gamepad val = CurrentGamepad(); int direction = 0; if (val != null) { if (val.dpad.left.isPressed) { direction = -1; } else if (val.dpad.right.isPressed && !val.rightShoulder.isPressed) { direction = 1; } } return HorizontalRepeat.Consume(direction); } public static void Reset() { VerticalRepeat.Reset(); HorizontalRepeat.Reset(); _confirmHeld = false; _backHeld = false; } private static Gamepad CurrentGamepad() { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) Gamepad current = Gamepad.current; if (current != null) { return current; } if (Gamepad.all.Count <= 0) { return null; } return Gamepad.all[0]; } private static bool ConsumePress(bool pressed, ref bool held) { bool result = pressed && !held; held = pressed; return result; } } internal static class MenuInputCapture { private static bool _active; private static bool _menuOpen; private static bool _savedCursorVisible; private static CursorLockMode _savedLockState; public static bool BlocksPlayerInput => _active; public static bool SuppressesMenuEmoteInput => _menuOpen; public static void SetMenuOpen(bool open) { _menuOpen = open; } public static void Begin() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) if (!_active) { _savedCursorVisible = Cursor.visible; _savedLockState = Cursor.lockState; _active = true; } ApplyCursor(); } public static void Tick() { if (_active) { ApplyCursor(); } } public static void End() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) if (_active) { _active = false; Cursor.visible = _savedCursorVisible; Cursor.lockState = _savedLockState; } } private static void ApplyCursor() { Cursor.visible = true; Cursor.lockState = (CursorLockMode)0; } } public class MenuUI : MonoBehaviour { private readonly struct MenuNavigationState { public string Category { get; } public int SelectedIndex { get; } public float ScrollY { get; } public float ScrollYTarget { get; } public MenuNavigationState(string category, int selectedIndex, float scrollY, float scrollYTarget) { Category = category; SelectedIndex = selectedIndex; ScrollY = scrollY; ScrollYTarget = scrollYTarget; } } private FeatureManager _features; private bool _isOpen; private string _category; private int _selected; private readonly List _rows = new List(); private readonly Dictionary _categoryTitles = new Dictionary(); private readonly Stack _navigationStack = new Stack(); private float _highlightY; private float _highlightYTarget; private float _scrollY; private float _scrollYTarget; private bool _animationsInited; private bool _editingNumber; private NumberFeature _editingNumberFeature; private int _editingNumberIndex = -1; private string _editingText = string.Empty; private bool _focusNumberInputNext; private const string NumberInputControl = "CubeX_NumberInput"; private bool _editingTextFeatureActive; private TextFeature _editingTextFeature; private int _editingTextIndex = -1; private string _editingTextOriginal = string.Empty; private bool _focusTextInputNext; private const string TextInputControl = "CubeX_TextInput"; private bool _editingColor; private ColorFeature _editingColorFeature; private int _editingColorIndex = -1; private float _colorHue; private float _colorSaturation; private float _colorValue; private Color _editingColorPreview = Color.white; private int _colorDragTarget; private Texture2D _colorHueTexture; private Texture2D _colorSatValTexture; private Texture2D _staminaStripeTexture; private float _colorSatValTextureHue = -1f; private GUIStyle _descriptionTextStyle; private float _descriptionTextStyleScale = -1f; private readonly StringBuilder _descriptionWrapBuilder = new StringBuilder(); private readonly Dictionary _smoothPlayerMetrics = new Dictionary(); private readonly SelectedPlayerPreviewPanel _selectedPlayerPreviewPanel = new SelectedPlayerPreviewPanel(); private Rect _window = new Rect(-1f, -1f, 480f, 720f); private bool _hasPositionedWindow; private bool _dragging; private Vector2 _dragOffset; private float _scale = 1f; private bool _themeInitialized; private bool _rowsDirty = true; private int _lastMenuRefreshFrame = -1; private int _lastRowsRefreshFrame = -1; private int _lastOverlayRenderFrame = -1; private float _nextRowsRefreshAt; private float _heroH; private float _titleH; private float _rowsH; private float _pickerH; private float _footerGapH; private float _footerH; private float _descriptionGapH; private float _descriptionH; private float _toggleTextWidth = -1f; private float _toggleTextWidthScale = -1f; private float _layoutScale = -1f; private float _layoutMenuWidth = -1f; private int _layoutRowsCount = -1; private int _layoutSelected = -1; private int _layoutMaxVisibleRows = -1; private bool _layoutEditingColor; private bool _layoutShowFooter; private bool _layoutShowDescription; private string _layoutDescription = string.Empty; private const float HeroH = 96f; private const float TitleBarH = 34f; private const float RowH = 38f; private const float Gap = 8f; private const float DescMinH = 54f; private const float DescMaxH = 320f; private const float FooterH = 38f; private const float FooterGapH = 8f; private const float DiamondSize = 56f; private const float NumberBoolValueW = 72f; private const float ToggleGapW = 2f; private const float ColorPickerH = 224f; private const float ColorSwatchSize = 20f; private const float ColorHueStripW = 22f; private const float DescPadX = 16f; private const float DescPadTop = 12f; private const float DescPadBottom = 12f; private const float SidePanelW = 430f; private const float SidePanelGap = 10f; private const float SidePanelTitleH = 38f; private const float PlayerPreviewPanelW = 300f; private const float ScrollbarW = 8f; private const float ScrollbarGap = 9f; private const float InitialWindowInsetX = 88f; private const float InitialWindowInsetY = 48f; private const int OverlayGuiDepth = 2000; private const int MenuGuiDepth = 0; private const int NotificationGuiDepth = -2000; private const int ColorTextureSize = 128; private const int ColorDragNone = 0; private const int ColorDragSaturationValue = 1; private const int ColorDragHue = 2; private const float RowsRefreshInterval = 0.12f; private static int _lastNotificationRenderFrame = -1; public bool IsOpen { get { return _isOpen; } set { if (_isOpen != value) { _isOpen = value; MenuInputCapture.SetMenuOpen(value); MenuControllerInput.Reset(); } } } private float RowHeight => S(38f); public MenuUI() { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) IsOpen = true; } private float S(float value) { return value * _scale; } private void Awake() { EnsureThemeInitialized(); } public void Bind(FeatureManager fm) { _features = fm; RefreshRows(force: true); RecalculateMenuLayout(); } private void Update() { if (IsOpen && _features != null) { HandleController(); } if (_animationsInited) { float unscaledDeltaTime = Time.unscaledDeltaTime; float num = Mathf.Max(1f, MenuConfig.HighlightLerpSpeed); float num2 = 1f - Mathf.Exp((0f - num) * unscaledDeltaTime); _highlightY = Mathf.Lerp(_highlightY, _highlightYTarget, num2); _scrollY = Mathf.Lerp(_scrollY, _scrollYTarget, num2); } } private void OnGUI() { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Invalid comparison between Unknown and I4 //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Invalid comparison between Unknown and I4 //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_01c4: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_023a: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Unknown result type (might be due to invalid IL or missing references) EnsureThemeInitialized(); EventType type = Event.current.type; if (((int)type == 8 || (int)type == 11) ? true : false) { return; } RenderFeatureOverlays(); if (!IsOpen || _features == null) { _selectedPlayerPreviewPanel.SetVisible(visible: false); if (_editingColor) { CancelColorPicker(); } RenderDiscordPrompt(); RenderNotifications(); return; } GUI.depth = 0; HandleNumberEditorCommitKeys(); HandleTextEditorCommitKeys(); RefreshMenuForFrame(); float y = ((Rect)(ref _window)).y; DrawShadow(); DrawHero(new Rect(((Rect)(ref _window)).x, y, ((Rect)(ref _window)).width, _heroH)); y += _heroH; DrawTitleBar(new Rect(((Rect)(ref _window)).x, y, ((Rect)(ref _window)).width, _titleH), _titleH); y += _titleH; DrawRows(new Rect(((Rect)(ref _window)).x, y, ((Rect)(ref _window)).width, _rowsH)); y += _rowsH; if (_editingColor && _editingColorFeature != null) { MenuInputCapture.Tick(); DrawColorPicker(new Rect(((Rect)(ref _window)).x, y, ((Rect)(ref _window)).width, _pickerH), _editingColorFeature); y += _pickerH; } if (MenuConfig.ShowFooter) { DrawFooterSpacer(new Rect(((Rect)(ref _window)).x, y, ((Rect)(ref _window)).width, _footerGapH)); y += _footerGapH; DrawFooter(new Rect(((Rect)(ref _window)).x, y, ((Rect)(ref _window)).width, _footerH)); y += _footerH; } if (MenuConfig.ShowDescription) { if (_descriptionGapH > 0f) { DrawGap(new Rect(((Rect)(ref _window)).x, y, ((Rect)(ref _window)).width, _descriptionGapH)); y += _descriptionGapH; } DrawDescription(new Rect(((Rect)(ref _window)).x, y, ((Rect)(ref _window)).width, _descriptionH)); } DrawSidePanelIfNeeded(); HandleKeyboard(); HandleDrag(); RenderDiscordPrompt(); RenderNotifications(); } private void OnDestroy() { MenuInputCapture.SetMenuOpen(open: false); MenuControllerInput.Reset(); _selectedPlayerPreviewPanel.Dispose(); } private void EnsureThemeInitialized() { if (!_themeInitialized) { Theme.Init(); _themeInitialized = true; } } private void RefreshMenuForFrame() { int frameCount = Time.frameCount; if (_lastMenuRefreshFrame != frameCount) { _lastMenuRefreshFrame = frameCount; _scale = MenuConfig.GetResolvedUIScale(); Theme.ApplyScale(_scale); RefreshRows(); RecalculateMenuLayout(); } } private void RecalculateMenuLayout() { string text = (MenuConfig.ShowDescription ? DescriptionFor(SelectedRow()) : string.Empty); if (!NeedsLayoutRecalculation(text)) { EnsureInitialWindowPosition(); ClampWindowToScreen(); return; } ((Rect)(ref _window)).width = MenuConfig.MenuWidth * _scale; _heroH = S(96f); _titleH = S(34f); _footerH = (MenuConfig.ShowFooter ? S(38f) : 0f); _footerGapH = (MenuConfig.ShowFooter ? S(8f) : 0f); _descriptionGapH = ((MenuConfig.ShowDescription && !MenuConfig.ShowFooter) ? S(8f) : 0f); _descriptionH = (MenuConfig.ShowDescription ? CalculateDescriptionHeight(((Rect)(ref _window)).width, text) : 0f); _pickerH = (_editingColor ? S(224f) : 0f); int num = Mathf.Min(_rows.Count, Mathf.Max(1, MenuConfig.MaxVisibleRows)); _rowsH = (float)num * RowHeight; _highlightYTarget = (float)_selected * RowHeight; EnsureSelectedVisible(); ((Rect)(ref _window)).height = _heroH + _titleH + _rowsH + _pickerH + _footerGapH + _footerH + _descriptionGapH + _descriptionH; EnsureInitialWindowPosition(); ClampWindowToScreen(); CacheLayoutState(text); if (!_animationsInited) { _highlightY = (float)_selected * RowHeight; _highlightYTarget = _highlightY; _animationsInited = true; } } private bool NeedsLayoutRecalculation(string selectedDescription) { if (Mathf.Approximately(_layoutScale, _scale) && Mathf.Approximately(_layoutMenuWidth, MenuConfig.MenuWidth) && _layoutRowsCount == _rows.Count && _layoutSelected == _selected && _layoutMaxVisibleRows == MenuConfig.MaxVisibleRows && _layoutEditingColor == _editingColor && _layoutShowFooter == MenuConfig.ShowFooter && _layoutShowDescription == MenuConfig.ShowDescription) { return !string.Equals(_layoutDescription, selectedDescription, StringComparison.Ordinal); } return true; } private void CacheLayoutState(string selectedDescription) { _layoutScale = _scale; _layoutMenuWidth = MenuConfig.MenuWidth; _layoutRowsCount = _rows.Count; _layoutSelected = _selected; _layoutMaxVisibleRows = MenuConfig.MaxVisibleRows; _layoutEditingColor = _editingColor; _layoutShowFooter = MenuConfig.ShowFooter; _layoutShowDescription = MenuConfig.ShowDescription; _layoutDescription = selectedDescription ?? string.Empty; } private void RenderFeatureOverlays() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Invalid comparison between Unknown and I4 if ((int)Event.current.type != 7) { return; } int frameCount = Time.frameCount; if (_lastOverlayRenderFrame == frameCount) { return; } _lastOverlayRenderFrame = frameCount; int depth = GUI.depth; GUI.depth = 2000; try { _features?.Render(); } finally { GUI.depth = depth; } } private static void RenderNotifications() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Invalid comparison between Unknown and I4 if ((int)Event.current.type != 7) { return; } int frameCount = Time.frameCount; if (_lastNotificationRenderFrame == frameCount) { return; } _lastNotificationRenderFrame = frameCount; int depth = GUI.depth; GUI.depth = -2000; try { NotificationSystem.Render(); } finally { GUI.depth = depth; } } private static void RenderDiscordPrompt() { int depth = GUI.depth; GUI.depth = -2100; try { DiscordCommunityPrompt.Render(); } finally { GUI.depth = depth; } } private void RefreshRows(bool force = false) { int frameCount = Time.frameCount; if ((!force && (_editingNumber || _editingColor)) || (!force && _editingTextFeatureActive && !CanRefreshRowsWhileEditingText()) || (!force && !_rowsDirty && _lastRowsRefreshFrame == frameCount) || (!force && !_rowsDirty && Time.unscaledTime < _nextRowsRefreshAt)) { return; } _rowsDirty = false; _lastRowsRefreshFrame = frameCount; _nextRowsRefreshAt = Time.unscaledTime + 0.12f; _rows.Clear(); if (_features == null) { return; } if (_category == null) { foreach (string category in _features.Categories) { _rows.Add(category); } } else { foreach (Feature item in _features.InCategory(_category)) { _rows.Add(item); } foreach (IMenuRowProvider rowProvider in _features.RowProviders) { foreach (object row in rowProvider.GetRows(_category)) { if (row != null) { _rows.Add(row); } } } } _selected = Mathf.Clamp(_selected, 0, Mathf.Max(0, _rows.Count - 1)); NormalizeSelected(); _highlightYTarget = (float)_selected * RowHeight; EnsureSelectedVisible(); } private void RefreshRowsNow() { _rowsDirty = true; RefreshRows(force: true); RecalculateMenuLayout(); } private void EnsureSelectedVisible() { float rowHeight = RowHeight; float num = (float)Mathf.Max(1, MenuConfig.MaxVisibleRows) * rowHeight; float num2 = (float)_selected * rowHeight; float num3 = num2 + rowHeight; if (num2 < _scrollYTarget) { _scrollYTarget = num2; } if (num3 > _scrollYTarget + num) { _scrollYTarget = num3 - num; } float num4 = Mathf.Max(0f, (float)_rows.Count * rowHeight - num); _scrollYTarget = Mathf.Clamp(_scrollYTarget, 0f, num4); } private void DrawShadow() { //IL_0044: 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) Theme.Fill(new Rect(((Rect)(ref _window)).x + S(4f), ((Rect)(ref _window)).y + S(8f), ((Rect)(ref _window)).width, ((Rect)(ref _window)).height), new Color(0f, 0f, 0f, 0.55f)); } private void DrawHero(Rect rect) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) Theme.Fill(rect, Theme.Accent); Theme.DrawDiamond(((Rect)(ref rect)).center, S(56f)); } private void DrawTitleBar(Rect rect, float h) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) Theme.Fill(rect, Theme.BarBg); Theme.Fill(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).yMax - Mathf.Max(1f, S(2f)), ((Rect)(ref rect)).width, Mathf.Max(1f, S(2f))), Theme.Accent); string text = ((!MenuConfig.ShowBreadcrumb) ? ((_category == null) ? "Main Menu" : GetCategoryTitle(_category)) : ((_category == null) ? "Home" : ("Home › " + FormatCategoryPath(_category)))); string counterText = GetCounterText(); GUI.Label(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, ((Rect)(ref rect)).width - S(92f), h), text, Theme.Breadcrumb); GUI.Label(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, ((Rect)(ref rect)).width, h), counterText, Theme.Counter); } private void DrawRows(Rect rect) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0012: 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_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Unknown result type (might be due to invalid IL or missing references) Theme.Fill(rect, Theme.MenuBg); float rowHeight = RowHeight; GUI.BeginGroup(rect); int num = 0; int num2 = -1; if (_rows.Count > 0) { num = ((rowHeight > 0f) ? Mathf.Clamp(Mathf.FloorToInt(_scrollY / rowHeight), 0, _rows.Count - 1) : 0); num2 = ((rowHeight > 0f) ? Mathf.Clamp(Mathf.CeilToInt((_scrollY + ((Rect)(ref rect)).height) / rowHeight), 0, _rows.Count - 1) : (_rows.Count - 1)); } for (int i = num; i <= num2; i++) { Theme.Fill(new Rect(0f, (float)i * rowHeight - _scrollY, ((Rect)(ref rect)).width, rowHeight), Theme.RowBg); } if (_rows.Count > 0) { Rect r = default(Rect); ((Rect)(ref r))..ctor(0f, _highlightY - _scrollY, ((Rect)(ref rect)).width, rowHeight); if (IsSelectable(SelectedRow())) { Theme.Fill(r, Theme.SelectedBg); } } int num3 = ((rowHeight > 0f) ? Mathf.Clamp(Mathf.RoundToInt(_highlightY / rowHeight), 0, Mathf.Max(0, _rows.Count - 1)) : 0); Rect rowRect = default(Rect); for (int j = num; j <= num2; j++) { ((Rect)(ref rowRect))..ctor(0f, (float)j * rowHeight - _scrollY, ((Rect)(ref rect)).width, rowHeight); DrawRowContent(rowRect, _rows[j], j, j == num3); } GUI.EndGroup(); DrawRowsScrollbar(rect); HandleRowMouse(rect); } private void DrawRowContent(Rect rowRect, object row, int index, bool highlighted) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) if (row is SeparatorFeature) { DrawSeparator(rowRect, highlighted); return; } DrawRowLabel(rowRect, row, highlighted); DrawRowRight(rowRect, row, index, highlighted); } private void DrawRowLabel(Rect rowRect, object row, bool highlighted) { //IL_0060: 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) string text = RowLabel(row); GUIStyle val = (highlighted ? Theme.RowSelected : Theme.Row); List tags = GetTags(row); float rowRightReserve = GetRowRightReserve(row); Rect val2 = default(Rect); ((Rect)(ref val2))..ctor(((Rect)(ref rowRect)).x, ((Rect)(ref rowRect)).y, Mathf.Max(1f, ((Rect)(ref rowRect)).width - rowRightReserve), ((Rect)(ref rowRect)).height); if (tags == null || tags.Count == 0) { GUI.Label(val2, text, val); } else { DrawLabelWithTags(val2, text, val, Mathf.Max(8, Mathf.RoundToInt(10f * _scale)), tags, highlighted, alignTagsRight: true); } } private float GetRowRightReserve(object row) { if (row is string || row is SubmenuFeature) { return S(48f); } if (row is ButtonFeature) { return S(96f); } if (row is InfoFeature) { return S(120f); } if (row is ColorFeature) { return S(118f); } if (row is TextFeature) { return S(132f); } if (row is NumberBoolFeature) { return S(142f); } if (row is NumberFeature) { return S(118f); } if (row is Feature) { return S(52f); } return 0f; } private static string RowLabel(object row) { if (row is string result) { return result; } if (row is Feature feature) { return feature.Name; } if (row == null) { return "?"; } return row.ToString(); } private static List GetTags(object row) { if (!(row is IMenuTagProvider menuTagProvider)) { return null; } return menuTagProvider.Tags; } private void DrawRowRight(Rect rowRect, object row, int index, bool highlighted) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: 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_00d8: Unknown result type (might be due to invalid IL or missing references) if (row is string || row is SubmenuFeature) { DrawChevron(rowRect, highlighted); } else if (row is InfoFeature infoFeature) { GUI.Label(rowRect, infoFeature.ValueText, highlighted ? Theme.RowRightSelected : Theme.RowRight); } else if (row is ButtonFeature buttonFeature) { GUI.Label(rowRect, buttonFeature.ButtonLabel.ToUpperInvariant(), highlighted ? Theme.RowRightSelected : Theme.RowRight); } else if (row is ColorFeature color) { DrawColorRight(rowRect, color, index, highlighted); } else if (row is TextFeature text) { DrawTextRight(rowRect, text, index, highlighted); } else if (row is NumberBoolFeature number) { DrawNumberBoolRight(rowRect, number, index, highlighted); } else if (row is NumberFeature number2) { DrawNumberRight(rowRect, number2, index, highlighted); } else if (row is Feature feature) { DrawToggleState(rowRect, feature.Enabled, highlighted); } } private void DrawChevron(Rect rowRect, bool highlighted) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown //IL_0039: Unknown result type (might be due to invalid IL or missing references) GUIStyle val = new GUIStyle(highlighted ? Theme.RowRightSelected : Theme.RowRight) { fontSize = Mathf.Max(1, Mathf.RoundToInt(20f * _scale)), fontStyle = (FontStyle)1 }; GUI.Label(rowRect, "›", val); } private void DrawNumberRight(Rect rowRect, NumberFeature number, int index, bool highlighted) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) if (IsEditing(number, index) && number.AllowTextInput) { DrawNumberTextInput(GetNumberValueRect(rowRect, reserveToggleSlot: false)); return; } string displayValue = number.GetDisplayValue(); string text = ((highlighted && number.AllowTextInput) ? ("‹ " + displayValue + " ›") : displayValue); GUI.Label(rowRect, text, highlighted ? Theme.RowRightSelected : Theme.RowRight); } private void DrawNumberBoolRight(Rect rowRect, NumberBoolFeature number, int index, bool highlighted) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0024: 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_0071: 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_007d: 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) //IL_008c: Expected O, but got Unknown //IL_008e: Expected O, but got Unknown //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) Rect numberValueRect = GetNumberValueRect(rowRect, reserveToggleSlot: true); Rect numberBoolToggleRect = GetNumberBoolToggleRect(rowRect); if (IsEditing(number, index) && number.AllowTextInput) { DrawNumberTextInput(numberValueRect); DrawNumberBoolToggle(numberBoolToggleRect, number.Enabled, highlighted); return; } string displayValue = number.GetDisplayValue(); string text = ((highlighted && number.AllowTextInput) ? ("‹ " + displayValue + " ›") : displayValue); GUIStyle val = new GUIStyle(highlighted ? Theme.RowRightSelected : Theme.RowRight) { alignment = (TextAnchor)5, padding = new RectOffset(0, 0, 0, 0) }; GUI.Label(numberValueRect, text, val); DrawNumberBoolToggle(numberBoolToggleRect, number.Enabled, highlighted); } private void DrawTextRight(Rect rowRect, TextFeature text, int index, bool highlighted) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0014: 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_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Expected O, but got Unknown //IL_0047: Expected O, but got Unknown //IL_004e: Unknown result type (might be due to invalid IL or missing references) Rect numberValueRect = GetNumberValueRect(rowRect, reserveToggleSlot: false); if (IsEditing(text, index)) { DrawTextInput(numberValueRect); return; } GUIStyle val = new GUIStyle(highlighted ? Theme.RowRightSelected : Theme.RowRight) { alignment = (TextAnchor)5, padding = new RectOffset(0, 0, 0, 0) }; string displayValue = text.GetDisplayValue(); GUI.Label(numberValueRect, highlighted ? ("‹ " + displayValue + " ›") : displayValue, val); } private void DrawColorRight(Rect rowRect, ColorFeature color, int index, bool highlighted) { //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: 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_007a: Expected O, but got Unknown //IL_007b: Expected O, but got Unknown //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) float num = S(20f); float num2 = S(16f); Rect rect = default(Rect); ((Rect)(ref rect))..ctor(((Rect)(ref rowRect)).xMax - num2 - num, ((Rect)(ref rowRect)).y + (((Rect)(ref rowRect)).height - num) * 0.5f, num, num); GUIStyle val = new GUIStyle(highlighted ? Theme.RowRightSelected : Theme.RowRight) { padding = new RectOffset(0, Mathf.RoundToInt(num2 + num + S(10f)), 0, 0) }; GUI.Label(rowRect, color.GetDisplayValue(), val); DrawColorSwatch(rect, color.Value, highlighted, IsEditing(color, index)); } private bool IsEditing(NumberFeature number, int index) { if (_editingNumber && _editingNumberFeature == number) { return _editingNumberIndex == index; } return false; } private bool IsEditing(TextFeature text, int index) { if (_editingTextFeatureActive && _editingTextFeature == text) { return _editingTextIndex == index; } return false; } private bool IsEditing(ColorFeature color, int index) { if (_editingColor && _editingColorFeature == color) { return _editingColorIndex == index; } return false; } private bool CanRefreshRowsWhileEditingText() { if (_editingTextFeatureActive && _editingTextFeature != null) { return _editingTextFeature.RefreshRowsWhileEditing; } return false; } private Rect GetNumberValueRect(Rect rowRect, bool reserveToggleSlot) { //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) if (reserveToggleSlot) { float num = S(72f); Rect numberBoolToggleRect = GetNumberBoolToggleRect(rowRect); return new Rect(((Rect)(ref numberBoolToggleRect)).x - S(2f) - num, ((Rect)(ref rowRect)).y, num, ((Rect)(ref rowRect)).height); } float num2 = ((Rect)(ref rowRect)).x + ((Rect)(ref rowRect)).width * 0.55f; float num3 = S(16f); float num4 = Mathf.Max(S(96f), ((Rect)(ref rowRect)).xMax - num3 - num2); return new Rect(num2, ((Rect)(ref rowRect)).y, num4, ((Rect)(ref rowRect)).height); } private Rect GetNumberBoolToggleRect(Rect rowRect) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) float num = S(16f); float toggleTextWidth = GetToggleTextWidth(); return new Rect(((Rect)(ref rowRect)).xMax - num - toggleTextWidth, ((Rect)(ref rowRect)).y, toggleTextWidth, ((Rect)(ref rowRect)).height); } private void DrawNumberTextInput(Rect valueRect) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) Rect val = default(Rect); ((Rect)(ref val))..ctor(((Rect)(ref valueRect)).x, ((Rect)(ref valueRect)).y + S(5f), ((Rect)(ref valueRect)).width, ((Rect)(ref valueRect)).height - S(10f)); GUI.SetNextControlName("CubeX_NumberInput"); _editingText = GUI.TextField(val, _editingText, Theme.NumberInput); if (_focusNumberInputNext) { GUI.FocusControl("CubeX_NumberInput"); _focusNumberInputNext = false; } } private void DrawTextInput(Rect valueRect) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005a: 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_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Expected O, but got Unknown //IL_00b8: 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_00c5: 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) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: 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) //IL_0100: Expected O, but got Unknown //IL_01b9: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Invalid comparison between Unknown and I4 //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Expected O, but got Unknown //IL_018d: Unknown result type (might be due to invalid IL or missing references) Rect val = default(Rect); ((Rect)(ref val))..ctor(((Rect)(ref valueRect)).x, ((Rect)(ref valueRect)).y + S(5f), ((Rect)(ref valueRect)).width, ((Rect)(ref valueRect)).height - S(10f)); Theme.Fill(val, new Color(0f, 0f, 0f, 0.72f)); DrawRectOutline(val, Theme.Accent, Mathf.Max(1f, S(1f))); GUIStyle val2 = new GUIStyle(Theme.NumberInput) { alignment = (TextAnchor)3, padding = new RectOffset(Mathf.RoundToInt(S(8f)), Mathf.RoundToInt(S(8f)), 0, 0), clipping = (TextClipping)1 }; val2.normal.textColor = Theme.Text; val2.focused.textColor = Theme.Text; val2.active.textColor = Theme.Text; val2.hover.textColor = Theme.Text; GUIStyle val3 = val2; if (string.IsNullOrEmpty(_editingText) && (int)Event.current.type == 7) { GUIStyle val4 = new GUIStyle(val3); val4.normal.textColor = new Color(Theme.TextDim.r, Theme.TextDim.g, Theme.TextDim.b, 0.78f); val4.focused.textColor = new Color(Theme.TextDim.r, Theme.TextDim.g, Theme.TextDim.b, 0.78f); GUIStyle val5 = val4; GUI.Label(val, _editingTextFeature?.EmptyDisplayText ?? "Text", val5); } GUI.SetNextControlName("CubeX_TextInput"); string text = GUI.TextField(val, _editingText, Mathf.Max(1, _editingTextFeature?.MaxLength ?? 64), val3); if (text != _editingText) { _editingText = text; _editingTextFeature?.SetText(_editingText); if (CanRefreshRowsWhileEditingText()) { _rowsDirty = true; } } if (_focusTextInputNext) { GUI.FocusControl("CubeX_TextInput"); _focusTextInputNext = false; } } private void DrawToggleState(Rect rowRect, bool on, bool highlighted) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) GUIStyle val = CreateToggleStyle(highlighted); GUI.Label(rowRect, on ? "✓" : "X", val); } private void DrawNumberBoolToggle(Rect rowRect, bool on, bool highlighted) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown //IL_001e: Unknown result type (might be due to invalid IL or missing references) GUIStyle val = CreateToggleStyle(highlighted); val.alignment = (TextAnchor)5; val.padding = new RectOffset(0, 0, 0, 0); GUI.Label(rowRect, on ? "✓" : "X", val); } private void DrawColorSwatch(Rect rect, Color color, bool highlighted, bool active) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: 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_0047: Unknown result type (might be due to invalid IL or missing references) Color c = ((!active) ? (highlighted ? Theme.SelectedFg : Theme.TextDim) : (highlighted ? Theme.SelectedFg : Theme.Text)); Theme.Fill(rect, c); Theme.Fill(Inset(rect, Mathf.Max(1f, S(2f))), color); } private GUIStyle CreateToggleStyle(bool highlighted) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown return new GUIStyle(highlighted ? Theme.RowRightSelected : Theme.RowRight) { fontStyle = (FontStyle)1, fontSize = Mathf.Max(1, Mathf.RoundToInt(15f * _scale)) }; } private float GetToggleTextWidth() { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Expected O, but got Unknown //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Expected O, but got Unknown //IL_005d: Unknown result type (might be due to invalid IL or missing references) if (_toggleTextWidth > 0f && Mathf.Approximately(_toggleTextWidthScale, _scale)) { return _toggleTextWidth; } GUIStyle obj = CreateToggleStyle(highlighted: false); obj.padding = new RectOffset(0, 0, 0, 0); float x = obj.CalcSize(new GUIContent("X")).x; float x2 = obj.CalcSize(new GUIContent("✓")).x; _toggleTextWidthScale = _scale; _toggleTextWidth = Mathf.Max(x, x2); return _toggleTextWidth; } private void HandleRowMouse(Rect rowsArea) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Invalid comparison between Unknown and I4 //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Invalid comparison between Unknown and I4 //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Invalid comparison between Unknown and I4 //IL_00bc: 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_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_01bf: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Invalid comparison between Unknown and I4 //IL_015b: Unknown result type (might be due to invalid IL or missing references) if (!ShouldAcceptMenuMouseInput()) { return; } Event current = Event.current; if (((int)current.type != 0 && (int)current.type != 7 && (int)current.type != 6) || !((Rect)(ref rowsArea)).Contains(current.mousePosition)) { return; } if ((int)current.type == 6) { int num = Mathf.Min(_rows.Count, Mathf.Max(1, MenuConfig.MaxVisibleRows)); if (_rows.Count > num) { int direction = ((current.delta.y > 0f) ? 1 : (-1)); int steps = Mathf.Max(1, Mathf.RoundToInt(Mathf.Abs(current.delta.y) / 3f)); MoveSelectionClamped(direction, steps); current.Use(); } return; } float num2 = current.mousePosition.y - ((Rect)(ref rowsArea)).y + _scrollY; float rowHeight = RowHeight; int num3 = ((rowHeight > 0f) ? Mathf.FloorToInt(num2 / rowHeight) : 0); if (num3 < 0 || num3 >= _rows.Count || !IsSelectable(_rows[num3])) { return; } if ((int)current.type == 0) { if (_selected != num3) { SetSelected(num3); current.Use(); return; } object obj = _rows[num3]; NumberFeature numberFeature = obj as NumberFeature; TextFeature textFeature = obj as TextFeature; bool flag = current.mousePosition.x > ((Rect)(ref rowsArea)).x + ((Rect)(ref rowsArea)).width * 0.55f; if ((numberFeature?.AllowTextInput ?? false) && flag) { BeginNumberTextInput(numberFeature); } else if (textFeature != null && flag) { BeginTextInput(textFeature); } else { Activate(obj); } current.Use(); } else if ((int)current.type == 7 && _selected != num3 && !_dragging && !_editingNumber && !_editingColor && !_editingTextFeatureActive) { SetSelected(num3); } } private void DrawRowsScrollbar(Rect rowsArea) { //IL_009e: 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_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_01cf: 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) if (MenuConfig.ShowScrollbar) { int num = Mathf.Min(_rows.Count, Mathf.Max(1, MenuConfig.MaxVisibleRows)); if (_rows.Count > num && num > 0 && !(((Rect)(ref rowsArea)).height <= 0f)) { float num2 = S(8f); float num3 = S(9f); float num4 = ((((Rect)(ref rowsArea)).x >= num2 + num3) ? (((Rect)(ref rowsArea)).x - num3 - num2) : (((Rect)(ref rowsArea)).xMax - num3 - num2)); Rect r = default(Rect); ((Rect)(ref r))..ctor(num4, ((Rect)(ref rowsArea)).y, num2, ((Rect)(ref rowsArea)).height); Theme.Fill(r, new Color(0.05f, 0.05f, 0.05f, 0.72f)); float num5 = Mathf.Max(1f, S(1f)); Theme.Fill(new Rect(((Rect)(ref r)).center.x - num5 * 0.5f, ((Rect)(ref r)).y, num5, ((Rect)(ref r)).height), new Color(0.18f, 0.18f, 0.18f, 0.9f)); float num6 = (float)_rows.Count * RowHeight; float height = ((Rect)(ref rowsArea)).height; float num7 = Mathf.Max(num2 * 2f, height * (height / Mathf.Max(height, num6))); float num8 = Mathf.Max(1f, num6 - height); float num9 = Mathf.Clamp01(_scrollY / num8); float num10 = ((Rect)(ref r)).y + (((Rect)(ref r)).height - num7) * num9; float num11 = Mathf.Max(1f, S(1f)); Theme.Fill(new Rect(((Rect)(ref r)).x + num11, num10, Mathf.Max(1f, ((Rect)(ref r)).width - num11 * 2f), num7), new Color(0.93f, 0.93f, 0.93f, 0.96f)); } } } private void DrawGap(Rect rect) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) Theme.Fill(rect, Theme.MenuBg); } private void DrawSeparator(Rect rowRect, bool highlighted) { //IL_0054: 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_007d: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) float num = S(16f); float num2 = ((Rect)(ref rowRect)).y + ((Rect)(ref rowRect)).height * 0.5f; float num3 = Mathf.Max(1f, S(1f)); Theme.Fill(new Rect(((Rect)(ref rowRect)).x + num, num2 - num3, ((Rect)(ref rowRect)).width - num * 2f, num3), Theme.Separator); Theme.Fill(new Rect(((Rect)(ref rowRect)).x + num, num2, ((Rect)(ref rowRect)).width - num * 2f, num3), new Color(Theme.TextDim.r, Theme.TextDim.g, Theme.TextDim.b, 0.45f)); } private void DrawDescription(Rect rect) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_003d: 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_005e: Unknown result type (might be due to invalid IL or missing references) Theme.Fill(rect, Theme.DescBg); Theme.Fill(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, ((Rect)(ref rect)).width, 1f), Theme.Separator); GUIStyle descriptionTextStyle = GetDescriptionTextStyle(); Rect descriptionTextRect = GetDescriptionTextRect(rect); string text = WrapDescriptionText(DescriptionFor(SelectedRow()), descriptionTextStyle, ((Rect)(ref descriptionTextRect)).width); GUI.Label(descriptionTextRect, text, descriptionTextStyle); } private void DrawSidePanelIfNeeded() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0064: 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_0087: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: 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) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Unknown result type (might be due to invalid IL or missing references) //IL_0208: Unknown result type (might be due to invalid IL or missing references) //IL_0256: Unknown result type (might be due to invalid IL or missing references) //IL_0262: Unknown result type (might be due to invalid IL or missing references) if (!TryGetSidePanel(out var panel) || panel == null) { _selectedPlayerPreviewPanel.SetVisible(visible: false); return; } Rect sidePanelRect = GetSidePanelRect(panel); bool flag = IsPlayerPanel(panel); bool flag2 = IsItemPanel(panel); Theme.Fill(new Rect(((Rect)(ref sidePanelRect)).x + S(4f), ((Rect)(ref sidePanelRect)).y + S(8f), ((Rect)(ref sidePanelRect)).width, ((Rect)(ref sidePanelRect)).height), new Color(0f, 0f, 0f, 0.55f)); Theme.Fill(sidePanelRect, flag ? new Color(0.015f, 0.018f, 0.016f, 0.9f) : new Color(0f, 0f, 0f, 0.82f)); if (flag) { DrawPlayerPanelBackdrop(sidePanelRect); } Theme.Fill(new Rect(((Rect)(ref sidePanelRect)).x, ((Rect)(ref sidePanelRect)).y, ((Rect)(ref sidePanelRect)).width, Mathf.Max(1f, S(2f))), Theme.Accent); DrawRectOutline(sidePanelRect, new Color(Theme.TextDim.r, Theme.TextDim.g, Theme.TextDim.b, 0.48f), Mathf.Max(1f, S(1f))); float amount = S(14f); Rect val = Inset(sidePanelRect, amount); float num = (flag ? S(116f) : (flag2 ? S(92f) : S(72f))); Rect rect = default(Rect); ((Rect)(ref rect))..ctor(((Rect)(ref val)).x, ((Rect)(ref val)).y, ((Rect)(ref val)).width, num); DrawSidePanelHeader(rect, panel); float num2 = ((Rect)(ref rect)).yMax + S(flag ? 8f : (flag2 ? 6f : 2f)); Theme.Fill(new Rect(((Rect)(ref val)).x, num2, ((Rect)(ref val)).width, Mathf.Max(1f, S(1f))), Theme.Separator); Rect rect2 = default(Rect); ((Rect)(ref rect2))..ctor(((Rect)(ref val)).x, num2 + S(10f), ((Rect)(ref val)).width, Mathf.Max(0f, ((Rect)(ref val)).yMax - num2 - S(10f))); DrawSidePanelRows(rect2, panel); if (flag) { DrawSelectedPlayerPreviewPanel(sidePanelRect); } else { _selectedPlayerPreviewPanel.SetVisible(visible: false); } } private void DrawSelectedPlayerPreviewPanel(Rect playerPanelRect) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0088: 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_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Invalid comparison between Unknown and I4 //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) Rect selectedPlayerPreviewRect = GetSelectedPlayerPreviewRect(playerPanelRect); if (((Rect)(ref selectedPlayerPreviewRect)).width <= 0f || ((Rect)(ref selectedPlayerPreviewRect)).height <= 0f) { _selectedPlayerPreviewPanel.SetVisible(visible: false); return; } Theme.Fill(new Rect(((Rect)(ref selectedPlayerPreviewRect)).x + S(4f), ((Rect)(ref selectedPlayerPreviewRect)).y + S(8f), ((Rect)(ref selectedPlayerPreviewRect)).width, ((Rect)(ref selectedPlayerPreviewRect)).height), new Color(0f, 0f, 0f, 0.5f)); Theme.Fill(selectedPlayerPreviewRect, new Color(0.01f, 0.011f, 0.013f, 0.95f)); Theme.Fill(new Rect(((Rect)(ref selectedPlayerPreviewRect)).x, ((Rect)(ref selectedPlayerPreviewRect)).y, ((Rect)(ref selectedPlayerPreviewRect)).width, Mathf.Max(1f, S(2f))), Theme.Accent); DrawRectOutline(selectedPlayerPreviewRect, new Color(Theme.TextDim.r, Theme.TextDim.g, Theme.TextDim.b, 0.46f), Mathf.Max(1f, S(1f))); Rect val = Inset(selectedPlayerPreviewRect, S(8f)); Theme.Fill(val, new Color(0.018f, 0.019f, 0.022f, 1f)); if ((int)Event.current.type == 7) { Texture texture = _selectedPlayerPreviewPanel.GetTexture(); if (Object.op_Implicit((Object)(object)texture)) { GUI.DrawTexture(val, texture, (ScaleMode)1, false); } } DrawPortraitCorners(Inset(selectedPlayerPreviewRect, S(4f))); } private Rect GetSelectedPlayerPreviewRect(Rect playerPanelRect) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_013a: 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_011e: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) if (!PlayerDirectory.TryGetSelectedCharacter(out var character) || !Object.op_Implicit((Object)(object)character)) { return Rect.zero; } float num = S(10f); float minWidth = S(190f); float num2 = Mathf.Clamp(S(300f), S(220f), Mathf.Max(S(220f), (float)Screen.width * 0.22f)); float height = ((Rect)(ref playerPanelRect)).height; float num3 = Mathf.Max(0f, (float)Screen.width - ((Rect)(ref playerPanelRect)).xMax - num); float num4 = Mathf.Max(0f, ((Rect)(ref playerPanelRect)).x - num); Rect val = default(Rect); ((Rect)(ref val))..ctor(((Rect)(ref playerPanelRect)).xMax + num, ((Rect)(ref playerPanelRect)).y, Mathf.Min(num2, num3), height); Rect val2 = default(Rect); ((Rect)(ref val2))..ctor(((Rect)(ref playerPanelRect)).x - num - Mathf.Min(num2, num4), ((Rect)(ref playerPanelRect)).y, Mathf.Min(num2, num4), height); if (((Rect)(ref playerPanelRect)).center.x >= ((Rect)(ref _window)).center.x) { if (CanUsePlayerPreviewRect(val, minWidth)) { return val; } if (CanUsePlayerPreviewRect(val2, minWidth)) { return val2; } } else { if (CanUsePlayerPreviewRect(val2, minWidth)) { return val2; } if (CanUsePlayerPreviewRect(val, minWidth)) { return val; } } return Rect.zero; } private bool CanUsePlayerPreviewRect(Rect rect, float minWidth) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) if (((Rect)(ref rect)).width >= minWidth && ((Rect)(ref rect)).height > 0f) { return !((Rect)(ref rect)).Overlaps(_window); } return false; } private void DrawSidePanelHeader(Rect rect, MenuSidePanel panel) { //IL_009a: 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_00bd: 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: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_031d: Unknown result type (might be due to invalid IL or missing references) //IL_0322: Unknown result type (might be due to invalid IL or missing references) //IL_0327: Unknown result type (might be due to invalid IL or missing references) //IL_0331: Expected O, but got Unknown //IL_0331: Unknown result type (might be due to invalid IL or missing references) //IL_0338: Unknown result type (might be due to invalid IL or missing references) //IL_033f: Unknown result type (might be due to invalid IL or missing references) //IL_0346: Unknown result type (might be due to invalid IL or missing references) //IL_034d: Unknown result type (might be due to invalid IL or missing references) //IL_036c: Expected O, but got Unknown //IL_0371: 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_037b: Unknown result type (might be due to invalid IL or missing references) //IL_0385: Expected O, but got Unknown //IL_0385: Unknown result type (might be due to invalid IL or missing references) //IL_038c: Unknown result type (might be due to invalid IL or missing references) //IL_0393: Unknown result type (might be due to invalid IL or missing references) //IL_039a: Unknown result type (might be due to invalid IL or missing references) //IL_03a1: Unknown result type (might be due to invalid IL or missing references) //IL_03c0: Expected O, but got Unknown //IL_020a: Unknown result type (might be due to invalid IL or missing references) //IL_0218: Unknown result type (might be due to invalid IL or missing references) //IL_021d: Unknown result type (might be due to invalid IL or missing references) //IL_021f: Unknown result type (might be due to invalid IL or missing references) //IL_043f: Unknown result type (might be due to invalid IL or missing references) //IL_0483: Unknown result type (might be due to invalid IL or missing references) //IL_04e7: Unknown result type (might be due to invalid IL or missing references) //IL_04ec: Unknown result type (might be due to invalid IL or missing references) //IL_0246: 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_0250: Unknown result type (might be due to invalid IL or missing references) //IL_0252: Unknown result type (might be due to invalid IL or missing references) //IL_025c: Unknown result type (might be due to invalid IL or missing references) //IL_0266: Unknown result type (might be due to invalid IL or missing references) //IL_0275: Unknown result type (might be due to invalid IL or missing references) //IL_02b0: Unknown result type (might be due to invalid IL or missing references) //IL_02a9: Unknown result type (might be due to invalid IL or missing references) //IL_02ba: Unknown result type (might be due to invalid IL or missing references) //IL_02cf: Unknown result type (might be due to invalid IL or missing references) //IL_02f0: Unknown result type (might be due to invalid IL or missing references) bool flag = IsPlayerPanel(panel); bool flag2 = IsItemPanel(panel); float num = (flag ? S(78f) : (flag2 ? S(72f) : S(54f))); float num2 = (flag ? S(16f) : (flag2 ? S(14f) : S(12f))); float num3 = ((Rect)(ref rect)).x; float num4 = ((Rect)(ref rect)).width; if (flag) { Theme.Fill(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, ((Rect)(ref rect)).width, ((Rect)(ref rect)).height), new Color(0f, 0f, 0f, 0.28f)); DrawRectOutline(rect, new Color(Theme.Accent.r, Theme.Accent.g, Theme.Accent.b, 0.32f), Mathf.Max(1f, S(1f))); Theme.Fill(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, Mathf.Max(2f, S(3f)), ((Rect)(ref rect)).height), Theme.Accent); Theme.Fill(new Rect(((Rect)(ref rect)).x + S(10f), ((Rect)(ref rect)).yMax - S(10f), Mathf.Min(((Rect)(ref rect)).width * 0.42f, S(150f)), Mathf.Max(1f, S(1f))), Theme.Accent); } if ((Object)(object)panel.PreviewTexture != (Object)null) { Rect val = default(Rect); ((Rect)(ref val))..ctor(((Rect)(ref rect)).x + (flag ? S(14f) : 0f), ((Rect)(ref rect)).y + (flag ? S(18f) : (flag2 ? S(8f) : S(2f))), num, num); Rect r = Inset(val, 0f - S(4f)); Rect val2 = Inset(val, Mathf.Max(1f, flag ? S(3f) : S(2f))); if (flag || flag2) { Theme.Fill(r, new Color(Theme.Accent.r, Theme.Accent.g, Theme.Accent.b, 0.18f)); } Theme.Fill(val, (Color)((flag || flag2) ? Theme.Accent : new Color(Theme.TextDim.r, Theme.TextDim.g, Theme.TextDim.b, 0.45f))); Theme.Fill(val2, new Color(0f, 0f, 0f, 0.28f)); GUI.DrawTexture(val2, panel.PreviewTexture, (ScaleMode)((!flag2) ? 1 : 2), true); if (flag) { DrawPortraitCorners(val); } num3 = ((Rect)(ref val)).xMax + num2; num4 = Mathf.Max(1f, ((Rect)(ref rect)).xMax - num3); } GUIStyle baseStyle = new GUIStyle(Theme.DescTitle) { padding = new RectOffset(0, 0, 0, 0), alignment = (TextAnchor)0, wordWrap = false, clipping = (TextClipping)1, fontStyle = (FontStyle)1, fontSize = Mathf.Max(1, Mathf.RoundToInt(18f * _scale)) }; GUIStyle baseStyle2 = new GUIStyle(Theme.DescBody) { padding = new RectOffset(0, 0, 0, 0), alignment = (TextAnchor)0, wordWrap = false, clipping = (TextClipping)1, fontStyle = (FontStyle)1, fontSize = Mathf.Max(1, Mathf.RoundToInt(12f * _scale)) }; string text = (string.IsNullOrEmpty(panel.Title) ? "PLAYER INFORMATION" : panel.Title); string text2 = (string.IsNullOrEmpty(panel.Subtitle) ? string.Empty : panel.Subtitle); float num5 = ((Rect)(ref rect)).y + (flag ? S(20f) : (flag2 ? S(10f) : S(3f))); DrawFittingLabel(new Rect(num3, num5, num4, S(26f)), text, baseStyle, Mathf.Max(10, Mathf.RoundToInt(13f * _scale))); DrawLabelWithTags(new Rect(num3, num5 + S(32f), num4, S(20f)), text2, baseStyle2, Mathf.Max(8, Mathf.RoundToInt(10f * _scale)), panel.Tags, highlighted: false); Theme.Fill(new Rect(num3, num5 + S(58f), Mathf.Min(num4, S(190f)), Mathf.Max(1f, S(1f))), Theme.Accent); } private void DrawSidePanelRows(Rect rect, MenuSidePanel panel) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_01af: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) List list = panel?.Rows; if (list == null || list.Count == 0) { return; } if (IsPlayerPanel(panel)) { DrawPlayerSidePanelRows(rect, list); return; } bool num = ((Rect)(ref rect)).width >= S(560f) && list.Count >= 12; float num2 = S(14f); float num3 = S(5f); if (num) { int num4 = Mathf.CeilToInt((float)list.Count * 0.5f); float num5 = (((Rect)(ref rect)).width - num2) * 0.5f; float sidePanelRowHeight = GetSidePanelRowHeight(rect, num4, twoColumns: true); Rect val = default(Rect); ((Rect)(ref val))..ctor(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, num5, ((Rect)(ref rect)).height); Rect val2 = default(Rect); ((Rect)(ref val2))..ctor(((Rect)(ref val)).xMax + num2, ((Rect)(ref rect)).y, num5, ((Rect)(ref rect)).height); for (int i = 0; i < num4 && i < list.Count; i++) { DrawSidePanelInfoRow(new Rect(((Rect)(ref val)).x, ((Rect)(ref val)).y + (float)i * (sidePanelRowHeight + num3), ((Rect)(ref val)).width, sidePanelRowHeight), list[i]); } for (int j = num4; j < list.Count; j++) { DrawSidePanelInfoRow(new Rect(((Rect)(ref val2)).x, ((Rect)(ref val2)).y + (float)(j - num4) * (sidePanelRowHeight + num3), ((Rect)(ref val2)).width, sidePanelRowHeight), list[j]); } } else { float sidePanelRowHeight2 = GetSidePanelRowHeight(rect, list.Count, twoColumns: false); Rect rect2 = default(Rect); for (int k = 0; k < list.Count; k++) { ((Rect)(ref rect2))..ctor(((Rect)(ref rect)).x, ((Rect)(ref rect)).y + (float)k * (sidePanelRowHeight2 + num3), ((Rect)(ref rect)).width, sidePanelRowHeight2); DrawSidePanelInfoRow(rect2, list[k]); } } } private bool TryGetSidePanel(out MenuSidePanel panel) { panel = null; if (_features == null) { return false; } object selectedRow = SelectedRow(); foreach (IMenuSidePanelProvider sidePanelProvider in _features.SidePanelProviders) { if (sidePanelProvider.TryGetSidePanel(_category, selectedRow, out panel)) { return true; } } return false; } private Rect GetSidePanelRect(MenuSidePanel panel) { //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_01f7: Unknown result type (might be due to invalid IL or missing references) float num = S(10f); float num2 = Mathf.Min(S(430f), Mathf.Max(S(260f), (float)Screen.width - num * 2f)); float num3 = S(300f); float num4 = Mathf.Clamp(GetSidePanelDesiredHeight(panel), S(180f), Mathf.Max(S(180f), (float)Screen.height - num * 2f)); bool flag = ((Rect)(ref _window)).center.x < (float)Screen.width * 0.5f; float num5 = Mathf.Max(0f, (float)Screen.width - ((Rect)(ref _window)).xMax - num); float num6 = Mathf.Max(0f, ((Rect)(ref _window)).x - num); bool flag2 = flag; float num7 = num2; if (flag && num5 >= num3) { num7 = Mathf.Min(num2, num5); flag2 = true; } else if (!flag && num6 >= num3) { num7 = Mathf.Min(num2, num6); flag2 = false; } else if (num5 >= num6 && num5 >= num3) { num7 = Mathf.Min(num2, num5); flag2 = true; } else if (num6 >= num3) { num7 = Mathf.Min(num2, num6); flag2 = false; } float num8 = ((Rect)(ref _window)).xMax + num; float num9 = ((Rect)(ref _window)).x - num - num7; float num10 = ((flag2 && num8 + num7 <= (float)Screen.width) ? num8 : ((!flag2 && num9 >= 0f) ? num9 : ((num8 + num7 <= (float)Screen.width) ? num8 : ((!(num9 >= 0f)) ? Mathf.Clamp(num8, 0f, Mathf.Max(0f, (float)Screen.width - num7)) : num9)))); float num11 = Mathf.Clamp(((Rect)(ref _window)).y, 0f, Mathf.Max(0f, (float)Screen.height - num4)); return new Rect(num10, num11, num7, num4); } private float GetSidePanelDesiredHeight(MenuSidePanel panel) { if (IsPlayerPanel(panel)) { int num = Mathf.CeilToInt((float)CountPlayerGridRows(panel?.Rows) / 2f); float num2 = S(14f); float num3 = S(116f); float num4 = S(19f); float num5 = S(44f) + GetPlayerVitalsHeight(GetPlayerAfflictionRows(panel?.Rows)) + S(8f) + (float)num * S(38f) + (float)Mathf.Max(0, num - 1) * S(6f); return num2 * 2f + num3 + num4 + num5; } int num6 = ((panel != null && panel.Rows != null) ? panel.Rows.Count : 0); int num7 = Mathf.Max(1, num6); float num8 = S(14f); float num9 = (IsItemPanel(panel) ? S(92f) : S(72f)); float num10 = (IsItemPanel(panel) ? S(6f) : S(2f)); float num11 = Mathf.Max(1f, S(1f)); float num12 = S(10f); float num13 = S(29f); float num14 = S(5f); float num15 = (float)num7 * num13 + (float)Mathf.Max(0, num7 - 1) * num14; return num8 * 2f + num9 + num10 + num11 + num12 + num15 + S(2f); } private float GetSidePanelRowHeight(Rect statsBody, int rowCount, bool twoColumns) { if (rowCount <= 0) { return S(29f); } float num = (twoColumns ? S(28f) : S(29f)); float num2 = S(5f); float num3 = (((Rect)(ref statsBody)).height - (float)Mathf.Max(0, rowCount - 1) * num2) / (float)rowCount; return Mathf.Max(S(18f), Mathf.Min(num, num3)); } private void DrawSidePanelInfoRow(Rect rect, InfoFeature info) { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: 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_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0073: 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_007a: 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) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Expected O, but got Unknown //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_012f: 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_013d: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Expected O, but got Unknown //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Expected O, but got Unknown //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Expected O, but got Unknown //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_01bf: Unknown result type (might be due to invalid IL or missing references) //IL_01c4: Unknown result type (might be due to invalid IL or missing references) //IL_01ce: Expected O, but got Unknown //IL_01ce: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Unknown result type (might be due to invalid IL or missing references) //IL_01dc: 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_01ea: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Expected O, but got Unknown //IL_0299: Unknown result type (might be due to invalid IL or missing references) //IL_02ae: 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) if (info != null) { Color c = default(Color); ((Color)(ref c))..ctor(0f, 0f, 0f, 0.24f); Color color = default(Color); ((Color)(ref color))..ctor(Theme.TextDim.r, Theme.TextDim.g, Theme.TextDim.b, 0.28f); Color sidePanelAccentColor = GetSidePanelAccentColor(info.Name); Color c2 = default(Color); ((Color)(ref c2))..ctor(sidePanelAccentColor.r, sidePanelAccentColor.g, sidePanelAccentColor.b, 0.78f); Theme.Fill(rect, c); DrawRectOutline(rect, color, Mathf.Max(1f, S(1f))); Theme.Fill(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, Mathf.Max(2f, S(2f)), ((Rect)(ref rect)).height), c2); float num = S(20f); float num2 = S(8f); float num3 = ((Rect)(ref rect)).width * 0.46f; float num4 = ((Rect)(ref rect)).x + num3; float num5 = ((Rect)(ref rect)).xMax - num4 - num2; GUIStyle val = new GUIStyle(Theme.Row) { padding = new RectOffset(0, 0, 0, 0), alignment = (TextAnchor)4, clipping = (TextClipping)1, fontStyle = (FontStyle)1, fontSize = Mathf.Max(1, Mathf.RoundToInt(12f * _scale)) }; val.normal.textColor = sidePanelAccentColor; GUIStyle val2 = val; GUIStyle baseStyle = new GUIStyle(Theme.Row) { padding = new RectOffset(0, 0, 0, 0), alignment = (TextAnchor)3, clipping = (TextClipping)1, fontStyle = (FontStyle)1, fontSize = Mathf.Max(1, Mathf.RoundToInt(11f * _scale)) }; GUIStyle baseStyle2 = new GUIStyle(Theme.RowRight) { padding = new RectOffset(0, 0, 0, 0), alignment = (TextAnchor)5, wordWrap = false, clipping = (TextClipping)1, fontStyle = (FontStyle)1, fontSize = Mathf.Max(1, Mathf.RoundToInt(10f * _scale)) }; Rect val3 = default(Rect); ((Rect)(ref val3))..ctor(((Rect)(ref rect)).x + S(4f), ((Rect)(ref rect)).y, num, ((Rect)(ref rect)).height); Rect rect2 = default(Rect); ((Rect)(ref rect2))..ctor(((Rect)(ref val3)).xMax + S(4f), ((Rect)(ref rect)).y, Mathf.Max(1f, num3 - num - S(8f)), ((Rect)(ref rect)).height); Rect rect3 = default(Rect); ((Rect)(ref rect3))..ctor(num4, ((Rect)(ref rect)).y, Mathf.Max(1f, num5), ((Rect)(ref rect)).height); GUI.Label(val3, GetSidePanelIcon(info.Name), val2); DrawFittingLabel(rect2, info.Name, baseStyle, Mathf.Max(8, Mathf.RoundToInt(9f * _scale))); DrawFittingLabel(rect3, info.ValueText, baseStyle2, Mathf.Max(8, Mathf.RoundToInt(8f * _scale))); } } private static bool IsPlayerPanel(MenuSidePanel panel) { if (panel != null) { return string.Equals(panel.Title, "PLAYER INFORMATION", StringComparison.Ordinal); } return false; } private static bool IsItemPanel(MenuSidePanel panel) { if (panel != null) { return string.Equals(panel.Title, "ITEM INFORMATION", StringComparison.Ordinal); } return false; } private void DrawPlayerPanelBackdrop(Rect rect) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0036: 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) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0091: 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) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) Color c = default(Color); ((Color)(ref c))..ctor(Theme.Accent.r, Theme.Accent.g, Theme.Accent.b, 0.1f); Color c2 = default(Color); ((Color)(ref c2))..ctor(Theme.Accent.r, Theme.Accent.g, Theme.Accent.b, 0.22f); Theme.Fill(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y + ((Rect)(ref rect)).height * 0.22f, ((Rect)(ref rect)).width, Mathf.Max(1f, S(1f))), c); Theme.Fill(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y + ((Rect)(ref rect)).height * 0.58f, ((Rect)(ref rect)).width, Mathf.Max(1f, S(1f))), c); Theme.Fill(new Rect(((Rect)(ref rect)).x + S(12f), ((Rect)(ref rect)).yMax - S(30f), ((Rect)(ref rect)).width - S(24f), Mathf.Max(1f, S(1f))), c2); } private void DrawPortraitCorners(Rect rect) { //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_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_007c: 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) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: 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_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) Color white = Color.white; white.a = 0.72f; float num = S(12f); float num2 = Mathf.Max(1f, S(2f)); Theme.Fill(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, num, num2), white); Theme.Fill(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, num2, num), white); Theme.Fill(new Rect(((Rect)(ref rect)).xMax - num, ((Rect)(ref rect)).y, num, num2), white); Theme.Fill(new Rect(((Rect)(ref rect)).xMax - num2, ((Rect)(ref rect)).y, num2, num), white); Theme.Fill(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).yMax - num2, num, num2), white); Theme.Fill(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).yMax - num, num2, num), white); Theme.Fill(new Rect(((Rect)(ref rect)).xMax - num, ((Rect)(ref rect)).yMax - num2, num, num2), white); Theme.Fill(new Rect(((Rect)(ref rect)).xMax - num2, ((Rect)(ref rect)).yMax - num, num2, num), white); } private void DrawPlayerSidePanelRows(Rect rect, List rows) { //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) InfoFeature infoFeature = FindInfo(rows, "Status"); InfoFeature infoFeature2 = FindInfo(rows, "Session"); InfoFeature stamina = FindInfo(rows, "Stamina"); List playerAfflictionRows = GetPlayerAfflictionRows(rows); float num = S(6f); float y = ((Rect)(ref rect)).y; DrawPlayerStatusBanner(new Rect(((Rect)(ref rect)).x, y, ((Rect)(ref rect)).width, S(38f)), infoFeature?.ValueText ?? "-", infoFeature2?.ValueText ?? "-"); y += S(38f) + num; float playerVitalsHeight = GetPlayerVitalsHeight(playerAfflictionRows); DrawPlayerVitalsBar(new Rect(((Rect)(ref rect)).x, y, ((Rect)(ref rect)).width, playerVitalsHeight), stamina, playerAfflictionRows); y += playerVitalsHeight + S(8f); float num2 = S(6f); float num3 = S(38f); float num4 = (((Rect)(ref rect)).width - num2) * 0.5f; int num5 = 0; for (int i = 0; i < rows.Count; i++) { InfoFeature infoFeature3 = rows[i]; if (infoFeature3 != null && !IsPrimaryPlayerInfo(infoFeature3.Name) && !IsAfflictionInfo(infoFeature3.Name)) { int num6 = num5 % 2; int num7 = num5 / 2; float num8 = ((Rect)(ref rect)).x + (float)num6 * (num4 + num2); float num9 = y + (float)num7 * (num3 + num); if (num9 + num3 > ((Rect)(ref rect)).yMax) { break; } DrawPlayerMiniCard(new Rect(num8, num9, num4, num3), infoFeature3.Name, infoFeature3.ValueText, GetPlayerStatIcon(infoFeature3.Name)); num5++; } } } private static bool IsPrimaryPlayerInfo(string name) { if (string.IsNullOrEmpty(name)) { return false; } switch (name.ToLowerInvariant()) { case "status": case "session": case "stamina": case "pass out": return true; default: return false; } } private static int CountPlayerGridRows(List rows) { if (rows == null) { return 0; } int num = 0; for (int i = 0; i < rows.Count; i++) { InfoFeature infoFeature = rows[i]; if (infoFeature != null && !IsPrimaryPlayerInfo(infoFeature.Name) && !IsAfflictionInfo(infoFeature.Name)) { num++; } } return num; } private float GetPlayerVitalsHeight(List afflictions) { if (afflictions == null || afflictions.Count <= 0) { return S(62f); } return S(104f); } private static List GetPlayerAfflictionRows(List rows) { List list = new List(); if (rows == null) { return list; } for (int i = 0; i < rows.Count; i++) { InfoFeature infoFeature = rows[i]; if (infoFeature != null && IsAfflictionStatus(infoFeature.Name)) { list.Add(infoFeature); } } return list; } private static bool IsAfflictionInfo(string name) { if (!string.Equals(name, "Affliction Sum", StringComparison.OrdinalIgnoreCase)) { return IsAfflictionStatus(name); } return true; } private static bool IsAfflictionStatus(string name) { if (string.IsNullOrEmpty(name)) { return false; } switch (name.ToLowerInvariant()) { case "injury": case "hunger": case "poison": case "drowsy": case "weight": case "thorns": case "spores": case "cold": case "crab": case "hot": case "web": case "curse": return true; default: return false; } } private static string GetPlayerStatIcon(string name) { if (string.IsNullOrEmpty(name)) { return "--"; } switch (name.ToLowerInvariant()) { case "actor": return "#"; case "steam": return "ID"; case "distance": return "M"; case "position": return "XYZ"; case "max stamina": case "stamina mod": case "total stamina": case "extra stamina": case "stamina delta": return "ST"; case "speed": case "move mod": case "move force": case "sprint mod": return "MV"; case "jumps": case "jump impulse": return "JP"; case "fall time": return "FT"; case "grounded": return "GR"; case "climbing": case "rope": case "vine": return "CL"; case "full pass out": case "will pass out": case "passed out": return "PO"; case "affliction sum": return "AF"; case "webbed": case "web": return "WB"; default: if (name.Length > 2) { return name.Substring(0, 2).ToUpperInvariant(); } return name.ToUpperInvariant(); } } private void DrawPlayerStatusBanner(Rect rect, string status, string session) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: 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_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0086: 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) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Expected O, but got Unknown //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Expected O, but got Unknown //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Expected O, but got Unknown //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Expected O, but got Unknown //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Expected O, but got Unknown //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01b9: Expected O, but got Unknown //IL_01f7: Unknown result type (might be due to invalid IL or missing references) //IL_0245: Unknown result type (might be due to invalid IL or missing references) //IL_0282: Unknown result type (might be due to invalid IL or missing references) Color c = (string.Equals(status, "Alive", StringComparison.OrdinalIgnoreCase) ? new Color(0.16f, 0.66f, 0.38f, 1f) : new Color(0.78f, 0.16f, 0.14f, 1f)); Theme.Fill(rect, new Color(0f, 0f, 0f, 0.28f)); DrawRectOutline(rect, new Color(Theme.TextDim.r, Theme.TextDim.g, Theme.TextDim.b, 0.24f), Mathf.Max(1f, S(1f))); Theme.Fill(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, Mathf.Max(3f, S(3f)), ((Rect)(ref rect)).height), c); GUIStyle val = new GUIStyle(Theme.Row) { padding = new RectOffset(0, 0, 0, 0), alignment = (TextAnchor)0, fontStyle = (FontStyle)1, fontSize = Mathf.Max(1, Mathf.RoundToInt(9f * _scale)) }; val.normal.textColor = Theme.TextDim; GUIStyle val2 = val; GUIStyle val3 = new GUIStyle(Theme.Row) { padding = new RectOffset(0, 0, 0, 0), alignment = (TextAnchor)6, fontStyle = (FontStyle)1, fontSize = Mathf.Max(1, Mathf.RoundToInt(14f * _scale)) }; GUIStyle baseStyle = new GUIStyle(Theme.RowRight) { padding = new RectOffset(0, 0, 0, 0), alignment = (TextAnchor)5, fontStyle = (FontStyle)1, fontSize = Mathf.Max(1, Mathf.RoundToInt(11f * _scale)) }; GUI.Label(new Rect(((Rect)(ref rect)).x + S(12f), ((Rect)(ref rect)).y + S(6f), ((Rect)(ref rect)).width * 0.4f, S(14f)), "STATUS", val2); GUI.Label(new Rect(((Rect)(ref rect)).x + S(12f), ((Rect)(ref rect)).y + S(19f), ((Rect)(ref rect)).width * 0.4f, S(18f)), status, val3); DrawFittingLabel(new Rect(((Rect)(ref rect)).x + ((Rect)(ref rect)).width * 0.44f, ((Rect)(ref rect)).y, ((Rect)(ref rect)).width * 0.52f, ((Rect)(ref rect)).height), session, baseStyle, Mathf.Max(8, Mathf.RoundToInt(8f * _scale))); } private void DrawPlayerVitalsBar(Rect rect, InfoFeature stamina, List afflictions) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Expected O, but got Unknown //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Expected O, but got Unknown //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Expected O, but got Unknown //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Expected O, but got Unknown //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_01fc: Unknown result type (might be due to invalid IL or missing references) //IL_0261: Unknown result type (might be due to invalid IL or missing references) float staminaPercent = SmoothPlayerMetric("stamina", ExtractPercent(stamina?.ValueText, 1f)); Theme.Fill(rect, new Color(0f, 0f, 0f, 0.25f)); DrawRectOutline(rect, new Color(Theme.TextDim.r, Theme.TextDim.g, Theme.TextDim.b, 0.24f), Mathf.Max(1f, S(1f))); GUIStyle val = new GUIStyle(Theme.Row) { padding = new RectOffset(0, 0, 0, 0), alignment = (TextAnchor)0, fontStyle = (FontStyle)1, fontSize = Mathf.Max(1, Mathf.RoundToInt(10f * _scale)) }; GUIStyle baseStyle = new GUIStyle(Theme.RowRight) { padding = new RectOffset(0, 0, 0, 0), alignment = (TextAnchor)2, fontStyle = (FontStyle)1, fontSize = Mathf.Max(1, Mathf.RoundToInt(10f * _scale)) }; Rect val2 = default(Rect); ((Rect)(ref val2))..ctor(((Rect)(ref rect)).x + S(10f), ((Rect)(ref rect)).y + S(6f), ((Rect)(ref rect)).width - S(20f), S(16f)); string text = ((afflictions != null && afflictions.Count > 0) ? "STAMINA / AFFLICTIONS" : "STAMINA"); GUI.Label(val2, text, val); DrawFittingLabel(val2, stamina?.ValueText ?? "--", baseStyle, Mathf.Max(8, Mathf.RoundToInt(8f * _scale))); Rect rect2 = default(Rect); ((Rect)(ref rect2))..ctor(((Rect)(ref rect)).x + S(10f), ((Rect)(ref rect)).y + S(26f), ((Rect)(ref rect)).width - S(20f), S(22f)); DrawGameStaminaBar(rect2, staminaPercent, afflictions); Rect rect3 = default(Rect); ((Rect)(ref rect3))..ctor(((Rect)(ref rect)).x + S(10f), ((Rect)(ref rect2)).yMax + S(6f), ((Rect)(ref rect)).width - S(20f), ((Rect)(ref rect)).yMax - ((Rect)(ref rect2)).yMax - S(10f)); DrawAfflictionBadges(rect3, afflictions); } private void DrawGameStaminaBar(Rect rect, float staminaPercent, List afflictions) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: 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_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0065: 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_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Unknown result type (might be due to invalid IL or missing references) //IL_01ea: Unknown result type (might be due to invalid IL or missing references) //IL_0189: 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_0191: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Unknown result type (might be due to invalid IL or missing references) staminaPercent = Mathf.Clamp01(staminaPercent); float num = Mathf.Max(1f, S(2f)); Theme.Fill(rect, new Color(0.015f, 0.017f, 0.013f, 1f)); DrawRectOutline(rect, new Color(0f, 0f, 0f, 0.9f), num); Rect val = Inset(rect, num); Theme.Fill(val, new Color(0.08f, 0.09f, 0.07f, 0.95f)); float afflictionTotal = GetAfflictionTotal(afflictions); float num2 = Mathf.Clamp01(afflictionTotal); float num3 = Mathf.Clamp01(1f - num2); float width = ((Rect)(ref val)).width * num3 * staminaPercent; DrawClippedStaminaFill(val, ((Rect)(ref val)).x, width, new Color(0.28f, 0.72f, 0.08f, 1f), striped: false); if (afflictions != null) { float num4 = ((afflictionTotal > 1f) ? (1f / afflictionTotal) : 1f); float num5 = ((Rect)(ref val)).x + ((Rect)(ref val)).width * num3; for (int i = 0; i < afflictions.Count; i++) { InfoFeature infoFeature = afflictions[i]; float num6 = SmoothPlayerMetric("affliction:" + infoFeature.Name, ExtractPercent(infoFeature.ValueText, 0f)); if (!(num6 <= 0.001f)) { float num7 = ((Rect)(ref val)).width * Mathf.Clamp01(num6 * num4); if (num5 >= ((Rect)(ref val)).xMax) { break; } num7 = Mathf.Min(num7, ((Rect)(ref val)).xMax - num5); Color afflictionColor = GetAfflictionColor(infoFeature.Name); DrawClippedStaminaFill(val, num5, num7, new Color(afflictionColor.r, afflictionColor.g, afflictionColor.b, 0.9f), striped: true); num5 += num7; } } } DrawRectOutline(rect, new Color(1f, 1f, 1f, 0.36f), Mathf.Max(1f, S(1f))); } private float GetAfflictionTotal(List afflictions) { if (afflictions == null || afflictions.Count == 0) { return 0f; } float num = 0f; for (int i = 0; i < afflictions.Count; i++) { InfoFeature infoFeature = afflictions[i]; if (infoFeature != null) { num += Mathf.Clamp01(SmoothPlayerMetric("affliction:" + infoFeature.Name, ExtractPercent(infoFeature.ValueText, 0f))); } } return num; } private void DrawClippedStaminaFill(Rect track, float startX, float width, Color color, bool striped) { //IL_003f: 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) if (!(width <= 0f)) { float num = Mathf.Max(((Rect)(ref track)).x, startX); float num2 = Mathf.Min(((Rect)(ref track)).xMax, startX + width); if (!(num2 <= num)) { DrawStaminaFill(new Rect(num, ((Rect)(ref track)).y, num2 - num, ((Rect)(ref track)).height), color, striped); } } } private void DrawStaminaFill(Rect rect, Color color, bool striped) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: 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) //IL_005e: Unknown result type (might be due to invalid IL or missing references) Theme.Fill(rect, color); if (striped) { Texture2D staminaStripeTexture = GetStaminaStripeTexture(); if (Object.op_Implicit((Object)(object)staminaStripeTexture)) { float num = Mathf.Max(2f, S(7f)); Color color2 = GUI.color; GUI.color = Color.white; GUI.DrawTextureWithTexCoords(rect, (Texture)(object)staminaStripeTexture, new Rect(0f, 0f, ((Rect)(ref rect)).width / num, ((Rect)(ref rect)).height / num), true); GUI.color = color2; } } } private Texture2D GetStaminaStripeTexture() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)_staminaStripeTexture)) { return _staminaStripeTexture; } Texture2D val = new Texture2D(16, 16, (TextureFormat)4, false) { hideFlags = (HideFlags)61, wrapMode = (TextureWrapMode)0, filterMode = (FilterMode)0, name = "CubeX_StaminaStripe" }; Color val2 = default(Color); ((Color)(ref val2))..ctor(0f, 0f, 0f, 0f); Color val3 = default(Color); ((Color)(ref val3))..ctor(0f, 0f, 0f, 0.28f); for (int i = 0; i < 16; i++) { for (int j = 0; j < 16; j++) { int num = (j + i) % 8; val.SetPixel(j, i, (num <= 2) ? val3 : val2); } } val.Apply(false, false); return _staminaStripeTexture = val; } private void DrawAfflictionBadges(Rect rect, List afflictions) { //IL_0054: 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_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Expected O, but got Unknown //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006f: 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_007d: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Expected O, but got Unknown //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_01f5: Unknown result type (might be due to invalid IL or missing references) if (afflictions == null || afflictions.Count == 0) { return; } int num = ((!(((Rect)(ref rect)).width >= S(320f))) ? 1 : 2); float num2 = S(4f); float num3 = S(16f); float num4 = (((Rect)(ref rect)).width - num2 * (float)(num - 1)) / (float)num; GUIStyle baseStyle = new GUIStyle(Theme.Row) { padding = new RectOffset(0, 0, 0, 0), alignment = (TextAnchor)3, clipping = (TextClipping)1, fontStyle = (FontStyle)1, fontSize = Mathf.Max(1, Mathf.RoundToInt(8f * _scale)) }; Rect val = default(Rect); for (int i = 0; i < afflictions.Count; i++) { int num5 = i % num; int num6 = i / num; ((Rect)(ref val))..ctor(((Rect)(ref rect)).x + (float)num5 * (num4 + num2), ((Rect)(ref rect)).y + (float)num6 * (num3 + S(1f)), num4, num3); if (!(((Rect)(ref val)).yMax > ((Rect)(ref rect)).yMax)) { InfoFeature infoFeature = afflictions[i]; Color afflictionColor = GetAfflictionColor(infoFeature.Name); Theme.Fill(val, new Color(afflictionColor.r, afflictionColor.g, afflictionColor.b, 0.28f)); Theme.Fill(new Rect(((Rect)(ref val)).x, ((Rect)(ref val)).y, Mathf.Max(2f, S(2f)), ((Rect)(ref val)).height), afflictionColor); DrawRectOutline(val, new Color(1f, 1f, 1f, 0.12f), Mathf.Max(1f, S(1f))); string text = infoFeature.Name + " " + (infoFeature.ValueText ?? "--"); DrawFittingLabel(new Rect(((Rect)(ref val)).x + S(5f), ((Rect)(ref val)).y, ((Rect)(ref val)).width - S(8f), ((Rect)(ref val)).height), text, baseStyle, Mathf.Max(6, Mathf.RoundToInt(7f * _scale))); continue; } break; } } private float SmoothPlayerMetric(string key, float target) { target = Mathf.Clamp01(target); if (string.IsNullOrEmpty(key)) { return target; } if (!_smoothPlayerMetrics.TryGetValue(key, out var value)) { _smoothPlayerMetrics[key] = target; return target; } float num = 1f - Mathf.Exp(-10f * Time.unscaledDeltaTime); value = Mathf.Lerp(value, target, num); _smoothPlayerMetrics[key] = value; return value; } private static Color GetAfflictionColor(string name) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0326: Unknown result type (might be due to invalid IL or missing references) //IL_0270: 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_0222: Unknown result type (might be due to invalid IL or missing references) //IL_030c: Unknown result type (might be due to invalid IL or missing references) //IL_0256: Unknown result type (might be due to invalid IL or missing references) //IL_01ee: Unknown result type (might be due to invalid IL or missing references) //IL_028a: Unknown result type (might be due to invalid IL or missing references) //IL_023c: Unknown result type (might be due to invalid IL or missing references) //IL_02f2: Unknown result type (might be due to invalid IL or missing references) //IL_02d8: Unknown result type (might be due to invalid IL or missing references) //IL_0208: Unknown result type (might be due to invalid IL or missing references) //IL_02a4: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrEmpty(name)) { return new Color(0.55f, 0.55f, 0.55f, 1f); } return (Color)(name.ToLowerInvariant() switch { "injury" => new Color(0.82f, 0.16f, 0.14f, 1f), "hunger" => new Color(0.92f, 0.54f, 0.12f, 1f), "cold" => new Color(0.22f, 0.58f, 0.94f, 1f), "poison" => new Color(0.46f, 0.78f, 0.18f, 1f), "crab" => new Color(0.9f, 0.32f, 0.22f, 1f), "curse" => new Color(0.56f, 0.28f, 0.86f, 1f), "drowsy" => new Color(0.56f, 0.58f, 0.66f, 1f), "weight" => new Color(0.86f, 0.68f, 0.28f, 1f), "hot" => new Color(0.95f, 0.28f, 0.08f, 1f), "thorns" => new Color(0.24f, 0.72f, 0.26f, 1f), "spores" => new Color(0.32f, 0.74f, 0.52f, 1f), "web" => new Color(0.72f, 0.82f, 0.9f, 1f), _ => new Color(0.55f, 0.55f, 0.55f, 1f), }); } private void DrawPlayerMiniCard(Rect rect, string label, string value, string icon) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0091: 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_00a5: 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_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Expected O, but got Unknown //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Expected O, but got Unknown //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Expected O, but got Unknown //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Expected O, but got Unknown //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Expected O, but got Unknown //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_0252: Unknown result type (might be due to invalid IL or missing references) //IL_028c: Unknown result type (might be due to invalid IL or missing references) Theme.Fill(rect, new Color(0f, 0f, 0f, 0.23f)); DrawRectOutline(rect, new Color(Theme.TextDim.r, Theme.TextDim.g, Theme.TextDim.b, 0.2f), Mathf.Max(1f, S(1f))); Theme.Fill(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, Mathf.Max(2f, S(2f)), ((Rect)(ref rect)).height), new Color(Theme.Accent.r, Theme.Accent.g, Theme.Accent.b, 0.5f)); GUIStyle val = new GUIStyle(Theme.Row) { padding = new RectOffset(0, 0, 0, 0), alignment = (TextAnchor)0, fontStyle = (FontStyle)1, fontSize = Mathf.Max(1, Mathf.RoundToInt(9f * _scale)) }; val.normal.textColor = Theme.TextDim; GUIStyle val2 = val; GUIStyle val3 = new GUIStyle(val2) { alignment = (TextAnchor)2, fontSize = Mathf.Max(1, Mathf.RoundToInt(8f * _scale)) }; GUIStyle baseStyle = new GUIStyle(Theme.RowRight) { padding = new RectOffset(0, 0, 0, 0), alignment = (TextAnchor)6, clipping = (TextClipping)1, fontStyle = (FontStyle)1, fontSize = Mathf.Max(1, Mathf.RoundToInt(10f * _scale)) }; Rect val4 = default(Rect); ((Rect)(ref val4))..ctor(((Rect)(ref rect)).x + S(9f), ((Rect)(ref rect)).y + S(5f), ((Rect)(ref rect)).width - S(18f), ((Rect)(ref rect)).height - S(10f)); GUI.Label(new Rect(((Rect)(ref val4)).x, ((Rect)(ref val4)).y, ((Rect)(ref val4)).width - S(38f), S(14f)), label.ToUpperInvariant(), val2); GUI.Label(new Rect(((Rect)(ref val4)).x + ((Rect)(ref val4)).width - S(36f), ((Rect)(ref val4)).y, S(36f), S(14f)), icon, val3); DrawFittingLabel(new Rect(((Rect)(ref val4)).x, ((Rect)(ref val4)).y + S(15f), ((Rect)(ref val4)).width, S(18f)), value, baseStyle, Mathf.Max(7, Mathf.RoundToInt(8f * _scale))); } private static InfoFeature FindInfo(List rows, string name) { if (rows == null || string.IsNullOrEmpty(name)) { return null; } for (int i = 0; i < rows.Count; i++) { InfoFeature infoFeature = rows[i]; if (infoFeature != null && string.Equals(infoFeature.Name, name, StringComparison.OrdinalIgnoreCase)) { return infoFeature; } } return null; } private static float ExtractPercent(string text, float fallback) { if (string.IsNullOrEmpty(text)) { return Mathf.Clamp01(fallback); } int num = text.IndexOf('%'); if (num < 0) { return Mathf.Clamp01(fallback); } int num2 = num - 1; while (num2 >= 0 && (char.IsDigit(text[num2]) || text[num2] == '.' || text[num2] == '-')) { num2--; } if (float.TryParse(text.Substring(num2 + 1, num - num2 - 1), NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { return Mathf.Clamp01(result / 100f); } return Mathf.Clamp01(fallback); } private static string GetSidePanelIcon(string name) { if (string.IsNullOrEmpty(name)) { return "•"; } switch (name.ToLowerInvariant()) { case "status": return "●"; case "actor": return "#"; case "steam": return "◎"; case "session": return "◆"; case "stamina": return "★"; case "bonus stamina": case "infinite stamina": return "⚡"; case "run": return "▲"; case "climb": return "△"; case "hunger": case "no hunger": return "☾"; case "drowsy": return "Zz"; case "weight": return "▰"; case "cold": return "❄"; case "poison": return "!"; case "injury": return "+"; case "curse": return "?"; case "clear status": return "✓"; case "low gravity": return "↟"; case "jump": return "↥"; case "morale": case "invincibility": return "★"; case "random effect": return "?"; case "effects": return "FX"; case "category": return "CAT"; case "use": return "USE"; case "mass": case "carry weight": return "WT"; case "total uses": return "#"; case "item tags": return "TAG"; case "pass out": return "!"; case "distance": return "◇"; case "position": return "⌖"; case "speed": return "MV"; default: return "•"; } } private static Color GetSidePanelAccentColor(string name) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0327: Unknown result type (might be due to invalid IL or missing references) //IL_0251: Unknown result type (might be due to invalid IL or missing references) //IL_02b9: Unknown result type (might be due to invalid IL or missing references) //IL_0285: Unknown result type (might be due to invalid IL or missing references) //IL_0321: Unknown result type (might be due to invalid IL or missing references) //IL_0307: Unknown result type (might be due to invalid IL or missing references) //IL_026b: Unknown result type (might be due to invalid IL or missing references) //IL_02d3: Unknown result type (might be due to invalid IL or missing references) //IL_029f: Unknown result type (might be due to invalid IL or missing references) //IL_02ed: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrEmpty(name)) { return Theme.Accent; } switch (name.ToLowerInvariant()) { case "climb": case "bonus stamina": case "run": case "infinite stamina": return new Color(0.62f, 0.92f, 0.12f, 1f); case "drowsy": return new Color(0.96f, 0.34f, 0.72f, 1f); case "hunger": case "no hunger": return new Color(1f, 0.72f, 0.16f, 1f); case "weight": return new Color(0.78f, 0.42f, 0.08f, 1f); case "cold": return new Color(0.28f, 0.7f, 1f, 1f); case "poison": return new Color(0.54f, 0.86f, 0.18f, 1f); case "injury": return new Color(0.9f, 0.22f, 0.18f, 1f); case "curse": case "random effect": return new Color(0.62f, 0.34f, 0.9f, 1f); case "invincibility": case "morale": case "clear status": return new Color(0.24f, 0.74f, 0.46f, 1f); default: return Theme.Accent; } } private void DrawFittingLabel(Rect rect, string text, GUIStyle baseStyle, int minFontSize) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Expected O, but got Unknown //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) GUIStyle val = new GUIStyle(baseStyle); GUIContent val2 = new GUIContent(text ?? string.Empty); while (val.fontSize > minFontSize && val.CalcSize(val2).x > ((Rect)(ref rect)).width) { int fontSize = val.fontSize; val.fontSize = fontSize - 1; } GUI.Label(rect, val2, val); } private void DrawLabelWithTags(Rect rect, string text, GUIStyle baseStyle, int minFontSize, List tags, bool highlighted, bool alignTagsRight = false) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) if (tags == null || tags.Count == 0) { DrawFittingLabel(rect, text, baseStyle, minFontSize); return; } GUIStyle val = new GUIStyle(baseStyle); GUIContent val2 = new GUIContent(text ?? string.Empty); float tagGroupWidth = GetTagGroupWidth(tags); float num = S(8f); float num2 = Mathf.Max(1f, ((Rect)(ref rect)).width - tagGroupWidth - num); while (val.fontSize > minFontSize && val.CalcSize(val2).x > num2) { int fontSize = val.fontSize; val.fontSize = fontSize - 1; } GUI.Label(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, num2, ((Rect)(ref rect)).height), val2, val); float num3 = (alignTagsRight ? (((Rect)(ref rect)).xMax - tagGroupWidth) : (((Rect)(ref rect)).x + Mathf.Min(val.CalcSize(val2).x, num2) + num)); float num4 = (alignTagsRight ? (tagGroupWidth + S(2f)) : Mathf.Max(1f, ((Rect)(ref rect)).xMax - num3)); DrawMenuTags(new Rect(num3, ((Rect)(ref rect)).y, num4, ((Rect)(ref rect)).height), tags, highlighted); } private float GetTagGroupWidth(List tags) { if (tags == null || tags.Count == 0) { return 0f; } GUIStyle tagTextStyle = GetTagTextStyle(highlighted: false); float num = 0f; for (int i = 0; i < tags.Count; i++) { if (i > 0) { num += S(4f); } num += GetTagWidth(tags[i], tagTextStyle); } return num; } private float GetTagWidth(MenuTag tag, GUIStyle style) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown //IL_0018: Unknown result type (might be due to invalid IL or missing references) string text = ((tag != null) ? tag.Text : string.Empty); return style.CalcSize(new GUIContent(text)).x + S(12f); } private void DrawMenuTags(Rect rect, List tags, bool highlighted) { //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) if (tags == null || tags.Count == 0) { return; } GUIStyle tagTextStyle = GetTagTextStyle(highlighted); float num = ((Rect)(ref rect)).x; float num2 = Mathf.Min(S(18f), ((Rect)(ref rect)).height - S(4f)); float num3 = ((Rect)(ref rect)).y + (((Rect)(ref rect)).height - num2) * 0.5f; for (int i = 0; i < tags.Count; i++) { MenuTag menuTag = tags[i]; if (menuTag != null && !string.IsNullOrEmpty(menuTag.Text)) { float tagWidth = GetTagWidth(menuTag, tagTextStyle); if (num + tagWidth > ((Rect)(ref rect)).xMax + S(1f)) { break; } Rect val = new Rect(num, num3, tagWidth, num2); Color color = menuTag.Color; color.a = (highlighted ? 0.95f : 0.82f); Theme.Fill(val, color); DrawRectOutline(val, new Color(1f, 1f, 1f, highlighted ? 0.32f : 0.2f), Mathf.Max(1f, S(1f))); GUI.Label(val, menuTag.Text, tagTextStyle); num += tagWidth + S(4f); } } } private GUIStyle GetTagTextStyle(bool highlighted) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_004e: 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_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0065: 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_0075: 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) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Expected O, but got Unknown GUIStyle val = new GUIStyle(highlighted ? Theme.RowSelected : Theme.Row) { padding = new RectOffset(0, 0, 0, 0), alignment = (TextAnchor)4, fontStyle = (FontStyle)1, fontSize = Mathf.Max(1, Mathf.RoundToInt(9f * _scale)), clipping = (TextClipping)1 }; val.normal.textColor = Color.white; val.hover.textColor = Color.white; val.active.textColor = Color.white; val.focused.textColor = Color.white; return val; } private void DrawColorPicker(Rect rect, ColorFeature color) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_019e: 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_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_01f3: Unknown result type (might be due to invalid IL or missing references) //IL_01f5: Unknown result type (might be due to invalid IL or missing references) Theme.Fill(rect, Theme.DescBg); Theme.Fill(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, ((Rect)(ref rect)).width, Mathf.Max(1f, S(1f))), Theme.Accent); float num = S(14f); float num2 = S(10f); float num3 = S(22f); float num4 = ((Rect)(ref rect)).width - num * 2f - num3 - num2 - S(140f); float num5 = Mathf.Clamp(Mathf.Min(S(152f), num4), S(96f), S(170f)); Rect val = default(Rect); ((Rect)(ref val))..ctor(((Rect)(ref rect)).x + num, ((Rect)(ref rect)).y + S(40f), num5, num5); Rect val2 = default(Rect); ((Rect)(ref val2))..ctor(((Rect)(ref val)).xMax + num2, ((Rect)(ref val)).y, num3, num5); Rect rect2 = default(Rect); ((Rect)(ref rect2))..ctor(((Rect)(ref val2)).xMax + S(14f), ((Rect)(ref val)).y, ((Rect)(ref rect)).xMax - num - ((Rect)(ref val2)).xMax - S(14f), num5); EnsureColorPickerTextures(); GUI.DrawTexture(val, (Texture)(object)_colorSatValTexture, (ScaleMode)0, false); GUI.DrawTexture(val2, (Texture)(object)_colorHueTexture, (ScaleMode)0, false); DrawRectOutline(val, Theme.TextDim, Mathf.Max(1f, S(1f))); DrawRectOutline(val2, Theme.TextDim, Mathf.Max(1f, S(1f))); DrawColorPickerMarkers(val, val2); DrawColorPickerReadout(rect2, color); DrawColorPresetSwatches(new Rect(((Rect)(ref rect)).x + num, ((Rect)(ref rect)).yMax - S(38f), ((Rect)(ref rect)).width - num * 2f, S(26f)), color); HandleColorPickerMouse(val, val2, color); } private void DrawColorPickerReadout(Rect rect, ColorFeature color) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: 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_0057: Expected O, but got Unknown //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Expected O, but got Unknown //IL_0064: 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) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Expected O, but got Unknown //IL_0078: 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: Expected O, but got Unknown //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_0168: 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) float num = Mathf.Min(S(54f), ((Rect)(ref rect)).height); Rect rect2 = default(Rect); ((Rect)(ref rect2))..ctor(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, num, num); DrawColorSwatch(rect2, _editingColorPreview, highlighted: false, active: true); GUIStyle val = new GUIStyle(Theme.DescTitle) { padding = new RectOffset(0, 0, 0, 0), alignment = (TextAnchor)0 }; GUIStyle val2 = new GUIStyle(Theme.DescBody) { padding = new RectOffset(0, 0, 0, 0), alignment = (TextAnchor)0, wordWrap = false }; Rect val3 = default(Rect); ((Rect)(ref val3))..ctor(((Rect)(ref rect)).x, ((Rect)(ref rect2)).yMax + S(10f), ((Rect)(ref rect)).width, ((Rect)(ref rect)).height - num - S(10f)); GUI.Label(new Rect(((Rect)(ref val3)).x, ((Rect)(ref val3)).y, ((Rect)(ref val3)).width, S(22f)), "#" + ColorUtility.ToHtmlStringRGB(_editingColorPreview), val); Color editingColorPreview = _editingColorPreview; string text = "R " + Mathf.RoundToInt(editingColorPreview.r * 255f) + " G " + Mathf.RoundToInt(editingColorPreview.g * 255f) + " B " + Mathf.RoundToInt(editingColorPreview.b * 255f); GUI.Label(new Rect(((Rect)(ref val3)).x, ((Rect)(ref val3)).y + S(24f), ((Rect)(ref val3)).width, S(22f)), text, val2); } private void DrawColorPresetSwatches(Rect rect, ColorFeature color) { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0058: 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_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006a: 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_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) if (color.PresetCount <= 0) { return; } float num = S(22f); float num2 = S(8f); float num3 = ((Rect)(ref rect)).x; Rect rect2 = default(Rect); for (int i = 0; i < color.PresetCount; i++) { ((Rect)(ref rect2))..ctor(num3, ((Rect)(ref rect)).y, num, num); if (!(((Rect)(ref rect2)).xMax > ((Rect)(ref rect)).xMax)) { Color presetColor = color.GetPresetColor(i); bool active = ColorApproximately(presetColor, _editingColorPreview); DrawColorSwatch(rect2, presetColor, highlighted: false, active); Event current = Event.current; if ((int)current.type == 0 && ((Rect)(ref rect2)).Contains(current.mousePosition)) { SetPickerFromColor(presetColor); current.Use(); } num3 += num + num2; continue; } break; } } private void DrawColorPickerMarkers(Rect squareRect, Rect hueRect) { //IL_0050: 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_0056: Unknown result type (might be due to invalid IL or missing references) //IL_008a: 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_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) float num = S(10f); Rect rect = new Rect(((Rect)(ref squareRect)).x + _colorSaturation * ((Rect)(ref squareRect)).width - num * 0.5f, ((Rect)(ref squareRect)).y + (1f - _colorValue) * ((Rect)(ref squareRect)).height - num * 0.5f, num, num); DrawRectOutline(rect, Color.black, Mathf.Max(1f, S(2f))); DrawRectOutline(Inset(rect, Mathf.Max(1f, S(2f))), Color.white, Mathf.Max(1f, S(1f))); float num2 = ((Rect)(ref hueRect)).y + _colorHue * ((Rect)(ref hueRect)).height; Rect val = new Rect(((Rect)(ref hueRect)).x - S(3f), num2 - S(2f), ((Rect)(ref hueRect)).width + S(6f), S(4f)); Theme.Fill(val, Color.black); Theme.Fill(Inset(val, Mathf.Max(1f, S(1f))), Color.white); } private void HandleColorPickerMouse(Rect squareRect, Rect hueRect, ColorFeature color) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Invalid comparison between Unknown and I4 //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Invalid comparison between Unknown and I4 //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0027: 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_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0095: 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) Event current = Event.current; if ((int)current.type == 0) { if (((Rect)(ref squareRect)).Contains(current.mousePosition)) { _colorDragTarget = 1; UpdatePickerSaturationValue(squareRect, current.mousePosition, color); current.Use(); } else if (((Rect)(ref hueRect)).Contains(current.mousePosition)) { _colorDragTarget = 2; UpdatePickerHue(hueRect, current.mousePosition, color); current.Use(); } } else if ((int)current.type == 3) { if (_colorDragTarget == 1) { UpdatePickerSaturationValue(squareRect, current.mousePosition, color); current.Use(); } else if (_colorDragTarget == 2) { UpdatePickerHue(hueRect, current.mousePosition, color); current.Use(); } } else if ((int)current.type == 1) { _colorDragTarget = 0; } } private void UpdatePickerSaturationValue(Rect rect, Vector2 mouse, ColorFeature color) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) _colorSaturation = Mathf.Clamp01((mouse.x - ((Rect)(ref rect)).x) / Mathf.Max(1f, ((Rect)(ref rect)).width)); _colorValue = Mathf.Clamp01(1f - (mouse.y - ((Rect)(ref rect)).y) / Mathf.Max(1f, ((Rect)(ref rect)).height)); UpdatePickerPreview(); } private void UpdatePickerHue(Rect rect, Vector2 mouse, ColorFeature color) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) _colorHue = Mathf.Clamp01((mouse.y - ((Rect)(ref rect)).y) / Mathf.Max(1f, ((Rect)(ref rect)).height)); UpdatePickerPreview(); } private void UpdatePickerPreview() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) Color editingColorPreview = Color.HSVToRGB(_colorHue, _colorSaturation, _colorValue); editingColorPreview.a = 1f; _editingColorPreview = editingColorPreview; } private void SetPickerFromColor(Color color) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) Color.RGBToHSV(color, ref _colorHue, ref _colorSaturation, ref _colorValue); _colorHue = Mathf.Clamp01(_colorHue); _colorSaturation = Mathf.Clamp01(_colorSaturation); _colorValue = Mathf.Clamp01(_colorValue); UpdatePickerPreview(); } private void EnsureColorPickerTextures() { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Expected O, but got Unknown //IL_0098: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_colorHueTexture == (Object)null) { _colorHueTexture = BuildHueTexture(); } if ((Object)(object)_colorSatValTexture == (Object)null) { _colorSatValTexture = new Texture2D(128, 128, (TextureFormat)4, false) { hideFlags = (HideFlags)61, wrapMode = (TextureWrapMode)1, filterMode = (FilterMode)1 }; } if (Mathf.Abs(_colorSatValTextureHue - _colorHue) <= 0.001f) { return; } for (int i = 0; i < 128; i++) { float num = (float)i / 127f; for (int j = 0; j < 128; j++) { float num2 = (float)j / 127f; _colorSatValTexture.SetPixel(j, i, Color.HSVToRGB(_colorHue, num2, num)); } } _colorSatValTexture.Apply(false, false); _colorSatValTextureHue = _colorHue; } private static Texture2D BuildHueTexture() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown //IL_0045: Unknown result type (might be due to invalid IL or missing references) Texture2D val = new Texture2D(1, 128, (TextureFormat)4, false) { hideFlags = (HideFlags)61, wrapMode = (TextureWrapMode)1, filterMode = (FilterMode)1 }; for (int i = 0; i < 128; i++) { float num = 1f - (float)i / 127f; val.SetPixel(0, i, Color.HSVToRGB(num, 1f, 1f)); } val.Apply(false, false); return val; } private static bool ColorApproximately(Color a, Color b) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) if (Mathf.Abs(a.r - b.r) <= 0.001f && Mathf.Abs(a.g - b.g) <= 0.001f) { return Mathf.Abs(a.b - b.b) <= 0.001f; } return false; } private static Rect Inset(Rect rect, float amount) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) return new Rect(((Rect)(ref rect)).x + amount, ((Rect)(ref rect)).y + amount, Mathf.Max(0f, ((Rect)(ref rect)).width - amount * 2f), Mathf.Max(0f, ((Rect)(ref rect)).height - amount * 2f)); } private static void DrawRectOutline(Rect rect, Color color, float thickness) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: 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_0082: Unknown result type (might be due to invalid IL or missing references) Theme.Fill(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, ((Rect)(ref rect)).width, thickness), color); Theme.Fill(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).yMax - thickness, ((Rect)(ref rect)).width, thickness), color); Theme.Fill(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, thickness, ((Rect)(ref rect)).height), color); Theme.Fill(new Rect(((Rect)(ref rect)).xMax - thickness, ((Rect)(ref rect)).y, thickness, ((Rect)(ref rect)).height), color); } private float CalculateDescriptionHeight(float width, string description) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown GUIStyle descriptionTextStyle = GetDescriptionTextStyle(); float num = Mathf.Max(1f, width - S(32f)); string text = WrapDescriptionText(description, descriptionTextStyle, num); float num2 = descriptionTextStyle.CalcHeight(new GUIContent(text), num); float num3 = Mathf.Max(S(54f), Mathf.Min(S(320f), (float)Screen.height * 0.35f)); return Mathf.Clamp(num2 + S(24f), S(54f), num3); } private Rect GetDescriptionTextRect(Rect rect) { //IL_005e: Unknown result type (might be due to invalid IL or missing references) float num = S(16f); return new Rect(((Rect)(ref rect)).x + num, ((Rect)(ref rect)).y + S(12f), Mathf.Max(1f, ((Rect)(ref rect)).width - num * 2f), Mathf.Max(1f, ((Rect)(ref rect)).height - S(24f))); } private GUIStyle GetDescriptionTextStyle() { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Expected O, but got Unknown //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Expected O, but got Unknown if (_descriptionTextStyle != null && Mathf.Approximately(_descriptionTextStyleScale, _scale)) { return _descriptionTextStyle; } _descriptionTextStyleScale = _scale; _descriptionTextStyle = new GUIStyle(Theme.DescBody) { padding = new RectOffset(0, 0, 0, 0), wordWrap = false }; return _descriptionTextStyle; } private string WrapDescriptionText(string text, GUIStyle style, float maxWidth) { if (string.IsNullOrEmpty(text)) { return string.Empty; } _descriptionWrapBuilder.Length = 0; string[] array = text.Replace("\r\n", "\n").Replace('\r', '\n').Split('\n'); for (int i = 0; i < array.Length; i++) { if (i > 0) { _descriptionWrapBuilder.Append('\n'); } AppendWrappedParagraph(array[i], style, maxWidth, _descriptionWrapBuilder); } return _descriptionWrapBuilder.ToString(); } private static void AppendWrappedParagraph(string paragraph, GUIStyle style, float maxWidth, StringBuilder output) { if (string.IsNullOrEmpty(paragraph)) { return; } string[] array = paragraph.Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries); string line = string.Empty; foreach (string text in array) { string text2 = (string.IsNullOrEmpty(line) ? text : (line + " " + text)); if (Fits(style, text2, maxWidth)) { line = text2; continue; } if (!string.IsNullOrEmpty(line)) { output.AppendLine(line); line = string.Empty; } if (Fits(style, text, maxWidth)) { line = text; } else { AppendHardWrappedWord(text, style, maxWidth, output, ref line); } } if (!string.IsNullOrEmpty(line)) { output.Append(line); } } private static void AppendHardWrappedWord(string word, GUIStyle style, float maxWidth, StringBuilder output, ref string line) { line = string.Empty; for (int i = 0; i < word.Length; i++) { string text = line + word[i]; if (Fits(style, text, maxWidth)) { line = text; continue; } if (!string.IsNullOrEmpty(line)) { output.AppendLine(line); } line = word[i].ToString(); } } private static bool Fits(GUIStyle style, string text, float maxWidth) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_0007: Unknown result type (might be due to invalid IL or missing references) return style.CalcSize(new GUIContent(text)).x <= maxWidth; } private object SelectedRow() { if (_rows.Count == 0 || _selected < 0 || _selected >= _rows.Count) { return null; } return _rows[_selected]; } private string GetCounterText() { int num = 0; int num2 = 0; for (int i = 0; i < _rows.Count; i++) { if (IsSelectable(_rows[i])) { num++; if (i <= _selected) { num2 = num; } } } if (num != 0) { return num2 + "/" + num; } return "0/0"; } private static bool IsSelectable(object row) { if (row != null) { return !(row is SeparatorFeature); } return false; } private static string ParentCategory(string category) { if (string.IsNullOrEmpty(category)) { return null; } int num = category.LastIndexOf('/'); if (num <= 0) { return null; } return category.Substring(0, num); } private static string LastCategorySegment(string category) { if (string.IsNullOrEmpty(category)) { return string.Empty; } int num = category.LastIndexOf('/'); if (num < 0) { return category; } return category.Substring(num + 1); } private string GetCategoryTitle(string category) { if (string.IsNullOrEmpty(category)) { return string.Empty; } if (!_categoryTitles.TryGetValue(category, out var value)) { return LastCategorySegment(category); } return value; } private string FormatCategoryPath(string category) { if (string.IsNullOrEmpty(category)) { return string.Empty; } string[] array = category.Split('/'); string text = string.Empty; string text2 = string.Empty; for (int i = 0; i < array.Length; i++) { text = (string.IsNullOrEmpty(text) ? array[i] : (text + "/" + array[i])); if (i > 0) { text2 += " › "; } text2 += GetCategoryTitle(text); } return text2; } private string DescriptionFor(object row) { if (row == null) { return "No items in this category."; } if (row is string text) { return "Press Enter to open the " + text + " menu."; } if (row is SubmenuFeature submenuFeature) { if (!string.IsNullOrEmpty(submenuFeature.Description)) { return submenuFeature.Description; } return "Press Enter to open the " + submenuFeature.Name + " menu."; } if (row is SeparatorFeature) { return string.Empty; } if (row is InfoFeature infoFeature) { if (!string.IsNullOrEmpty(infoFeature.Description)) { return infoFeature.Description; } return infoFeature.Name + ": " + infoFeature.ValueText; } if (row is ButtonFeature buttonFeature) { if (!string.IsNullOrEmpty(buttonFeature.Description)) { return buttonFeature.Description; } return "Press Enter to run this action."; } if (row is ColorFeature colorFeature) { if (!string.IsNullOrEmpty(colorFeature.Description)) { return colorFeature.Description; } return "Enter opens the color picker. Drag the square for saturation/value and the strip for hue."; } if (row is NumberBoolFeature numberBoolFeature) { if (!string.IsNullOrEmpty(numberBoolFeature.Description)) { return numberBoolFeature.Description; } return "Enter toggles. Left/Right adjusts the number. Shift+Enter edits the value."; } if (row is NumberFeature numberFeature) { if (!string.IsNullOrEmpty(numberFeature.Description)) { return numberFeature.Description; } return "Min " + numberFeature.Min.ToString("F1") + " Max " + numberFeature.Max.ToString("F1"); } if (row is TextFeature textFeature) { if (!string.IsNullOrEmpty(textFeature.Description)) { return textFeature.Description; } return "Enter edits the text value."; } if (row is Feature feature) { if (!string.IsNullOrEmpty(feature.Description)) { return feature.Description; } return "Press Enter to toggle."; } return string.Empty; } private void DrawFooterSpacer(Rect rect) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0054: 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) Theme.Fill(rect, Theme.BarBg); Theme.Fill(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, ((Rect)(ref rect)).width, 1f), Theme.Accent); Theme.Fill(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).yMax - 1f, ((Rect)(ref rect)).width, 1f), Theme.Accent); } private void DrawFooter(Rect rect) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: 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_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Unknown result type (might be due to invalid IL or missing references) Theme.Fill(rect, Theme.BarBg); Theme.Fill(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).yMax - 1f, ((Rect)(ref rect)).width, 1f), Theme.Accent); GUI.Label(rect, "v1.3.2", Theme.FooterVersion); DrawFooterKeybindHint(rect); bool num = _rows.Count > 0; bool flag = num && _selected > 0; bool flag2 = num && _selected < _rows.Count - 1; float num2 = ((Rect)(ref rect)).x + ((Rect)(ref rect)).width / 2f; float num3 = S(22f); if (flag && flag2) { GUI.Label(new Rect(num2 - num3 / 2f, ((Rect)(ref rect)).y + S(2f), num3, ((Rect)(ref rect)).height / 2f), "▲", Theme.FooterArrow); GUI.Label(new Rect(num2 - num3 / 2f, ((Rect)(ref rect)).y + ((Rect)(ref rect)).height / 2f - S(2f), num3, ((Rect)(ref rect)).height / 2f), "▼", Theme.FooterArrow); } else if (flag) { GUI.Label(new Rect(num2 - num3 / 2f, ((Rect)(ref rect)).y, num3, ((Rect)(ref rect)).height), "▲", Theme.FooterArrow); } else if (flag2) { GUI.Label(new Rect(num2 - num3 / 2f, ((Rect)(ref rect)).y, num3, ((Rect)(ref rect)).height), "▼", Theme.FooterArrow); } } private void DrawFooterKeybindHint(Rect rect) { //IL_0054: Unknown result type (might be due to invalid IL or missing references) if (SelectedRow() is Feature feature) { string featureBindDescription = RuntimeKeybinds.GetFeatureBindDescription(feature); if (!string.IsNullOrEmpty(featureBindDescription)) { GUI.Label(new Rect(((Rect)(ref rect)).x + ((Rect)(ref rect)).width - S(230f), ((Rect)(ref rect)).y, S(220f), ((Rect)(ref rect)).height), featureBindDescription, Theme.RowRight); } } } private void HandleNumberEditorCommitKeys() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Invalid comparison between Unknown and I4 //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Invalid comparison between Unknown and I4 //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Invalid comparison between Unknown and I4 if (!_editingNumber) { return; } Event current = Event.current; if ((int)current.type == 4) { if ((int)current.keyCode == 13 || (int)current.keyCode == 271) { CommitNumberTextInput(); current.Use(); } else if ((int)current.keyCode == 27) { CancelNumberTextInput(); current.Use(); } } } private void HandleTextEditorCommitKeys() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Invalid comparison between Unknown and I4 //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Invalid comparison between Unknown and I4 //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Invalid comparison between Unknown and I4 if (!_editingTextFeatureActive) { return; } Event current = Event.current; if ((int)current.type == 4) { if ((int)current.keyCode == 13 || (int)current.keyCode == 271) { CommitTextInput(); current.Use(); } else if ((int)current.keyCode == 27) { CancelTextInput(restoreOriginal: true); current.Use(); } } } private void HandleController() { if (RuntimeKeybinds.IsCapturing) { MenuControllerInput.Reset(); } else { if (MenuControllerInput.ToggleMenuChordHeld()) { return; } if (_editingNumber) { HandleControllerNumberEditor(); return; } if (_editingTextFeatureActive) { HandleControllerTextEditor(); return; } if (_editingColor) { HandleControllerColorPicker(); return; } int num = MenuControllerInput.ConsumeVerticalDirection(); if (num != 0) { MoveSelection(num); } int num2 = MenuControllerInput.ConsumeHorizontalDirection(); if (num2 != 0) { HandleControllerHorizontal(num2); } if (MenuControllerInput.ConfirmPressed()) { object obj = SelectedRow(); if (obj != null) { Activate(obj); } } if (MenuControllerInput.BackPressed()) { NavigateBackOrClose(); } } } private void HandleControllerNumberEditor() { MenuControllerInput.ConsumeVerticalDirection(); MenuControllerInput.ConsumeHorizontalDirection(); if (MenuControllerInput.ConfirmPressed()) { CommitNumberTextInput(); MenuControllerInput.Reset(); } else if (MenuControllerInput.BackPressed()) { CancelNumberTextInput(); MenuControllerInput.Reset(); } } private void HandleControllerTextEditor() { MenuControllerInput.ConsumeVerticalDirection(); MenuControllerInput.ConsumeHorizontalDirection(); if (MenuControllerInput.ConfirmPressed()) { CommitTextInput(); MenuControllerInput.Reset(); } else if (MenuControllerInput.BackPressed()) { CancelTextInput(restoreOriginal: true); MenuControllerInput.Reset(); } } private void HandleControllerColorPicker() { if (_editingColorFeature == null) { CancelColorPicker(); return; } int num = MenuControllerInput.ConsumeHorizontalDirection(); if (num != 0) { AdjustColorHue(num, 0.01f); } int num2 = MenuControllerInput.ConsumeVerticalDirection(); if (num2 != 0) { AdjustColorValue(num2, 0.02f); } if (MenuControllerInput.ConfirmPressed()) { CommitColorPicker(); MenuControllerInput.Reset(); } else if (MenuControllerInput.BackPressed()) { CancelColorPicker(); MenuControllerInput.Reset(); } } private void HandleControllerHorizontal(int direction) { if (SelectedRow() is NumberFeature) { AdjustNumber(direction); } } private void NavigateBackOrClose() { if (_category != null) { NavigateBack(); } else { IsOpen = false; } } private void HandleKeyboard() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Invalid comparison between Unknown and I4 //IL_003b: 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) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Invalid comparison between Unknown and I4 //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Invalid comparison between Unknown and I4 //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Invalid comparison between Unknown and I4 //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Expected I4, but got Unknown //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Invalid comparison between Unknown and I4 //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Invalid comparison between Unknown and I4 Event current = Event.current; if ((int)current.type != 4 || RuntimeKeybinds.IsCapturing || _editingNumber || _editingTextFeatureActive) { return; } if (_editingColor) { HandleColorPickerKeyboard(current); return; } KeyCode keyCode = current.keyCode; if ((int)keyCode <= 13) { if ((int)keyCode != 8) { if ((int)keyCode != 13) { return; } goto IL_00c7; } } else if ((int)keyCode != 27) { switch (keyCode - 271) { default: if ((int)keyCode == 289 && SelectedRow() is Feature feature) { RuntimeKeybinds.BeginCapture(feature); current.Use(); } return; case 2: MoveSelection(-1); current.Use(); return; case 3: MoveSelection(1); current.Use(); return; case 5: AdjustNumber(-1); current.Use(); return; case 4: AdjustNumber(1); current.Use(); return; case 0: break; case 1: return; } goto IL_00c7; } if (_category != null) { NavigateBack(); } current.Use(); return; IL_00c7: object obj = SelectedRow(); if (obj is NumberBoolFeature numberBoolFeature && current.shift && numberBoolFeature.AllowTextInput) { BeginNumberTextInput(numberBoolFeature); } else if (obj != null) { Activate(obj); } current.Use(); } private void HandleColorPickerKeyboard(Event e) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Invalid comparison between Unknown and I4 //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Invalid comparison between Unknown and I4 //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected I4, but got Unknown //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Invalid comparison between Unknown and I4 if (_editingColorFeature == null) { CancelColorPicker(); return; } KeyCode keyCode = e.keyCode; if ((int)keyCode <= 13) { if ((int)keyCode != 8) { if ((int)keyCode != 13) { return; } goto IL_00ee; } } else if ((int)keyCode != 27) { switch (keyCode - 271) { default: return; case 5: AdjustColorHue(-1, e.shift ? 0.05f : 0.01f); e.Use(); return; case 4: AdjustColorHue(1, e.shift ? 0.05f : 0.01f); e.Use(); return; case 2: if (e.shift) { AdjustColorSaturation(1, 0.02f); } else { AdjustColorValue(-1, 0.02f); } e.Use(); return; case 3: if (e.shift) { AdjustColorSaturation(-1, 0.02f); } else { AdjustColorValue(1, 0.02f); } e.Use(); return; case 0: break; case 1: return; } goto IL_00ee; } CancelColorPicker(); e.Use(); return; IL_00ee: CommitColorPicker(); e.Use(); } private void AdjustColorHue(int direction, float step) { _colorHue = Repeat01(_colorHue + (float)direction * step); UpdatePickerPreview(); } private void AdjustColorSaturation(int direction, float step) { _colorSaturation = Mathf.Clamp01(_colorSaturation + (float)direction * step); UpdatePickerPreview(); } private void AdjustColorValue(int menuDirection, float step) { _colorValue = Mathf.Clamp01(_colorValue - (float)menuDirection * step); UpdatePickerPreview(); } private void SetSelected(int idx) { if (_editingNumber && idx != _selected) { CancelNumberTextInput(); } if (_editingTextFeatureActive && idx != _selected) { CancelTextInput(restoreOriginal: false); } if (_editingColor && idx != _selected) { CancelColorPicker(); } _selected = Mathf.Clamp(idx, 0, Mathf.Max(0, _rows.Count - 1)); NormalizeSelected(); _highlightYTarget = (float)_selected * RowHeight; EnsureSelectedVisible(); } private void MoveSelection(int direction) { if (_rows.Count != 0) { int num = NextSelectableIndex(_selected, direction); if (num >= 0) { SetSelected(num); } } } private void MoveSelectionClamped(int direction, int steps) { if (_rows.Count == 0 || direction == 0) { return; } int num = _selected; int num2 = Mathf.Max(1, steps); for (int i = 0; i < num2; i++) { int num3 = NextSelectableIndexClamped(num, direction); if (num3 < 0) { break; } num = num3; } if (num != _selected) { SetSelected(num); } } private void NormalizeSelected() { if (_rows.Count == 0) { _selected = 0; return; } _selected = Mathf.Clamp(_selected, 0, _rows.Count - 1); if (!IsSelectable(_rows[_selected])) { int num = NextSelectableIndex(_selected, 1); if (num >= 0) { _selected = num; } else { _selected = 0; } } } private int NextSelectableIndex(int start, int direction) { if (_rows.Count == 0) { return -1; } int num = ((direction >= 0) ? 1 : (-1)); for (int i = 1; i <= _rows.Count; i++) { int num2 = (start + num * i) % _rows.Count; if (num2 < 0) { num2 += _rows.Count; } if (IsSelectable(_rows[num2])) { return num2; } } return -1; } private int NextSelectableIndexClamped(int start, int direction) { if (_rows.Count == 0) { return -1; } int num = ((direction >= 0) ? 1 : (-1)); for (int i = start + num; i >= 0 && i < _rows.Count; i += num) { if (IsSelectable(_rows[i])) { return i; } } return -1; } private void AdjustNumber(int direction) { if (SelectedRow() is NumberFeature numberFeature) { numberFeature.Adjust(direction); } } private void Activate(object row) { if (row is IMenuNavigationTarget target) { NavigateTo(target); } else if (row is string text) { CancelNumberTextInput(); CancelTextInput(restoreOriginal: false); CancelColorPicker(); PushNavigationState(); _category = text; _categoryTitles[text] = text; _selected = 0; _scrollYTarget = 0f; RefreshRowsNow(); } else if (row is SubmenuFeature submenuFeature) { CancelNumberTextInput(); CancelTextInput(restoreOriginal: false); CancelColorPicker(); PushNavigationState(); _category = submenuFeature.ChildCategory; _categoryTitles[submenuFeature.ChildCategory] = submenuFeature.Name; _selected = 0; _scrollYTarget = 0f; RefreshRowsNow(); } else { if (row is SeparatorFeature || row is InfoFeature) { return; } if (row is ButtonFeature buttonFeature) { CancelNumberTextInput(); CancelTextInput(restoreOriginal: false); CancelColorPicker(); try { buttonFeature.Execute(); return; } catch (Exception ex) { Plugin.Log.LogError((object)("[" + buttonFeature.Name + "] " + ex)); return; } } if (row is ColorFeature color) { CancelNumberTextInput(); CancelTextInput(restoreOriginal: false); if (IsEditing(color, _selected)) { CommitColorPicker(); } else { BeginColorPicker(color); } } else if (row is TextFeature text2) { CancelNumberTextInput(); CancelColorPicker(); if (IsEditing(text2, _selected)) { CommitTextInput(); } else { BeginTextInput(text2); } } else if (row is NumberBoolFeature numberBoolFeature) { CancelNumberTextInput(); CancelTextInput(restoreOriginal: false); CancelColorPicker(); numberBoolFeature.Enabled = !numberBoolFeature.Enabled; } else if (row is NumberFeature numberFeature) { CancelTextInput(restoreOriginal: false); CancelColorPicker(); if (numberFeature.AllowTextInput) { BeginNumberTextInput(numberFeature); } } else if (row is Feature feature) { CancelNumberTextInput(); CancelTextInput(restoreOriginal: false); CancelColorPicker(); feature.Enabled = !feature.Enabled; } } } private void NavigateTo(IMenuNavigationTarget target) { if (target != null) { CancelNumberTextInput(); CancelTextInput(restoreOriginal: false); CancelColorPicker(); _navigationStack.Clear(); _category = (string.IsNullOrEmpty(target.TargetCategory) ? null : target.TargetCategory); if (_category != null) { CacheCategoryTitles(_category); } _selected = 0; _scrollYTarget = 0f; _scrollY = 0f; RefreshRowsNow(); int num = FindNavigationTargetIndex(target); if (num >= 0) { SetSelected(num); } } } private int FindNavigationTargetIndex(IMenuNavigationTarget target) { if (target == null || _rows.Count == 0) { return -1; } for (int i = 0; i < _rows.Count; i++) { object obj = _rows[i]; if (IsSelectable(obj)) { if (!string.IsNullOrEmpty(target.TargetChildCategory) && obj is SubmenuFeature submenuFeature && string.Equals(submenuFeature.ChildCategory, target.TargetChildCategory, StringComparison.Ordinal)) { return i; } if (target.TargetFeatureType != null && obj != null && obj.GetType() == target.TargetFeatureType) { return i; } if (!string.IsNullOrEmpty(target.TargetRowName) && string.Equals(RowLabel(obj), target.TargetRowName, StringComparison.OrdinalIgnoreCase)) { return i; } } } return -1; } private void PushNavigationState() { _navigationStack.Push(new MenuNavigationState(_category, _selected, _scrollY, _scrollYTarget)); } private void NavigateBack() { CancelNumberTextInput(); CancelTextInput(restoreOriginal: false); CancelColorPicker(); if (_navigationStack.Count > 0) { MenuNavigationState menuNavigationState = _navigationStack.Pop(); _category = menuNavigationState.Category; _selected = menuNavigationState.SelectedIndex; _scrollY = menuNavigationState.ScrollY; _scrollYTarget = menuNavigationState.ScrollYTarget; RefreshRowsNow(); _scrollY = menuNavigationState.ScrollY; _scrollYTarget = menuNavigationState.ScrollYTarget; _highlightY = (float)_selected * RowHeight; _highlightYTarget = _highlightY; EnsureSelectedVisible(); } else { _category = ParentCategory(_category); _selected = 0; _scrollY = 0f; _scrollYTarget = 0f; RefreshRowsNow(); } } private void CacheCategoryTitles(string category) { if (string.IsNullOrEmpty(category)) { return; } string[] array = category.Split('/'); string text = string.Empty; for (int i = 0; i < array.Length; i++) { text = (string.IsNullOrEmpty(text) ? array[i] : (text + "/" + array[i])); if (!_categoryTitles.ContainsKey(text)) { _categoryTitles[text] = array[i]; } } } private void BeginNumberTextInput(NumberFeature number) { CancelTextInput(restoreOriginal: false); CancelColorPicker(); _editingNumber = true; _editingNumberFeature = number; _editingNumberIndex = _selected; _editingText = number.Value.ToString("F" + Mathf.Max(0, number.Decimals), CultureInfo.InvariantCulture); _focusNumberInputNext = true; } private void BeginColorPicker(ColorFeature color) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) CancelNumberTextInput(); CancelTextInput(restoreOriginal: false); _editingColor = true; _editingColorFeature = color; _editingColorIndex = _selected; _colorDragTarget = 0; SetPickerFromColor(color.Value); MenuInputCapture.Begin(); } private void CommitNumberTextInput() { if (_editingNumberFeature != null && TryParseFloat(_editingText, out var value)) { _editingNumberFeature.SetValue(value); } CancelNumberTextInput(); } private void BeginTextInput(TextFeature text) { CancelNumberTextInput(); CancelColorPicker(); _editingTextFeatureActive = true; _editingTextFeature = text; _editingTextIndex = _selected; _editingText = text.Value; _editingTextOriginal = text.Value; _focusTextInputNext = true; } private void CommitTextInput() { _editingTextFeature?.SetText(_editingText); CancelTextInput(restoreOriginal: false); } private void CancelNumberTextInput() { _editingNumber = false; _editingNumberFeature = null; _editingNumberIndex = -1; _editingText = string.Empty; _focusNumberInputNext = false; _rowsDirty = true; GUI.FocusControl(string.Empty); } private void CancelTextInput(bool restoreOriginal) { if (restoreOriginal) { _editingTextFeature?.SetText(_editingTextOriginal); } _editingTextFeatureActive = false; _editingTextFeature = null; _editingTextIndex = -1; _editingText = string.Empty; _editingTextOriginal = string.Empty; _focusTextInputNext = false; _rowsDirty = true; GUI.FocusControl(string.Empty); } private void CancelColorPicker() { _editingColor = false; _editingColorFeature = null; _editingColorIndex = -1; _colorDragTarget = 0; _rowsDirty = true; MenuInputCapture.End(); } private void CommitColorPicker() { //IL_000d: Unknown result type (might be due to invalid IL or missing references) _editingColorFeature?.SetColor(_editingColorPreview); CancelColorPicker(); } private static bool TryParseFloat(string text, out float value) { if (float.TryParse(text, NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { value = result; return true; } if (float.TryParse(text, NumberStyles.Float, CultureInfo.CurrentCulture, out result)) { value = result; return true; } value = 0f; return false; } private static float Repeat01(float value) { value %= 1f; if (value < 0f) { value += 1f; } return value; } private void HandleDrag() { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Invalid comparison between Unknown and I4 //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0093: 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) //IL_00c2: Invalid comparison between Unknown and I4 //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) if (ShouldAcceptMenuMouseInput()) { Rect val = default(Rect); ((Rect)(ref val))..ctor(((Rect)(ref _window)).x, ((Rect)(ref _window)).y, ((Rect)(ref _window)).width, S(96f)); Event current = Event.current; if ((int)current.type == 0 && ((Rect)(ref val)).Contains(current.mousePosition)) { CancelNumberTextInput(); CancelColorPicker(); _dragging = true; _dragOffset = current.mousePosition - new Vector2(((Rect)(ref _window)).x, ((Rect)(ref _window)).y); current.Use(); } else if ((int)current.type == 1) { _dragging = false; } else if (_dragging && (int)current.type == 3) { ((Rect)(ref _window)).x = Mathf.Clamp(current.mousePosition.x - _dragOffset.x, 0f, Mathf.Max(0f, (float)Screen.width - ((Rect)(ref _window)).width)); ((Rect)(ref _window)).y = Mathf.Clamp(current.mousePosition.y - _dragOffset.y, 0f, Mathf.Max(0f, (float)Screen.height - ((Rect)(ref _window)).height)); current.Use(); } } } private void EnsureInitialWindowPosition() { if (!_hasPositionedWindow && Screen.width > 0 && Screen.height > 0) { float num = Mathf.Max(0f, (float)Screen.width - ((Rect)(ref _window)).width); float num2 = Mathf.Max(0f, (float)Screen.height - ((Rect)(ref _window)).height); float num3 = Mathf.Min(S(88f), (float)Screen.width * 0.06f); float num4 = Mathf.Min(S(48f), (float)Screen.height * 0.06f); ((Rect)(ref _window)).x = ((num <= num3 * 2f) ? (num * 0.5f) : Mathf.Clamp(num3, 0f, num)); ((Rect)(ref _window)).y = ((num2 <= num4 * 2f) ? (num2 * 0.5f) : Mathf.Clamp(num4, 0f, num2)); _hasPositionedWindow = true; } } private bool ShouldAcceptMenuMouseInput() { if (IsOpen) { return _features != null; } return false; } private void ClampWindowToScreen() { ((Rect)(ref _window)).x = Mathf.Clamp(((Rect)(ref _window)).x, 0f, Mathf.Max(0f, (float)Screen.width - ((Rect)(ref _window)).width)); ((Rect)(ref _window)).y = Mathf.Clamp(((Rect)(ref _window)).y, 0f, Mathf.Max(0f, (float)Screen.height - ((Rect)(ref _window)).height)); } } public enum NotificationKind { Info, Success, Warning, Error } public static class NotificationSystem { private sealed class Notification { public string Title { get; } public string Description { get; } public NotificationKind Kind { get; } public float CreatedAt { get; } public Notification(string title, string description, NotificationKind kind, float createdAt) { Title = title; Description = description; Kind = kind; CreatedAt = createdAt; base..ctor(); } } private const int MaxOnScreen = 10; private const float Width = 360f; private const float MinHeight = 64f; private const float MaxHeight = 136f; private const float Gap = 10f; private const float Margin = 18f; private const float SlideDistance = 34f; private const float Lifetime = 3.6f; private const float Transition = 0.28f; private static readonly List Items = new List(); private static GUIStyle _titleStyle; private static GUIStyle _descriptionStyle; private static bool _ready; public static void MarkReady() { _ready = true; } public static void Push(string title, string description = "", NotificationKind kind = NotificationKind.Info) { if (_ready) { title = (string.IsNullOrWhiteSpace(title) ? "Notification" : title.Trim()); description = (description ?? string.Empty).Trim(); Items.Insert(0, new Notification(title, description, kind, Time.unscaledTime)); while (Items.Count > 10) { Items.RemoveAt(Items.Count - 1); } } } public static void Render() { //IL_013d: Unknown result type (might be due to invalid IL or missing references) if (!_ready || Items.Count == 0) { return; } EnsureStyles(); float unscaledTime = Time.unscaledTime; float num = Mathf.Max(18f, (float)Screen.width - 360f - 18f); float num2 = 18f; for (int num3 = Items.Count - 1; num3 >= 0; num3--) { Notification notification = Items[num3]; if (unscaledTime - notification.CreatedAt >= 3.6f) { Items.RemoveAt(num3); } } float[] array = new float[Items.Count]; float[] array2 = new float[Items.Count]; float num4 = 0f; for (int i = 0; i < Items.Count; i++) { array[i] = CalculateHeight(Items[i]); array2[i] = num4; num4 += array[i] + 10f; } for (int num5 = Items.Count - 1; num5 >= 0; num5--) { Notification notification2 = Items[num5]; float age = unscaledTime - notification2.CreatedAt; float alpha = GetAlpha(age); float slide = GetSlide(age); DrawItem(new Rect(num + slide, num2 + array2[num5], 360f, array[num5]), notification2, alpha); } } private static float GetAlpha(float age) { float num = Mathf.Clamp01(age / 0.28f); float num2 = Mathf.Clamp01((3.6f - age) / 0.28f); return Mathf.Min(num, num2); } private static float GetSlide(float age) { if (age < 0.28f) { return Mathf.Lerp(34f, 0f, EaseOutCubic(age / 0.28f)); } float num = 3.6f - age; if (!(num < 0.28f)) { return 0f; } return Mathf.Lerp(0f, 34f, EaseInCubic(1f - num / 0.28f)); } private static void DrawItem(Rect rect, Notification item, float alpha) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0086: 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) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_008e: 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_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Expected O, but got Unknown //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Unknown result type (might be due to invalid IL or missing references) Color color = GetColor(item.Kind); Color c = default(Color); ((Color)(ref c))..ctor(0.035f, 0.035f, 0.038f, 0.88f * alpha); Color color2 = default(Color); ((Color)(ref color2))..ctor(1f, 1f, 1f, 0.12f * alpha); Color textColor = default(Color); ((Color)(ref textColor))..ctor(0.96f, 0.96f, 0.96f, alpha); Color textColor2 = default(Color); ((Color)(ref textColor2))..ctor(0.96f, 0.96f, 0.96f, 0.92f * alpha); color.a *= alpha; Theme.Fill(rect, c); DrawOutline(rect, color2, 1f); Theme.Fill(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, 4f, ((Rect)(ref rect)).height), color); _titleStyle.normal.textColor = textColor; _descriptionStyle.normal.textColor = textColor2; float num = ((Rect)(ref rect)).width - 34f; float num2 = Mathf.Min(42f, _titleStyle.CalcHeight(new GUIContent(item.Title), num)); Rect val = default(Rect); ((Rect)(ref val))..ctor(((Rect)(ref rect)).x + 18f, ((Rect)(ref rect)).y + 10f, num, num2); GUI.Label(val, item.Title, _titleStyle); if (!string.IsNullOrEmpty(item.Description)) { float num3 = ((Rect)(ref val)).yMax + 4f; GUI.Label(new Rect(((Rect)(ref rect)).x + 18f, num3, num, Mathf.Max(0f, ((Rect)(ref rect)).yMax - num3 - 10f)), item.Description, _descriptionStyle); } } private static float CalculateHeight(Notification item) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Expected O, but got Unknown if (item == null) { return 64f; } float num = 326f; float num2 = Mathf.Min(42f, _titleStyle.CalcHeight(new GUIContent(item.Title), num)); float num3 = (string.IsNullOrEmpty(item.Description) ? 0f : _descriptionStyle.CalcHeight(new GUIContent(item.Description), num)); float num4 = (string.IsNullOrEmpty(item.Description) ? 0f : 4f); return Mathf.Clamp(20f + num2 + num4 + num3 + 12f, 64f, 136f); } private static void EnsureStyles() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003b: 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) //IL_004a: Expected O, but got Unknown //IL_004f: Expected O, but got Unknown //IL_0054: 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_0061: 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_0074: Expected O, but got Unknown if (_titleStyle == null) { _titleStyle = new GUIStyle(GUI.skin.label) { alignment = (TextAnchor)3, clipping = (TextClipping)1, wordWrap = true, fontSize = 14, fontStyle = (FontStyle)1, padding = new RectOffset(0, 0, 0, 0) }; _descriptionStyle = new GUIStyle(_titleStyle) { fontSize = 12, fontStyle = (FontStyle)0, alignment = (TextAnchor)0 }; } } private static Color GetColor(NotificationKind kind) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: 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_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) return (Color)(kind switch { NotificationKind.Success => new Color(0.25f, 0.78f, 0.52f, 1f), NotificationKind.Warning => new Color(0.92f, 0.68f, 0.2f, 1f), NotificationKind.Error => new Color(0.95f, 0.28f, 0.28f, 1f), _ => MenuConfig.AccentColor, }); } private static void DrawOutline(Rect rect, Color color, float thickness) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: 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_0082: Unknown result type (might be due to invalid IL or missing references) Theme.Fill(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, ((Rect)(ref rect)).width, thickness), color); Theme.Fill(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).yMax - thickness, ((Rect)(ref rect)).width, thickness), color); Theme.Fill(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, thickness, ((Rect)(ref rect)).height), color); Theme.Fill(new Rect(((Rect)(ref rect)).xMax - thickness, ((Rect)(ref rect)).y, thickness, ((Rect)(ref rect)).height), color); } private static float EaseOutCubic(float value) { value = Mathf.Clamp01(value); value -= 1f; return value * value * value + 1f; } private static float EaseInCubic(float value) { value = Mathf.Clamp01(value); return value * value * value; } } internal sealed class SelectedPlayerPreviewPanel : IDisposable { private const int TextureWidth = 384; private const int TextureHeight = 512; private static readonly Color BackgroundColor = new Color(0.015f, 0.016f, 0.018f, 1f); private GameObject _root; private Camera _camera; private RenderTexture _target; private bool _visible; public Texture GetTexture() { SetVisible(visible: true); EnsureResources(); RefreshCamera(); return (Texture)(object)_target; } public void SetVisible(bool visible) { _visible = visible; if (!visible && Object.op_Implicit((Object)(object)_camera)) { ((Behaviour)_camera).enabled = false; } } public void Dispose() { if (Object.op_Implicit((Object)(object)_camera)) { ((Behaviour)_camera).enabled = false; } if (Object.op_Implicit((Object)(object)_target)) { _target.Release(); Object.Destroy((Object)(object)_target); _target = null; } if (Object.op_Implicit((Object)(object)_root)) { Object.Destroy((Object)(object)_root); _root = null; } _camera = null; } private void EnsureResources() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Expected O, but got Unknown if (!Object.op_Implicit((Object)(object)_root)) { _root = new GameObject("CubeX Selected Player Live Preview") { hideFlags = (HideFlags)61 }; Object.DontDestroyOnLoad((Object)(object)_root); _camera = _root.AddComponent(); ((Behaviour)_camera).enabled = false; _camera.clearFlags = (CameraClearFlags)2; _camera.backgroundColor = BackgroundColor; _camera.orthographic = true; _camera.nearClipPlane = 0.02f; _camera.farClipPlane = 18f; _camera.allowHDR = false; _camera.allowMSAA = false; _camera.useOcclusionCulling = false; _camera.depthTextureMode = (DepthTextureMode)0; _camera.renderingPath = (RenderingPath)1; } if (!Object.op_Implicit((Object)(object)_target)) { _target = new RenderTexture(384, 512, 16, (RenderTextureFormat)0) { hideFlags = (HideFlags)61, filterMode = (FilterMode)1, wrapMode = (TextureWrapMode)1, antiAliasing = 1, useMipMap = false, autoGenerateMips = false }; _target.Create(); } if (Object.op_Implicit((Object)(object)_camera) && (Object)(object)_camera.targetTexture != (Object)(object)_target) { _camera.targetTexture = _target; } } private void RefreshCamera() { if (!Object.op_Implicit((Object)(object)_camera)) { return; } if (_visible && PlayerDirectory.TryGetSelectedCharacter(out var character) && Object.op_Implicit((Object)(object)character)) { CharacterData data = character.data; if (data == null || !data.dead) { ConfigureCamera(character); ((Behaviour)_camera).enabled = true; return; } } ((Behaviour)_camera).enabled = false; ClearTarget(); } private void ConfigureCamera(Character character) { //IL_0039: 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) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_005a: 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_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: 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_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) Camera main = Camera.main; _camera.cullingMask = ((Object.op_Implicit((Object)(object)main) && (Object)(object)main != (Object)(object)_camera) ? (main.cullingMask & -33) : (-1)); _camera.backgroundColor = BackgroundColor; Bounds bounds; bool num = TryGetCharacterBounds(character, out bounds); Vector3 fallbackCenter = GetFallbackCenter(character); Vector3 val = (num ? ((Bounds)(ref bounds)).center : fallbackCenter); float num2 = (num ? Mathf.Max(0.75f, ((Bounds)(ref bounds)).size.y) : 1.7f); float num3 = (num ? Mathf.Max(0.45f, ((Bounds)(ref bounds)).size.x) : 0.8f); Vector3 val2 = (Vector3)(num ? new Vector3(val.x, ((Bounds)(ref bounds)).min.y + num2 * 0.52f, val.z) : (fallbackCenter + Vector3.up * 0.15f)); Vector3 frontViewDirection = GetFrontViewDirection(character, val, main); float num4 = Mathf.Clamp(num2 * 1.3f, 1.5f, 4f); Vector3 val3 = val2 + frontViewDirection * num4 + Vector3.up * num2 * 0.02f; _camera.orthographic = true; ((Component)_camera).transform.position = val3; ((Component)_camera).transform.rotation = Quaternion.LookRotation(val2 - val3, Vector3.up); float num5 = 0.75f; float num6 = Mathf.Max(0.45f, num2 * 0.53f); float num7 = Mathf.Max(0.45f, num3 / Mathf.Max(0.1f, num5) * 0.68f); _camera.orthographicSize = Mathf.Max(num6, num7); _camera.nearClipPlane = 0.02f; _camera.farClipPlane = Mathf.Max(8f, num4 + 8f); } private static Vector3 GetFrontViewDirection(Character character, Vector3 bodyCenter, Camera main) { //IL_0001: 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) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //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_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: 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) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0027: 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_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) if (!TryGetFaceDirection(character, bodyCenter, out var direction)) { Transform previewRoot = GetPreviewRoot(character); direction = (Object.op_Implicit((Object)(object)previewRoot) ? (-previewRoot.forward) : (Object.op_Implicit((Object)(object)((Component)character).transform) ? (-((Component)character).transform.forward) : Vector3.forward)); } direction = Vector3.ProjectOnPlane(direction, Vector3.up); if (((Vector3)(ref direction)).sqrMagnitude < 0.0001f) { direction = (Object.op_Implicit((Object)(object)main) ? Vector3.ProjectOnPlane(-((Component)main).transform.forward, Vector3.up) : Vector3.forward); if (((Vector3)(ref direction)).sqrMagnitude < 0.0001f) { direction = Vector3.forward; } } ((Vector3)(ref direction)).Normalize(); return direction; } private static bool TryGetFaceDirection(Character character, Vector3 bodyCenter, out Vector3 direction) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: 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_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00af: 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_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: 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_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) direction = Vector3.zero; CustomizationRefs val = (Object.op_Implicit((Object)(object)character.refs?.customization) ? character.refs.customization.refs : null); if (!Object.op_Implicit((Object)(object)val)) { return false; } Vector3 center = Vector3.zero; int count = 0; AddRendererCenter(val.mouthRenderer, ref center, ref count); Renderer[] eyeRenderers = val.EyeRenderers; if (eyeRenderers != null) { for (int i = 0; i < eyeRenderers.Length; i++) { AddRendererCenter(eyeRenderers[i], ref center, ref count); } } if (count <= 0) { return false; } center /= (float)count; Vector3 val2 = ((Object.op_Implicit((Object)(object)character) && IsFinite(character.Head)) ? character.Head : bodyCenter); direction = Vector3.ProjectOnPlane(center - val2, Vector3.up); return ((Vector3)(ref direction)).sqrMagnitude > 0.0001f; } private static void AddRendererCenter(Renderer renderer, ref Vector3 center, ref int count) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) if (ShouldUseRenderer(renderer)) { Vector3 val = center; Bounds bounds = renderer.bounds; center = val + ((Bounds)(ref bounds)).center; count++; } } private static bool TryGetCharacterBounds(Character character, out Bounds bounds) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) bounds = default(Bounds); Transform previewRoot = GetPreviewRoot(character); if (!Object.op_Implicit((Object)(object)previewRoot)) { return false; } bool flag = TryGetRendererBounds(previewRoot, out bounds); if (!flag && Object.op_Implicit((Object)(object)((Component)character).transform) && (Object)(object)previewRoot != (Object)(object)((Component)character).transform) { flag = TryGetRendererBounds(((Component)character).transform, out bounds); } return flag; } private static Transform GetPreviewRoot(Character character) { if (!Object.op_Implicit((Object)(object)character)) { return null; } CustomizationRefs val = (Object.op_Implicit((Object)(object)character.refs?.customization) ? character.refs.customization.refs : null); if (Object.op_Implicit((Object)(object)val)) { return ((Component)val).transform; } if (Object.op_Implicit((Object)(object)character.refs?.animationPositionTransform)) { return character.refs.animationPositionTransform; } return ((Component)character).transform; } private static bool TryGetRendererBounds(Transform root, out Bounds bounds) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0058: 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_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) bounds = default(Bounds); if (!Object.op_Implicit((Object)(object)root)) { return false; } Renderer[] componentsInChildren = ((Component)root).GetComponentsInChildren(false); bool flag = false; foreach (Renderer val in componentsInChildren) { if (ShouldUseRenderer(val)) { if (!flag) { bounds = val.bounds; flag = true; } else { ((Bounds)(ref bounds)).Encapsulate(val.bounds); } } } if (flag) { Vector3 size = ((Bounds)(ref bounds)).size; return ((Vector3)(ref size)).sqrMagnitude > 0.0001f; } return false; } private static bool ShouldUseRenderer(Renderer renderer) { if (!Object.op_Implicit((Object)(object)renderer) || !renderer.enabled || !((Component)renderer).gameObject.activeInHierarchy) { return false; } Type type = ((object)renderer).GetType(); if (type == typeof(ParticleSystemRenderer) || type == typeof(LineRenderer) || type == typeof(TrailRenderer)) { return false; } string obj = ((Object)renderer).name ?? string.Empty; string text = (Object.op_Implicit((Object)(object)((Component)renderer).gameObject) ? (((Object)((Component)renderer).gameObject).name ?? string.Empty) : string.Empty); if (obj.IndexOf("shadow", StringComparison.OrdinalIgnoreCase) < 0) { return text.IndexOf("shadow", StringComparison.OrdinalIgnoreCase) < 0; } return false; } private void ClearTarget() { //IL_0020: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)_target)) { RenderTexture active = RenderTexture.active; RenderTexture.active = _target; GL.Clear(true, true, BackgroundColor); RenderTexture.active = active; } } private static Vector3 GetFallbackCenter(Character character) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //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) //IL_002c: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)character)) { return Vector3.zero; } Vector3 center = character.Center; if (IsFinite(center)) { return center; } if (!Object.op_Implicit((Object)(object)((Component)character).transform)) { return Vector3.zero; } return ((Component)character).transform.position + Vector3.up * 0.9f; } private static bool IsFinite(Vector3 value) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) if (float.IsFinite(value.x) && float.IsFinite(value.y)) { return float.IsFinite(value.z); } return false; } } public static class Theme { public static readonly Color MenuBg = Hex("#0A0A0Aff"); public static readonly Color RowBg = Hex("#0E0E0Eff"); public static readonly Color SelectedBg = Hex("#FFFFFFff"); public static readonly Color SelectedFg = Hex("#000000ff"); public static readonly Color Text = Hex("#F2F2F2ff"); public static readonly Color TextDim = Hex("#9A9A9Aff"); public static readonly Color Separator = Hex("#1B1B1Bff"); public static readonly Color BarBg = Hex("#000000ff"); public static readonly Color DescBg = Hex("#0A0A0Aff"); public static Texture2D TexTransparent; public static Texture2D TexCubeLogo; public static GUIStyle Breadcrumb; public static GUIStyle Counter; public static GUIStyle Row; public static GUIStyle RowSelected; public static GUIStyle RowRight; public static GUIStyle RowRightSelected; public static GUIStyle NumberInput; public static GUIStyle DescTitle; public static GUIStyle DescBody; public static GUIStyle FooterVersion; public static GUIStyle FooterArrow; private static bool _init; private static float _appliedScale = -1f; public static Color Accent => MenuConfig.AccentColor; public static void Init() { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_003b: 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) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Expected O, but got Unknown //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Expected O, but got Unknown //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Expected O, but got Unknown //IL_00e1: 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_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Expected O, but got Unknown //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Expected O, but got Unknown //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_014d: 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_015d: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Expected O, but got Unknown //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0184: 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_019e: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Unknown result type (might be due to invalid IL or missing references) //IL_01c4: 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_01de: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_01ee: Unknown result type (might be due to invalid IL or missing references) //IL_01fe: Unknown result type (might be due to invalid IL or missing references) //IL_0205: Unknown result type (might be due to invalid IL or missing references) //IL_0211: Expected O, but got Unknown //IL_0211: Unknown result type (might be due to invalid IL or missing references) //IL_0216: Unknown result type (might be due to invalid IL or missing references) //IL_021c: Unknown result type (might be due to invalid IL or missing references) //IL_0226: Unknown result type (might be due to invalid IL or missing references) //IL_0236: 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_0249: Expected O, but got Unknown //IL_0249: 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_0254: Unknown result type (might be due to invalid IL or missing references) //IL_025e: Unknown result type (might be due to invalid IL or missing references) //IL_026e: Unknown result type (might be due to invalid IL or missing references) //IL_0275: Unknown result type (might be due to invalid IL or missing references) //IL_0281: Expected O, but got Unknown //IL_0281: Unknown result type (might be due to invalid IL or missing references) //IL_0286: Unknown result type (might be due to invalid IL or missing references) //IL_028c: Unknown result type (might be due to invalid IL or missing references) //IL_0296: 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_02ad: Unknown result type (might be due to invalid IL or missing references) //IL_02b9: Expected O, but got Unknown //IL_02b9: 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_02c4: Unknown result type (might be due to invalid IL or missing references) //IL_02ce: Unknown result type (might be due to invalid IL or missing references) //IL_02de: Unknown result type (might be due to invalid IL or missing references) //IL_02e5: Unknown result type (might be due to invalid IL or missing references) //IL_02f1: Expected O, but got Unknown if (!_init) { _init = true; TexTransparent = Solid(new Color(0f, 0f, 0f, 0f)); TexCubeLogo = BuildCubeLogoTexture(); GUIStyle val = new GUIStyle(); val.normal.textColor = Text; val.normal.background = TexTransparent; val.fontStyle = (FontStyle)1; val.alignment = (TextAnchor)3; Breadcrumb = val; GUIStyle val2 = new GUIStyle(); val2.normal.textColor = Text; val2.normal.background = TexTransparent; val2.alignment = (TextAnchor)5; val2.fontStyle = (FontStyle)1; Counter = val2; GUIStyle val3 = new GUIStyle(); val3.normal.textColor = Text; val3.normal.background = TexTransparent; val3.alignment = (TextAnchor)3; Row = val3; GUIStyle val4 = new GUIStyle(Row); val4.normal.textColor = SelectedFg; val4.normal.background = TexTransparent; val4.fontStyle = (FontStyle)1; RowSelected = val4; GUIStyle val5 = new GUIStyle(); val5.normal.textColor = Text; val5.normal.background = TexTransparent; val5.alignment = (TextAnchor)5; RowRight = val5; GUIStyle val6 = new GUIStyle(RowRight); val6.normal.textColor = SelectedFg; val6.normal.background = TexTransparent; val6.fontStyle = (FontStyle)1; RowRightSelected = val6; GUIStyle val7 = new GUIStyle(); val7.normal.textColor = SelectedFg; val7.normal.background = TexTransparent; val7.focused.textColor = SelectedFg; val7.focused.background = TexTransparent; val7.active.textColor = SelectedFg; val7.active.background = TexTransparent; val7.hover.textColor = SelectedFg; val7.hover.background = TexTransparent; val7.fontStyle = (FontStyle)1; val7.alignment = (TextAnchor)5; NumberInput = val7; GUIStyle val8 = new GUIStyle(); val8.normal.textColor = Text; val8.normal.background = TexTransparent; val8.fontStyle = (FontStyle)1; val8.alignment = (TextAnchor)0; DescTitle = val8; GUIStyle val9 = new GUIStyle(); val9.normal.textColor = Text; val9.normal.background = TexTransparent; val9.alignment = (TextAnchor)0; val9.wordWrap = true; DescBody = val9; GUIStyle val10 = new GUIStyle(); val10.normal.textColor = Text; val10.normal.background = TexTransparent; val10.alignment = (TextAnchor)3; val10.fontStyle = (FontStyle)1; FooterVersion = val10; GUIStyle val11 = new GUIStyle(); val11.normal.textColor = Text; val11.normal.background = TexTransparent; val11.fontStyle = (FontStyle)1; val11.alignment = (TextAnchor)4; FooterArrow = val11; ApplyScale(1f); } } public static void ApplyScale(float scale) { if (_init) { scale = Mathf.Clamp(scale, 0.5f, 4f); if (!Mathf.Approximately(_appliedScale, scale)) { _appliedScale = scale; Breadcrumb.fontSize = Font(13f, scale); Counter.fontSize = Font(13f, scale); Row.fontSize = Font(14f, scale); RowSelected.fontSize = Font(14f, scale); RowRight.fontSize = Font(13f, scale); RowRightSelected.fontSize = Font(13f, scale); NumberInput.fontSize = Font(13f, scale); DescTitle.fontSize = Font(11f, scale); DescBody.fontSize = Font(12f, scale); FooterVersion.fontSize = Font(11f, scale); FooterArrow.fontSize = Font(14f, scale); Breadcrumb.padding = Pad(16, 16, 0, 0, scale); Counter.padding = Pad(0, 16, 0, 0, scale); Row.padding = Pad(16, 16, 0, 0, scale); RowSelected.padding = Pad(16, 16, 0, 0, scale); RowRight.padding = Pad(0, 16, 0, 0, scale); RowRightSelected.padding = Pad(0, 16, 0, 0, scale); NumberInput.padding = Pad(0, 16, 0, 0, scale); DescTitle.padding = Pad(16, 16, 10, 2, scale); DescBody.padding = Pad(16, 16, 12, 12, scale); FooterVersion.padding = Pad(14, 0, 0, 0, scale); FooterArrow.padding = Pad(0, 0, 0, 0, scale); } } } private static int Font(float baseSize, float scale) { return Mathf.Max(1, Mathf.RoundToInt(baseSize * scale)); } private static RectOffset Pad(int left, int right, int top, int bottom, float scale) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected O, but got Unknown return new RectOffset(Mathf.RoundToInt((float)left * scale), Mathf.RoundToInt((float)right * scale), Mathf.RoundToInt((float)top * scale), Mathf.RoundToInt((float)bottom * scale)); } private static Texture2D Solid(Color c) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown Texture2D val = new Texture2D(1, 1, (TextureFormat)4, false) { hideFlags = (HideFlags)61 }; val.SetPixel(0, 0, c); val.Apply(); return val; } private static Color Hex(string h) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) Color result = default(Color); ColorUtility.TryParseHtmlString(h, ref result); return result; } public static void Fill(Rect r, Color c) { //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_000b: Unknown result type (might be due to invalid IL or missing references) Color color = GUI.color; GUI.color = c; GUI.DrawTexture(r, (Texture)(object)Texture2D.whiteTexture); GUI.color = color; } public static void DrawDiamond(Vector2 center, float size) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)TexCubeLogo)) { TexCubeLogo = BuildCubeLogoTexture(); } GUI.DrawTexture(new Rect(Mathf.Round(center.x - size * 0.5f), Mathf.Round(center.y - size * 0.5f), Mathf.Round(size), Mathf.Round(size)), (Texture)(object)TexCubeLogo, (ScaleMode)0, true); } private static Texture2D BuildCubeLogoTexture() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0094: 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_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00af: 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_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: 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) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_0198: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_01bf: Unknown result type (might be due to invalid IL or missing references) //IL_01c4: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: Unknown result type (might be due to invalid IL or missing references) //IL_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Unknown result type (might be due to invalid IL or missing references) //IL_01d7: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_01ec: Unknown result type (might be due to invalid IL or missing references) //IL_01f4: Unknown result type (might be due to invalid IL or missing references) //IL_01f8: Unknown result type (might be due to invalid IL or missing references) //IL_01fd: Unknown result type (might be due to invalid IL or missing references) //IL_0202: Unknown result type (might be due to invalid IL or missing references) //IL_0210: Unknown result type (might be due to invalid IL or missing references) //IL_0215: Unknown result type (might be due to invalid IL or missing references) //IL_021a: 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_022a: Unknown result type (might be due to invalid IL or missing references) //IL_022f: 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) Texture2D val = new Texture2D(100, 100, (TextureFormat)4, false) { hideFlags = (HideFlags)61, wrapMode = (TextureWrapMode)1, filterMode = (FilterMode)1 }; Color val2 = default(Color); ((Color)(ref val2))..ctor(0f, 0f, 0f, 0f); for (int i = 0; i < 100; i++) { for (int j = 0; j < 100; j++) { val.SetPixel(j, i, val2); } } Vector2 val3 = default(Vector2); ((Vector2)(ref val3))..ctor(50f, 52.999996f); float num = 30.000002f; float num2 = num * 0.58f; Color col = Hex("#F4F4F4ff"); Color col2 = Hex("#C4C4C8ff"); Color col3 = Hex("#9A9AA0ff"); FillTri(val, val3 + new Vector2(0f, (0f - num2) * 2f), val3 + new Vector2(0f - num, 0f - num2), val3 + new Vector2(0f, 0f), col); FillTri(val, val3 + new Vector2(0f, (0f - num2) * 2f), val3 + new Vector2(num, 0f - num2), val3 + new Vector2(0f, 0f), col); FillTri(val, val3 + new Vector2(0f - num, 0f - num2), val3 + new Vector2(0f - num, num2), val3 + new Vector2(0f, 0f), col2); FillTri(val, val3 + new Vector2(0f - num, num2), val3 + new Vector2(0f, num2 * 2f), val3 + new Vector2(0f, 0f), col2); FillTri(val, val3 + new Vector2(num, 0f - num2), val3 + new Vector2(num, num2), val3 + new Vector2(0f, 0f), col3); FillTri(val, val3 + new Vector2(num, num2), val3 + new Vector2(0f, num2 * 2f), val3 + new Vector2(0f, 0f), col3); val.Apply(false, false); return val; } private static void FillTri(Texture2D tex, Vector2 a, Vector2 b, Vector2 c, Color col) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) int num = Mathf.Clamp(Mathf.FloorToInt(Mathf.Min(a.x, Mathf.Min(b.x, c.x))), 0, ((Texture)tex).width - 1); int num2 = Mathf.Clamp(Mathf.CeilToInt(Mathf.Max(a.x, Mathf.Max(b.x, c.x))), 0, ((Texture)tex).width - 1); int num3 = Mathf.Clamp(Mathf.FloorToInt(Mathf.Min(a.y, Mathf.Min(b.y, c.y))), 0, ((Texture)tex).height - 1); int num4 = Mathf.Clamp(Mathf.CeilToInt(Mathf.Max(a.y, Mathf.Max(b.y, c.y))), 0, ((Texture)tex).height - 1); float num5 = Edge(a, b, c); if (Mathf.Approximately(num5, 0f)) { return; } Vector2 p = default(Vector2); for (int i = num3; i <= num4; i++) { for (int j = num; j <= num2; j++) { ((Vector2)(ref p))..ctor((float)j + 0.5f, (float)i + 0.5f); float num6 = Edge(b, c, p); float num7 = Edge(c, a, p); float num8 = Edge(a, b, p); bool num9; if (!(num5 > 0f)) { if (!(num6 <= 0f) || !(num7 <= 0f)) { continue; } num9 = num8 <= 0f; } else { if (!(num6 >= 0f) || !(num7 >= 0f)) { continue; } num9 = num8 >= 0f; } if (num9) { SetLogoPixel(tex, j, i, col); } } } } private static float Edge(Vector2 a, Vector2 b, Vector2 p) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) return (p.x - a.x) * (b.y - a.y) - (p.y - a.y) * (b.x - a.x); } private static void SetLogoPixel(Texture2D tex, int x, int topDownY, Color col) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) tex.SetPixel(x, ((Texture)tex).height - 1 - topDownY, col); } } } namespace CubeX.UI.Features { public class AccentColor : ColorFeature, ISettingsFeature { public override int PresetCount => MenuConfig.Presets.Length; public AccentColor() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) base.Name = "Accent Color"; base.Description = "Pick the menu accent color with the color picker and preset swatches."; base.Value = MenuConfig.AccentColor; } public override string GetPresetName(int index) { if (index < 0 || index >= MenuConfig.Presets.Length) { return string.Empty; } return MenuConfig.Presets[index].Name; } public override Color GetPresetColor(int index) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) if (index < 0 || index >= MenuConfig.Presets.Length) { return Color.white; } return MenuConfig.Presets[index].Color; } public override void ApplyPreset(int index) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) if (index >= 0 && index < MenuConfig.Presets.Length) { MenuConfig.ApplyPreset(index); base.Value = MenuConfig.AccentColor; ConfigService.MarkDirty(); } } protected override void OnColorChanged(Color newColor) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) MenuConfig.SetAccentColor(newColor); } public void SyncFromConfig() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) SetColor(MenuConfig.AccentColor); } } public class AutoLoadOnStartConfig : Feature, ISettingsFeature { public AutoLoadOnStartConfig() { base.Name = "Auto Load on Start"; base.Description = "Load the saved config automatically when CubeX starts."; base.Enabled = MenuConfig.AutoLoadOnStart; } protected override void OnEnable() { MenuConfig.AutoLoadOnStart = true; SaveFlagChange(); } protected override void OnDisable() { MenuConfig.AutoLoadOnStart = false; SaveFlagChange(); } public void SyncFromConfig() { base.Enabled = MenuConfig.AutoLoadOnStart; } private static void SaveFlagChange() { if (!ConfigService.IsApplying && !ConfigService.IsShuttingDown) { ConfigService.SaveCurrent(); } } } public class AutoSaveConfig : Feature, ISettingsFeature { public AutoSaveConfig() { base.Name = "Auto Save"; base.Description = "Automatically save config changes without pressing Save."; base.Enabled = MenuConfig.AutoSave; } protected override void OnEnable() { MenuConfig.AutoSave = true; SaveFlagChange(); } protected override void OnDisable() { MenuConfig.AutoSave = false; SaveFlagChange(); } public void SyncFromConfig() { base.Enabled = MenuConfig.AutoSave; } private static void SaveFlagChange() { if (!ConfigService.IsApplying && !ConfigService.IsShuttingDown) { ConfigService.SaveCurrent(); } } } public class CustomConfigDirectory : Feature, IMenuRowProvider, IMenuSidePanelProvider { private sealed class ConfigFileSubmenu : SubmenuFeature { public ConfigFileEntry Entry { get; } public ConfigFileSubmenu(ConfigFileEntry entry) : base(entry?.DisplayName ?? "Config", "Settings/Config/Custom Saves/" + (entry?.FileName ?? string.Empty), "Open actions for this saved config.", BuildTags(entry)) { Entry = entry; } } private abstract class ConfigFileAction : ButtonFeature, IMenuTagProvider { public ConfigFileEntry Entry { get; } public List Tags { get; } protected ConfigFileAction(ConfigFileEntry entry) { Entry = entry; Tags = BuildTags(entry); } } private abstract class ConfigFileText : TextFeature, IMenuTagProvider { public ConfigFileEntry Entry { get; } public List Tags { get; } protected ConfigFileText(ConfigFileEntry entry) { Entry = entry; Tags = BuildTags(entry); } } private sealed class ConfigFileNameText : ConfigFileText { public ConfigFileNameText(ConfigFileEntry entry) : base(entry) { base.Name = "File Name"; base.Description = "New custom config filename. Rename writes to config_.json."; base.EmptyDisplayText = "Config name"; base.MaxLength = 64; SetText(CustomConfigSelection.GetEditName(entry)); } protected override void OnTextChanged(string newValue) { CustomConfigSelection.SetEditName(base.Entry, newValue); } } private sealed class ConfigFileNoteText : ConfigFileText { public ConfigFileNoteText(ConfigFileEntry entry) : base(entry) { base.Name = "File Note"; base.Description = "Optional note stored inside this config file."; base.EmptyDisplayText = "Optional note"; base.MaxLength = 220; SetText(CustomConfigSelection.GetEditNote(entry)); } protected override void OnTextChanged(string newValue) { CustomConfigSelection.SetEditNote(base.Entry, newValue); } } private sealed class SaveConfigFileNote : ConfigFileAction { public SaveConfigFileNote(ConfigFileEntry entry) : base(entry) { base.Name = "Save Note"; base.Description = "Update this config file's note without changing feature settings."; base.ButtonLabel = "Save"; } public override void Execute() { if (ConfigService.UpdateFileNote(base.Entry?.FileName, CustomConfigSelection.GetEditNote(base.Entry))) { NotificationSystem.Push("Config Note Saved", base.Entry.FileName, NotificationKind.Success); } else { NotificationSystem.Push("Config Note Failed", base.Entry?.FileName ?? "Config", NotificationKind.Warning); } } } private sealed class LoadConfigFile : ConfigFileAction { public LoadConfigFile(ConfigFileEntry entry) : base(entry) { base.Name = "Load"; base.Description = "Load this saved config."; base.ButtonLabel = "Load"; } public override void Execute() { if (ConfigService.LoadFile(base.Entry?.FileName)) { NotificationSystem.Push("Config Loaded", base.Entry.FileName, NotificationKind.Success); } else { NotificationSystem.Push("Config Load Failed", base.Entry?.FileName ?? "Config", NotificationKind.Warning); } } } private sealed class OverrideConfigFile : ConfigFileAction { public OverrideConfigFile(ConfigFileEntry entry) : base(entry) { base.Name = "Override"; base.Description = "Overwrite this config file with current menu settings."; base.ButtonLabel = "Save"; } public override void Execute() { if (ConfigService.SaveToFile(base.Entry?.FileName, CustomConfigSelection.GetEditNote(base.Entry))) { NotificationSystem.Push("Config Overridden", base.Entry.FileName, NotificationKind.Success); } else { NotificationSystem.Push("Config Override Failed", base.Entry?.FileName ?? "Config", NotificationKind.Warning); } } } private sealed class RenameConfigFile : ConfigFileAction { public RenameConfigFile(ConfigFileEntry entry) : base(entry) { base.Name = "Rename"; base.Description = "Rename this custom config file and keep its saved settings."; base.ButtonLabel = "Rename"; } public override void Execute() { string editName = CustomConfigSelection.GetEditName(base.Entry); if (ConfigService.RenameFile(base.Entry?.FileName, editName)) { NotificationSystem.Push("Config Renamed", ConfigService.NormalizeConfigName(editName), NotificationKind.Success); CustomConfigSelection.ClearEdit(base.Entry); } else { NotificationSystem.Push("Config Rename Failed", base.Entry?.FileName ?? "Config", NotificationKind.Warning); } } } private sealed class DeleteConfigFile : ConfigFileAction { public DeleteConfigFile(ConfigFileEntry entry) : base(entry) { base.Name = "Delete"; base.Description = "Delete this saved config file."; base.ButtonLabel = "Delete"; } public override void Execute() { if (ConfigService.DeleteFile(base.Entry?.FileName)) { NotificationSystem.Push("Config Deleted", base.Entry.FileName, NotificationKind.Success); CustomConfigSelection.ClearEdit(base.Entry); } else { NotificationSystem.Push("Config Delete Failed", base.Entry?.FileName ?? "Config", NotificationKind.Warning); } } } private const string CustomConfigCategory = "Settings/Config/Custom Saves"; private const string CustomConfigPrefix = "Settings/Config/Custom Saves/"; public CustomConfigDirectory() { base.Name = "Config Directory"; base.Description = "Lists saved config JSON files."; } public IEnumerable GetRows(string category) { if (category == "Settings/Config/Custom Saves") { return BuildConfigRows(); } if (category != null && category.StartsWith("Settings/Config/Custom Saves/", StringComparison.Ordinal)) { return BuildConfigActions(category.Substring("Settings/Config/Custom Saves/".Length)); } return Array.Empty(); } public bool TryGetSidePanel(string category, object selectedRow, out MenuSidePanel panel) { panel = null; ConfigFileEntry configFileEntry = null; if (selectedRow is ConfigFileAction configFileAction) { configFileEntry = configFileAction.Entry; } else if (selectedRow is ConfigFileText configFileText) { configFileEntry = configFileText.Entry; } else if (selectedRow is ConfigFileSubmenu configFileSubmenu) { configFileEntry = configFileSubmenu.Entry; } if (configFileEntry == null) { return false; } FileInfo fileInfo = null; try { if (File.Exists(configFileEntry.Path)) { fileInfo = new FileInfo(configFileEntry.Path); } } catch { fileInfo = null; } panel = new MenuSidePanel("CONFIG FILE", configFileEntry.DisplayName, new List { new InfoFeature("File", configFileEntry.FileName), new InfoFeature("Note", string.IsNullOrWhiteSpace(configFileEntry.Note) ? "-" : configFileEntry.Note), new InfoFeature("Folder", ConfigService.ConfigDirectory), new InfoFeature("Size", (fileInfo == null) ? "-" : FormatBytes(fileInfo.Length)), new InfoFeature("Created", FormatUtc(configFileEntry.CreatedAtUtc)), new InfoFeature("Updated", FormatUtc(configFileEntry.UpdatedAtUtc)), new InfoFeature("Modified", (fileInfo == null) ? "-" : fileInfo.LastWriteTime.ToString("yyyy-MM-dd HH:mm", CultureInfo.InvariantCulture)) }, null, BuildTags(configFileEntry)); return true; } private static IEnumerable BuildConfigRows() { IReadOnlyList configFiles = ConfigService.GetConfigFiles(); List list = new List { new CustomConfigName(), new CustomConfigNote(), new SaveCustomConfig() }; if (configFiles.Count > 0) { list.Add(new SeparatorFeature()); } list.AddRange(configFiles.Select((ConfigFileEntry file) => new ConfigFileSubmenu(file))); if (configFiles.Count == 0) { list.Add(new InfoFeature("Config Files", "None", "Save a custom config first.")); } return list; } private static IEnumerable BuildConfigActions(string fileName) { ConfigFileEntry configFileEntry = ConfigService.GetConfigFiles().FirstOrDefault((ConfigFileEntry file) => string.Equals(file.FileName, fileName, StringComparison.OrdinalIgnoreCase)); if (configFileEntry == null) { return new <>z__ReadOnlySingleElementList(new InfoFeature("Config", "Not found", "This config file no longer exists.")); } List list = new List { new ConfigFileNoteText(configFileEntry), new SaveConfigFileNote(configFileEntry), new LoadConfigFile(configFileEntry), new OverrideConfigFile(configFileEntry) }; if (!configFileEntry.IsMain) { list.Insert(0, new ConfigFileNameText(configFileEntry)); list.Add(new RenameConfigFile(configFileEntry)); list.Add(new DeleteConfigFile(configFileEntry)); } return list; } private static List BuildTags(ConfigFileEntry entry) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) List list = new List { new MenuTag("JSON", new Color(0.22f, 0.5f, 0.9f, 1f)) }; if (string.Equals(entry?.FileName, "config.json", StringComparison.OrdinalIgnoreCase)) { list.Add(new MenuTag("MAIN", new Color(0.18f, 0.58f, 0.48f, 1f))); } else { list.Add(new MenuTag("CUSTOM", new Color(0.42f, 0.56f, 0.22f, 1f))); } return list; } private static string FormatBytes(long bytes) { if (bytes < 1024) { return bytes.ToString(CultureInfo.InvariantCulture) + " B"; } return ((float)bytes / 1024f).ToString("F1", CultureInfo.InvariantCulture) + " KB"; } private static string FormatUtc(string value) { if (string.IsNullOrWhiteSpace(value)) { return "-"; } if (!DateTime.TryParse(value, CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal, out var result)) { return "-"; } return result.ToLocalTime().ToString("yyyy-MM-dd HH:mm", CultureInfo.InvariantCulture); } } public class CustomConfigName : TextFeature { public CustomConfigName() { base.Name = "New File Name"; base.Description = "Name for the next custom config file. Spaces are saved as underscores in the filename."; base.EmptyDisplayText = "1 or name"; base.MaxLength = 64; SetText(CustomConfigSelection.Name); } public override string GetDisplayValue() { if (!string.IsNullOrWhiteSpace(CustomConfigSelection.Name)) { return CustomConfigSelection.Name; } return "1"; } protected override void OnTextChanged(string newValue) { CustomConfigSelection.Name = (string.IsNullOrWhiteSpace(newValue) ? "1" : newValue.Trim()); } } public class CustomConfigNote : TextFeature { public CustomConfigNote() { base.Name = "New File Note"; base.Description = "Optional note stored inside the next custom config file."; base.EmptyDisplayText = "Optional note"; base.MaxLength = 220; SetText(CustomConfigSelection.Note); } protected override void OnTextChanged(string newValue) { CustomConfigSelection.Note = newValue ?? string.Empty; } } internal static class CustomConfigSelection { public static string Name = "1"; public static string Note = string.Empty; private static readonly Dictionary EditNames = new Dictionary(StringComparer.OrdinalIgnoreCase); private static readonly Dictionary EditNotes = new Dictionary(StringComparer.OrdinalIgnoreCase); public static string GetEditName(ConfigFileEntry entry) { if (entry == null) { return string.Empty; } if (!EditNames.TryGetValue(entry.FileName, out var value)) { return entry.DisplayName; } return value; } public static void SetEditName(ConfigFileEntry entry, string value) { if (entry != null) { EditNames[entry.FileName] = (string.IsNullOrWhiteSpace(value) ? entry.DisplayName : value.Trim()); } } public static string GetEditNote(ConfigFileEntry entry) { if (entry == null) { return string.Empty; } if (!EditNotes.TryGetValue(entry.FileName, out var value)) { return entry.Note; } return value; } public static void SetEditNote(ConfigFileEntry entry, string value) { if (entry != null) { EditNotes[entry.FileName] = value ?? string.Empty; } } public static void ClearEdit(ConfigFileEntry entry) { if (entry != null) { EditNames.Remove(entry.FileName); EditNotes.Remove(entry.FileName); } } } public class HighlightSpeed : NumberFeature, ISettingsFeature { public HighlightSpeed() { base.Name = "Highlight Speed"; base.Description = "How quickly the white highlight slides between rows. Higher = snappier."; base.Min = 4f; base.Max = 40f; base.Decimals = 0; base.Step = 1f; base.Value = MenuConfig.HighlightLerpSpeed; } protected override void OnValueChanged(float v) { MenuConfig.HighlightLerpSpeed = v; } public void SyncFromConfig() { SetValue(MenuConfig.HighlightLerpSpeed); } } internal interface ISettingsFeature { void SyncFromConfig(); } public class LoadConfig : ButtonFeature { public LoadConfig() { base.Name = "Load"; base.Description = "Load menu settings and feature states from " + ConfigService.ConfigPath + "."; base.ButtonLabel = "Load"; } public override void Execute() { ConfigService.LoadCurrent(); } } public class LoadCustomConfig : ButtonFeature { public LoadCustomConfig() { base.Name = "Load Custom"; base.Description = "Load menu settings and feature states from the selected custom config file."; base.ButtonLabel = "Load"; } public override void Execute() { string text = ConfigService.NormalizeConfigName(CustomConfigSelection.Name); if (ConfigService.LoadNamed(text)) { NotificationSystem.Push("Config Loaded", "config_" + text + ".json", NotificationKind.Success); } else { NotificationSystem.Push("Config Load Failed", text, NotificationKind.Warning); } } } public class MenuWidth : NumberFeature, ISettingsFeature { public MenuWidth() { base.Name = "Menu Width"; base.Description = "Width of the menu window before UI scale is applied."; base.Min = 380f; base.Max = 720f; base.Decimals = 0; base.Step = 1f; base.Unit = "px"; base.Value = MenuConfig.MenuWidth; } protected override void OnValueChanged(float v) { MenuConfig.MenuWidth = v; } public void SyncFromConfig() { SetValue(MenuConfig.MenuWidth); } } public class ResetCustomization : ButtonFeature { public ResetCustomization() { base.Name = "Reset to Defaults"; base.Description = "Reset all customization options back to their defaults."; base.ButtonLabel = "Reset"; } public override void Execute() { MenuConfig.ResetToDefaults(); FeatureManager current = FeatureManager.Current; if (current == null) { return; } foreach (Feature item in current.All) { if (item is ISettingsFeature settingsFeature) { settingsFeature.SyncFromConfig(); } } } } public class SaveConfig : ButtonFeature { public SaveConfig() { base.Name = "Save"; base.Description = "Write the current menu settings and feature states to " + ConfigService.ConfigPath + "."; base.ButtonLabel = "Save"; } public override void Execute() { ConfigService.SaveCurrent(); } } public class SaveCustomConfig : ButtonFeature { public SaveCustomConfig() { base.Name = "Save Custom"; base.Description = "Write current menu settings and feature states to a custom config file."; base.ButtonLabel = "Save"; } public override void Execute() { string text = ConfigService.NormalizeConfigName(CustomConfigSelection.Name); if (ConfigService.SaveCurrentAs(text, CustomConfigSelection.Note)) { NotificationSystem.Push("Config Saved", "config_" + text + ".json", NotificationKind.Success); } else { NotificationSystem.Push("Config Save Failed", text, NotificationKind.Warning); } } } public class ShowBreadcrumb : Feature, ISettingsFeature { public ShowBreadcrumb() { base.Name = "Show Breadcrumb"; base.Description = "Display the navigation path under the title."; base.Enabled = MenuConfig.ShowBreadcrumb; } protected override void OnEnable() { MenuConfig.ShowBreadcrumb = true; } protected override void OnDisable() { MenuConfig.ShowBreadcrumb = false; } public void SyncFromConfig() { base.Enabled = MenuConfig.ShowBreadcrumb; } } public class ShowDescription : Feature, ISettingsFeature { public ShowDescription() { base.Name = "Show Description"; base.Description = "Display the description box under the menu."; base.Enabled = MenuConfig.ShowDescription; } protected override void OnEnable() { MenuConfig.ShowDescription = true; } protected override void OnDisable() { MenuConfig.ShowDescription = false; } public void SyncFromConfig() { base.Enabled = MenuConfig.ShowDescription; } } public class ShowFooter : Feature, ISettingsFeature { public ShowFooter() { base.Name = "Show Footer"; base.Description = "Display the version and arrow indicators at the bottom."; base.Enabled = MenuConfig.ShowFooter; } protected override void OnEnable() { MenuConfig.ShowFooter = true; } protected override void OnDisable() { MenuConfig.ShowFooter = false; } public void SyncFromConfig() { base.Enabled = MenuConfig.ShowFooter; } } public class ShowScrollbar : Feature, ISettingsFeature { public ShowScrollbar() { base.Name = "Show Scrollbar"; base.Description = "Display the left-side scrollbar for long menus."; base.Enabled = MenuConfig.ShowScrollbar; } protected override void OnEnable() { MenuConfig.ShowScrollbar = true; } protected override void OnDisable() { MenuConfig.ShowScrollbar = false; } public void SyncFromConfig() { base.Enabled = MenuConfig.ShowScrollbar; } } public class UIScale : NumberFeature, ISettingsFeature { public UIScale() { base.Name = "UI Scale"; base.Description = "Scale the whole menu. 1920x1080 is 1.0x; higher resolutions allow larger values."; base.Min = 0.5f; base.Max = MenuConfig.GetMaxUIScale(); base.Decimals = 1; base.Step = 0.1f; base.Unit = "x"; base.Value = MenuConfig.UIScale; } public override string GetDisplayValue() { base.Max = MenuConfig.GetMaxUIScale(); return MenuConfig.GetResolvedUIScale().ToString("F1") + base.Unit; } protected override void OnValueChanged(float v) { base.Max = MenuConfig.GetMaxUIScale(); MenuConfig.SetUIScale(v); } public void SyncFromConfig() { base.Max = MenuConfig.GetMaxUIScale(); SetValue(MenuConfig.UIScale); } } public class VisibleRows : NumberFeature, ISettingsFeature { public VisibleRows() { base.Name = "Visible Rows"; base.Description = "Maximum number of rows shown before scrolling kicks in."; base.Min = 6f; base.Max = 18f; base.Decimals = 0; base.Step = 1f; base.Value = MenuConfig.MaxVisibleRows; } protected override void OnValueChanged(float v) { MenuConfig.MaxVisibleRows = Mathf.RoundToInt(v); } public void SyncFromConfig() { SetValue(MenuConfig.MaxVisibleRows); } } } namespace CubeX.Runtime.Player { internal static class SteamPlayerActions { public struct SteamFriendPresence { public static readonly SteamFriendPresence Empty = new SteamFriendPresence { PersonaState = "-" }; public bool HasSteamId; public float CheckedAt; public bool IsOnline; public bool IsInGame; public bool IsInPeak; public bool IsJoinable; public ulong LobbyId; public uint AppId; public string PersonaState; public string AppName; public string GameText { get { if (!IsInGame) { return "-"; } if (IsInPeak) { return "PEAK"; } if (!string.IsNullOrWhiteSpace(AppName)) { return AppName; } if (AppId != 0) { return "App " + AppId.ToString(CultureInfo.InvariantCulture); } return "In game"; } } } public struct SteamFriendInfo { public ulong SteamId; public string Name; public SteamFriendPresence Presence; } [CompilerGenerated] private sealed class d__25 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public ulong lobbyId; private float 5__2; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__25(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || (uint)(num - 1) <= 1u) { try { } finally { <>m__Finally1(); } } <>1__state = -2; } private bool MoveNext() { //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Expected O, but got Unknown bool result; try { switch (<>1__state) { default: result = false; break; case 0: <>1__state = -1; <>1__state = -3; if (PhotonNetwork.InRoom) { try { Player.LeaveCurrentGame(); } catch { if (PhotonNetwork.InRoom) { PhotonNetwork.LeaveRoom(true); } } } 5__2 = Time.realtimeSinceStartup + 12f; goto IL_007e; case 1: <>1__state = -3; goto IL_007e; case 2: { <>1__state = -3; if (TryJoinLobbyNow(lobbyId)) { NotificationSystem.Push("Steam Join", "Join request sent.", NotificationKind.Success); } else { NotificationSystem.Push("Steam Join Failed", "Steam lobby join API was not available.", NotificationKind.Warning); } <>m__Finally1(); result = false; break; } IL_007e: if (PhotonNetwork.InRoom && Time.realtimeSinceStartup < 5__2) { <>2__current = null; <>1__state = 1; result = true; } else if (PhotonNetwork.InRoom) { NotificationSystem.Push("Steam Join Failed", "Timed out while leaving the current room.", NotificationKind.Warning); result = false; <>m__Finally1(); } else { <>2__current = (object)new WaitForSecondsRealtime(0.35f); <>1__state = 2; result = true; } break; } } catch { //try-fault ((IDisposable)this).Dispose(); throw; } return result; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; _joinAfterLeaveRoutine = null; } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class d__30 : IEnumerable, IEnumerable, IEnumerator, IEnumerator, IDisposable { private int <>1__state; private SteamFriendInfo <>2__current; private int <>l__initialThreadId; private object 5__2; private MethodInfo 5__3; private MethodInfo 5__4; private int 5__5; private int 5__6; SteamFriendInfo IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__30(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { 5__2 = null; 5__3 = null; 5__4 = null; <>1__state = -2; } private bool MoveNext() { int num = <>1__state; if (num != 0) { if (num != 1) { return false; } <>1__state = -1; goto IL_01a0; } <>1__state = -1; Type type = FindSteamworksType("Steamworks.CSteamID"); Type type2 = FindSteamworksType("Steamworks.SteamFriends"); if (type == null || type2 == null) { return false; } 5__2 = GetFriendFlagImmediate(); MethodInfo steamFriendsMethod = GetSteamFriendsMethod(type2, "GetFriendCount", 1); 5__3 = GetSteamFriendsMethod(type2, "GetFriendByIndex", 2); 5__4 = type2.GetMethod("GetFriendPersonaName", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { type }, null); if (5__2 == null || steamFriendsMethod == null || 5__3 == null) { return false; } 5__5 = Convert.ToInt32(steamFriendsMethod.Invoke(null, new object[1] { 5__2 }), CultureInfo.InvariantCulture); 5__6 = 0; goto IL_01b2; IL_01a0: 5__6++; goto IL_01b2; IL_01b2: if (5__6 < 5__5) { object obj = 5__3.Invoke(null, new object[2] { 5__6, 5__2 }); if (TryConvertSteamId(obj, out var steamId) && steamId != 0L) { string text = 5__4?.Invoke(null, new object[1] { obj }) as string; SteamFriendPresence friendPresence = GetFriendPresence(steamId); <>2__current = new SteamFriendInfo { SteamId = steamId, Name = (string.IsNullOrWhiteSpace(text) ? steamId.ToString(CultureInfo.InvariantCulture) : text), Presence = friendPresence }; <>1__state = 1; return true; } goto IL_01a0; } 5__2 = null; 5__3 = null; 5__4 = null; 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(); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; return this; } return new d__30(0); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)this).GetEnumerator(); } } private const BindingFlags StaticFlags = BindingFlags.Static | BindingFlags.Public; private const BindingFlags InstanceFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; private const uint PeakSteamAppId = 3527290u; private const float PresenceCacheSeconds = 8f; private const float FriendsCacheSeconds = 10f; private const string SteamFolderName = "Steam"; private const string AppNameCacheFileName = "steam_app_names.json"; private static readonly Dictionary PresenceCache = new Dictionary(); private static readonly Dictionary AppNameCache = new Dictionary(); private static readonly HashSet FailedAppNameLookups = new HashSet(); private static readonly List FriendsCache = new List(); private static float _friendsCacheAt = -999f; private static bool _loadedPersistentAppNames; private static bool _loadedLocalAppNames; private static Coroutine _joinAfterLeaveRoutine; public static bool OpenAddFriend(ulong steamId) { if (steamId != 0L) { return ActivateGameOverlayToUser("friendadd", steamId); } return false; } public static bool OpenProfile(ulong steamId) { if (steamId == 0L) { return false; } if (ActivateGameOverlayToUser("steamid", steamId)) { return true; } Application.OpenURL("steam://url/SteamIDPage/" + steamId.ToString(CultureInfo.InvariantCulture)); return true; } public static bool InviteToCurrentLobby(ulong steamId) { if (steamId == 0L) { return false; } return TryInviteUserToCurrentLobby(steamId); } private static bool TryInviteUserToCurrentLobby(ulong steamId) { try { if (!TryGetCurrentSteamLobbyObject(out var lobbyId)) { return false; } Type type = FindSteamworksType("Steamworks.CSteamID"); Type type2 = FindSteamworksType("Steamworks.SteamMatchmaking"); if (type == null || type2 == null) { return false; } if (!EnsureSteamIdObject(lobbyId, type, out var steamIdObject)) { return false; } object obj = Activator.CreateInstance(type, steamId); if (obj == null) { return false; } MethodInfo method = type2.GetMethod("InviteUserToLobby", BindingFlags.Static | BindingFlags.Public, null, new Type[2] { type, type }, null); if (method == null) { return false; } object obj2 = method.Invoke(null, new object[2] { steamIdObject, obj }); bool flag = default(bool); int num; if (obj2 is bool) { flag = (bool)obj2; num = ((1 == 0) ? 1 : 0); } else { num = 1; } return (byte)((uint)num | (flag ? 1u : 0u)) != 0; } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Steam Direct Invite] " + ex.Message)); } return false; } } public static bool TryGetJoinableGameLobby(ulong steamId, out ulong lobbyId) { lobbyId = 0uL; if (steamId == 0L) { return false; } SteamFriendPresence friendPresence = GetFriendPresence(steamId); lobbyId = friendPresence.LobbyId; return friendPresence.IsJoinable; } public static SteamFriendPresence GetFriendPresence(ulong steamId) { if (steamId == 0L) { return SteamFriendPresence.Empty; } float unscaledTime = Time.unscaledTime; if (PresenceCache.TryGetValue(steamId, out var value) && unscaledTime - value.CheckedAt < 8f) { return value; } SteamFriendPresence steamFriendPresence = QueryFriendPresence(steamId); steamFriendPresence.CheckedAt = unscaledTime; PresenceCache[steamId] = steamFriendPresence; return steamFriendPresence; } public static IReadOnlyList GetFriends() { float unscaledTime = Time.unscaledTime; if (FriendsCache.Count > 0 && unscaledTime - _friendsCacheAt < 10f) { return FriendsCache; } FriendsCache.Clear(); FriendsCache.AddRange(QueryFriends()); _friendsCacheAt = unscaledTime; return FriendsCache; } public static bool IsFriend(ulong steamId) { if (steamId == 0L) { return false; } IReadOnlyList friends = GetFriends(); for (int i = 0; i < friends.Count; i++) { if (friends[i].SteamId == steamId) { return true; } } return false; } public static string GetPersonaName(ulong steamId) { if (steamId == 0L) { return string.Empty; } try { Type type = FindSteamworksType("Steamworks.CSteamID"); Type type2 = FindSteamworksType("Steamworks.SteamFriends"); if (type == null || type2 == null) { return string.Empty; } object obj = Activator.CreateInstance(type, steamId); if (obj == null) { return string.Empty; } return (type2.GetMethod("GetFriendPersonaName", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { type }, null)?.Invoke(null, new object[1] { obj }) as string) ?? string.Empty; } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Steam Persona] " + ex.Message)); } return string.Empty; } } public static bool JoinLobby(ulong lobbyId) { if (lobbyId == 0L) { return false; } if (PhotonNetwork.InRoom) { if (!Object.op_Implicit((Object)(object)Plugin.Instance)) { return false; } if (_joinAfterLeaveRoutine != null) { ((MonoBehaviour)Plugin.Instance).StopCoroutine(_joinAfterLeaveRoutine); } _joinAfterLeaveRoutine = ((MonoBehaviour)Plugin.Instance).StartCoroutine(JoinLobbyAfterLeavingRoom(lobbyId)); NotificationSystem.Push("Steam Join", "Leaving current room before joining..."); return true; } return TryJoinLobbyNow(lobbyId); } [IteratorStateMachine(typeof(d__25))] private static IEnumerator JoinLobbyAfterLeavingRoom(ulong lobbyId) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__25(0) { lobbyId = lobbyId }; } private static bool TryJoinLobbyNow(ulong lobbyId) { if (lobbyId == 0L) { return false; } try { object steamLobbyHandler = GetSteamLobbyHandler(); if (steamLobbyHandler == null) { return false; } Type type = FindSteamworksType("Steamworks.CSteamID"); if (type == null) { return false; } object obj = Activator.CreateInstance(type, lobbyId); if (obj == null) { return false; } MethodInfo method = steamLobbyHandler.GetType().GetMethod("JoinLobby", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (method == null) { return false; } method.Invoke(steamLobbyHandler, new object[1] { obj }); return true; } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Steam Join] " + ex.Message)); } return false; } } public static bool SetCurrentLobbyJoinable(bool joinable) { try { if (!TryGetCurrentSteamLobbyObject(out var lobbyId)) { return false; } Type type = FindSteamworksType("Steamworks.CSteamID"); Type type2 = FindSteamworksType("Steamworks.SteamMatchmaking"); if (type == null || type2 == null) { return false; } if (!EnsureSteamIdObject(lobbyId, type, out var steamIdObject)) { return false; } MethodInfo method = type2.GetMethod("SetLobbyJoinable", BindingFlags.Static | BindingFlags.Public, null, new Type[2] { type, typeof(bool) }, null); if (method == null) { return false; } object obj = method.Invoke(null, new object[2] { steamIdObject, joinable }); bool flag = default(bool); int num; if (obj is bool) { flag = (bool)obj; num = ((1 == 0) ? 1 : 0); } else { num = 1; } return (byte)((uint)num | (flag ? 1u : 0u)) != 0; } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Steam Lobby Lock] " + ex.Message)); } return false; } } public static bool TryGetCurrentLobbyId(out ulong lobbyId) { lobbyId = 0uL; if (TryConvertSteamId(GetCurrentSteamLobbyId(), out lobbyId)) { return lobbyId != 0; } return false; } private static SteamFriendPresence QueryFriendPresence(ulong steamId) { SteamFriendPresence empty = SteamFriendPresence.Empty; empty.HasSteamId = steamId != 0; empty.PersonaState = "-"; if (steamId == 0L) { return empty; } try { Type type = FindSteamworksType("Steamworks.CSteamID"); Type type2 = FindSteamworksType("Steamworks.SteamFriends"); if (type == null || type2 == null) { return empty; } object obj = Activator.CreateInstance(type, steamId); if (obj == null) { return empty; } empty.PersonaState = QueryPersonaState(type2, type, obj); empty.IsOnline = IsOnlinePersonaState(empty.PersonaState); if (!TryQueryFriendGameInfo(obj, type, type2, out var gameInfo)) { return empty; } empty.IsInGame = TryGetGameAppId(GetFieldValue(gameInfo, "m_gameID"), out var appId); empty.AppId = appId; empty.IsInPeak = empty.IsInGame && appId == 3527290; empty.AppName = ResolveSteamAppName(appId); object fieldValue = GetFieldValue(gameInfo, "m_steamIDLobby"); if (empty.IsInPeak && TryConvertSteamId(fieldValue, out var steamId2) && steamId2 != 0L) { empty.IsJoinable = true; empty.LobbyId = steamId2; } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Steam Presence] " + ex.Message)); } } return empty; } [IteratorStateMachine(typeof(d__30))] private static IEnumerable QueryFriends() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__30(-2); } private static object GetFriendFlagImmediate() { Type type = FindSteamworksType("Steamworks.EFriendFlags"); if (type == null) { return null; } string[] array = new string[2] { "k_EFriendFlagImmediate", "Immediate" }; foreach (string value in array) { try { if (Enum.IsDefined(type, value)) { return Enum.Parse(type, value); } } catch { } } return Enum.ToObject(type, 4); } private static MethodInfo GetSteamFriendsMethod(Type steamFriendsType, string methodName, int parameterCount) { if (steamFriendsType == null) { return null; } return steamFriendsType.GetMethods(BindingFlags.Static | BindingFlags.Public).FirstOrDefault((MethodInfo method) => string.Equals(method.Name, methodName, StringComparison.Ordinal) && method.GetParameters().Length == parameterCount); } private static bool TryQueryFriendGameInfo(object steam, Type cSteamIdType, Type steamFriendsType, out object gameInfo) { gameInfo = null; try { Type type = FindSteamworksType("Steamworks.FriendGameInfo_t"); if (steam == null || cSteamIdType == null || steamFriendsType == null || type == null) { return false; } MethodInfo friendGamePlayedMethod = GetFriendGamePlayedMethod(steamFriendsType, cSteamIdType, type); if (friendGamePlayedMethod == null) { return false; } object[] array = new object[2] { steam, Activator.CreateInstance(type) }; object obj = friendGamePlayedMethod.Invoke(null, array); if (!(obj is bool) || !(bool)obj) { return false; } gameInfo = array[1]; return gameInfo != null; } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Steam Friend Game] " + ex.Message)); } return false; } } private static string QueryPersonaState(Type steamFriendsType, Type cSteamIdType, object steam) { return FormatPersonaState(steamFriendsType.GetMethod("GetFriendPersonaState", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { cSteamIdType }, null)?.Invoke(null, new object[1] { steam })); } private static string FormatPersonaState(object state) { if (state == null) { return "-"; } string text = state.ToString(); if (string.IsNullOrWhiteSpace(text)) { return "-"; } int num = text.LastIndexOf('.'); if (num >= 0 && num + 1 < text.Length) { text = text.Substring(num + 1); } if (text.StartsWith("k_EPersonaState", StringComparison.OrdinalIgnoreCase)) { text = text.Substring("k_EPersonaState".Length); } return SplitPascalCase(text); } private static bool IsOnlinePersonaState(string state) { if (string.IsNullOrWhiteSpace(state) || state == "-") { return false; } if (!state.Equals("Offline", StringComparison.OrdinalIgnoreCase) && !state.Equals("Unknown", StringComparison.OrdinalIgnoreCase)) { return !state.Equals("Invisible", StringComparison.OrdinalIgnoreCase); } return false; } private static string SplitPascalCase(string value) { if (string.IsNullOrWhiteSpace(value)) { return "-"; } List list = new List(value.Length + 4); for (int i = 0; i < value.Length; i++) { char c = value[i]; if (i > 0 && char.IsUpper(c) && char.IsLower(value[i - 1])) { list.Add(' '); } list.Add(c); } return new string(list.ToArray()); } private static bool TryQueryJoinableGameLobby(ulong steamId, out ulong lobbyId) { lobbyId = 0uL; try { Type type = FindSteamworksType("Steamworks.CSteamID"); Type type2 = FindSteamworksType("Steamworks.SteamFriends"); if (type == null || type2 == null) { return false; } object obj = Activator.CreateInstance(type, steamId); if (obj == null) { return false; } if (!TryQueryFriendGameInfo(obj, type, type2, out var gameInfo)) { return false; } if (!IsPeakGameInfo(gameInfo)) { return false; } return TryConvertSteamId(GetFieldValue(gameInfo, "m_steamIDLobby"), out lobbyId) && lobbyId != 0; } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Steam Joinable Game] " + ex.Message)); } lobbyId = 0uL; return false; } } private static MethodInfo GetFriendGamePlayedMethod(Type steamFriendsType, Type cSteamIdType, Type friendGameInfoType) { return (from method in steamFriendsType.GetMethods(BindingFlags.Static | BindingFlags.Public) where string.Equals(method.Name, "GetFriendGamePlayed", StringComparison.Ordinal) let parameters = method.GetParameters() where parameters.Length == 2 where parameters[0].ParameterType == cSteamIdType where parameters[1].ParameterType == friendGameInfoType.MakeByRefType() select method).FirstOrDefault(); } private static bool IsPeakGameInfo(object gameInfo) { if (TryGetGameAppId(GetFieldValue(gameInfo, "m_gameID"), out var appId)) { return appId == 3527290; } return false; } private static bool TryGetGameAppId(object gameId, out uint appId) { appId = 0u; if (gameId == null) { return false; } if (TryConvertAppId(gameId.GetType().GetMethod("AppID", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.Invoke(gameId, null), out appId)) { return true; } if (TryConvertUInt64(GetFieldValue(gameId, "m_GameID"), out var result)) { appId = (uint)(result & 0xFFFFFF); return appId != 0; } return false; } private static bool TryConvertAppId(object value, out uint appId) { appId = 0u; if (value == null) { return false; } if (value is uint num) { appId = num; return true; } if (GetFieldValue(value, "m_AppId") is uint num2) { appId = num2; return true; } return uint.TryParse(value.ToString(), NumberStyles.Integer, CultureInfo.InvariantCulture, out appId); } private static string ResolveSteamAppName(uint appId) { switch (appId) { case 0u: return string.Empty; case 3527290u: return "PEAK"; default: { LoadPersistentAppNameCache(); if (AppNameCache.TryGetValue(appId, out var value)) { return value; } string knownSteamAppName = GetKnownSteamAppName(appId); if (!string.IsNullOrEmpty(knownSteamAppName)) { CacheSteamAppName(appId, knownSteamAppName, persist: true); return knownSteamAppName; } LoadLocalSteamAppNames(); if (AppNameCache.TryGetValue(appId, out var value2)) { return value2; } string text = QuerySteamStoreAppName(appId); if (!string.IsNullOrWhiteSpace(text)) { CacheSteamAppName(appId, text, persist: true); return text; } return string.Empty; } } } private static string GetKnownSteamAppName(uint appId) { if (appId == 3241660) { return "R.E.P.O."; } return string.Empty; } private static void LoadPersistentAppNameCache() { if (_loadedPersistentAppNames) { return; } _loadedPersistentAppNames = true; try { AppDataPaths.MigrateFileToDirectory("steam_app_names.json", "Steam"); string path = AppDataPaths.FilePath("Steam", "steam_app_names.json"); if (!File.Exists(path)) { return; } foreach (JProperty item in JObject.Parse(File.ReadAllText(path)).Properties()) { if (uint.TryParse(item.Name, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result)) { string text = ((object)item.Value)?.ToString(); if (!string.IsNullOrWhiteSpace(text)) { AppNameCache[result] = text.Trim(); } } } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Steam App Name Cache] " + ex.Message)); } } } private static void SavePersistentAppNameCache() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown try { Directory.CreateDirectory(AppDataPaths.DirectoryPath("Steam")); JObject val = new JObject(); foreach (KeyValuePair item in AppNameCache.OrderBy((KeyValuePair pair) => pair.Key)) { if (item.Key != 0 && !string.IsNullOrWhiteSpace(item.Value)) { val[item.Key.ToString(CultureInfo.InvariantCulture)] = JToken.op_Implicit(item.Value); } } File.WriteAllText(AppDataPaths.FilePath("Steam", "steam_app_names.json"), ((object)val).ToString()); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Steam App Name Cache] " + ex.Message)); } } } private static void CacheSteamAppName(uint appId, string name, bool persist) { if (appId != 0 && !string.IsNullOrWhiteSpace(name)) { AppNameCache[appId] = name.Trim(); if (persist) { SavePersistentAppNameCache(); } } } private static string QuerySteamStoreAppName(uint appId) { if (appId == 0 || FailedAppNameLookups.Contains(appId)) { return string.Empty; } try { HttpWebRequest obj = (HttpWebRequest)WebRequest.Create("https://store.steampowered.com/api/appdetails?appids=" + appId.ToString(CultureInfo.InvariantCulture) + "&filters=basic"); obj.Method = "GET"; obj.Timeout = 1500; obj.ReadWriteTimeout = 1500; obj.UserAgent = "Cube-X"; using WebResponse webResponse = obj.GetResponse(); using Stream stream = webResponse.GetResponseStream(); if (stream == null) { return string.Empty; } using StreamReader streamReader = new StreamReader(stream); JToken obj2 = JObject.Parse(streamReader.ReadToEnd())[appId.ToString(CultureInfo.InvariantCulture)]; JObject val = (JObject)(object)((obj2 is JObject) ? obj2 : null); if (val == null || !((JToken)val).Value((object)"success").GetValueOrDefault()) { return string.Empty; } JToken obj3 = val["data"]; string text = ((obj3 != null) ? obj3.Value((object)"name") : null); if (!string.IsNullOrWhiteSpace(text)) { return text.Trim(); } } catch (Exception ex) { FailedAppNameLookups.Add(appId); ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Steam App Name Lookup] " + appId.ToString(CultureInfo.InvariantCulture) + ": " + ex.Message)); } } return string.Empty; } private static void LoadLocalSteamAppNames() { if (_loadedLocalAppNames) { return; } _loadedLocalAppNames = true; try { foreach (string steamAppsPath in GetSteamAppsPaths()) { if (!string.IsNullOrEmpty(steamAppsPath) && Directory.Exists(steamAppsPath)) { string[] files; try { files = Directory.GetFiles(steamAppsPath, "appmanifest_*.acf", SearchOption.TopDirectoryOnly); } catch { continue; } for (int i = 0; i < files.Length; i++) { LoadAppManifestName(files[i]); } } } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Steam App Names] " + ex.Message)); } } } private static IEnumerable GetSteamAppsPaths() { HashSet hashSet = new HashSet(StringComparer.OrdinalIgnoreCase); AddSteamAppsPath(hashSet, Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), "Steam", "steamapps")); AddSteamAppsPath(hashSet, Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "Steam", "steamapps")); string dataPath = Application.dataPath; if (!string.IsNullOrEmpty(dataPath)) { for (DirectoryInfo parent = Directory.GetParent(dataPath); parent != null; parent = parent.Parent) { if (string.Equals(parent.Name, "common", StringComparison.OrdinalIgnoreCase) && parent.Parent != null && string.Equals(parent.Parent.Name, "steamapps", StringComparison.OrdinalIgnoreCase)) { AddSteamAppsPath(hashSet, parent.Parent.FullName); break; } } } string[] array = hashSet.ToArray(); foreach (string steamAppsPath in array) { AddLibrarySteamAppsPaths(hashSet, steamAppsPath); } return hashSet; } private static void AddSteamAppsPath(HashSet paths, string path) { if (!string.IsNullOrEmpty(path)) { paths.Add(path); } } private static void AddLibrarySteamAppsPaths(HashSet paths, string steamAppsPath) { try { string path = Path.Combine(steamAppsPath, "libraryfolders.vdf"); if (!File.Exists(path)) { return; } string[] array = File.ReadAllLines(path); for (int i = 0; i < array.Length; i++) { string text = ReadVdfValue(array[i], "path"); if (!string.IsNullOrEmpty(text)) { AddSteamAppsPath(paths, Path.Combine(text.Replace("\\\\", "\\"), "steamapps")); } } } catch { } } private static void LoadAppManifestName(string manifestPath) { try { uint result = 0u; string text = string.Empty; string[] array = File.ReadAllLines(manifestPath); foreach (string line in array) { string text2 = ReadVdfValue(line, "appid"); if (!string.IsNullOrEmpty(text2)) { uint.TryParse(text2, NumberStyles.Integer, CultureInfo.InvariantCulture, out result); } string text3 = ReadVdfValue(line, "name"); if (!string.IsNullOrEmpty(text3)) { text = text3; } } if (result != 0 && !string.IsNullOrWhiteSpace(text)) { CacheSteamAppName(result, text, persist: true); } } catch { } } private static string ReadVdfValue(string line, string key) { if (string.IsNullOrWhiteSpace(line) || string.IsNullOrEmpty(key)) { return string.Empty; } string text = line.Trim(); string text2 = "\"" + key + "\""; if (!text.StartsWith(text2, StringComparison.OrdinalIgnoreCase)) { return string.Empty; } int num = text.IndexOf('"', text2.Length); if (num < 0) { return string.Empty; } int num2 = text.IndexOf('"', num + 1); if (num2 < 0) { return string.Empty; } return text.Substring(num + 1, num2 - num - 1); } private static bool ActivateGameOverlayToUser(string dialog, ulong steamId) { try { Type type = FindSteamworksType("Steamworks.CSteamID"); Type type2 = FindSteamworksType("Steamworks.SteamFriends"); if (type == null || type2 == null) { return false; } object obj = Activator.CreateInstance(type, steamId); if (obj == null) { return false; } MethodInfo method = type2.GetMethod("ActivateGameOverlayToUser", BindingFlags.Static | BindingFlags.Public, null, new Type[2] { typeof(string), type }, null); if (method == null) { return false; } method.Invoke(null, new object[2] { dialog, obj }); return true; } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Steam Overlay] " + ex.Message)); } return false; } } private static object GetCurrentSteamLobbyId() { if (!TryGetCurrentSteamLobbyObject(out var lobbyId)) { return null; } return lobbyId; } private static bool TryGetCurrentSteamLobbyObject(out object lobbyId) { lobbyId = null; try { object steamLobbyHandler = GetSteamLobbyHandler(); if (steamLobbyHandler == null) { return false; } if (TryGetLobbyIdFromInSteamLobby(steamLobbyHandler, out lobbyId)) { return true; } if (TryNormalizeCurrentLobbyId(GetPropertyValue(steamLobbyHandler, "LobbySteamId"), out lobbyId)) { return true; } if (TryNormalizeCurrentLobbyId(GetFieldValue(steamLobbyHandler, "k__BackingField"), out lobbyId)) { return true; } return TryNormalizeCurrentLobbyId(GetFieldValue(steamLobbyHandler, "m_currentLobby"), out lobbyId); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Steam Lobby] " + ex.Message)); } lobbyId = null; return false; } } private static bool TryGetLobbyIdFromInSteamLobby(object lobbyHandler, out object lobbyId) { lobbyId = null; Type type = FindSteamworksType("Steamworks.CSteamID"); if (lobbyHandler == null || type == null) { return false; } MethodInfo method = lobbyHandler.GetType().GetMethod("InSteamLobby", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { type.MakeByRefType() }, null); if (method == null) { return false; } object[] array = new object[1] { Activator.CreateInstance(type) }; object obj = method.Invoke(lobbyHandler, array); if (obj is bool && (bool)obj) { return TryNormalizeCurrentLobbyId(array[0], out lobbyId); } return false; } private static bool TryNormalizeCurrentLobbyId(object value, out object lobbyId) { lobbyId = null; if (!TryConvertSteamId(value, out var steamId) || steamId == 0L) { return false; } lobbyId = value; return lobbyId != null; } private static bool EnsureSteamIdObject(object value, Type cSteamIdType, out object steamIdObject) { steamIdObject = null; if (cSteamIdType == null) { return false; } if (value != null && cSteamIdType.IsInstanceOfType(value)) { steamIdObject = value; return true; } if (TryConvertSteamId(value, out var steamId) && steamId != 0L) { return TryCreateSteamIdObject(steamId, cSteamIdType, out steamIdObject); } return false; } private static bool TryCreateSteamIdObject(ulong steamId, Type cSteamIdType, out object steamIdObject) { steamIdObject = null; if (steamId == 0L || cSteamIdType == null) { return false; } try { steamIdObject = Activator.CreateInstance(cSteamIdType, steamId); return steamIdObject != null; } catch { return false; } } private static object GetSteamLobbyHandler() { MethodInfo method = typeof(GameHandler).GetMethod("GetService", BindingFlags.Static | BindingFlags.Public); if (method == null) { return null; } Type type = FindSteamworksType("SteamLobbyHandler") ?? FindSteamworksType("pworld.Scripts.Extensions.SteamLobbyHandler"); if (!(type == null)) { return method.MakeGenericMethod(type).Invoke(null, null); } return null; } private static bool TryConvertSteamId(object value, out ulong steamId) { steamId = 0uL; if (value == null) { return false; } if (TryConvertUInt64(value, out var result)) { steamId = result; return true; } try { object fieldValue = GetFieldValue(value, "m_SteamID"); if (fieldValue != null && ulong.TryParse(fieldValue.ToString(), NumberStyles.Integer, CultureInfo.InvariantCulture, out steamId)) { return true; } } catch { } return ulong.TryParse(value.ToString(), NumberStyles.Integer, CultureInfo.InvariantCulture, out steamId); } private static bool TryConvertUInt64(object value, out ulong result) { result = 0uL; if (!(value is ulong num)) { if (value is uint num2) { result = num2; return true; } if (value != null) { return ulong.TryParse(value.ToString(), NumberStyles.Integer, CultureInfo.InvariantCulture, out result); } return false; } result = num; return true; } private static object GetFieldValue(object target, string name) { return (target?.GetType().GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))?.GetValue(target); } private static object GetPropertyValue(object target, string name) { return (target?.GetType().GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))?.GetValue(target, null); } private static Type FindSteamworksType(string fullName) { Type type = Type.GetType(fullName); if (type != null) { return type; } Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { try { type = assembly.GetType(fullName); if (type != null) { return type; } } catch { } } return null; } } } namespace CubeX.Runtime.Network { internal static class LocalNetworkStateResync { [CompilerGenerated] private sealed class d__2 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public string reason; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__2(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Expected O, but got Unknown //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = null; <>1__state = 1; return true; case 1: <>1__state = -1; Reassert(reason); <>2__current = (object)new WaitForSecondsRealtime(0.25f); <>1__state = 2; return true; case 2: <>1__state = -1; Reassert(reason); <>2__current = (object)new WaitForSecondsRealtime(0.75f); <>1__state = 3; return true; case 3: <>1__state = -1; Reassert(reason); _routine = null; 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 Coroutine _routine; public static void Schedule(string reason) { if (Object.op_Implicit((Object)(object)Plugin.Instance) && PhotonNetwork.InRoom && _routine == null) { _routine = ((MonoBehaviour)Plugin.Instance).StartCoroutine(ResyncRoutine(reason ?? "network state")); } } [IteratorStateMachine(typeof(d__2))] private static IEnumerator ResyncRoutine(string reason) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__2(0) { reason = reason }; } private static void Reassert(string reason) { RepairLocalCharacterOwnership(reason); try { GameActions.SyncLocalInventory(); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Network Resync] Inventory sync after " + reason + " failed: " + ex.Message)); } } try { PhotonNetwork.SendAllOutgoingCommands(); } catch (Exception ex2) { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogWarning((object)("[Network Resync] Photon command flush after " + reason + " failed: " + ex2.Message)); } } } private static void RepairLocalCharacterOwnership(string reason) { //IL_0056: Unknown result type (might be due to invalid IL or missing references) Character localCharacter = Character.localCharacter; if (!Object.op_Implicit((Object)(object)localCharacter) || PhotonNetwork.LocalPlayer == null) { return; } PhotonView val = localCharacter.refs?.view; if (!Object.op_Implicit((Object)(object)val)) { val = ((Component)localCharacter).GetComponent() ?? ((Component)localCharacter).GetComponentInChildren(); } if (!Object.op_Implicit((Object)(object)val) || IsLocalOwned(val)) { return; } try { val.OwnershipTransfer = (OwnershipOption)1; val.RequestOwnership(); val.TransferOwnership(PhotonNetwork.LocalPlayer); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Network Resync] Ownership repair after " + reason + " failed: " + ex.Message)); } } } private static bool IsLocalOwned(PhotonView view) { if (!Object.op_Implicit((Object)(object)view) || PhotonNetwork.LocalPlayer == null) { return false; } int actorNumber = PhotonNetwork.LocalPlayer.ActorNumber; if (!view.IsMine && view.OwnerActorNr != actorNumber && view.ControllerActorNr != actorNumber) { Player owner = view.Owner; if (owner == null || owner.ActorNumber != actorNumber) { Player controller = view.Controller; if (controller == null) { return false; } return controller.ActorNumber == actorNumber; } } return true; } } } namespace CubeX.Runtime.Diagnostics { internal static class CubeXDiagnostics { public static void Info(string area, string message, bool notify = false) { string text = Format(area, message); ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)text); } if (notify) { SafeNotify(area, message, NotificationKind.Info); } } public static void Warning(string area, string message, bool notify = true) { string text = Format(area, message); ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)text); } if (notify) { SafeNotify(area, message, NotificationKind.Warning); } } public static void Error(string area, string message, Exception exception = null, bool notify = true) { string text = Format(area, message); if (exception == null) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogError((object)text); } } else { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogError((object)(text + "\n" + exception)); } Debug.LogException(exception); } if (notify) { SafeNotify(area, (exception == null) ? message : (message + " " + GetBaseMessage(exception)), NotificationKind.Error); } } public static bool Try(string area, string actionName, Action action, bool notifyErrors = true) { if (action == null) { Warning(area, actionName + " was skipped because action was null.", notifyErrors); return false; } try { action(); return true; } catch (Exception exception) { Error(area, actionName + " failed.", exception, notifyErrors); return false; } } public static string GetBaseMessage(Exception exception) { if (exception == null) { return string.Empty; } Exception baseException = exception.GetBaseException(); if (!string.IsNullOrWhiteSpace(baseException.Message)) { return baseException.Message; } return baseException.GetType().Name; } private static string Format(string area, string message) { area = (string.IsNullOrWhiteSpace(area) ? "CubeX" : area.Trim()); message = (string.IsNullOrWhiteSpace(message) ? "No details." : message.Trim()); return "[" + area + "] " + message; } private static void SafeNotify(string title, string description, NotificationKind kind) { try { NotificationSystem.Push(title, description, kind); } catch (Exception exception) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Diagnostics] Notification failed: " + GetBaseMessage(exception))); } } } } } namespace CubeX.Patches.Visuals { [HarmonyPatch(typeof(CenterOfMass), "FixedUpdate")] internal static class BetterFpsCenterOfMassPatch { private static bool Prefix(CenterOfMass __instance) { //IL_0068: 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_0044: 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_006f: 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_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) if (!EntityPerformanceSettings.OptimizedCenterOfMass || !Object.op_Implicit((Object)(object)__instance)) { return true; } Item field = GetField(__instance, "item"); Rigidbody field2 = GetField(__instance, "rb"); if (!Object.op_Implicit((Object)(object)field2)) { return true; } if (__instance.onlyOnGround && Object.op_Implicit((Object)(object)field) && (int)field.itemState != 0) { return false; } Vector3 val = (Object.op_Implicit((Object)(object)__instance.centerOfMassTransform) ? __instance.centerOfMassTransform.localPosition : __instance.localCenterOfMass); Vector3 centerOfMass = field2.centerOfMass; if (!((Vector3)(ref centerOfMass)).Equals(val)) { field2.centerOfMass = val; } if (!Mathf.Approximately(field2.angularDamping, __instance.angularDamping)) { field2.angularDamping = __instance.angularDamping; } return false; } private static T GetField(object target, string name) where T : class { FieldInfo fieldInfo = AccessTools.Field(target.GetType(), name); if (!(fieldInfo == null)) { return fieldInfo.GetValue(target) as T; } return null; } } [HarmonyPatch(typeof(CharacterRagdoll), "FixedUpdate")] internal static class BetterFpsRagdollPatch { private static readonly Dictionary UpdateTime = new Dictionary(); private static bool Prefix(CharacterRagdoll __instance) { //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) Character field = GetField(__instance, "character"); if (!EntityPerformanceSettings.ThrottleRemoteRagdolls || !Object.op_Implicit((Object)(object)__instance) || !Object.op_Implicit((Object)(object)field)) { return true; } if (field.IsLocal || field.isScoutmaster) { return true; } float num = EntityPerformanceSettings.CharacterUpdateSpeed; float characterDistance = GetCharacterDistance(field); if (characterDistance > EntityPerformanceSettings.CharacterFarDistance) { num = EntityPerformanceSettings.CharacterFarUpdateSpeed; } else if (characterDistance > EntityPerformanceSettings.CharacterMediumDistance) { num = EntityPerformanceSettings.CharacterMediumUpdateSpeed; } if (num <= 0f) { return false; } float num2 = 1f / num; if (!UpdateTime.ContainsKey(__instance)) { UpdateTime[__instance] = 0f; } UpdateTime[__instance] += Time.fixedDeltaTime; if (UpdateTime[__instance] < num2) { return false; } UpdateTime[__instance] -= num2; Call(__instance, "SetPhysicsMats"); if (GetField(__instance, "firstFrame")) { SetField(__instance, "firstFrame", false); return false; } if (Object.op_Implicit((Object)(object)field.data.currentItem)) { field.refs.animations.PrepIK(); } Call(__instance, "RotateCharacter"); field.refs.ikRigBuilder.SyncLayers(); field.refs.ikRigBuilder.Evaluate(num2); PlayableGraph playableGraph = field.refs.animator.playableGraph; ((PlayableGraph)(ref playableGraph)).Evaluate(num2); field.refs.animations.ConfigureIK(); foreach (Bodypart part in __instance.partList) { part.SaveAnimationData(); Call(__instance, "DrawLines", GetField(part, "jointParent"), part); } Call(__instance, "SaveAdditionalTransformPositions"); Call(__instance, "ResetRotation"); foreach (Bodypart part2 in __instance.partList) { part2.ResetTransform(); } return false; } private static float GetCharacterDistance(Character character) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) Camera main = Camera.main; if (!Object.op_Implicit((Object)(object)main) || !Object.op_Implicit((Object)(object)character)) { return 0f; } Vector3 val = ((Component)main).transform.position - character.Center; return ((Vector3)(ref val)).magnitude; } private static T GetField(object target, string name) { FieldInfo fieldInfo = AccessTools.Field(target.GetType(), name); if (fieldInfo == null) { return default(T); } object value = fieldInfo.GetValue(target); if (value is T) { return (T)value; } return default(T); } private static void SetField(object target, string name, object value) { AccessTools.Field(target.GetType(), name)?.SetValue(target, value); } private static void Call(object target, string name, params object[] args) { AccessTools.Method(target.GetType(), name, (Type[])null, (Type[])null)?.Invoke(target, args); } } [HarmonyPatch(typeof(WindChillZone), "AddWindForceToCharacter")] internal static class BetterFpsWindCharacterPatch { private static bool Prefix(Character character) { if (!EntityPerformanceSettings.SkipRemoteCharacterWind || !Object.op_Implicit((Object)(object)character)) { return true; } return character.IsLocal; } } [HarmonyPatch(typeof(WindChillZone), "AddWindForceToItem")] internal static class BetterFpsWindItemPatch { private static bool Prefix() { return !EntityPerformanceSettings.SkipItemWind; } } [HarmonyPatch] internal static class DeadScoutColliderOptimizationPatches { [HarmonyPatch(typeof(Character), "Start")] [HarmonyPostfix] private static void CharacterStartPostfix(Character __instance) { if (Object.op_Implicit((Object)(object)__instance) && Object.op_Implicit((Object)(object)__instance.data) && __instance.data.dead) { DeadScoutColliderOptimizationSettings.ApplyForDeath(__instance); } } [HarmonyPatch(typeof(Character), "RPCA_Die")] [HarmonyPostfix] private static void CharacterDiePostfix(Character __instance) { DeadScoutColliderOptimizationSettings.ApplyForDeath(__instance); } [HarmonyPatch(typeof(Character), "RPCA_SetDead")] [HarmonyPostfix] private static void CharacterSetDeadPostfix(Character __instance) { DeadScoutColliderOptimizationSettings.ApplyForDeath(__instance); } [HarmonyPatch(typeof(Character), "SetDeadAfterReconnect")] [HarmonyPostfix] private static void CharacterSetDeadAfterReconnectPostfix(Character __instance) { DeadScoutColliderOptimizationSettings.ApplyForDeath(__instance); } [HarmonyPatch(typeof(Character), "RPCA_Revive")] [HarmonyPrefix] private static void CharacterRevivePrefix(Character __instance) { DeadScoutColliderOptimizationSettings.ApplyForRevive(__instance); } [HarmonyPatch(typeof(Character), "RPCA_ReviveAtPosition")] [HarmonyPrefix] private static void CharacterReviveAtPositionPrefix(Character __instance) { DeadScoutColliderOptimizationSettings.ApplyForRevive(__instance); } } [HarmonyPatch(typeof(Mob), "Update")] internal static class DistantMobCullPatch { private static bool Prefix(Mob __instance) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) if (!EntityPerformanceSettings.CullDistantMobs || !Object.op_Implicit((Object)(object)__instance)) { return true; } Camera main = Camera.main; if (!Object.op_Implicit((Object)(object)main)) { return true; } return Vector3.Distance(((Component)__instance).transform.position, ((Component)main).transform.position) <= Mathf.Max(1f, EntityPerformanceSettings.MobCullDistance); } } [HarmonyPatch(typeof(ExplosionEffect), "Start")] internal static class ExplosionEffectStartPatch { private static void Prefix(ExplosionEffect __instance) { if (VisualsRuntimeSettings.SkipExplosionPlume && Object.op_Implicit((Object)(object)__instance)) { __instance.explosionPointCount = 0; __instance.subExplosionPointCount = 0; StopLocalParticles((Component)(object)__instance); } } private static void StopLocalParticles(Component root) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)root)) { return; } ParticleSystem[] componentsInChildren = root.GetComponentsInChildren(true); foreach (ParticleSystem val in componentsInChildren) { if (Object.op_Implicit((Object)(object)val)) { EmissionModule emission = val.emission; ((EmissionModule)(ref emission)).enabled = false; val.Stop(true, (ParticleSystemStopBehavior)0); } } } } [HarmonyPatch(typeof(Dynamite), "RPC_Explode")] internal static class DynamiteExplodeSmokePatch { private static void Prefix(Dynamite __instance) { if (VisualsRuntimeSettings.SkipExplosionPlume && Object.op_Implicit((Object)(object)__instance)) { __instance.smokeVFXPrefab = null; } } } } namespace CubeX.Patches.Self.ReachPatches { [HarmonyPatch(typeof(CharacterGrabbing), "Reach")] internal static class PullDistanceReachPatch { private static bool Prefix(Character ___character) { try { return !PullDistanceRuntime.TryRunReach(___character); } catch { return true; } } } } namespace CubeX.Patches.Network { [HarmonyPatch(typeof(MagicBean), "Update")] internal static class MagicBeanNonHostGrowPatch { [CompilerGenerated] private sealed class d__0 : IEnumerable, IEnumerable, IEnumerator, IEnumerator, IDisposable { private int <>1__state; private CodeInstruction <>2__current; private int <>l__initialThreadId; private IEnumerable instructions; public IEnumerable <>3__instructions; private MethodInfo 5__2; private bool 5__3; private IEnumerator <>7__wrap3; CodeInstruction IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__0(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || (uint)(num - 1) <= 1u) { try { } finally { <>m__Finally1(); } } 5__2 = null; <>7__wrap3 = null; <>1__state = -2; } private bool MoveNext() { //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Expected O, but got Unknown try { switch (<>1__state) { default: return false; case 0: <>1__state = -1; 5__2 = AccessTools.PropertyGetter(typeof(PhotonNetwork), "IsMasterClient"); 5__3 = false; <>7__wrap3 = instructions.GetEnumerator(); <>1__state = -3; break; case 1: <>1__state = -3; break; case 2: <>1__state = -3; break; } if (<>7__wrap3.MoveNext()) { CodeInstruction current = <>7__wrap3.Current; if (!5__3 && CodeInstructionExtensions.Calls(current, 5__2)) { 5__3 = true; CodeInstruction val = new CodeInstruction(OpCodes.Ldc_I4_1, (object)null); val.labels.AddRange(current.labels); val.blocks.AddRange(current.blocks); <>2__current = val; <>1__state = 1; return true; } <>2__current = current; <>1__state = 2; return true; } <>m__Finally1(); <>7__wrap3 = null; if (!5__3) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)"[MagicBean] Failed to patch non-host grow check."); } } return false; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; if (<>7__wrap3 != null) { <>7__wrap3.Dispose(); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { d__0 d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; d__ = this; } else { d__ = new d__0(0); } d__.instructions = <>3__instructions; return d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)this).GetEnumerator(); } } [IteratorStateMachine(typeof(d__0))] private static IEnumerable Transpiler(IEnumerable instructions) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__0(-2) { <>3__instructions = instructions }; } } [HarmonyPatch(typeof(Character), "RPCA_ReviveAtPosition")] internal static class StatueReviveNetworkSyncPatch { private static void Postfix(Character __instance, Vector3 position, bool applyStatus, int statueSegment) { if (statueSegment >= 0 && IsLocalCharacter(__instance)) { LocalNetworkStateResync.Schedule("statue revive"); } } private static bool IsLocalCharacter(Character character) { if (!Object.op_Implicit((Object)(object)character)) { return false; } Character localCharacter = Character.localCharacter; if (Object.op_Implicit((Object)(object)localCharacter) && localCharacter == character) { return true; } try { if (character.IsLocal) { return true; } } catch { } PhotonView val = character.refs?.view; if (!Object.op_Implicit((Object)(object)val)) { val = ((Component)character).GetComponent() ?? ((Component)character).GetComponentInChildren(); } if (Object.op_Implicit((Object)(object)val)) { return val.IsMine; } return false; } } } namespace CubeX.Patches.Misc { [HarmonyPatch] internal static class DisableClientSideTimeoutPatch { [CompilerGenerated] private sealed class d__1 : IEnumerable, IEnumerable, IEnumerator, IEnumerator, IDisposable { private int <>1__state; private MethodBase <>2__current; private int <>l__initialThreadId; MethodBase IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__1(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { MethodBase methodBase2; switch (<>1__state) { default: return false; case 0: { <>1__state = -1; MethodBase methodBase = FindPhotonMethod("ExitGames.Client.Photon.EnetPeer", "SendOutgoingCommands"); if (methodBase != null) { <>2__current = methodBase; <>1__state = 1; return true; } goto IL_0052; } case 1: <>1__state = -1; goto IL_0052; case 2: { <>1__state = -1; break; } IL_0052: methodBase2 = FindPhotonMethod("ExitGames.Client.Photon.TPeer", "DispatchIncomingCommands"); if (methodBase2 != null) { <>2__current = methodBase2; <>1__state = 2; return true; } break; } 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(); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; return this; } return new d__1(0); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)this).GetEnumerator(); } } private const int TimeoutDisconnectStatus = 1040; [IteratorStateMachine(typeof(d__1))] private static IEnumerable TargetMethods() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__1(-2); } private static IEnumerable Transpiler(IEnumerable instructions, MethodBase original) { //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Expected O, but got Unknown List list = instructions.ToList(); MethodInfo methodInfo = AccessTools.Method(typeof(DisableClientSideTimeoutPatch), "ShouldRunTimeoutHandler", (Type[])null, (Type[])null); MethodInfo methodInfo2 = FindPhotonMethod("ExitGames.Client.Photon.PeerBase", "EnqueueStatusCallback") as MethodInfo; if (methodInfo == null || methodInfo2 == null) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Disable Client Timeout] Could not resolve timeout patch helpers for " + FormatMethodName(original) + ".")); } return list; } int num = FindTimeoutStatusCallback(list, methodInfo2); if (num < 0) { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogWarning((object)("[Disable Client Timeout] Could not find timeout status callback in " + FormatMethodName(original) + ".")); } return list; } int num2 = FindGuardBranch(list, num); if (num2 < 0) { ManualLogSource log3 = Plugin.Log; if (log3 != null) { log3.LogWarning((object)("[Disable Client Timeout] Could not find timeout handler guard in " + FormatMethodName(original) + ".")); } return list; } list.Insert(num2, new CodeInstruction(OpCodes.Call, (object)methodInfo)); return list; } private static bool ShouldRunTimeoutHandler(bool originalCondition) { if (originalCondition) { return !ClientTimeoutSettings.DisableClientSideTimeout; } return false; } private static MethodBase FindPhotonMethod(string typeName, string methodName) { Type type = AccessTools.TypeByName(typeName); if (!(type == null)) { return AccessTools.Method(type, methodName, (Type[])null, (Type[])null); } return null; } private static int FindTimeoutStatusCallback(IReadOnlyList codes, MethodInfo enqueueStatusCallback) { for (int i = 0; i < codes.Count - 1; i++) { if (IsTimeoutStatusLoad(codes[i]) && codes[i + 1].opcode == OpCodes.Call && object.Equals(codes[i + 1].operand, enqueueStatusCallback)) { return i; } } return -1; } private static int FindGuardBranch(IReadOnlyList codes, int beforeIndex) { Dictionary labelTargets = BuildLabelTargetMap(codes); for (int num = beforeIndex - 1; num > 0; num--) { if (IsFalseBranch(codes[num].opcode) && IsLoadLocal(codes[num - 1].opcode) && BranchesPastTimeoutCallback(codes[num], beforeIndex, labelTargets)) { return num; } } return -1; } private static Dictionary BuildLabelTargetMap(IReadOnlyList codes) { Dictionary dictionary = new Dictionary(); for (int i = 0; i < codes.Count; i++) { foreach (Label label in codes[i].labels) { dictionary[label] = i; } } return dictionary; } private static bool BranchesPastTimeoutCallback(CodeInstruction branch, int statusIndex, Dictionary labelTargets) { if (branch.operand is Label key && labelTargets.TryGetValue(key, out var value)) { return value > statusIndex; } return false; } private static bool IsTimeoutStatusLoad(CodeInstruction instruction) { //IL_0050: 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_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Invalid comparison between Unknown and I4 if (instruction.opcode == OpCodes.Ldc_I4) { object operand = instruction.operand; if (operand is int && (int)operand == 1040) { return true; } } if (instruction.opcode == OpCodes.Ldc_I4 && instruction.operand is StatusCode val) { return (int)val == 1040; } return false; } private static bool IsFalseBranch(OpCode opcode) { if (!(opcode == OpCodes.Brfalse)) { return opcode == OpCodes.Brfalse_S; } return true; } private static bool IsLoadLocal(OpCode opcode) { if (!(opcode == OpCodes.Ldloc) && !(opcode == OpCodes.Ldloc_S) && !(opcode == OpCodes.Ldloc_0) && !(opcode == OpCodes.Ldloc_1) && !(opcode == OpCodes.Ldloc_2)) { return opcode == OpCodes.Ldloc_3; } return true; } private static string FormatMethodName(MethodBase method) { if (!(method == null)) { return method.DeclaringType?.FullName + "." + method.Name; } return ""; } } [HarmonyPatch] internal static class HighScoutClientUiPatches { private const string VersionScoutMarker = " | Scouts "; private static FieldInfo _versionTextField; [HarmonyPatch(typeof(AudioLevels), "UpdateSliders")] [HarmonyPrefix] private static void AudioLevelsUpdateSlidersPrefix(AudioLevels __instance) { if (__instance?.sliders != null) { EnsureAudioSliders(__instance, GetNeededScoutCount()); } } [HarmonyPatch(typeof(UIPlayerNames), "Init")] [HarmonyPrefix] private static void UIPlayerNamesInitPrefix(UIPlayerNames __instance) { if (__instance?.playerNameText != null) { int value = Traverse.Create((object)__instance).Field("indexCounter").Value; int needed = Mathf.Max(GetNeededScoutCount(), value + 1); __instance.playerNameText = EnsureComponentArray(__instance.playerNameText, needed); } } [HarmonyPatch(typeof(EndScreen), "Initialize")] [HarmonyPrefix] private static void EndScreenInitializePrefix(EndScreen __instance) { EnsureEndScreenCapacity(__instance, GetNeededScoutCount()); } [HarmonyPatch(typeof(PeakHandler), "SetCosmetics")] [HarmonyPrefix] private static void PeakHandlerSetCosmeticsPrefix(PeakHandler __instance, List characters) { int needed = Mathf.Max(GetNeededScoutCount(), characters?.Count ?? 0); EnsureCutsceneScoutCapacity(__instance, needed); } [HarmonyPatch(typeof(VersionString), "Update")] [HarmonyPostfix] private static void VersionStringUpdatePostfix(VersionString __instance) { if (!PhotonNetwork.InRoom) { return; } if ((object)_versionTextField == null) { _versionTextField = AccessTools.Field(typeof(VersionString), "m_text"); } object? obj = _versionTextField?.GetValue(__instance); TextMeshProUGUI val = (TextMeshProUGUI)((obj is TextMeshProUGUI) ? obj : null); if (val != null && Object.op_Implicit((Object)(object)val)) { string text = ((TMP_Text)val).text ?? string.Empty; int num = text.IndexOf(" | Scouts ", StringComparison.Ordinal); if (num >= 0) { text = text.Substring(0, num); } ((TMP_Text)val).text = text + " | Scouts " + MoreScoutsRuntime.GetCurrentScoutCount() + "/" + MoreScoutsRuntime.GetCurrentRoomMax(); } } private static void EnsureAudioSliders(AudioLevels levels, int needed) { if (levels.sliders.Count >= needed || levels.sliders.Count == 0) { return; } AudioLevelSlider val = LastNonNull((IList)levels.sliders); if (!Object.op_Implicit((Object)(object)val)) { return; } while (levels.sliders.Count < needed) { GameObject obj = Object.Instantiate(((Component)val).gameObject, ((Component)val).transform.parent); ((Object)obj).name = ((Object)((Component)val).gameObject).name + "_CubeX_" + levels.sliders.Count; AudioLevelSlider component = obj.GetComponent(); if (Object.op_Implicit((Object)(object)component)) { levels.sliders.Add(component); continue; } break; } } private static void EnsureEndScreenCapacity(EndScreen screen, int needed) { if (Object.op_Implicit((Object)(object)screen) && needed > 0) { screen.scoutWindows = EnsureComponentArray(screen.scoutWindows, needed); screen.scoutLines = EnsureTransformArray(screen.scoutLines, needed); screen.scouts = EnsureComponentArray(screen.scouts, needed); screen.scoutsAtPeak = EnsureComponentArray(screen.scoutsAtPeak, needed); if (Object.op_Implicit((Object)(object)screen.WaitingForPlayersUI)) { screen.WaitingForPlayersUI.scoutImages = EnsureComponentArray(screen.WaitingForPlayersUI.scoutImages, needed); } } } private static void EnsureCutsceneScoutCapacity(PeakHandler handler, int needed) { if (!Object.op_Implicit((Object)(object)handler) || needed <= 0 || (handler.cutsceneScoutRefs != null && handler.cutsceneScoutRefs.Length >= needed && handler.cutsceneScoutAnims != null && handler.cutsceneScoutAnims.Length >= needed)) { return; } List list = new List(handler.cutsceneScoutRefs ?? Array.Empty()); List list2 = new List(handler.cutsceneScoutAnims ?? Array.Empty()); CustomizationRefs val = LastNonNull((IList)list); EndCutsceneScoutHelper val2 = LastNonNull((IList)list2); if (!Object.op_Implicit((Object)(object)val) && !Object.op_Implicit((Object)(object)val2)) { return; } while (list.Count < needed || list2.Count < needed) { int index = Mathf.Max(list.Count, list2.Count); GameObject val3 = (Object.op_Implicit((Object)(object)val) ? ((Component)val).gameObject : ((Component)val2).gameObject); GameObject val4 = Object.Instantiate(val3, val3.transform.parent); ((Object)val4).name = ((Object)val3).name + "_CubeX_" + index; OffsetLapSeat(val4.transform, index); CustomizationRefs val5 = val4.GetComponent() ?? val4.GetComponentInChildren(); EndCutsceneScoutHelper val6 = val4.GetComponent() ?? val4.GetComponentInChildren(); if (!Object.op_Implicit((Object)(object)val5) && Object.op_Implicit((Object)(object)val)) { GameObject val7 = Object.Instantiate(((Component)val).gameObject, ((Component)val).transform.parent); ((Object)val7).name = ((Object)((Component)val).gameObject).name + "_CubeX_" + index; OffsetLapSeat(val7.transform, index); val5 = val7.GetComponent() ?? val7.GetComponentInChildren(); } if (!Object.op_Implicit((Object)(object)val6) && Object.op_Implicit((Object)(object)val2)) { GameObject val8 = Object.Instantiate(((Component)val2).gameObject, ((Component)val2).transform.parent); ((Object)val8).name = ((Object)((Component)val2).gameObject).name + "_CubeX_" + index; OffsetLapSeat(val8.transform, index); val6 = val8.GetComponent() ?? val8.GetComponentInChildren(); } if (list.Count < needed) { list.Add(Object.op_Implicit((Object)(object)val5) ? val5 : val); } if (list2.Count < needed) { list2.Add(Object.op_Implicit((Object)(object)val6) ? val6 : val2); } if (!Object.op_Implicit((Object)(object)val5) && !Object.op_Implicit((Object)(object)val6)) { break; } } handler.cutsceneScoutRefs = list.ToArray(); handler.cutsceneScoutAnims = list2.ToArray(); } private static T[] EnsureComponentArray(T[] source, int needed) where T : Component { if (source == null || source.Length == 0 || source.Length >= needed) { return source; } T val = LastNonNull((IList)source); if (!Object.op_Implicit((Object)(object)val)) { return source; } List list = new List(source); while (list.Count < needed) { GameObject val2 = Object.Instantiate(((Component)val).gameObject, ((Component)val).transform.parent); ((Object)val2).name = ((Object)((Component)val).gameObject).name + "_CubeX_" + list.Count; T val3 = val2.GetComponent() ?? val2.GetComponentInChildren(); if (!Object.op_Implicit((Object)(object)val3)) { break; } list.Add(val3); } return list.ToArray(); } private static Transform[] EnsureTransformArray(Transform[] source, int needed) { return EnsureComponentArray(source, needed); } private static int GetNeededScoutCount() { int num = 1; try { if (PhotonNetwork.PlayerList != null) { num = Mathf.Max(num, PhotonNetwork.PlayerList.Length); } if (PhotonNetwork.CurrentRoom != null) { num = Mathf.Max(num, PhotonNetwork.CurrentRoom.PlayerCount); } } catch { } try { int num2 = 0; if (Character.AllCharacters != null) { foreach (Character allCharacter in Character.AllCharacters) { if (Object.op_Implicit((Object)(object)allCharacter) && !allCharacter.isBot) { num2++; } } } num = Mathf.Max(num, num2); } catch { } return Mathf.Clamp(num, 1, 30); } private static T LastNonNull(IList items) where T : Object { if (items == null) { return default(T); } for (int num = items.Count - 1; num >= 0; num--) { if (Object.op_Implicit((Object)(object)items[num])) { return items[num]; } } return default(T); } private static void OffsetLapSeat(Transform transform, int index) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)transform)) { int num = Mathf.Max(0, index - 4); Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor((num % 2 == 0) ? (-0.16f) : 0.16f, 0.06f * (float)(1 + num / 2), 0.1f * (float)(num % 3 - 1)); transform.localPosition += val; } } } [HarmonyPatch(typeof(CharacterInput), "GetMovementInput")] internal static class MenuInputCapturePatch { private static void Postfix(CharacterInput __instance) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)__instance == (Object)null)) { if (MenuInputCapture.SuppressesMenuEmoteInput) { __instance.emoteIsPressed = false; } if (MenuInputCapture.BlocksPlayerInput) { __instance.movementInput = Vector2.zero; __instance.lookInput = Vector2.zero; __instance.scrollInput = 0f; __instance.crouchIsPressed = false; __instance.crouchWasPressed = false; __instance.crouchToggleWasPressed = false; __instance.sprintIsPressed = false; __instance.sprintToggleIsPressed = false; __instance.sprintWasPressed = false; __instance.sprintToggleWasPressed = false; __instance.jumpWasPressed = false; __instance.jumpIsPressed = false; __instance.interactWasPressed = false; __instance.interactIsPressed = false; __instance.interactWasReleased = false; __instance.dropWasPressed = false; __instance.dropIsPressed = false; __instance.dropWasReleased = false; __instance.usePrimaryWasPressed = false; __instance.usePrimaryIsPressed = false; __instance.usePrimaryWasReleased = false; __instance.useSecondaryWasPressed = false; __instance.useSecondaryIsPressed = false; __instance.useSecondaryWasReleased = false; __instance.pingWasPressed = false; __instance.selectSlotForwardWasPressed = false; __instance.selectSlotBackwardWasPressed = false; __instance.unselectSlotWasPressed = false; __instance.selectBackpackWasPressed = false; __instance.scrollBackwardWasPressed = false; __instance.scrollForwardWasPressed = false; __instance.scrollBackwardIsPressed = false; __instance.scrollForwardIsPressed = false; __instance.emoteIsPressed = false; __instance.spectateLeftWasPressed = false; __instance.spectateRightWasPressed = false; } } } } [HarmonyPatch(typeof(PhotonNetwork), "RPC", new Type[] { typeof(PhotonView), typeof(string), typeof(RpcTarget), typeof(Player), typeof(bool), typeof(object[]) })] internal static class PhotonBufferedRpcStabilityPatch { private static void Prefix(string methodName, ref RpcTarget target) { if (string.Equals(methodName, "RemoveSkeletonRPC", StringComparison.Ordinal)) { if ((int)target == 3) { target = (RpcTarget)0; } else if ((int)target == 6) { target = (RpcTarget)5; } } } } [HarmonyPatch(typeof(VersionString), "Start")] internal static class VersionStringStartPositionPatch { private static void Postfix(VersionString __instance) { TopRightGameHudTextPositioner.Apply(Object.op_Implicit((Object)(object)__instance) ? ((Component)__instance).GetComponentInChildren(true) : null, 12f); } } [HarmonyPatch(typeof(VersionString), "Update")] internal static class VersionStringUpdatePositionPatch { private static void Postfix(VersionString __instance) { TopRightGameHudTextPositioner.Apply(Object.op_Implicit((Object)(object)__instance) ? ((Component)__instance).GetComponentInChildren(true) : null, 12f); } } [HarmonyPatch(typeof(AscentUI), "Start")] internal static class AscentUiStartPositionPatch { private static void Postfix(AscentUI __instance) { TopRightGameHudTextPositioner.Apply(Object.op_Implicit((Object)(object)__instance) ? __instance.text : null, 12f); } } internal static class TopRightGameHudTextPositioner { public static void Apply(TextMeshProUGUI text, float rightPadding) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: 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) //IL_0070: 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_007e: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)text)) { RectTransform rectTransform = ((TMP_Text)text).rectTransform; if (Object.op_Implicit((Object)(object)rectTransform)) { Vector2 anchorMin = rectTransform.anchorMin; Vector2 anchorMax = rectTransform.anchorMax; Vector2 pivot = rectTransform.pivot; Vector2 anchoredPosition = rectTransform.anchoredPosition; anchorMin.x = 1f; anchorMax.x = 1f; pivot.x = 1f; anchoredPosition.x = 0f - Mathf.Abs(rightPadding); rectTransform.anchorMin = anchorMin; rectTransform.anchorMax = anchorMax; rectTransform.pivot = pivot; rectTransform.anchoredPosition = anchoredPosition; ((TMP_Text)text).alignment = (TextAlignmentOptions)516; } } } } [HarmonyPatch] internal static class VersionCompatibilityPatch { private static MethodBase TargetMethod() { Type type = AccessTools.TypeByName("CloudAPI"); if (!(type == null)) { return AccessTools.Method(type, "CheckVersion", (Type[])null, (Type[])null); } return null; } private static bool Prefix(object __0) { if (!CompatibilitySettings.VersionCheckCompatibility) { return true; } if (!(__0 is Delegate @delegate)) { return false; } object obj = CreateVersionOkayResponse(@delegate); try { @delegate.DynamicInvoke(obj); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Version Compatibility] Callback failed: " + ex.Message)); } } return false; } private static object CreateVersionOkayResponse(Delegate callback) { Type callbackParameterType = GetCallbackParameterType(callback); if (callbackParameterType == null) { return null; } object? obj = Activator.CreateInstance(callbackParameterType); SetBooleanMember(obj, "VersionOkay", value: true); return obj; } private static Type GetCallbackParameterType(Delegate callback) { ParameterInfo[] array = callback.GetType().GetMethod("Invoke")?.GetParameters(); if (array == null || array.Length == 0) { return null; } return array[0].ParameterType; } private static void SetBooleanMember(object target, string name, bool value) { if (target == null || string.IsNullOrEmpty(name)) { return; } Type type = target.GetType(); FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null && field.FieldType == typeof(bool)) { field.SetValue(target, value); return; } PropertyInfo property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (property != null && property.CanWrite && property.PropertyType == typeof(bool)) { property.SetValue(target, value, null); } } } } namespace CubeX.Patches.Host { [HarmonyPatch(typeof(AirportCheckInKiosk), "StartGame", new Type[] { typeof(int) })] internal static class HostOnlyKioskStartGamePatch { private static void Prefix() { HostOnlyKioskSettings.MarkHostStartRequested(); } } [HarmonyPatch(typeof(AirportCheckInKiosk), "LoadIslandMaster", new Type[] { typeof(int), typeof(byte[]) })] internal static class HostOnlyKioskLoadIslandMasterPatch { private static bool Prefix() { if (!HostOnlyKioskSettings.ShouldEnforceAsHost) { HostOnlyKioskSettings.ResetHostStartRequest(); return true; } if (HostOnlyKioskSettings.ConsumeHostStartRequest()) { return true; } HostOnlyKioskSettings.NotifyBlockedLoadMaster(); return false; } } [HarmonyPatch] internal static class MoreScoutsPatches { [HarmonyPatch(/*Could not decode attribute arguments.*/)] [HarmonyPostfix] private static void NetworkingUtilitiesMaxPlayersPostfix(ref int __result) { if (MoreScoutsRuntime.Enabled) { __result = MoreScoutsRuntime.ClampedMaxScouts; } } [HarmonyPatch(typeof(NetworkingUtilities), "HostRoomOptions")] [HarmonyPostfix] private static void HostRoomOptionsPostfix(ref RoomOptions __result) { ApplyRoomOptions(__result); } [HarmonyPatch(typeof(PhotonNetwork), "CreateRoom", new Type[] { typeof(string), typeof(RoomOptions), typeof(TypedLobby), typeof(string[]) })] [HarmonyPrefix] private static void PhotonCreateRoomPrefix(RoomOptions roomOptions) { ApplyRoomOptions(roomOptions); } [HarmonyPatch(typeof(PhotonNetwork), "JoinOrCreateRoom", new Type[] { typeof(string), typeof(RoomOptions), typeof(TypedLobby), typeof(string[]) })] [HarmonyPrefix] private static void PhotonJoinOrCreateRoomPrefix(RoomOptions roomOptions) { ApplyRoomOptions(roomOptions); } [HarmonyPatch(typeof(PhotonNetwork), "JoinRandomOrCreateRoom", new Type[] { typeof(Hashtable), typeof(byte), typeof(MatchmakingMode), typeof(TypedLobby), typeof(string), typeof(string), typeof(RoomOptions), typeof(string[]) })] [HarmonyPrefix] private static void PhotonJoinRandomOrCreateRoomPrefix(ref byte expectedMaxPlayers, RoomOptions roomOptions) { if (MoreScoutsRuntime.Enabled) { expectedMaxPlayers = (byte)Mathf.Clamp(MoreScoutsRuntime.ClampedMaxScouts, 1, 255); ApplyRoomOptions(roomOptions); } } [HarmonyPatch(typeof(NetworkConnector), "OnCreatedRoom")] [HarmonyPostfix] private static void NetworkConnectorOnCreatedRoomPostfix() { MoreScoutsRuntime.ApplyCurrentRoomLimit(); } [HarmonyPatch(typeof(NetworkConnector), "OnJoinedRoom")] [HarmonyPostfix] private static void NetworkConnectorOnJoinedRoomPostfix() { MoreScoutsRuntime.ApplyCurrentRoomLimit(); } [HarmonyPatch(typeof(AirportCheckInKiosk), "BeginIslandLoadRPC")] [HarmonyPostfix] private static void AirportCheckInKioskBeginIslandLoadPostfix() { if (MoreScoutsRuntime.Enabled) { MoreScoutsRuntime.CaptureExpeditionScoutCount(); } } [HarmonyPatch(typeof(MapHandler), "InitializeMap")] [HarmonyPrefix] private static void MapHandlerInitializeMapPrefix() { if (MoreScoutsRuntime.Enabled && !MoreScoutsRuntime.HasCapturedExpeditionScoutCount) { MoreScoutsRuntime.CaptureExpeditionScoutCount(); } } [HarmonyPatch(typeof(MapHandler), "SpawnCampfireItems")] [HarmonyPostfix] private static void MapHandlerSpawnCampfireItemsPostfix(GameObject campfireRoot) { MoreScoutsRuntime.SpawnExtraCampfireFood(campfireRoot); } [HarmonyPatch(typeof(GameOverHandler), "BeginAirportLoadRPC")] [HarmonyPostfix] private static void GameOverHandlerBeginAirportLoadPostfix() { if (MoreScoutsRuntime.Enabled) { MoreScoutsRuntime.ClearExpeditionScoutCount(); } } private static void ApplyRoomOptions(RoomOptions options) { if (MoreScoutsRuntime.Enabled && options != null) { options.MaxPlayers = Mathf.Clamp(MoreScoutsRuntime.ClampedMaxScouts, 1, 30); } } } } namespace CubeX.Features.Game { internal static class GameActions { private readonly struct CharacterCandidate { public Character Character { get; } public int Score { get; } public int Order { get; } public CharacterCandidate(Character character, int score, int order) { Character = character; Score = score; Order = order; } } [CompilerGenerated] private sealed class d__35 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public GameObject scoutObject; public Character target; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__35(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = null; <>1__state = 1; return true; case 1: <>1__state = -1; <>2__current = (object)new WaitForSeconds(0.1f); <>1__state = 2; return true; case 2: { <>1__state = -1; if (!Object.op_Implicit((Object)(object)scoutObject) || !Object.op_Implicit((Object)(object)target)) { return false; } Scoutmaster component = scoutObject.GetComponent(); if (!Object.op_Implicit((Object)(object)component)) { return false; } MethodInfo method = typeof(Scoutmaster).GetMethod("SetCurrentTarget", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); try { method?.Invoke(component, new object[2] { target, 15f }); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogError((object)("[Scoutmaster] Failed to set target: " + ex)); } } 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 const BindingFlags InstanceFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; private const float CharacterCacheInterval = 0.15f; private static readonly List CharacterCache = new List(); private static readonly HashSet CharacterCacheSeen = new HashSet(); private static readonly Dictionary CharacterCachePlayerCandidates = new Dictionary(); private static readonly List CharacterCacheUnownedCandidates = new List(); private static readonly List CharacterCacheSortedCandidates = new List(); private static float _nextCharacterCacheRefreshAt; private static int _lastCharacterCacheRefreshFrame = -1; public static bool TryGetLocalCharacter(out Character character) { character = Character.localCharacter; return IsAlive(character); } private static bool IsAlive(Character character) { if (Object.op_Implicit((Object)(object)character)) { if (Object.op_Implicit((Object)(object)character.data)) { return !character.data.dead; } return true; } return false; } public static IEnumerable GetCharacters() { RefreshCharacterCacheIfNeeded(); return CharacterCache; } private static void RefreshCharacterCacheIfNeeded() { int frameCount = Time.frameCount; if (_lastCharacterCacheRefreshFrame != frameCount) { if (Time.unscaledTime < _nextCharacterCacheRefreshAt) { PruneCharacterCache(); _lastCharacterCacheRefreshFrame = frameCount; } else { RebuildCharacterCache(); _lastCharacterCacheRefreshFrame = frameCount; _nextCharacterCacheRefreshAt = Time.unscaledTime + 0.15f; } } } private static void PruneCharacterCache() { for (int num = CharacterCache.Count - 1; num >= 0; num--) { if (!Object.op_Implicit((Object)(object)CharacterCache[num])) { CharacterCache.RemoveAt(num); } } } private static void RebuildCharacterCache() { CharacterCache.Clear(); CharacterCacheSeen.Clear(); CharacterCachePlayerCandidates.Clear(); CharacterCacheUnownedCandidates.Clear(); CharacterCacheSortedCandidates.Clear(); int order = 0; AddCharacterCandidates(GetPlayerHandlerCharacters(), 3000); AddCharacterCandidates(Character.AllCharacters, 2000); Character[] source2; try { source2 = Object.FindObjectsByType((FindObjectsSortMode)0); } catch { source2 = Array.Empty(); } AddCharacterCandidates(source2, 1000); foreach (CharacterCandidate value2 in CharacterCachePlayerCandidates.Values) { CharacterCacheSortedCandidates.Add(value2); } CharacterCacheSortedCandidates.Sort(CompareCharacterCandidatesByOrder); CharacterCacheUnownedCandidates.Sort(CompareCharacterCandidatesByOrder); for (int i = 0; i < CharacterCacheSortedCandidates.Count; i++) { AddCachedCharacter(CharacterCacheSortedCandidates[i].Character); } for (int j = 0; j < CharacterCacheUnownedCandidates.Count; j++) { AddCachedCharacter(CharacterCacheUnownedCandidates[j].Character); } void AddCharacterCandidates(IEnumerable source, int sourceScore) { if (source == null) { return; } foreach (Character item in source) { if (Object.op_Implicit((Object)(object)item)) { int instanceID = ((Object)item).GetInstanceID(); if (CharacterCacheSeen.Add(instanceID)) { int actorNumber = GetActorNumber((Component)(object)item); int characterScore = GetCharacterScore(item, sourceScore); CharacterCandidate characterCandidate = new CharacterCandidate(item, characterScore, order++); CharacterCandidate value; if (actorNumber <= 0) { CharacterCacheUnownedCandidates.Add(characterCandidate); } else if ((!PhotonNetwork.InRoom || IsActorInCurrentRoom(actorNumber)) && (!CharacterCachePlayerCandidates.TryGetValue(actorNumber, out value) || characterCandidate.Score > value.Score)) { CharacterCachePlayerCandidates[actorNumber] = characterCandidate; } } } } } } private static void AddCachedCharacter(Character character) { if (Object.op_Implicit((Object)(object)character)) { CharacterCache.Add(character); } } private static int CompareCharacterCandidatesByOrder(CharacterCandidate a, CharacterCandidate b) { return a.Order.CompareTo(b.Order); } private static IEnumerable GetPlayerHandlerCharacters() { try { return PlayerHandler.GetAllPlayerCharacters(); } catch { return null; } } private static int GetActorNumber(Component component) { PhotonView photonView = GetPhotonView(component); if (!Object.op_Implicit((Object)(object)photonView)) { return -1; } try { if (photonView.ControllerActorNr > 0) { return photonView.ControllerActorNr; } } catch { } try { if (photonView.Controller != null && photonView.Controller.ActorNumber > 0) { return photonView.Controller.ActorNumber; } } catch { } try { if (photonView.OwnerActorNr > 0) { return photonView.OwnerActorNr; } } catch { } try { if (photonView.Owner != null && photonView.Owner.ActorNumber > 0) { return photonView.Owner.ActorNumber; } } catch { } return -1; } private static bool IsActorInCurrentRoom(int actorNumber) { if (actorNumber <= 0) { return false; } try { if (PhotonNetwork.CurrentRoom != null && PhotonNetwork.CurrentRoom.Players != null && PhotonNetwork.CurrentRoom.Players.ContainsKey(actorNumber)) { return true; } } catch { } try { return PhotonNetwork.PlayerList != null && PhotonNetwork.PlayerList.Any((Player player) => player != null && player.ActorNumber == actorNumber); } catch { return false; } } private static int GetCharacterScore(Character character, int sourceScore) { //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)character)) { return int.MinValue; } int num = sourceScore; Character localCharacter = Character.localCharacter; if (Object.op_Implicit((Object)(object)localCharacter) && character == localCharacter) { num += 100000; } try { if (((Component)character).gameObject.activeInHierarchy) { num += 10000; } } catch { } try { if (character.IsLocal) { num += 5000; } } catch { } try { if (character.IsRegisteredToPlayer) { num += 4000; } } catch { } PhotonView photonView = GetPhotonView((Component)(object)character); if (Object.op_Implicit((Object)(object)photonView)) { num += 1000; try { if (photonView.IsMine) { num += 5000; } } catch { } try { if (photonView.Controller != null) { num += 500; } } catch { } try { if (photonView.Owner != null) { num += 300; } } catch { } try { if (Object.op_Implicit((Object)(object)character.refs?.view) && character.refs.view == photonView) { num += 250; } } catch { } } try { if (Object.op_Implicit((Object)(object)character.data)) { num += 500; if (!character.data.dead) { num += 150; } if (character.data.currentStamina > 0.001f) { num += 25; } } } catch { } if (Object.op_Implicit((Object)(object)localCharacter) && character != localCharacter) { try { float num2 = Vector3.Distance(((Component)localCharacter).transform.position, ((Component)character).transform.position); if (!float.IsNaN(num2) && !float.IsInfinity(num2)) { num -= Mathf.RoundToInt(Mathf.Clamp(num2 * 0.02f, 0f, 250f)); } } catch { } } return num; } public static bool WarpLocalToPosition(Vector3 position) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) if (TryGetLocalCharacter(out var character)) { return WarpCharacter(character, position); } return false; } public static bool WarpCharacter(Character character, Vector3 position) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)character)) { return false; } PhotonView photonView = GetPhotonView((Component)(object)character); if (Object.op_Implicit((Object)(object)photonView)) { photonView.RPC("WarpPlayerRPC", (RpcTarget)0, new object[2] { position, true }); return true; } MoveTransform(character, position); return true; } public static bool KillCharacter(Character character) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)character)) { return false; } PhotonView photonView = GetPhotonView((Component)(object)character); if (!Object.op_Implicit((Object)(object)photonView)) { return false; } photonView.RPC("RPCA_Die", (RpcTarget)0, new object[1] { ((Component)character).transform.position }); return true; } public static bool ReviveCharacter(Character character) { if (!Object.op_Implicit((Object)(object)character)) { return false; } PhotonView photonView = GetPhotonView((Component)(object)character); if (!Object.op_Implicit((Object)(object)photonView)) { return false; } photonView.RPC("RPCA_Revive", (RpcTarget)0, new object[1] { false }); return true; } public static bool OpenLuggage(Luggage luggage) { if (!Object.op_Implicit((Object)(object)luggage)) { return false; } PhotonView component = ((Component)luggage).GetComponent(); if (!Object.op_Implicit((Object)(object)component)) { return false; } component.RPC("OpenLuggageRPC", (RpcTarget)0, new object[1] { true }); return true; } public static bool AssignInventoryItem(int slot, Item item) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown Player localPlayer = Player.localPlayer; if (!Object.op_Implicit((Object)(object)localPlayer) || localPlayer.itemSlots == null) { return false; } if (slot < 0 || slot >= localPlayer.itemSlots.Length) { return false; } if (!Object.op_Implicit((Object)(object)item)) { return false; } ItemSlot obj = localPlayer.itemSlots[slot]; obj.prefab = item; obj.data = new ItemInstanceData(Guid.NewGuid()); ItemInstanceDataHandler.AddInstanceData(obj.data); SyncInventory(localPlayer); return true; } public static bool RechargeInventorySlot(int slot) { Player localPlayer = Player.localPlayer; if (!Object.op_Implicit((Object)(object)localPlayer) || localPlayer.itemSlots == null) { return false; } if (slot < 0 || slot >= localPlayer.itemSlots.Length) { return false; } ItemSlot itemSlot = localPlayer.itemSlots[slot]; bool num = RechargeItemSlotData(itemSlot, createUseData: true) | RechargeMatchingHeldItemData(itemSlot); if (num) { SyncInventory(localPlayer); } return num; } public static bool RechargeItemSlotData(ItemSlot itemSlot, bool createUseData) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown if (itemSlot == null || !Object.op_Implicit((Object)(object)itemSlot.prefab)) { return false; } if (itemSlot.data == null) { itemSlot.data = new ItemInstanceData(Guid.NewGuid()); } if (itemSlot.data.data == null) { return false; } bool flag = false; int value = Mathf.Max(1, itemSlot.prefab.totalUses); if (itemSlot.prefab.totalUses > 0) { flag |= SetOptionableInt(itemSlot.data, (DataEntryKey)2, value, createUseData); flag |= SetFloat(itemSlot.data, (DataEntryKey)11, 1f, createUseData); } if (TryGetFuelRechargeValue(itemSlot.prefab, out var value2)) { flag |= SetFloat(itemSlot.data, (DataEntryKey)10, value2, createUseData); flag |= SetFloat(itemSlot.data, (DataEntryKey)11, 1f, createUseData); } else { flag |= SetExistingFloat(itemSlot.data, (DataEntryKey)10, 1f); } flag |= SetExistingInt(itemSlot.data, (DataEntryKey)12, value); return flag | SetExistingFloat(itemSlot.data, (DataEntryKey)11, 1f); } public static bool RechargeHeldItemData(Item item) { if (!Object.op_Implicit((Object)(object)item)) { return false; } bool flag = false; int num = Mathf.Max(1, item.totalUses); if (item.totalUses > 0) { OptionableIntItemData data = item.GetData((DataEntryKey)2); if (data != null) { if (!data.HasData) { data.HasData = true; flag = true; } if (data.Value < num) { data.Value = num; flag = true; } } flag |= SetHeldUseRemainingPercentage(item, 1f); } if (TryGetFuelRechargeValue(item, out var value)) { flag |= SetHeldFloat(item, (DataEntryKey)10, value); flag |= SetHeldUseRemainingPercentage(item, 1f); RefreshHeldFuelComponent(item, value); } else { flag |= SetHeldExistingFloat(item, (DataEntryKey)10, 1f); } return flag | SetHeldUseRemainingPercentage(item, 1f); } public static List FindItemPrefabs() { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) List list = new List(); Object[] array = Resources.FindObjectsOfTypeAll(typeof(Item)); foreach (Object obj in array) { Item val = (Item)(object)((obj is Item) ? obj : null); if (val != null && Object.op_Implicit((Object)(object)val)) { Scene scene = ((Component)val).gameObject.scene; if (((Scene)(ref scene)).handle == 0 && string.IsNullOrEmpty(((Scene)(ref scene)).name)) { list.Add(val); } } } list.Sort((Item a, Item b) => string.Compare(GetItemName(a), GetItemName(b), StringComparison.OrdinalIgnoreCase)); return list; } public static string GetItemName(Item item) { if (!Object.op_Implicit((Object)(object)item)) { return "None"; } try { string name = item.GetName(); return string.IsNullOrEmpty(name) ? ((Object)item).name : name; } catch { return ((Object)item).name; } } public static string GetCurrentSlotItemName(int slot) { Player localPlayer = Player.localPlayer; if (!Object.op_Implicit((Object)(object)localPlayer) || localPlayer.itemSlots == null) { return "None"; } if (slot < 0 || slot >= localPlayer.itemSlots.Length) { return "None"; } return GetItemName(localPlayer.itemSlots[slot]?.prefab); } public static void SpawnScoutmasterFor(Character target) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: 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) //IL_006e: 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_0075: Unknown result type (might be due to invalid IL or missing references) RaycastHit val = default(RaycastHit); if (Object.op_Implicit((Object)(object)target) && PhotonNetwork.IsMasterClient && Physics.Raycast(((Component)target).transform.position + new Vector3(Random.Range(-10f, 10f), 25f, Random.Range(-10f, 10f)), Vector3.down, ref val, 100f, -1)) { Vector3 val2 = ((RaycastHit)(ref val)).point + Vector3.up; GameObject val3 = PhotonNetwork.InstantiateRoomObject("Character_Scoutmaster", val2, Quaternion.identity, (byte)0, (object[])null); Character val4 = (Object.op_Implicit((Object)(object)val3) ? val3.GetComponent() : null); if (Object.op_Implicit((Object)(object)val4) && Object.op_Implicit((Object)(object)val4.data)) { val4.data.spawnPoint = ((Component)val4).transform; } if (Object.op_Implicit((Object)(object)Plugin.Instance)) { ((MonoBehaviour)Plugin.Instance).StartCoroutine(SetScoutmasterTargetNextFrame(val3, target)); } } } [IteratorStateMachine(typeof(d__35))] private static IEnumerator SetScoutmasterTargetNextFrame(GameObject scoutObject, Character target) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__35(0) { scoutObject = scoutObject, target = target }; } private static PhotonView GetPhotonView(Component component) { if (!Object.op_Implicit((Object)(object)component)) { return null; } return component.GetComponent() ?? component.GetComponentInChildren(); } private static void MoveTransform(Character character, Vector3 position) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) Rigidbody val = ((Component)character).GetComponent() ?? ((Component)character).GetComponentInChildren(); if (Object.op_Implicit((Object)(object)val)) { val.linearVelocity = Vector3.zero; val.angularVelocity = Vector3.zero; val.position = position; } else { ((Component)character).transform.position = position; } } private static void SyncInventory(Player player) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)player)) { PhotonView photonView = GetPhotonView((Component)(object)player); if (Object.op_Implicit((Object)(object)photonView)) { byte[] array = IBinarySerializable.ToManagedArray(new InventorySyncData(player.itemSlots, player.backpackSlot, player.tempFullSlot)); photonView.RPC("SyncInventoryRPC", (RpcTarget)1, new object[2] { array, true }); } } } public static void SyncLocalInventory() { SyncInventory(Player.localPlayer); } private static bool RechargeMatchingHeldItemData(ItemSlot itemSlot) { if (itemSlot == null) { return false; } Character localCharacter = Character.localCharacter; if (!Object.op_Implicit((Object)(object)localCharacter) || !Object.op_Implicit((Object)(object)localCharacter.data) || !Object.op_Implicit((Object)(object)localCharacter.data.currentItem)) { return false; } Item currentItem = localCharacter.data.currentItem; if (currentItem.data != null && itemSlot.data != null && currentItem.data == itemSlot.data) { return RechargeHeldItemData(currentItem); } return false; } private static bool TryGetFuelRechargeValue(Item item, out float value) { value = 0f; if (!Object.op_Implicit((Object)(object)item)) { return false; } try { MagicBugle val = default(MagicBugle); if (((Component)item).TryGetComponent(ref val)) { return TryUseFuelValue(Mathf.Max(val.totalTootTime, val.initialTootCost), out value); } Lantern val2 = default(Lantern); if (((Component)item).TryGetComponent(ref val2)) { return TryUseFuelValue(val2.startingFuel, out value); } Dynamite val3 = default(Dynamite); if (((Component)item).TryGetComponent(ref val3)) { return TryUseFuelValue(val3.startingFuseTime, out value); } RopeSpool val4 = default(RopeSpool); if (((Component)item).TryGetComponent(ref val4)) { return TryUseFuelValue(val4.ropeStartFuel, out value); } } catch { value = 0f; } return false; } private static bool TryUseFuelValue(float candidate, out float value) { value = candidate; if (candidate > 0f && !float.IsNaN(candidate)) { return !float.IsInfinity(candidate); } return false; } private static void RefreshHeldFuelComponent(Item item, float value) { if (!Object.op_Implicit((Object)(object)item)) { return; } try { MagicBugle target = default(MagicBugle); Lantern target2 = default(Lantern); Dynamite target3 = default(Dynamite); RopeSpool target4 = default(RopeSpool); if (((Component)item).TryGetComponent(ref target)) { SetPrivateFloat(target, "fuel", value); } else if (((Component)item).TryGetComponent(ref target2)) { SetPrivateFloat(target2, "fuel", value); } else if (((Component)item).TryGetComponent(ref target3)) { SetPrivateFloat(target3, "fuseTime", value); } else if (((Component)item).TryGetComponent(ref target4)) { SetPrivateFloat(target4, "ropeFuel", value); } item.SetUseRemainingPercentage(1f); } catch { } } private static void SetPrivateFloat(object target, string fieldName, float value) { (target?.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))?.SetValue(target, value); } private static bool SetOptionableInt(ItemInstanceData data, DataEntryKey key, int value, bool create) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) OptionableIntItemData val = default(OptionableIntItemData); if (!data.TryGetDataEntry(key, ref val)) { if (!create) { return false; } val = data.RegisterNewEntry(key); } bool result = false; if (!val.HasData) { val.HasData = true; result = true; } if (val.Value < value) { val.Value = value; result = true; } return result; } private static bool SetFloat(ItemInstanceData data, DataEntryKey key, float value, bool create) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) FloatItemData val = default(FloatItemData); if (!data.TryGetDataEntry(key, ref val)) { if (!create) { return false; } val = data.RegisterNewEntry(key); } if (val.Value >= value) { return false; } val.Value = value; return true; } private static bool SetExistingInt(ItemInstanceData data, DataEntryKey key, int value) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) IntItemData entry = default(IntItemData); if (data.TryGetDataEntry(key, ref entry)) { return SetInt(entry, value); } return false; } private static bool SetExistingFloat(ItemInstanceData data, DataEntryKey key, float value) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) FloatItemData entry = default(FloatItemData); if (data.TryGetDataEntry(key, ref entry)) { return SetFloat(entry, value); } return false; } private static bool SetInt(IntItemData entry, int value) { if (entry == null || entry.Value >= value) { return false; } entry.Value = value; return true; } private static bool SetFloat(FloatItemData entry, float value) { if (entry == null || entry.Value >= value) { return false; } entry.Value = value; return true; } private static bool SetHeldFloat(Item item, DataEntryKey key, float value) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) try { return SetFloat(item.GetData(key), value); } catch { return false; } } private static bool SetHeldExistingFloat(Item item, DataEntryKey key, float value) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) try { if (item?.data == null) { return false; } FloatItemData entry = default(FloatItemData); return item.data.TryGetDataEntry(key, ref entry) && SetFloat(entry, value); } catch { return false; } } private static bool SetHeldUseRemainingPercentage(Item item, float value) { if (!Object.op_Implicit((Object)(object)item)) { return false; } try { FloatItemData data = item.GetData((DataEntryKey)11); if (data == null || data.Value >= value) { return false; } item.SetUseRemainingPercentage(value); return true; } catch { return false; } } } } namespace CubeX.Features.World { public class LuggageDirectory : Feature, IMenuRowProvider, IMenuSidePanelProvider { private readonly struct CachedLuggagePosition { public readonly Luggage Luggage; public readonly Vector3 Position; public readonly float ExpiresAt; public CachedLuggagePosition(Luggage luggage, Vector3 position, float expiresAt) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) Luggage = luggage; Position = position; ExpiresAt = expiresAt; } } public sealed class LuggageInfo { public string Id { get; } public Luggage Luggage { get; } public string DisplayName { get; } public string MenuName { get; } public float Distance { get; } public Vector3 Position { get; } public LuggageInfo(string id, Luggage luggage, string displayName, string menuName, float distance, Vector3 position) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) Id = id; Luggage = luggage; DisplayName = displayName; MenuName = menuName; Distance = distance; Position = position; } } private const string WorldCategory = "World/Luggage"; private const string LuggageCategoryPrefix = "World/Luggage/"; private const float MaxDistance = 300f; private const float RefreshInterval = 1f; private const float PositionCacheSeconds = 0.5f; private static readonly List _luggage = new List(); private static readonly Dictionary _positionCache = new Dictionary(); private static readonly HashSet _skipCenterLookup = new HashSet(); private static float _nextRefreshAt; public static LuggageInfo SelectedLuggage { get; private set; } public static IReadOnlyList CurrentLuggage { get { RefreshIfNeeded(); return _luggage; } } public LuggageDirectory() { base.Name = "Luggage Directory"; base.Description = "Builds nearby luggage rows for the World menu."; } public IEnumerable GetRows(string category) { RefreshIfNeeded(); if (category == "World/Luggage") { return BuildLuggageRows(); } if (category != null && category.StartsWith("World/Luggage/", StringComparison.Ordinal)) { return BuildLuggageDetailRows(category.Substring("World/Luggage/".Length)); } return Array.Empty(); } public bool TryGetSidePanel(string category, object selectedRow, out MenuSidePanel panel) { //IL_007b: Unknown result type (might be due to invalid IL or missing references) panel = null; RefreshIfNeeded(); string panelLuggageId = GetPanelLuggageId(category, selectedRow); if (string.IsNullOrEmpty(panelLuggageId)) { return false; } LuggageInfo luggageInfo = FindLuggage(panelLuggageId); if (luggageInfo == null) { return false; } SelectedLuggage = luggageInfo; panel = new MenuSidePanel("CONTAINER", luggageInfo.DisplayName, new List { new InfoFeature("Distance", luggageInfo.Distance.ToString("F1", CultureInfo.InvariantCulture) + " m"), new InfoFeature("Position", FormatPosition(luggageInfo.Position)) }); return true; } public static void ForceRefresh() { Refresh(); } private static IEnumerable BuildLuggageRows() { if (_luggage.Count == 0) { return new object[1] { new InfoFeature("Containers", "None", "No nearby luggage was found.") }; } List list = new List(); for (int i = 0; i < _luggage.Count; i++) { LuggageInfo luggageInfo = _luggage[i]; list.Add(new SubmenuFeature(luggageInfo.MenuName, "World/Luggage/" + luggageInfo.Id, "Open actions for " + luggageInfo.DisplayName + ".")); } return list; } private static IEnumerable BuildLuggageDetailRows(string id) { //IL_00a6: Unknown result type (might be due to invalid IL or missing references) LuggageInfo luggageInfo = FindLuggage(id); if (luggageInfo == null) { SelectedLuggage = null; return new object[1] { new InfoFeature("Container", "Not found", "This container is no longer available.") }; } SelectedLuggage = luggageInfo; return new object[6] { new WarpToSelectedLuggage(), new OpenSelectedLuggage(), new SeparatorFeature(), new InfoFeature("Selected", luggageInfo.DisplayName), new InfoFeature("Distance", luggageInfo.Distance.ToString("F1", CultureInfo.InvariantCulture) + " m"), new InfoFeature("Position", FormatPosition(luggageInfo.Position)) }; } private static void RefreshIfNeeded() { if (!(Time.unscaledTime < _nextRefreshAt)) { Refresh(); } } private static void Refresh() { //IL_006d: 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_00e6: Unknown result type (might be due to invalid IL or missing references) _luggage.Clear(); SelectedLuggage = null; Character localCharacter = Character.localCharacter; if (!Object.op_Implicit((Object)(object)localCharacter) || Luggage.ALL_LUGGAGE == null) { _nextRefreshAt = Time.unscaledTime + 1f; return; } List list = new List(); foreach (Luggage item in Luggage.ALL_LUGGAGE) { if (Object.op_Implicit((Object)(object)item) && TryGetLuggagePosition(item, out var position)) { float num = Vector3.Distance(localCharacter.Head, position); if (!(num > 300f)) { string text = (string.IsNullOrEmpty(item.displayName) ? "Unnamed" : item.displayName); list.Add(new LuggageInfo("luggage-" + ((Object)item).GetInstanceID().ToString(CultureInfo.InvariantCulture), item, text, text + " [" + num.ToString("F1", CultureInfo.InvariantCulture) + "m]", num, position)); } } } list.Sort((LuggageInfo a, LuggageInfo b) => a.Distance.CompareTo(b.Distance)); _luggage.AddRange(list); _nextRefreshAt = Time.unscaledTime + 1f; } public static bool TryGetLuggagePosition(Luggage luggage, out Vector3 position) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: 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_0104: 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_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) position = Vector3.zero; if (!Object.op_Implicit((Object)(object)luggage)) { return false; } int instanceID = ((Object)luggage).GetInstanceID(); float unscaledTime = Time.unscaledTime; if (_positionCache.TryGetValue(instanceID, out var value) && (Object)(object)value.Luggage == (Object)(object)luggage && value.ExpiresAt > unscaledTime) { position = value.Position; return true; } if (!_skipCenterLookup.Contains(instanceID)) { try { position = luggage.Center(); if (IsFinite(position)) { CacheLuggagePosition(instanceID, luggage, position, unscaledTime); return true; } _skipCenterLookup.Add(instanceID); } catch (Exception ex) { if (_skipCenterLookup.Add(instanceID)) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogDebug((object)("[Luggage] Center unavailable for " + ((Object)luggage).name + ": " + ex.GetType().Name)); } } } } position = ((Component)luggage).transform.position; if (!IsFinite(position)) { return false; } CacheLuggagePosition(instanceID, luggage, position, unscaledTime); return true; } private static void CacheLuggagePosition(int id, Luggage luggage, Vector3 position, float now) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) _positionCache[id] = new CachedLuggagePosition(luggage, position, now + 0.5f); } private static bool IsFinite(Vector3 value) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) if (!float.IsNaN(value.x) && !float.IsInfinity(value.x) && !float.IsNaN(value.y) && !float.IsInfinity(value.y) && !float.IsNaN(value.z)) { return !float.IsInfinity(value.z); } return false; } private static LuggageInfo FindLuggage(string id) { for (int i = 0; i < _luggage.Count; i++) { if (_luggage[i].Id == id && Object.op_Implicit((Object)(object)_luggage[i].Luggage)) { return _luggage[i]; } } Refresh(); for (int j = 0; j < _luggage.Count; j++) { if (_luggage[j].Id == id && Object.op_Implicit((Object)(object)_luggage[j].Luggage)) { return _luggage[j]; } } return null; } private static string GetPanelLuggageId(string category, object selectedRow) { if (selectedRow is SubmenuFeature submenuFeature && submenuFeature.ChildCategory != null && submenuFeature.ChildCategory.StartsWith("World/Luggage/", StringComparison.Ordinal)) { return submenuFeature.ChildCategory.Substring("World/Luggage/".Length); } if (category != null && category.StartsWith("World/Luggage/", StringComparison.Ordinal)) { return category.Substring("World/Luggage/".Length); } return null; } private static string FormatPosition(Vector3 position) { return position.x.ToString("F1", CultureInfo.InvariantCulture) + ", " + position.y.ToString("F1", CultureInfo.InvariantCulture) + ", " + position.z.ToString("F1", CultureInfo.InvariantCulture); } } public class OpenAllNearbyLuggage : ButtonFeature { public OpenAllNearbyLuggage() { base.Name = "Open All Nearby"; base.Description = "Requests every nearby luggage container to open."; base.ButtonLabel = "Open"; } public override void Execute() { LuggageDirectory.ForceRefresh(); IReadOnlyList currentLuggage = LuggageDirectory.CurrentLuggage; List list = new List(currentLuggage.Count); for (int i = 0; i < currentLuggage.Count; i++) { Luggage luggage = currentLuggage[i].Luggage; if (Object.op_Implicit((Object)(object)luggage)) { list.Add(luggage); } } LuggageOpenRuntime.OpenMany(list, spawnItems: true, "Open Nearby Luggage"); } } public class OpenSelectedLuggage : ButtonFeature { public OpenSelectedLuggage() { base.Name = "Open Container"; base.Description = "Requests the selected container to open."; base.ButtonLabel = "Open"; } public override void Execute() { LuggageDirectory.LuggageInfo selectedLuggage = LuggageDirectory.SelectedLuggage; if ((Object)(object)selectedLuggage?.Luggage != (Object)null) { GameActions.OpenLuggage(selectedLuggage.Luggage); } } } public class RefreshLuggageList : ButtonFeature { public RefreshLuggageList() { base.Name = "Refresh Containers"; base.Description = "Reloads nearby luggage within 300 meters."; base.ButtonLabel = "Refresh"; } public override void Execute() { LuggageDirectory.ForceRefresh(); } } public class WarpToSelectedLuggage : ButtonFeature { public WarpToSelectedLuggage() { base.Name = "Warp To Container"; base.Description = "Warps your character to the selected container."; base.ButtonLabel = "Warp"; } public override void Execute() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: 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_0030: Unknown result type (might be due to invalid IL or missing references) LuggageDirectory.LuggageInfo selectedLuggage = LuggageDirectory.SelectedLuggage; if (!((Object)(object)selectedLuggage?.Luggage == (Object)null)) { GameActions.WarpLocalToPosition(selectedLuggage.Position + Vector3.up * 1.5f); } } } internal static class LuggageOpenRuntime { [CompilerGenerated] private sealed class d__4 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public IReadOnlyList luggage; public bool spawnItems; public string actionName; private int 5__2; private int 5__3; private int 5__4; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__4(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Expected O, but got Unknown int num = <>1__state; if (num != 0) { if (num != 1) { return false; } <>1__state = -1; goto IL_00c5; } <>1__state = -1; 5__2 = 0; 5__3 = 0; 5__4 = 0; goto IL_00d5; IL_00c5: 5__4++; goto IL_00d5; IL_00d5: if (5__4 < luggage.Count) { Luggage val = luggage[5__4]; if (!Object.op_Implicit((Object)(object)val)) { 5__3++; } else if (OpenSingle(val, spawnItems)) { 5__2++; } else { 5__3++; } if (5__4 + 1 < luggage.Count) { <>2__current = (object)new WaitForSecondsRealtime(0.2f); <>1__state = 1; return true; } goto IL_00c5; } _openRoutine = null; NotifyResult(actionName, 5__2, 5__3, luggage.Count); 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 const float OpenDelaySeconds = 0.2f; private static Coroutine _openRoutine; public static void OpenMany(IEnumerable source, bool spawnItems, string actionName) { Luggage[] array = BuildSnapshot(source); if (array.Length == 0) { NotificationSystem.Push(actionName, "No loaded luggage containers were found.", NotificationKind.Warning); return; } if (_openRoutine != null) { NotificationSystem.Push(actionName, "A luggage open batch is already running.", NotificationKind.Warning); return; } if (!Object.op_Implicit((Object)(object)Plugin.Instance)) { OpenImmediate(array, spawnItems, actionName); return; } _openRoutine = ((MonoBehaviour)Plugin.Instance).StartCoroutine(OpenRoutine(array, spawnItems, actionName)); NotificationSystem.Push(actionName, "Opening " + array.Length + " containers over time."); } private static Luggage[] BuildSnapshot(IEnumerable source) { if (source == null) { return Array.Empty(); } List list = new List(); HashSet hashSet = new HashSet(); foreach (Luggage item2 in source) { if (Object.op_Implicit((Object)(object)item2)) { PhotonView photonView = GetPhotonView((Component)(object)item2); int item = (Object.op_Implicit((Object)(object)photonView) ? photonView.ViewID : ((Object)item2).GetInstanceID()); if (hashSet.Add(item)) { list.Add(item2); } } } return list.ToArray(); } [IteratorStateMachine(typeof(d__4))] private static IEnumerator OpenRoutine(IReadOnlyList luggage, bool spawnItems, string actionName) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__4(0) { luggage = luggage, spawnItems = spawnItems, actionName = actionName }; } private static void OpenImmediate(IReadOnlyList luggage, bool spawnItems, string actionName) { int num = 0; int num2 = 0; for (int i = 0; i < luggage.Count; i++) { if (OpenSingle(luggage[i], spawnItems)) { num++; } else { num2++; } } NotifyResult(actionName, num, num2, luggage.Count); } private static bool OpenSingle(Luggage luggage, bool spawnItems) { PhotonView photonView = GetPhotonView((Component)(object)luggage); if (!Object.op_Implicit((Object)(object)photonView)) { return false; } try { photonView.RPC("OpenLuggageRPC", (RpcTarget)0, new object[1] { spawnItems }); return true; } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Open Luggage] " + ex.GetType().Name + ": " + ex.Message)); } return false; } } private static PhotonView GetPhotonView(Component component) { if (!Object.op_Implicit((Object)(object)component)) { return null; } return component.GetComponent() ?? component.GetComponentInParent() ?? component.GetComponentInChildren(); } private static void NotifyResult(string actionName, int success, int failed, int total) { string text = success + "/" + total + " sent"; if (failed > 0) { text = text + ", " + failed + " failed"; } NotificationSystem.Push(actionName, text + ".", (failed == 0) ? NotificationKind.Success : NotificationKind.Warning); } } } namespace CubeX.Features.Visuals { public class HdPeakLodBias : NumberFeature { public HdPeakLodBias() { base.Name = "HD LOD Bias"; base.Description = "Controls how aggressively distant models keep higher detail when HD Peak Quality is enabled."; base.Min = 0.5f; base.Max = 6f; base.Value = HdPeakRuntime.LodBias; base.Step = 0.1f; base.Decimals = 1; base.Unit = "x"; } protected override void OnValueChanged(float newValue) { HdPeakRuntime.LodBias = newValue; } } public class HdPeakQuality : Feature { private bool _captured; private int _textureMipmapLimit; private int _antiAliasing; private AnisotropicFiltering _anisotropicFiltering; private float _lodBias; private float _shadowDistance; private ShadowResolution _shadowResolution; public HdPeakQuality() { base.Name = "HD Peak Quality"; base.Description = "Applies higher texture, antialiasing, anisotropic filtering, shadow, LOD, and camera distance settings."; } protected override void OnEnable() { CaptureOriginals(); HdPeakRuntime.Enabled = true; ApplyQuality(); } protected override void OnDisable() { HdPeakRuntime.Enabled = false; RestoreOriginals(); } public override void OnTick() { ApplyQuality(); } private void CaptureOriginals() { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0048: 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) if (!_captured) { _captured = true; _textureMipmapLimit = QualitySettings.globalTextureMipmapLimit; _antiAliasing = QualitySettings.antiAliasing; _anisotropicFiltering = QualitySettings.anisotropicFiltering; _lodBias = QualitySettings.lodBias; _shadowDistance = QualitySettings.shadowDistance; _shadowResolution = QualitySettings.shadowResolution; } } private static void ApplyQuality() { QualitySettings.globalTextureMipmapLimit = 0; QualitySettings.antiAliasing = 4; QualitySettings.anisotropicFiltering = (AnisotropicFiltering)2; QualitySettings.lodBias = Mathf.Clamp(HdPeakRuntime.LodBias, 0.5f, 6f); QualitySettings.shadowDistance = Mathf.Clamp(HdPeakRuntime.RenderDistance, 100f, 3000f); QualitySettings.shadowResolution = (ShadowResolution)2; Camera[] allCameras = Camera.allCameras; foreach (Camera val in allCameras) { if (Object.op_Implicit((Object)(object)val) && ((Behaviour)val).isActiveAndEnabled) { val.farClipPlane = Mathf.Max(val.farClipPlane, HdPeakRuntime.RenderDistance); } } } private void RestoreOriginals() { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) if (_captured) { QualitySettings.globalTextureMipmapLimit = _textureMipmapLimit; QualitySettings.antiAliasing = _antiAliasing; QualitySettings.anisotropicFiltering = _anisotropicFiltering; QualitySettings.lodBias = _lodBias; QualitySettings.shadowDistance = _shadowDistance; QualitySettings.shadowResolution = _shadowResolution; } } } public class HdPeakRenderDistance : NumberFeature { public HdPeakRenderDistance() { base.Name = "HD Render Distance"; base.Description = "Controls shadow and camera render distance while HD Peak Quality is enabled."; base.Min = 250f; base.Max = 3000f; base.Value = HdPeakRuntime.RenderDistance; base.Step = 50f; base.Decimals = 0; base.Unit = "m"; } protected override void OnValueChanged(float newValue) { HdPeakRuntime.RenderDistance = newValue; } } public class ThirdPersonCamera : Feature { public ThirdPersonCamera() { base.Name = "Third Person"; base.Description = "Moves the local camera behind your character while enabled."; } protected override void OnEnable() { OnTick(); } protected override void OnDisable() { ThirdPersonRuntime.Enabled = false; } public override void OnTick() { ThirdPersonRuntime.Enabled = true; } } public class ThirdPersonDistance : NumberFeature { public ThirdPersonDistance() { base.Name = "Third Person Distance"; base.Description = "Controls how far behind your character the third-person camera sits."; base.Min = 1.2f; base.Max = 8f; base.Value = ThirdPersonRuntime.Distance; base.Step = 0.1f; base.Decimals = 1; base.Unit = "m"; } protected override void OnValueChanged(float newValue) { ThirdPersonRuntime.Distance = newValue; } } public class ThirdPersonHeight : NumberFeature { public ThirdPersonHeight() { base.Name = "Third Person Height"; base.Description = "Controls the vertical offset for the third-person camera."; base.Min = -1f; base.Max = 2f; base.Value = ThirdPersonRuntime.Height; base.Step = 0.05f; base.Decimals = 2; base.Unit = "m"; } protected override void OnValueChanged(float newValue) { ThirdPersonRuntime.Height = newValue; } } public class DisableFog : Feature { private const float ScanInterval = 1f; private float _nextScanAt; protected override void OnEnable() { _nextScanAt = 0f; SetFogActive(active: false); } protected override void OnDisable() { SetFogActive(active: true); } public DisableFog() { base.Name = "Disable Fog"; base.Description = "Disables loaded Post Fog camera quads while enabled."; } public override void OnTick() { if (!(Time.unscaledTime < _nextScanAt)) { _nextScanAt = Time.unscaledTime + 1f; SetFogActive(active: false); } } private static void SetFogActive(bool active) { CameraQuad[] array = Object.FindObjectsByType((FindObjectsInactive)1, (FindObjectsSortMode)0); foreach (CameraQuad val in array) { if (Object.op_Implicit((Object)(object)val) && !(((Object)((Component)val).gameObject).name != "Post Fog") && ((Component)val).gameObject.activeSelf != active) { ((Component)val).gameObject.SetActive(active); } } } } public class ItemTags : WorldTagFeature { public ItemTags() { base.Name = "Item Tags"; base.Description = "Draws item names and distances over loaded world items."; } protected override string BuildLabel(Item target, Character local, Vector3 position) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) string text = (Object.op_Implicit((Object)(object)target) ? target.GetName() : "Item"); if (string.IsNullOrEmpty(text) && Object.op_Implicit((Object)(object)target)) { text = ((Object)target).name; } return text + WorldTagFeature.FormatDistance(local, position); } } public class LuggageTags : WorldTagFeature { public LuggageTags() { base.Name = "Luggage Tags"; base.Description = "Draws luggage names and distances over loaded containers."; } protected override string BuildLabel(Luggage target, Character local, Vector3 position) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) return ((Object.op_Implicit((Object)(object)target) && !string.IsNullOrEmpty(target.displayName)) ? target.displayName : "Luggage") + WorldTagFeature.FormatDistance(local, position); } protected override Vector3 GetWorldPosition(Luggage target) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) if (!LuggageDirectory.TryGetLuggagePosition(target, out var position)) { return Vector3.zero; } return position + Vector3.up * 0.5f; } } public class Watermark : Feature { private GUIStyle _textStyle; private float _smoothedFps; public Watermark() { base.Name = "Watermark"; base.Description = "Draws a compact one-line HUD watermark."; } public override void OnRender() { //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Expected O, but got Unknown //IL_006d: 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_007f: 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_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: 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) //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: 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_01cf: 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) EnsureStyles(); DateTime now = DateTime.Now; string text = "Cube-X | v1.3.2 | " + now.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture) + " | " + now.ToString("HH:mm:ss", CultureInfo.InvariantCulture) + " | " + GetFpsText(); Vector2 val = _textStyle.CalcSize(new GUIContent(text)); Rect val2 = default(Rect); ((Rect)(ref val2))..ctor(12f, 12f, val.x + 24f + 3f + 8f, val.y + 12f); Rect r = new Rect(((Rect)(ref val2)).x, ((Rect)(ref val2)).y, 3f, ((Rect)(ref val2)).height); Rect val3 = default(Rect); ((Rect)(ref val3))..ctor(((Rect)(ref val2)).x + 3f + 8f, ((Rect)(ref val2)).y + 6f, val.x + 2f, val.y); Color c = default(Color); ((Color)(ref c))..ctor(0.035f, 0.036f, 0.04f, 0.86f); Color color = default(Color); ((Color)(ref color))..ctor(1f, 1f, 1f, 0.13f); Color c2 = default(Color); ((Color)(ref c2))..ctor(1f, 1f, 1f, 0.07f); Color textColor = default(Color); ((Color)(ref textColor))..ctor(0.92f, 0.93f, 0.94f, 1f); _textStyle.normal.textColor = textColor; Theme.Fill(val2, c); Theme.Fill(r, Theme.Accent); Theme.Fill(new Rect(((Rect)(ref val2)).x + 3f, ((Rect)(ref val2)).y + 1f, ((Rect)(ref val2)).width - 3f - 1f, 1f), c2); DrawOutline(val2, color, 1f); GUI.Label(val3, text, _textStyle); } private void EnsureStyles() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Expected O, but got Unknown //IL_004a: Expected O, but got Unknown if (_textStyle == null) { _textStyle = new GUIStyle(GUI.skin.label) { alignment = (TextAnchor)3, clipping = (TextClipping)1, fontSize = 13, fontStyle = (FontStyle)1, padding = new RectOffset(0, 0, 0, 0) }; } } private static void DrawOutline(Rect rect, Color color, float thickness) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: 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_0082: Unknown result type (might be due to invalid IL or missing references) Theme.Fill(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, ((Rect)(ref rect)).width, thickness), color); Theme.Fill(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).yMax - thickness, ((Rect)(ref rect)).width, thickness), color); Theme.Fill(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, thickness, ((Rect)(ref rect)).height), color); Theme.Fill(new Rect(((Rect)(ref rect)).xMax - thickness, ((Rect)(ref rect)).y, thickness, ((Rect)(ref rect)).height), color); } private string GetFpsText() { float unscaledDeltaTime = Time.unscaledDeltaTime; float num = ((unscaledDeltaTime > 0.0001f) ? (1f / unscaledDeltaTime) : 0f); _smoothedFps = ((_smoothedFps <= 0f) ? num : Mathf.Lerp(_smoothedFps, num, 0.08f)); return _smoothedFps.ToString("F0", CultureInfo.InvariantCulture) + " FPS"; } } public abstract class WorldTagFeature : Feature where T : Component { private const float ScanInterval = 0.75f; private readonly List _targets = new List(); private GUIStyle _style; private GUIStyle _shadowStyle; private float _nextScanAt; public override void OnRender() { //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) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0071: 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) //IL_008c: 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_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) Camera main = Camera.main; Character localCharacter = Character.localCharacter; if (!Object.op_Implicit((Object)(object)main)) { return; } EnsureStyles(); RefreshTargetsIfNeeded(); Rect val3 = default(Rect); for (int i = 0; i < _targets.Count; i++) { T val = _targets[i]; if (Object.op_Implicit((Object)(object)val)) { Vector3 worldPosition = GetWorldPosition(val); Vector3 val2 = main.WorldToScreenPoint(worldPosition); if (!(val2.z <= 0f)) { val2.y = (float)Screen.height - val2.y; string text = BuildLabel(val, localCharacter, worldPosition); ((Rect)(ref val3))..ctor(val2.x - 90f, val2.y - 14f, 180f, 24f); GUI.Label(new Rect(((Rect)(ref val3)).x + 1f, ((Rect)(ref val3)).y + 1f, ((Rect)(ref val3)).width, ((Rect)(ref val3)).height), text, _shadowStyle); GUI.Label(val3, text, _style); } } } } protected override void OnDisable() { _targets.Clear(); _nextScanAt = 0f; } protected abstract string BuildLabel(T target, Character local, Vector3 position); protected virtual Vector3 GetWorldPosition(T target) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) return ((Component)target).transform.position + Vector3.up * 0.5f; } private void RefreshTargetsIfNeeded() { if (Time.unscaledTime < _nextScanAt) { return; } _nextScanAt = Time.unscaledTime + 0.75f; _targets.Clear(); T[] array = Object.FindObjectsByType((FindObjectsSortMode)0); for (int i = 0; i < array.Length; i++) { if (Object.op_Implicit((Object)(object)array[i])) { _targets.Add(array[i]); } } } private void EnsureStyles() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Expected O, but got Unknown //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_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Expected O, but got Unknown if (_style == null) { GUIStyle val = new GUIStyle(GUI.skin.label) { alignment = (TextAnchor)4, fontSize = 12, fontStyle = (FontStyle)1, clipping = (TextClipping)1 }; val.normal.textColor = Color.white; _style = val; GUIStyle val2 = new GUIStyle(_style); val2.normal.textColor = new Color(0f, 0f, 0f, 0.9f); _shadowStyle = val2; } } protected static string FormatDistance(Character local, Vector3 position) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)local)) { return string.Empty; } return " [" + Vector3.Distance(local.Head, position).ToString("F1", CultureInfo.InvariantCulture) + "m]"; } } public class FootstepLifetime : NumberFeature { public FootstepLifetime() { base.Name = "Footstep Lifetime"; base.Description = "How long footprints remain visible, up to five minutes."; base.Min = 5f; base.Max = 300f; base.Value = FootstepSettings.Lifetime; base.Step = 1f; base.Decimals = 0; base.Unit = "s"; } protected override void OnValueChanged(float newValue) { FootstepSettings.Lifetime = Mathf.Clamp(newValue, base.Min, base.Max); FootstepRuntime.Update(); } } internal static class FootstepRuntime { private readonly struct PlayerFootState { public Vector3 LastPosition { get; } public bool LeftNext { get; } public PlayerFootState(Vector3 lastPosition, bool leftNext) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) LastPosition = lastPosition; LeftNext = leftNext; } } private readonly struct FootprintInstance { public GameObject Holder { get; } public float ExpiresAt { get; } public FootprintInstance(GameObject holder, float expiresAt) { Holder = holder; ExpiresAt = expiresAt; } } private const float SpawnDistance = 0.85f; private const int MaxFootprints = 512; private const float GroundRayHeight = 0.85f; private const float GroundRayDistance = 4f; private static readonly int ColorId = Shader.PropertyToID("_Color"); private static readonly int TintColorId = Shader.PropertyToID("_TintColor"); private static readonly Dictionary PlayerStates = new Dictionary(); private static readonly HashSet Wanted = new HashSet(); private static readonly Queue Footprints = new Queue(); private static readonly RaycastHit[] GroundHits = (RaycastHit[])(object)new RaycastHit[24]; private static MaterialPropertyBlock _propertyBlock; private static Material _material; private static Mesh _mesh; public static void Update() { float unscaledTime = Time.unscaledTime; Prune(unscaledTime); Wanted.Clear(); if (!FootstepSettings.AllPlayers) { ClearAll(); return; } Character localCharacter = Character.localCharacter; foreach (Character character in GameActions.GetCharacters()) { if (Object.op_Implicit((Object)(object)character) && ((Component)character).gameObject.activeInHierarchy && VisualPlayerText.IsRealPlayer(character) && !IsDead(character) && (!FootstepSettings.ExcludeSelf || !Object.op_Implicit((Object)(object)localCharacter) || character != localCharacter)) { int instanceID = ((Object)character).GetInstanceID(); Wanted.Add(instanceID); Track(character, instanceID, unscaledTime); } } RemoveUnwantedStates(); } private static void Track(Character character, int id, float now) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: 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_005a: 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_0075: Unknown result type (might be due to invalid IL or missing references) if (!TryGetGround(character, out var point, out var normal)) { return; } if (!PlayerStates.TryGetValue(id, out var value)) { PlayerStates[id] = new PlayerFootState(point, leftNext: false); return; } Vector3 val = point - value.LastPosition; val.y = 0f; if (!(((Vector3)(ref val)).sqrMagnitude < 0.7225f)) { SpawnFootprint(character, point, normal, ((Vector3)(ref val)).normalized, value.LeftNext, now); PlayerStates[id] = new PlayerFootState(point, !value.LeftNext); } } private static void SpawnFootprint(Character character, Vector3 groundPoint, Vector3 groundNormal, Vector3 forward, bool left, float now) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0043: 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_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: 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_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00af: 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_00b9: 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_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Expected O, but got Unknown //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) Vector3 val = Vector3.ProjectOnPlane(forward, groundNormal); if (((Vector3)(ref val)).sqrMagnitude < 0.01f) { val = Vector3.ProjectOnPlane(((Component)character).transform.forward, groundNormal); } if (((Vector3)(ref val)).sqrMagnitude < 0.01f) { val = Vector3.forward; } ((Vector3)(ref val)).Normalize(); Vector3 val2 = Vector3.Cross(groundNormal, val); Vector3 val3 = ((Vector3)(ref val2)).normalized; if (((Vector3)(ref val3)).sqrMagnitude < 0.01f) { val3 = ((Component)character).transform.right; } float num = Mathf.Clamp(FootstepSettings.Size, 0.45f, 2.5f); float num2 = (left ? (-1f) : 1f); Vector3 val4 = groundPoint + val3 * (0.115f * num2 * num) + groundNormal * 0.025f; Quaternion val5 = Quaternion.LookRotation(val, groundNormal); GameObject val6 = new GameObject("CubeX_Footstep") { hideFlags = (HideFlags)61 }; val6.transform.SetPositionAndRotation(val4, val5); val6.transform.localScale = new Vector3(0.16f * num, 1f, 0.34f * num); val6.AddComponent().sharedMesh = GetMesh(); MeshRenderer obj = val6.AddComponent(); ((Renderer)obj).sharedMaterial = GetMaterial(); ((Renderer)obj).shadowCastingMode = (ShadowCastingMode)0; ((Renderer)obj).receiveShadows = false; ((Renderer)obj).allowOcclusionWhenDynamic = false; SetRendererColor((Renderer)(object)obj, GetPlayerColor(character)); float num3 = Mathf.Clamp(FootstepSettings.Lifetime, 5f, 300f); Footprints.Enqueue(new FootprintInstance(val6, now + num3)); while (Footprints.Count > 512) { DestroyOldest(); } } private static bool TryGetGround(Character character, out Vector3 point, out Vector3 normal) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: 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_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: 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_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) point = default(Vector3); normal = Vector3.up; int num = Physics.RaycastNonAlloc(GetGroundProbeOrigin(character), Vector3.down, GroundHits, 4f, -1, (QueryTriggerInteraction)1); if (num <= 0) { return false; } float num2 = float.MaxValue; int num3 = -1; for (int i = 0; i < num; i++) { RaycastHit val = GroundHits[i]; if (Object.op_Implicit((Object)(object)((RaycastHit)(ref val)).collider) && !Object.op_Implicit((Object)(object)((Component)((RaycastHit)(ref val)).collider).GetComponentInParent()) && !(((RaycastHit)(ref val)).distance >= num2)) { num2 = ((RaycastHit)(ref val)).distance; num3 = i; } } if (num3 < 0) { return false; } RaycastHit val2 = GroundHits[num3]; point = ((RaycastHit)(ref val2)).point; Vector3 normal2 = ((RaycastHit)(ref val2)).normal; normal = ((((Vector3)(ref normal2)).sqrMagnitude > 0.01f) ? ((RaycastHit)(ref val2)).normal : Vector3.up); return true; } private static Vector3 GetGroundProbeOrigin(Character character) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: 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) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_002a: 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_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: 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_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0048: 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_0081: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0051: 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_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) if (VisualPlayerText.TryGetVisualPosition(character, out var position)) { return position + Vector3.up * 0.85f; } if (TryGetAverageFootPosition(character, out var position2)) { return position2 + Vector3.up * 0.85f; } try { Vector3 center = character.Center; if (IsFinite(center)) { return center + Vector3.up * 0.85f; } } catch { } try { Vector3 head = character.Head; if (IsFinite(head)) { return head + Vector3.down * 1.4f + Vector3.up * 0.85f; } } catch { } return ((Component)character).transform.position + Vector3.up * 0.85f; } private static bool IsDead(Character character) { try { return Object.op_Implicit((Object)(object)character) && Object.op_Implicit((Object)(object)character.data) && character.data.dead; } catch { return false; } } private static bool TryGetAverageFootPosition(Character character, out Vector3 position) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) position = default(Vector3); Vector3 sum = Vector3.zero; int count = 0; AddFootPosition(character, (BodypartType)27, ref sum, ref count); AddFootPosition(character, (BodypartType)28, ref sum, ref count); AddFootPosition(character, (BodypartType)13, ref sum, ref count); AddFootPosition(character, (BodypartType)16, ref sum, ref count); if (count <= 0) { return false; } position = sum / (float)count; return IsFinite(position); } private static void AddFootPosition(Character character, BodypartType partType, ref Vector3 sum, ref int count) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) if (TryGetBodypartPosition(character, partType, out var position)) { sum += position; count++; } } private static bool TryGetBodypartPosition(Character character, BodypartType partType, out Vector3 position) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_005c: 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_0067: Unknown result type (might be due to invalid IL or missing references) position = default(Vector3); if (!Object.op_Implicit((Object)(object)character)) { return false; } try { CharacterRagdoll val = character.refs?.ragdoll; if (!Object.op_Implicit((Object)(object)val) || val.partDict == null) { return false; } if (!val.partDict.TryGetValue(partType, out var value) || !Object.op_Implicit((Object)(object)value)) { return false; } position = ((Component)value).transform.position; return IsFinite(position); } catch { return false; } } private static Material GetMaterial() { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Expected O, but got Unknown if (Object.op_Implicit((Object)(object)_material)) { return _material; } _material = new Material(Shader.Find("Hidden/Internal-Colored") ?? Shader.Find("Sprites/Default") ?? Shader.Find("Unlit/Color")) { hideFlags = (HideFlags)61, name = "CubeX_FootstepMaterial", renderQueue = 3000 }; if (_material.HasProperty("_ZWrite")) { _material.SetInt("_ZWrite", 0); } if (_material.HasProperty("_ZTest")) { _material.SetInt("_ZTest", 4); } if (_material.HasProperty("_Cull")) { _material.SetInt("_Cull", 0); } if (_material.HasProperty("_SrcBlend")) { _material.SetInt("_SrcBlend", 5); } if (_material.HasProperty("_DstBlend")) { _material.SetInt("_DstBlend", 10); } return _material; } private static Mesh GetMesh() { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Expected O, but got Unknown //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)_mesh)) { return _mesh; } Vector3[] array = (Vector3[])(object)new Vector3[19]; Vector2[] array2 = (Vector2[])(object)new Vector2[array.Length]; int[] array3 = new int[54]; array[0] = Vector3.zero; array2[0] = new Vector2(0.5f, 0.5f); for (int i = 0; i < 18; i++) { float num = (float)i / 18f * MathF.PI * 2f; float num2 = Mathf.Cos(num) * 0.5f; float num3 = Mathf.Sin(num) * 0.5f; array[i + 1] = new Vector3(num2, 0f, num3); array2[i + 1] = new Vector2(num2 + 0.5f, num3 + 0.5f); } for (int j = 0; j < 18; j++) { int num4 = ((j + 1 == 18) ? 1 : (j + 2)); int num5 = j * 3; array3[num5] = 0; array3[num5 + 1] = num4; array3[num5 + 2] = j + 1; } _mesh = new Mesh { name = "CubeX_FootstepMesh", hideFlags = (HideFlags)61, vertices = array, uv = array2, triangles = array3 }; _mesh.RecalculateNormals(); _mesh.bounds = new Bounds(Vector3.zero, new Vector3(1f, 0.05f, 1f)); return _mesh; } private static void SetRendererColor(Renderer renderer, Color color) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown if (Object.op_Implicit((Object)(object)renderer)) { if (_propertyBlock == null) { _propertyBlock = new MaterialPropertyBlock(); } _propertyBlock.Clear(); _propertyBlock.SetColor(ColorId, color); _propertyBlock.SetColor(TintColorId, color); renderer.SetPropertyBlock(_propertyBlock); } } private static Color GetPlayerColor(Character character) { //IL_0052: 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_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: 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_0080: Unknown result type (might be due to invalid IL or missing references) //IL_008a: 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_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) Color val = default(Color); ((Color)(ref val))..ctor(0.25f, 0.85f, 1f, 1f); try { if (Object.op_Implicit((Object)(object)character) && Object.op_Implicit((Object)(object)character.refs?.customization)) { val = character.refs.customization.PlayerColor; } } catch { } if (val.r * 0.2126f + val.g * 0.7152f + val.b * 0.0722f < 0.25f) { val = Color.Lerp(val, Color.white, 0.35f); } return new Color(val.r, val.g, val.b, 0.68f); } private static void Prune(float now) { while (Footprints.Count > 0) { FootprintInstance footprintInstance = Footprints.Peek(); if (footprintInstance.ExpiresAt > now && Object.op_Implicit((Object)(object)footprintInstance.Holder)) { break; } DestroyOldest(); } } private static void DestroyOldest() { if (Footprints.Count != 0) { FootprintInstance footprintInstance = Footprints.Dequeue(); if (Object.op_Implicit((Object)(object)footprintInstance.Holder)) { Object.Destroy((Object)(object)footprintInstance.Holder); } } } private static void RemoveUnwantedStates() { List list = null; foreach (KeyValuePair playerState in PlayerStates) { if (!Wanted.Contains(playerState.Key)) { if (list == null) { list = new List(); } list.Add(playerState.Key); } } if (list != null) { for (int i = 0; i < list.Count; i++) { PlayerStates.Remove(list[i]); } } } private static void ClearAll() { while (Footprints.Count > 0) { DestroyOldest(); } PlayerStates.Clear(); Wanted.Clear(); } private static bool IsFinite(Vector3 value) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) if (!float.IsNaN(value.x) && !float.IsInfinity(value.x) && !float.IsNaN(value.y) && !float.IsInfinity(value.y) && !float.IsNaN(value.z)) { return !float.IsInfinity(value.z); } return false; } } public class FootSteps : Feature { public FootSteps() { base.Name = "Footsteps: All Players"; base.Description = "Leaves lightweight colored footprints behind every real player."; } protected override void OnEnable() { FootstepSettings.AllPlayers = true; FootstepRuntime.Update(); } protected override void OnDisable() { FootstepSettings.AllPlayers = false; FootstepRuntime.Update(); } public override void OnTick() { FootstepRuntime.Update(); } } internal static class FootstepSettings { public static bool AllPlayers; public static bool ExcludeSelf = true; public static float Lifetime = 300f; public static float Size = 1f; } public class FootstepSize : NumberFeature { public FootstepSize() { base.Name = "Footstep Size"; base.Description = "Scales footprint width and length."; base.Min = 0.45f; base.Max = 2.5f; base.Value = FootstepSettings.Size; base.Step = 0.05f; base.Decimals = 2; base.Unit = "x"; } protected override void OnValueChanged(float newValue) { FootstepSettings.Size = Mathf.Clamp(newValue, base.Min, base.Max); FootstepRuntime.Update(); } } public class FootStepsSelectedPlayer : Feature { public FootStepsSelectedPlayer() { base.Name = "Exclude Self"; base.Description = "Hides your local player footsteps while Footsteps is enabled."; base.Enabled = true; } protected override void OnEnable() { FootstepSettings.ExcludeSelf = true; FootstepRuntime.Update(); } protected override void OnDisable() { FootstepSettings.ExcludeSelf = false; FootstepRuntime.Update(); } public override void OnTick() { FootstepRuntime.Update(); } } public class Fov : NumberBoolFeature { private const float MaxFov = 130f; private bool _capturedDefault; private bool _hasExplicitValue; private float _defaultFov = 60f; private Camera[] _cameraBuffer = (Camera[])(object)new Camera[8]; private readonly Dictionary _defaultFovs = new Dictionary(); public Fov() { base.Name = "FOV"; base.Description = "Toggle custom camera field of view and adjust it from the game's default up to 130 degrees."; base.Min = _defaultFov; base.Max = 130f; base.Value = _defaultFov; base.Step = 1f; base.Decimals = 0; base.Unit = " deg"; } protected override void OnEnable() { FovRuntime.Enabled = true; FovRuntime.Value = Mathf.Clamp(base.Value, base.Min, base.Max); ZoomiesRuntime.Reset(); ApplyToAllCameras(applyConfigured: true); } protected override void OnDisable() { FovRuntime.Enabled = false; ZoomiesRuntime.Reset(); ApplyToAllCameras(applyConfigured: false); } public override void OnTick() { ApplyToAllCameras(applyConfigured: true); } protected override void OnValueChanged(float newValue) { _hasExplicitValue = true; FovRuntime.Value = Mathf.Clamp(newValue, base.Min, base.Max); ZoomiesRuntime.Reset(); if (base.Enabled) { ApplyToAllCameras(applyConfigured: true); } } private void CaptureDefaultIfNeeded(Camera cam) { int instanceID = ((Object)cam).GetInstanceID(); if (_defaultFovs.ContainsKey(instanceID)) { return; } float num = Mathf.Clamp(cam.fieldOfView, 1f, 130f); _defaultFovs[instanceID] = num; if (_capturedDefault) { base.Min = Mathf.Min(base.Min, num); return; } _capturedDefault = true; _defaultFov = num; base.Min = num; if (!_hasExplicitValue) { base.Value = num; } } private void ApplyFov(Camera cam) { if (!_hasExplicitValue && _defaultFovs.TryGetValue(((Object)cam).GetInstanceID(), out var value)) { cam.fieldOfView = value; return; } cam.fieldOfView = Mathf.Clamp(base.Value, base.Min, base.Max); FovRuntime.Value = cam.fieldOfView; } private void RestoreFov(Camera cam) { if (_defaultFovs.TryGetValue(((Object)cam).GetInstanceID(), out var value)) { cam.fieldOfView = value; } } private void ApplyToAllCameras(bool applyConfigured) { int allCamerasCount = Camera.allCamerasCount; if (allCamerasCount <= 0) { return; } EnsureCameraBuffer(allCamerasCount); allCamerasCount = Camera.GetAllCameras(_cameraBuffer); for (int i = 0; i < allCamerasCount; i++) { Camera val = _cameraBuffer[i]; if (Object.op_Implicit((Object)(object)val) && ((Behaviour)val).isActiveAndEnabled) { if (applyConfigured) { CaptureDefaultIfNeeded(val); ApplyFov(val); } else { RestoreFov(val); } } } } private void EnsureCameraBuffer(int count) { if (_cameraBuffer.Length < count) { int num; for (num = _cameraBuffer.Length; num < count; num *= 2) { } _cameraBuffer = (Camera[])(object)new Camera[num]; } } } internal static class FovRuntime { public static bool Enabled; public static float Value = 60f; public static bool TryGetFov(out float fov) { fov = 0f; if (!Enabled) { return false; } fov = Mathf.Clamp(Value, 1f, 130f); return true; } public static float GetBaseFov(float fallback) { if (!Enabled) { return fallback; } return Mathf.Clamp(Value, 1f, 130f); } } public class NumericalHud : NumberBoolFeature { public NumericalHud() { base.Name = "Numerical HUD"; base.Description = "Toggle numbers on PEAK's HUD and adjust their scale."; base.Min = 0.7f; base.Max = 1.6f; base.Value = NumericalHudSettings.Scale; base.Step = 0.05f; base.Decimals = 2; base.Unit = "x"; } protected override void OnEnable() { NumericalHudSettings.Scale = Mathf.Clamp(base.Value, base.Min, base.Max); NumericalHudRuntime.Enabled = true; NumericalHudRuntime.Rebuild(); } protected override void OnDisable() { NumericalHudRuntime.Enabled = false; NumericalHudRuntime.Clear(); } public override void OnTick() { NumericalHudRuntime.Tick(); } protected override void OnValueChanged(float newValue) { NumericalHudSettings.Scale = Mathf.Clamp(newValue, base.Min, base.Max); if (base.Enabled) { NumericalHudRuntime.Rebuild(); } } } public class NumericalHudAfflictions : Feature { public NumericalHudAfflictions() { base.Name = "Numerical HUD Afflictions"; base.Description = "Includes affliction numbers on the existing affliction HUD icons."; base.Enabled = true; } protected override void OnEnable() { NumericalHudSettings.ShowAfflictions = true; NumericalHudRuntime.Rebuild(); } protected override void OnDisable() { NumericalHudSettings.ShowAfflictions = false; NumericalHudRuntime.Rebuild(); } } internal static class NumericalHudRuntime { private sealed class TextBinding { [CompilerGenerated] private GameObject P; [CompilerGenerated] private TextMeshProUGUI P; [CompilerGenerated] private Func P; public bool IsAlive { get { if (Object.op_Implicit((Object)(object)P)) { return Object.op_Implicit((Object)(object)P); } return false; } } public TextBinding(GameObject gameObject, TextMeshProUGUI text, Func update) { P = gameObject; P = text; P = update; base..ctor(); } public void Update() { if (IsAlive) { ((TMP_Text)P).text = P() ?? string.Empty; } } public void Destroy() { if (Object.op_Implicit((Object)(object)P)) { Object.Destroy((Object)(object)P); } } } private const string Prefix = "CubeX_NumericalHud_"; private const BindingFlags ReflectionFlags = BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; private static readonly List Bindings = new List(); private static GUIManager _manager; private static bool _showAfflictions; private static float _scale = -1f; public static bool Enabled; public static void Rebuild() { Clear(); _manager = null; _scale = -1f; } public static void Clear() { foreach (TextBinding binding in Bindings) { binding.Destroy(); } Bindings.Clear(); DestroyExistingByPrefix(); } public static void Tick() { if (!Enabled) { Clear(); return; } GUIManager instance = GUIManager.instance; StaminaBar val = (Object.op_Implicit((Object)(object)instance) ? instance.bar : null); if (!Object.op_Implicit((Object)(object)instance) || (Object)(object)val == (Object)null || !Object.op_Implicit((Object)(object)instance.hudCanvas)) { Clear(); return; } float num = Mathf.Clamp(NumericalHudSettings.Scale, 0.7f, 1.6f); if ((Object)(object)_manager != (Object)(object)instance || _showAfflictions != NumericalHudSettings.ShowAfflictions || Mathf.Abs(_scale - num) > 0.001f || Bindings.Count == 0 || Bindings.Exists((TextBinding binding) => !binding.IsAlive)) { Build(instance, val, num); } foreach (TextBinding binding in Bindings) { binding.Update(); } } private static void Build(GUIManager manager, StaminaBar staminaBar, float scale) { Clear(); _manager = manager; _showAfflictions = NumericalHudSettings.ShowAfflictions; _scale = scale; TMP_FontAsset font = (Object.op_Implicit((Object)(object)manager.heroDayText) ? ((TMP_Text)manager.heroDayText).font : (Object.op_Implicit((Object)(object)manager.interactPromptText) ? ((TMP_Text)manager.interactPromptText).font : null)); CreateText((Transform)(object)staminaBar.staminaBar, "Stamina", font, scale, () => FormatBarValue(GetFloat(staminaBar, "desiredStaminaSize"), roundWhole: true)); CreateText((Transform)(object)staminaBar.extraBarStamina, "ExtraStamina", font, scale, () => FormatBarValue(GetFloat(staminaBar, "desiredExtraStaminaSize"), roundWhole: true)); if (!NumericalHudSettings.ShowAfflictions || staminaBar.afflictions == null) { return; } BarAffliction[] afflictions = staminaBar.afflictions; foreach (BarAffliction affliction in afflictions) { if (Object.op_Implicit((Object)(object)affliction)) { CreateText(((Component)affliction).transform, "Affliction_" + ((object)(STATUSTYPE)(ref affliction.afflictionType)).ToString(), font, scale, () => FormatAfflictionText(affliction)); } } } private static void CreateText(Transform parent, string name, TMP_FontAsset font, float scale, Func update) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0063: 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_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)parent) && update != null) { GameObject val = new GameObject("CubeX_NumericalHud_" + name, new Type[1] { typeof(RectTransform) }); ((Object)val).hideFlags = (HideFlags)61; val.transform.SetParent(parent, false); RectTransform component = val.GetComponent(); component.anchorMin = Vector2.zero; component.anchorMax = Vector2.one; component.offsetMin = Vector2.zero; component.offsetMax = Vector2.zero; TextMeshProUGUI val2 = val.AddComponent(); ((TMP_Text)val2).text = string.Empty; ((TMP_Text)val2).font = font; ((TMP_Text)val2).fontSize = 40f * scale; ((TMP_Text)val2).fontSizeMin = 20f * scale; ((TMP_Text)val2).fontSizeMax = 40f * scale; ((TMP_Text)val2).enableAutoSizing = false; ((TMP_Text)val2).alignment = (TextAlignmentOptions)514; ((TMP_Text)val2).verticalAlignment = (VerticalAlignmentOptions)8192; ((TMP_Text)val2).textWrappingMode = (TextWrappingModes)0; ((TMP_Text)val2).overflowMode = (TextOverflowModes)0; ((Graphic)val2).color = Color.white; ((TMP_Text)val2).outlineColor = new Color32((byte)0, (byte)0, (byte)0, (byte)220); ((TMP_Text)val2).outlineWidth = 0.08f; ((Graphic)val2).raycastTarget = false; Bindings.Add(new TextBinding(val, val2, update)); } } private static string FormatBarValue(float size, bool roundWhole) { if (size >= 30f) { if (!roundWhole) { return (size / 6f).ToString("F1", CultureInfo.InvariantCulture).Replace(".0", string.Empty); } return Mathf.Round(size / 6f).ToString(CultureInfo.InvariantCulture); } if (size >= 15f) { return Mathf.Round(size / 6f).ToString(CultureInfo.InvariantCulture); } return string.Empty; } private static string FormatAfflictionText(BarAffliction affliction) { //IL_0037: 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) if (!Object.op_Implicit((Object)(object)affliction) || affliction.size <= 0f) { return string.Empty; } string text = FormatBarValue(affliction.size, roundWhole: false); if (string.IsNullOrEmpty(text)) { return string.Empty; } if (ShouldShowReductionTime(affliction.afflictionType)) { float reductionTimeRemaining = GetReductionTimeRemaining(affliction.afflictionType); if (reductionTimeRemaining > 0f) { text = text + "(" + FormatTime(reductionTimeRemaining) + ")"; } } return text; } private static bool ShouldShowReductionTime(STATUSTYPE statusType) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Expected I4, but got Unknown int num = (int)statusType; if (num != 7 && num != 0) { return num != 5; } return false; } private static float GetReductionTimeRemaining(STATUSTYPE statusType) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Invalid comparison between Unknown and I4 //IL_0041: 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_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) CharacterAfflictions val = ((!Object.op_Implicit((Object)(object)Character.observedCharacter)) ? null : Character.observedCharacter.refs?.afflictions); if (!Object.op_Implicit((Object)(object)val)) { return 0f; } if ((int)statusType == 9) { return GetAverageThornTime(val); } float currentStatus = val.GetCurrentStatus(statusType); if (currentStatus <= 0f) { return 0f; } float reductionRate = GetReductionRate(val, statusType); if (reductionRate <= 0f) { return 0f; } float cooldown = GetCooldown(val, statusType); float num = val.LastAddedStatus(statusType); if (cooldown > 0f && Time.time - num < cooldown) { return cooldown - (Time.time - num) + currentStatus / reductionRate; } return currentStatus / reductionRate; } private static float GetAverageThornTime(CharacterAfflictions afflictions) { float num = 0f; int num2 = 0; foreach (ThornOnMe physicalThorn in afflictions.physicalThorns) { if (physicalThorn.stuckIn) { num2++; num += Time.time - GetFloat(physicalThorn, "popOutTime"); } } if (num2 != 0) { return Mathf.Abs(num) / (float)num2; } return 0f; } private static float GetReductionRate(CharacterAfflictions afflictions, STATUSTYPE statusType) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Invalid comparison between Unknown and I4 //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Expected I4, but got Unknown if ((int)statusType == 3) { return afflictions.poisonReductionPerSecond; } return (statusType - 6) switch { 0 => afflictions.drowsyReductionPerSecond, 2 => afflictions.hotReductionPerSecond, 4 => afflictions.sporesReductionPerSecond, _ => 0f, }; } private static float GetCooldown(CharacterAfflictions afflictions, STATUSTYPE statusType) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Invalid comparison between Unknown and I4 //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Expected I4, but got Unknown if ((int)statusType == 3) { return afflictions.poisonReductionCooldown; } return (statusType - 6) switch { 0 => afflictions.drowsyReductionCooldown, 2 => afflictions.hotReductionCooldown, 4 => afflictions.sporesReductionCooldown, _ => 0f, }; } private static string FormatTime(float seconds) { if (seconds < 60f) { return Mathf.CeilToInt(seconds).ToString(CultureInfo.InvariantCulture); } if (seconds < 3600f) { int num = Mathf.FloorToInt(seconds / 60f); int num2 = Mathf.CeilToInt(seconds % 60f); return num.ToString(CultureInfo.InvariantCulture) + ":" + num2.ToString("D2", CultureInfo.InvariantCulture); } int num3 = Mathf.FloorToInt(seconds / 3600f); int num4 = Mathf.FloorToInt(seconds % 3600f / 60f); return num3.ToString(CultureInfo.InvariantCulture) + ":" + num4.ToString("D2", CultureInfo.InvariantCulture); } private static float GetFloat(object target, string name) { if (target == null || string.IsNullOrEmpty(name)) { return 0f; } try { Type type = target.GetType(); MemberInfo memberInfo = (MemberInfo)(((object)type.GetField(name, BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) ?? ((object)type.GetProperty(name, BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))); object obj = ((memberInfo is FieldInfo fieldInfo) ? fieldInfo.GetValue(target) : ((!(memberInfo is PropertyInfo propertyInfo) || propertyInfo.GetIndexParameters().Length != 0) ? null : propertyInfo.GetValue(target, null))); object obj2 = obj; if (obj2 is float result) { return result; } if (obj2 is double num) { return (float)num; } if (obj2 is int num2) { return num2; } return (obj2 == null) ? 0f : Convert.ToSingle(obj2, CultureInfo.InvariantCulture); } catch { return 0f; } } private static void DestroyExistingByPrefix() { RectTransform[] array = Object.FindObjectsByType((FindObjectsInactive)1, (FindObjectsSortMode)0); foreach (RectTransform val in array) { if (Object.op_Implicit((Object)(object)val) && ((Object)((Component)val).gameObject).name.StartsWith("CubeX_NumericalHud_", StringComparison.Ordinal)) { Object.Destroy((Object)(object)((Component)val).gameObject); } } } } internal static class NumericalHudSettings { public static float Scale = 0.5f; public static bool ShowAfflictions = true; } public class PeakTrailLifetime : NumberFeature { public PeakTrailLifetime() { base.Name = "Trail Lifetime"; base.Description = "How long trail segments remain visible, up to five minutes."; base.Min = 5f; base.Max = 300f; base.Value = PeakTrailSettings.Lifetime; base.Step = 1f; base.Decimals = 0; base.Unit = "s"; } protected override void OnValueChanged(float newValue) { PeakTrailSettings.Lifetime = Mathf.Clamp(newValue, base.Min, base.Max); PeakTrailRuntime.Update(); } } internal static class PeakTrailRuntime { private readonly struct TrailBinding { private Character Character { get; } private GameObject Holder { get; } public TrailRenderer Trail { get; } public bool IsAlive { get { if (Object.op_Implicit((Object)(object)Character) && Object.op_Implicit((Object)(object)Holder)) { return Object.op_Implicit((Object)(object)Trail); } return false; } } public TrailBinding(Character character, GameObject holder, TrailRenderer trail) { Character = character; Holder = holder; Trail = trail; } public bool IsValidFor(Character character, Transform anchor) { if (IsAlive && Character == character) { return (Object)(object)Holder.transform.parent == (Object)(object)anchor; } return false; } public void Destroy() { if (Object.op_Implicit((Object)(object)Holder)) { Object.Destroy((Object)(object)Holder); } } } private static readonly Dictionary Trails = new Dictionary(); private static readonly HashSet Wanted = new HashSet(); private static Material _material; public static void Update() { Wanted.Clear(); if (!PeakTrailSettings.AllPlayers) { ClearAll(); return; } Character localCharacter = Character.localCharacter; foreach (Character character in GameActions.GetCharacters()) { if (Object.op_Implicit((Object)(object)character) && VisualPlayerText.IsRealPlayer(character) && !IsDead(character) && (!PeakTrailSettings.ExcludeSelf || !Object.op_Implicit((Object)(object)localCharacter) || character != localCharacter)) { int instanceID = ((Object)character).GetInstanceID(); Wanted.Add(instanceID); EnsureTrail(character, instanceID); } } RemoveUnwanted(); } private static void ClearAll() { foreach (TrailBinding value in Trails.Values) { value.Destroy(); } Trails.Clear(); } private static void EnsureTrail(Character character, int id) { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Expected O, but got Unknown //IL_007f: 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_009f: Unknown result type (might be due to invalid IL or missing references) Transform trailAnchor = GetTrailAnchor(character); if (!Object.op_Implicit((Object)(object)trailAnchor)) { return; } if (Trails.TryGetValue(id, out var value) && value.IsValidFor(character, trailAnchor)) { Configure(value.Trail, character); return; } if (Object.op_Implicit((Object)(object)value.Trail)) { value.Destroy(); } GameObject val = new GameObject("CubeX_Trail_" + id) { hideFlags = (HideFlags)61 }; val.transform.SetParent(trailAnchor, false); val.transform.localPosition = Vector3.zero; val.transform.localRotation = Quaternion.identity; val.transform.localScale = Vector3.one; TrailRenderer trail = val.AddComponent(); Trails[id] = new TrailBinding(character, val, trail); Configure(trail, character); } private static Transform GetTrailAnchor(Character character) { if (!Object.op_Implicit((Object)(object)character)) { return null; } try { if (Object.op_Implicit((Object)(object)character.refs?.animationPositionTransform)) { return character.refs.animationPositionTransform; } } catch { } return ((Component)character).transform; } private static bool IsDead(Character character) { try { return Object.op_Implicit((Object)(object)character) && Object.op_Implicit((Object)(object)character.data) && character.data.dead; } catch { return false; } } private static void Configure(TrailRenderer trail, Character character) { //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Expected O, but got Unknown //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: 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) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)trail)) { ((Renderer)trail).enabled = true; trail.emitting = true; trail.autodestruct = false; float num = Mathf.Clamp(PeakTrailSettings.Width, 0.01f, 0.35f); trail.time = Mathf.Clamp(PeakTrailSettings.Lifetime, 0.15f, 300f); trail.widthMultiplier = 1f; trail.startWidth = num; trail.endWidth = num; trail.minVertexDistance = 0.035f; trail.numCornerVertices = 3; trail.numCapVertices = 2; trail.alignment = (LineAlignment)0; trail.textureMode = (LineTextureMode)0; ((Renderer)trail).shadowCastingMode = (ShadowCastingMode)0; ((Renderer)trail).receiveShadows = false; ((Renderer)trail).material = GetMaterial(); Color playerColor = GetPlayerColor(character); Gradient val = new Gradient(); val.SetKeys((GradientColorKey[])(object)new GradientColorKey[2] { new GradientColorKey(playerColor, 0f), new GradientColorKey(playerColor, 1f) }, (GradientAlphaKey[])(object)new GradientAlphaKey[2] { new GradientAlphaKey(0.78f, 0f), new GradientAlphaKey(0f, 1f) }); trail.colorGradient = val; } } private static Material GetMaterial() { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Expected O, but got Unknown if (Object.op_Implicit((Object)(object)_material)) { return _material; } _material = new Material(Shader.Find("Sprites/Default") ?? Shader.Find("Unlit/Color")) { hideFlags = (HideFlags)61, name = "CubeX_TrailMaterial" }; return _material; } private static Color GetPlayerColor(Character character) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) try { if (Object.op_Implicit((Object)(object)character) && Object.op_Implicit((Object)(object)character.refs?.customization)) { return character.refs.customization.PlayerColor; } } catch { } return new Color(0.25f, 0.85f, 1f, 1f); } private static void RemoveUnwanted() { List list = null; foreach (KeyValuePair item in Trails.Where((KeyValuePair pair) => !Wanted.Contains(pair.Key) || !pair.Value.IsAlive)) { if (list == null) { list = new List(); } list.Add(item.Key); } if (list == null) { return; } foreach (int item2 in list) { if (Trails.TryGetValue(item2, out var value)) { value.Destroy(); } Trails.Remove(item2); } } } public class PeakTrailsAllPlayers : Feature { public PeakTrailsAllPlayers() { base.Name = "Trails"; base.Description = "Adds lightweight colored trails to every real player."; } protected override void OnEnable() { PeakTrailSettings.AllPlayers = true; PeakTrailRuntime.Update(); } protected override void OnDisable() { PeakTrailSettings.AllPlayers = false; PeakTrailRuntime.Update(); } public override void OnTick() { PeakTrailRuntime.Update(); } } internal static class PeakTrailSettings { public static bool AllPlayers; public static bool ExcludeSelf = true; public static float Lifetime = 300f; public static float Width = 0.18f; } public class PeakTrailsSelectedPlayer : Feature { public PeakTrailsSelectedPlayer() { base.Name = "Exclude Self"; base.Description = "Hides your local player trail while Trails is enabled."; base.Enabled = true; } protected override void OnEnable() { PeakTrailSettings.ExcludeSelf = true; PeakTrailRuntime.Update(); } protected override void OnDisable() { PeakTrailSettings.ExcludeSelf = false; PeakTrailRuntime.Update(); } public override void OnTick() { PeakTrailRuntime.Update(); } } public class PeakTrailWidth : NumberFeature { public PeakTrailWidth() { base.Name = "Trail Width"; base.Description = "How wide player trails appear."; base.Min = 0.01f; base.Max = 0.35f; base.Value = PeakTrailSettings.Width; base.Step = 0.01f; base.Decimals = 2; base.Unit = "m"; } protected override void OnValueChanged(float newValue) { PeakTrailSettings.Width = Mathf.Clamp(newValue, base.Min, base.Max); PeakTrailRuntime.Update(); } } public class CheapThrownItemRendering : Feature { public CheapThrownItemRendering() { base.Name = "Cheap Dynamite Rendering"; base.Description = "Skips dynamite explosion plume particles."; } protected override void OnEnable() { VisualsRuntimeSettings.SkipExplosionPlume = true; } protected override void OnDisable() { VisualsRuntimeSettings.SkipExplosionPlume = false; } } public class CheapWorldItemRendering : Feature { private sealed class RendererState { private readonly Renderer _renderer; private readonly ShadowCastingMode _shadowCastingMode; private readonly bool _receiveShadows; private readonly ReflectionProbeUsage _reflectionProbeUsage; private readonly LightProbeUsage _lightProbeUsage; private readonly MotionVectorGenerationMode _motionVectorGenerationMode; public bool IsAlive => Object.op_Implicit((Object)(object)_renderer); public RendererState(Renderer renderer) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003f: 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) _renderer = renderer; _shadowCastingMode = renderer.shadowCastingMode; _receiveShadows = renderer.receiveShadows; _reflectionProbeUsage = renderer.reflectionProbeUsage; _lightProbeUsage = renderer.lightProbeUsage; _motionVectorGenerationMode = renderer.motionVectorGenerationMode; } public void Restore() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0048: 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) if (Object.op_Implicit((Object)(object)_renderer)) { _renderer.shadowCastingMode = _shadowCastingMode; _renderer.receiveShadows = _receiveShadows; _renderer.reflectionProbeUsage = _reflectionProbeUsage; _renderer.lightProbeUsage = _lightProbeUsage; _renderer.motionVectorGenerationMode = _motionVectorGenerationMode; } } } private const float ScanInterval = 2.5f; private const int MaxOptimizationsPerFrame = 16; private const int MaxRememberedRenderers = 4096; private readonly HashSet _queuedItems = new HashSet(); private readonly Queue _pendingItems = new Queue(); private readonly Dictionary _rendererStates = new Dictionary(); private float _nextScanAt; public CheapWorldItemRendering() { base.Name = "Cheap World Item Rendering"; base.Description = "Reduces shadows, probes, and motion vectors on spawned item renderers. Enable when item-heavy levels are slow."; } protected override void OnEnable() { _nextScanAt = 0f; OnTick(); } protected override void OnDisable() { foreach (RendererState value in _rendererStates.Values) { value.Restore(); } _queuedItems.Clear(); _pendingItems.Clear(); _rendererStates.Clear(); } public override void OnTick() { if (Object.op_Implicit((Object)(object)Character.localCharacter)) { float unscaledTime = Time.unscaledTime; if (unscaledTime >= _nextScanAt) { _nextScanAt = unscaledTime + 2.5f; QueueNewItems(); } ProcessPendingItems(); } } private void QueueNewItems() { Item[] array = Object.FindObjectsByType((FindObjectsInactive)0, (FindObjectsSortMode)0); foreach (Item val in array) { if (Object.op_Implicit((Object)(object)val)) { int instanceID = ((Object)val).GetInstanceID(); if (_queuedItems.Add(instanceID)) { _pendingItems.Enqueue(val); } } } if (_rendererStates.Count > 4096) { PruneDeadState(); } } private void ProcessPendingItems() { int num = 0; while (_pendingItems.Count > 0 && num < 16) { Item val = _pendingItems.Dequeue(); if (Object.op_Implicit((Object)(object)val)) { OptimizeItem(val); } num++; } } private void OptimizeItem(Item item) { Renderer[] componentsInChildren = ((Component)item).GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { OptimizeRenderer(componentsInChildren[i]); } } private void OptimizeRenderer(Renderer renderer) { if (Object.op_Implicit((Object)(object)renderer)) { int instanceID = ((Object)renderer).GetInstanceID(); if (!_rendererStates.ContainsKey(instanceID)) { _rendererStates[instanceID] = new RendererState(renderer); } renderer.shadowCastingMode = (ShadowCastingMode)0; renderer.receiveShadows = false; renderer.reflectionProbeUsage = (ReflectionProbeUsage)0; renderer.lightProbeUsage = (LightProbeUsage)0; renderer.motionVectorGenerationMode = (MotionVectorGenerationMode)2; } } private void PruneDeadState() { List list = null; foreach (KeyValuePair rendererState in _rendererStates) { if (!rendererState.Value.IsAlive) { if (list == null) { list = new List(); } list.Add(rendererState.Key); } } if (list != null) { for (int i = 0; i < list.Count; i++) { _rendererStates.Remove(list[i]); } } } } internal static class EntityPerformanceSettings { public static bool CullDistantMobs; public static float MobCullDistance = 500f; public static bool OptimizedCenterOfMass; public static bool ThrottleRemoteRagdolls; public static float CharacterUpdateSpeed = 5f; public static float CharacterMediumDistance = 30f; public static float CharacterMediumUpdateSpeed = 2f; public static float CharacterFarDistance = 60f; public static float CharacterFarUpdateSpeed = 1f; public static bool SkipRemoteCharacterWind; public static bool SkipItemWind; } public class MobCullDistance : NumberBoolFeature { public MobCullDistance() { base.Name = "Distant Mob Cull"; base.Description = "Skips Mob.Update for mobs farther than the configured distance from the active camera."; base.Min = 100f; base.Max = 5000f; base.Value = EntityPerformanceSettings.MobCullDistance; base.Step = 50f; base.Decimals = 0; base.Unit = "m"; } protected override void OnEnable() { EntityPerformanceSettings.CullDistantMobs = true; } protected override void OnDisable() { EntityPerformanceSettings.CullDistantMobs = false; } protected override void OnValueChanged(float newValue) { EntityPerformanceSettings.MobCullDistance = Mathf.Clamp(newValue, base.Min, base.Max); } } public class OptimizedCenterOfMass : Feature { public OptimizedCenterOfMass() { base.Name = "Optimized Center Of Mass"; base.Description = "Uses BetterFPS-style center-of-mass updates that only write Rigidbody values when they changed."; } protected override void OnEnable() { EntityPerformanceSettings.OptimizedCenterOfMass = true; } protected override void OnDisable() { EntityPerformanceSettings.OptimizedCenterOfMass = false; } } public class RagdollFarDistance : NumberFeature { public RagdollFarDistance() { base.Name = "Far Distance"; base.Description = "Distance where remote ragdolls switch from medium update speed to far update speed."; base.Min = 10f; base.Max = 500f; base.Value = EntityPerformanceSettings.CharacterFarDistance; base.Step = 5f; base.Decimals = 0; base.Unit = "m"; } protected override void OnValueChanged(float newValue) { EntityPerformanceSettings.CharacterFarDistance = Mathf.Clamp(newValue, base.Min, base.Max); } } public class RagdollFarUpdateSpeed : NumberFeature { public RagdollFarUpdateSpeed() { base.Name = "Far Update Speed"; base.Description = "Remote character ragdoll updates per second after the far-distance threshold."; base.Min = 0f; base.Max = 60f; base.Value = EntityPerformanceSettings.CharacterFarUpdateSpeed; base.Step = 1f; base.Decimals = 0; base.Unit = "/s"; } protected override void OnValueChanged(float newValue) { EntityPerformanceSettings.CharacterFarUpdateSpeed = Mathf.Clamp(newValue, base.Min, base.Max); } } public class RagdollMediumDistance : NumberFeature { public RagdollMediumDistance() { base.Name = "Medium Distance"; base.Description = "Distance where remote ragdolls switch from near update speed to medium update speed."; base.Min = 5f; base.Max = 250f; base.Value = EntityPerformanceSettings.CharacterMediumDistance; base.Step = 5f; base.Decimals = 0; base.Unit = "m"; } protected override void OnValueChanged(float newValue) { EntityPerformanceSettings.CharacterMediumDistance = Mathf.Clamp(newValue, base.Min, base.Max); } } public class RagdollMediumUpdateSpeed : NumberFeature { public RagdollMediumUpdateSpeed() { base.Name = "Medium Update Speed"; base.Description = "Remote character ragdoll updates per second after the medium-distance threshold."; base.Min = 0f; base.Max = 60f; base.Value = EntityPerformanceSettings.CharacterMediumUpdateSpeed; base.Step = 1f; base.Decimals = 0; base.Unit = "/s"; } protected override void OnValueChanged(float newValue) { EntityPerformanceSettings.CharacterMediumUpdateSpeed = Mathf.Clamp(newValue, base.Min, base.Max); } } public class RagdollNearUpdateSpeed : NumberFeature { public RagdollNearUpdateSpeed() { base.Name = "Near Update Speed"; base.Description = "Remote character ragdoll updates per second before the medium-distance threshold. Base game is about 60."; base.Min = 0f; base.Max = 60f; base.Value = EntityPerformanceSettings.CharacterUpdateSpeed; base.Step = 1f; base.Decimals = 0; base.Unit = "/s"; } protected override void OnValueChanged(float newValue) { EntityPerformanceSettings.CharacterUpdateSpeed = Mathf.Clamp(newValue, base.Min, base.Max); } } public class RemoteRagdollThrottling : Feature { public RemoteRagdollThrottling() { base.Name = "Remote Ragdoll Throttling"; base.Description = "Throttles non-local, non-scoutmaster character ragdoll animation updates by distance."; } protected override void OnEnable() { EntityPerformanceSettings.ThrottleRemoteRagdolls = true; } protected override void OnDisable() { EntityPerformanceSettings.ThrottleRemoteRagdolls = false; } } public class SkipItemWind : Feature { public SkipItemWind() { base.Name = "Skip Item Wind"; base.Description = "Skips wind-force application for items."; } protected override void OnEnable() { EntityPerformanceSettings.SkipItemWind = true; } protected override void OnDisable() { EntityPerformanceSettings.SkipItemWind = false; } } public class SkipRemoteCharacterWind : Feature { public SkipRemoteCharacterWind() { base.Name = "Skip Remote Character Wind"; base.Description = "Skips wind-force application for non-local characters."; } protected override void OnEnable() { EntityPerformanceSettings.SkipRemoteCharacterWind = true; } protected override void OnDisable() { EntityPerformanceSettings.SkipRemoteCharacterWind = false; } } public class DeadScoutColliderOptimization : Feature { public DeadScoutColliderOptimization() { base.Name = "Dead Ragdoll Optimization"; base.Description = "Disables dead scout ragdoll colliders locally to reduce CPU-bound physics lag."; base.Enabled = DeadScoutColliderOptimizationSettings.Enabled; } protected override void OnEnable() { DeadScoutColliderOptimizationSettings.Enabled = true; DeadScoutColliderOptimizationSettings.ApplyToExistingCharacters(); } protected override void OnDisable() { DeadScoutColliderOptimizationSettings.Enabled = false; DeadScoutColliderOptimizationSettings.RestoreExistingCharacters(); } } internal static class DeadScoutColliderOptimizationSettings { public static bool Enabled = true; public static void ApplyToExistingCharacters() { if (Character.AllCharacters == null) { return; } foreach (Character item in Character.AllCharacters.Where(IsDead)) { SetCollision(item, enabled: false); } } public static void RestoreExistingCharacters() { if (Character.AllCharacters == null) { return; } foreach (Character allCharacter in Character.AllCharacters) { SetCollision(allCharacter, enabled: true); } } public static void ApplyForDeath(Character character) { if (Enabled) { SetCollision(character, enabled: false); } } public static void ApplyForRevive(Character character) { if (Enabled) { SetCollision(character, enabled: true); } } private static bool IsDead(Character character) { if (Object.op_Implicit((Object)(object)character) && Object.op_Implicit((Object)(object)character.data)) { return character.data.dead; } return false; } private static void SetCollision(Character character, bool enabled) { if (!Object.op_Implicit((Object)(object)character) || !Object.op_Implicit((Object)(object)character.refs?.ragdoll)) { return; } try { character.refs.ragdoll.ToggleCollision(enabled); } catch { } } } public class DisablePostProcessing : Feature { private readonly struct CameraQuadState { public GameObject GameObject { get; } public bool WasActive { get; } public CameraQuadState(GameObject gameObject, bool wasActive) { GameObject = gameObject; WasActive = wasActive; } } private readonly Dictionary _states = new Dictionary(); private float _nextScanAt; public DisablePostProcessing() { base.Name = "Disable Post FX"; base.Description = "Disables loaded camera post-effect quads such as blur, bloom, vignette, and cloud layers."; } protected override void OnEnable() { _nextScanAt = 0f; OnTick(); } protected override void OnDisable() { foreach (CameraQuadState value in _states.Values) { if (Object.op_Implicit((Object)(object)value.GameObject)) { value.GameObject.SetActive(value.WasActive); } } _states.Clear(); } public override void OnTick() { if (Time.unscaledTime < _nextScanAt) { return; } _nextScanAt = Time.unscaledTime + 1f; CameraQuad[] array = Object.FindObjectsByType((FindObjectsInactive)1, (FindObjectsSortMode)0); foreach (CameraQuad val in array) { if (Object.op_Implicit((Object)(object)val) && IsHeavyPostEffect(((Object)((Component)val).gameObject).name)) { GameObject gameObject = ((Component)val).gameObject; int instanceID = ((Object)gameObject).GetInstanceID(); if (!_states.ContainsKey(instanceID)) { _states[instanceID] = new CameraQuadState(gameObject, gameObject.activeSelf); } if (gameObject.activeSelf) { gameObject.SetActive(false); } } } } private static bool IsHeavyPostEffect(string name) { if (string.IsNullOrWhiteSpace(name)) { return false; } if (name.IndexOf("Fog", StringComparison.OrdinalIgnoreCase) >= 0) { return false; } if (name.IndexOf("Post", StringComparison.OrdinalIgnoreCase) < 0 && name.IndexOf("Blur", StringComparison.OrdinalIgnoreCase) < 0 && name.IndexOf("Bloom", StringComparison.OrdinalIgnoreCase) < 0 && name.IndexOf("Vignette", StringComparison.OrdinalIgnoreCase) < 0) { return name.IndexOf("Cloud", StringComparison.OrdinalIgnoreCase) >= 0; } return true; } } public class FpsBoostMode : Feature { private readonly struct CameraFarClipState { public Camera Camera { get; } public float FarClipPlane { get; } public CameraFarClipState(Camera camera, float farClipPlane) { Camera = camera; FarClipPlane = farClipPlane; } } private readonly Dictionary _cameraFarClips = new Dictionary(); private bool _captured; private int _textureMipmapLimit; private int _antiAliasing; private AnisotropicFiltering _anisotropicFiltering; private float _lodBias; private float _shadowDistance; private ShadowResolution _shadowResolution; private int _shadowCascades; private int _pixelLightCount; private int _vSyncCount; private bool _realtimeReflectionProbes; private int _targetFrameRate; public FpsBoostMode() { base.Name = "FPS Boost"; base.Description = "Applies lower-cost Unity quality settings while enabled."; } protected override void OnEnable() { CaptureOriginals(); ApplyPerformanceSettings(); } protected override void OnDisable() { RestoreOriginals(); } public override void OnTick() { ApplyPerformanceSettings(); } private void CaptureOriginals() { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0048: 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) if (!_captured) { _captured = true; _textureMipmapLimit = QualitySettings.globalTextureMipmapLimit; _antiAliasing = QualitySettings.antiAliasing; _anisotropicFiltering = QualitySettings.anisotropicFiltering; _lodBias = QualitySettings.lodBias; _shadowDistance = QualitySettings.shadowDistance; _shadowResolution = QualitySettings.shadowResolution; _shadowCascades = QualitySettings.shadowCascades; _pixelLightCount = QualitySettings.pixelLightCount; _vSyncCount = QualitySettings.vSyncCount; _realtimeReflectionProbes = QualitySettings.realtimeReflectionProbes; _targetFrameRate = Application.targetFrameRate; } } private void ApplyPerformanceSettings() { QualitySettings.globalTextureMipmapLimit = Mathf.Clamp(PerformanceRuntime.TextureMipmapLimit, 0, 3); QualitySettings.antiAliasing = 0; QualitySettings.anisotropicFiltering = (AnisotropicFiltering)0; QualitySettings.lodBias = Mathf.Clamp(PerformanceRuntime.LodBias, 0.25f, 1.25f); QualitySettings.shadowDistance = 0f; QualitySettings.shadowResolution = (ShadowResolution)0; QualitySettings.shadowCascades = 0; QualitySettings.pixelLightCount = 0; QualitySettings.realtimeReflectionProbes = false; QualitySettings.vSyncCount = 0; Application.targetFrameRate = Mathf.Clamp(PerformanceRuntime.TargetFrameRate, 30, 240); float num = Mathf.Clamp(PerformanceRuntime.RenderDistance, 100f, 3000f); Camera[] allCameras = Camera.allCameras; foreach (Camera val in allCameras) { if (Object.op_Implicit((Object)(object)val) && ((Behaviour)val).isActiveAndEnabled) { int instanceID = ((Object)val).GetInstanceID(); if (!_cameraFarClips.ContainsKey(instanceID)) { _cameraFarClips[instanceID] = new CameraFarClipState(val, val.farClipPlane); } val.farClipPlane = Mathf.Min(_cameraFarClips[instanceID].FarClipPlane, num); } } } private void RestoreOriginals() { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) if (!_captured) { return; } QualitySettings.globalTextureMipmapLimit = _textureMipmapLimit; QualitySettings.antiAliasing = _antiAliasing; QualitySettings.anisotropicFiltering = _anisotropicFiltering; QualitySettings.lodBias = _lodBias; QualitySettings.shadowDistance = _shadowDistance; QualitySettings.shadowResolution = _shadowResolution; QualitySettings.shadowCascades = _shadowCascades; QualitySettings.pixelLightCount = _pixelLightCount; QualitySettings.vSyncCount = _vSyncCount; QualitySettings.realtimeReflectionProbes = _realtimeReflectionProbes; Application.targetFrameRate = _targetFrameRate; foreach (CameraFarClipState value in _cameraFarClips.Values) { if (Object.op_Implicit((Object)(object)value.Camera)) { value.Camera.farClipPlane = value.FarClipPlane; } } _cameraFarClips.Clear(); _captured = false; } } public class LeanMenuRendering : Feature { private bool _captured; private bool _showBreadcrumb; private bool _showDescription; private bool _showFooter; private bool _showScrollbar; private float _highlightLerpSpeed; private int _maxVisibleRows; public LeanMenuRendering() { base.Name = "Lean Menu Rendering"; base.Description = "Reduces extra menu layout and animation work while enabled."; } protected override void OnEnable() { CaptureOriginals(); ApplyLeanMenu(); } protected override void OnDisable() { if (_captured) { MenuConfig.ShowBreadcrumb = _showBreadcrumb; MenuConfig.ShowDescription = _showDescription; MenuConfig.ShowFooter = _showFooter; MenuConfig.ShowScrollbar = _showScrollbar; MenuConfig.HighlightLerpSpeed = _highlightLerpSpeed; MenuConfig.MaxVisibleRows = _maxVisibleRows; _captured = false; } } public override void OnTick() { ApplyLeanMenu(); } private void CaptureOriginals() { if (!_captured) { _captured = true; _showBreadcrumb = MenuConfig.ShowBreadcrumb; _showDescription = MenuConfig.ShowDescription; _showFooter = MenuConfig.ShowFooter; _showScrollbar = MenuConfig.ShowScrollbar; _highlightLerpSpeed = MenuConfig.HighlightLerpSpeed; _maxVisibleRows = MenuConfig.MaxVisibleRows; } } private static void ApplyLeanMenu() { MenuConfig.ShowBreadcrumb = false; MenuConfig.ShowDescription = false; MenuConfig.ShowFooter = false; MenuConfig.ShowScrollbar = false; MenuConfig.HighlightLerpSpeed = 40f; MenuConfig.MaxVisibleRows = Mathf.Min(MenuConfig.MaxVisibleRows, 10); } } public class PerformanceLodBias : NumberFeature { public PerformanceLodBias() { base.Name = "FPS LOD Bias"; base.Description = "Lower values make distant models switch to cheaper LODs sooner."; base.Min = 0.25f; base.Max = 1.25f; base.Value = PerformanceRuntime.LodBias; base.Step = 0.05f; base.Decimals = 2; base.Unit = "x"; } protected override void OnValueChanged(float newValue) { PerformanceRuntime.LodBias = Mathf.Clamp(newValue, base.Min, base.Max); } } public class PerformanceRenderDistance : NumberFeature { public PerformanceRenderDistance() { base.Name = "FPS Render Distance"; base.Description = "Camera render distance used while FPS Boost is enabled."; base.Min = 100f; base.Max = 3000f; base.Value = PerformanceRuntime.RenderDistance; base.Step = 50f; base.Decimals = 0; base.Unit = "m"; } protected override void OnValueChanged(float newValue) { PerformanceRuntime.RenderDistance = Mathf.Clamp(newValue, base.Min, base.Max); } } public class PerformanceTargetFps : NumberFeature { public PerformanceTargetFps() { base.Name = "FPS Target"; base.Description = "Application frame-rate cap used while FPS Boost is enabled."; base.Min = 30f; base.Max = 600f; base.Value = PerformanceRuntime.TargetFrameRate; base.Step = 5f; base.Decimals = 0; base.Unit = "fps"; } protected override void OnValueChanged(float newValue) { PerformanceRuntime.TargetFrameRate = Mathf.Clamp(Mathf.RoundToInt(newValue), (int)base.Min, (int)base.Max); } } public class PerformanceTextureLimit : NumberFeature { public override bool AllowTextInput => false; public PerformanceTextureLimit() { base.Name = "FPS Texture Limit"; base.Description = "Raises Unity's texture mipmap limit while FPS Boost is enabled."; base.Min = 0f; base.Max = 3f; base.Value = PerformanceRuntime.TextureMipmapLimit; base.Step = 1f; base.Decimals = 0; } protected override void OnValueChanged(float newValue) { PerformanceRuntime.TextureMipmapLimit = Mathf.Clamp(Mathf.RoundToInt(newValue), (int)base.Min, (int)base.Max); } } public class GhostPing : Feature { public GhostPing() { base.Name = "Ghost Ping"; base.Description = "Allows pinging while downed or dead and keeps received pings visible through terrain."; } protected override void OnEnable() { OnTick(); } protected override void OnDisable() { PingVisualRuntime.GhostPing = false; } public override void OnTick() { PingVisualRuntime.GhostPing = true; } } public class PingDistanceDisplay : Feature { private const float PingRefreshInterval = 0.25f; private readonly List _pings = new List(); private GUIStyle _style; private GUIStyle _shadowStyle; private float _nextPingRefreshAt; public PingDistanceDisplay() { base.Name = "Ping Distance"; base.Description = "Draws the distance to active ping markers."; } protected override void OnEnable() { PingVisualRuntime.ShowDistance = true; RefreshPingsIfNeeded(force: true); } protected override void OnDisable() { PingVisualRuntime.ShowDistance = false; _pings.Clear(); _nextPingRefreshAt = 0f; } public override void OnRender() { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: 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_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_006b: 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_0072: 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_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0091: 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) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) Camera main = Camera.main; Character localCharacter = Character.localCharacter; if (!Object.op_Implicit((Object)(object)main) || !Object.op_Implicit((Object)(object)localCharacter)) { return; } EnsureStyles(); RefreshPingsIfNeeded(force: false); Rect val4 = default(Rect); for (int i = 0; i < _pings.Count; i++) { PointPing val = _pings[i]; if (Object.op_Implicit((Object)(object)val)) { Vector3 val2 = ((Component)val).transform.position + Vector3.up * 0.25f; Vector3 val3 = main.WorldToScreenPoint(val2); if (!(val3.z <= 0f)) { string text = Vector3.Distance(localCharacter.Head, ((Component)val).transform.position).ToString("F1", CultureInfo.InvariantCulture) + "m"; ((Rect)(ref val4))..ctor(val3.x - 50f, (float)Screen.height - val3.y - 32f, 100f, 22f); GUI.Label(new Rect(((Rect)(ref val4)).x + 1f, ((Rect)(ref val4)).y + 1f, ((Rect)(ref val4)).width, ((Rect)(ref val4)).height), text, _shadowStyle); GUI.Label(val4, text, _style); } } } } public override void OnTick() { RefreshPingsIfNeeded(force: false); } private void RefreshPingsIfNeeded(bool force) { if (!force && Time.unscaledTime < _nextPingRefreshAt) { return; } _pings.Clear(); PointPing[] array = Object.FindObjectsByType((FindObjectsSortMode)0); for (int i = 0; i < array.Length; i++) { if (Object.op_Implicit((Object)(object)array[i])) { _pings.Add(array[i]); } } _nextPingRefreshAt = Time.unscaledTime + 0.25f; } private void EnsureStyles() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Expected O, but got Unknown //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_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Expected O, but got Unknown if (_style == null) { GUIStyle val = new GUIStyle(GUI.skin.label) { alignment = (TextAnchor)4, clipping = (TextClipping)1, fontSize = 13, fontStyle = (FontStyle)1 }; val.normal.textColor = Color.white; _style = val; GUIStyle val2 = new GUIStyle(_style); val2.normal.textColor = new Color(0f, 0f, 0f, 0.92f); _shadowStyle = val2; } } } public class PingPointScale : NumberFeature { public PingPointScale() { base.Name = "Ping Point Scale"; base.Description = "Scales ping markers after the game applies its normal distance scaling."; base.Min = 0.5f; base.Max = 6f; base.Value = 1f; base.Step = 0.1f; base.Decimals = 1; base.Unit = "x"; PingVisualRuntime.ScaleMultiplier = base.Value; } protected override void OnValueChanged(float newValue) { PingVisualRuntime.ScaleMultiplier = newValue; } } public class AllPlayerStaminaBars : Feature { private GUIStyle _labelStyle; private GUIStyle _shadowStyle; public AllPlayerStaminaBars() { base.Name = "Display Stamina Bars"; base.Description = "Adds stamina bars inside player profile cards."; } protected override void OnEnable() { ProfileCardSettings.ShowStaminaBars = true; } protected override void OnDisable() { ProfileCardSettings.ShowStaminaBars = false; } public override void OnRender() { if (ProfileCardSettings.ProfileCardsEnabled) { return; } Camera main = Camera.main; if (!Object.op_Implicit((Object)(object)main)) { return; } EnsureStyles(); foreach (Character character in GameActions.GetCharacters()) { if (Object.op_Implicit((Object)(object)character) && Object.op_Implicit((Object)(object)character.data) && VisualPlayerText.IsRealPlayer(character)) { DrawStaminaBar(main, character); } } } private void DrawStaminaBar(Camera camera, Character character) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0071: 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_009d: 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_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_01ee: Unknown result type (might be due to invalid IL or missing references) //IL_0200: Unknown result type (might be due to invalid IL or missing references) //IL_0210: Unknown result type (might be due to invalid IL or missing references) //IL_0217: Unknown result type (might be due to invalid IL or missing references) Vector3 anchor = GetAnchor(character); Vector3 val = anchor - ((Component)camera).transform.position; if (!(Vector3.Angle(((Component)camera).transform.forward, val) >= 90f)) { Vector3 val2 = camera.WorldToScreenPoint(anchor); if (!(val2.z <= 0f)) { float num = Mathf.Max(0.01f, character.GetMaxStamina()); float num2 = Mathf.Clamp01(character.data.currentStamina) * num; float num3 = Vector3.Distance(((Component)camera).transform.position, anchor); float num4 = Mathf.Clamp(142f - num3 * 0.18f, 78f, 142f); float num5 = val2.x - num4 * 0.5f; float num6 = (float)Screen.height - val2.y - 34f; Rect val3 = default(Rect); ((Rect)(ref val3))..ctor(num5, num6, num4, 34f); Color playerColor = GetPlayerColor(character); Theme.Fill(val3, new Color(0.035f, 0.036f, 0.04f, 0.86f)); Theme.Fill(new Rect(((Rect)(ref val3)).x, ((Rect)(ref val3)).y, 3f, ((Rect)(ref val3)).height), playerColor); Theme.Fill(new Rect(((Rect)(ref val3)).x, ((Rect)(ref val3)).y, ((Rect)(ref val3)).width, 1f), new Color(1f, 1f, 1f, 0.14f)); string text = Mathf.RoundToInt(num2).ToString(CultureInfo.InvariantCulture) + "/" + Mathf.RoundToInt(num).ToString(CultureInfo.InvariantCulture); Rect val4 = default(Rect); ((Rect)(ref val4))..ctor(((Rect)(ref val3)).x + 8f, ((Rect)(ref val3)).y + 4f, ((Rect)(ref val3)).width - 16f, 16f); GUI.Label(new Rect(((Rect)(ref val4)).x + 1f, ((Rect)(ref val4)).y + 1f, ((Rect)(ref val4)).width, ((Rect)(ref val4)).height), text, _shadowStyle); GUI.Label(val4, text, _labelStyle); ProfileCardsOverlay.DrawStaminaBar(character, val3, 1f, playerColor); } } } private static Vector3 GetAnchor(Character character) { //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003f: 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_0049: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)character)) { return Vector3.zero; } if (VisualPlayerText.TryGetVisualPosition(character, out var position)) { return position + Vector3.up * 2.05f; } try { return character.Center + Vector3.up * 0.8f; } catch { return ((Component)character).transform.position + Vector3.up * 1.8f; } } private static Color GetPlayerColor(Character character) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) try { if (Object.op_Implicit((Object)(object)character) && Object.op_Implicit((Object)(object)character.refs?.customization)) { return character.refs.customization.PlayerColor; } } catch { } return Theme.Accent; } private void EnsureStyles() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Expected O, but got Unknown //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_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Expected O, but got Unknown if (_labelStyle == null) { GUIStyle val = new GUIStyle(GUI.skin.label) { alignment = (TextAnchor)4, clipping = (TextClipping)1, fontSize = 11, fontStyle = (FontStyle)1 }; val.normal.textColor = Color.white; _labelStyle = val; GUIStyle val2 = new GUIStyle(_labelStyle); val2.normal.textColor = new Color(0f, 0f, 0f, 0.95f); _shadowStyle = val2; } } } public class DownedAwareness : Feature { private sealed class DownedMarker { public Vector3 Position; public bool IsDead; public int Percent; public float ExpiresAt; public Color Color = Color.white; } private const float DeadMarkerSeconds = 10f; private readonly Dictionary _markers = new Dictionary(); private readonly HashSet _seenThisFrame = new HashSet(); private int _lastRefreshFrame = -1; private GUIStyle _statusStyle; private GUIStyle _statusShadowStyle; private GUIStyle _distanceStyle; private GUIStyle _distanceShadowStyle; public DownedAwareness() { base.Name = "Downed Awareness"; base.Description = "Draws DownedAwareness-style markers over downed or dead players."; } protected override void OnEnable() { _markers.Clear(); _seenThisFrame.Clear(); _lastRefreshFrame = -1; RefreshMarkersIfNeeded(); } protected override void OnDisable() { _markers.Clear(); _seenThisFrame.Clear(); _lastRefreshFrame = -1; } public override void OnRender() { Camera main = Camera.main; Character localCharacter = Character.localCharacter; if (Object.op_Implicit((Object)(object)main) && Object.op_Implicit((Object)(object)localCharacter)) { EnsureStyles(); RefreshMarkersIfNeeded(localCharacter); DrawMarkers(main); } } public override void OnTick() { RefreshMarkersIfNeeded(); } private void RefreshMarkersIfNeeded(Character local = null) { int frameCount = Time.frameCount; if (_lastRefreshFrame != frameCount) { if (local == null) { local = Character.localCharacter; } if (Object.op_Implicit((Object)(object)local)) { _lastRefreshFrame = frameCount; RefreshMarkers(local); } } } private void RefreshMarkers(Character local) { //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) _seenThisFrame.Clear(); float unscaledTime = Time.unscaledTime; foreach (Character character in GameActions.GetCharacters()) { if (!Object.op_Implicit((Object)(object)character) || character == local || !VisualPlayerText.IsRealPlayer(character) || !Object.op_Implicit((Object)(object)character.data)) { continue; } int instanceID = ((Object)character).GetInstanceID(); _seenThisFrame.Add(instanceID); bool fullyPassedOut = character.data.fullyPassedOut; bool dead = character.data.dead; if (!fullyPassedOut && !dead) { _markers.Remove(instanceID); continue; } if (!_markers.TryGetValue(instanceID, out var value)) { value = new DownedMarker(); _markers[instanceID] = value; } value.Position = GetAnchor(character); if (dead && !value.IsDead) { value.ExpiresAt = unscaledTime + 10f; } value.IsDead = dead; value.Percent = 100 - Mathf.CeilToInt(character.data.deathTimer * 100f); value.Color = GetPlayerColor(character); } PruneMarkers(unscaledTime); } private void PruneMarkers(float now) { List list = new List(); foreach (KeyValuePair marker in _markers) { DownedMarker value = marker.Value; if (value.IsDead) { if (value.ExpiresAt > 0f && now > value.ExpiresAt) { list.Add(marker.Key); } } else if (!_seenThisFrame.Contains(marker.Key)) { list.Add(marker.Key); } } for (int i = 0; i < list.Count; i++) { _markers.Remove(list[i]); } } private void DrawMarkers(Camera camera) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003f: 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_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0050: 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_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: 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_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: 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_0160: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: 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_01ed: Unknown result type (might be due to invalid IL or missing references) Rect val3 = default(Rect); Rect val4 = default(Rect); foreach (DownedMarker value in _markers.Values) { if (value.Position == Vector3.zero) { continue; } Vector3 val = value.Position - ((Component)camera).transform.position; if (!(Vector3.Angle(((Component)camera).transform.forward, val) >= 90f)) { Vector3 val2 = camera.WorldToScreenPoint(value.Position); if (!(val2.z <= 0f)) { float x = val2.x; float num = (float)Screen.height - val2.y; string text = (value.IsDead ? "(x_x;)" : "(@_@;)"); string text2 = Mathf.Round(Vector3.Distance(value.Position, ((Component)camera).transform.position)).ToString("F0", CultureInfo.InvariantCulture) + "m | " + (value.IsDead ? "DEAD" : (value.Percent.ToString(CultureInfo.InvariantCulture) + "%")); ((Rect)(ref val3))..ctor(x - 100f, num - 48f, 200f, 42f); ((Rect)(ref val4))..ctor(x - 100f, num - 10f, 200f, 28f); _statusStyle.normal.textColor = value.Color; GUI.Label(new Rect(((Rect)(ref val3)).x + 2f, ((Rect)(ref val3)).y + 2f, ((Rect)(ref val3)).width, ((Rect)(ref val3)).height), text, _statusShadowStyle); GUI.Label(val3, text, _statusStyle); GUI.Label(new Rect(((Rect)(ref val4)).x + 2f, ((Rect)(ref val4)).y + 2f, ((Rect)(ref val4)).width, ((Rect)(ref val4)).height), text2, _distanceShadowStyle); GUI.Label(val4, text2, _distanceStyle); } } } } private static Vector3 GetAnchor(Character character) { //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_006f: 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_007e: 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_0088: 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_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)character)) { return Vector3.zero; } if (VisualPlayerText.TryGetVisualPosition(character, out var position)) { return position + Vector3.up * 1.8f; } try { MethodInfo method = ((object)character).GetType().GetMethod("TorsoPos", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (method != null) { object obj = method.Invoke(character, null); if (obj is Vector3) { return (Vector3)obj; } } } catch { } try { return character.Center + Vector3.up * 0.35f; } catch { return ((Component)character).transform.position + Vector3.up * 1.2f; } } private static Color GetPlayerColor(Character character) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) try { if (Object.op_Implicit((Object)(object)character) && Object.op_Implicit((Object)(object)character.refs?.customization)) { return character.refs.customization.PlayerColor; } } catch { } return new Color(1f, 0.88f, 0.24f, 1f); } private void EnsureStyles() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Expected O, but got Unknown //IL_0066: 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_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Expected O, but got Unknown //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: 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_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Expected O, but got Unknown //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Expected O, but got Unknown if (_statusStyle == null) { GUIStyle val = new GUIStyle(GUI.skin.label) { alignment = (TextAnchor)4, clipping = (TextClipping)1, fontSize = 35, fontStyle = (FontStyle)0 }; val.normal.textColor = new Color(1f, 0.88f, 0.24f, 1f); _statusStyle = val; GUIStyle val2 = new GUIStyle(_statusStyle); val2.normal.textColor = new Color(0f, 0f, 0f, 0.95f); _statusShadowStyle = val2; GUIStyle val3 = new GUIStyle(GUI.skin.label) { alignment = (TextAnchor)4, clipping = (TextClipping)1, fontSize = 20, fontStyle = (FontStyle)1 }; val3.normal.textColor = Color.white; _distanceStyle = val3; GUIStyle val4 = new GUIStyle(_distanceStyle); val4.normal.textColor = new Color(0f, 0f, 0f, 0.95f); _distanceShadowStyle = val4; } } } public class PlayerStatusHud : Feature { private readonly struct HudPlayer { public Character Character { get; } public float Distance { get; } public IReadOnlyList Afflictions { get; } public HudPlayer(Character character, float distance, IReadOnlyList afflictions) { Character = character; Distance = distance; Afflictions = afflictions; } } private GUIStyle _headerStyle; private GUIStyle _nameStyle; private GUIStyle _metaStyle; private GUIStyle _shadowStyle; public PlayerStatusHud() { base.Name = "Player Status HUD"; base.Description = "Draws PlayersInfo-style stamina and affliction bars for nearby players in the game HUD."; } public override void OnRender() { //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) Character localCharacter = Character.localCharacter; if (!Object.op_Implicit((Object)(object)localCharacter)) { return; } List list = BuildPlayers(localCharacter); if (list.Count != 0) { float num = Mathf.Clamp(PlayerStatusHudSettings.Scale, 0.75f, 1.4f); EnsureStyles(num); float num2 = 16f * num; float num3 = 92f * num; float num4 = 344f * num; float num5 = 24f * num; float num6 = 8f * num; float num7 = num5 + num6 + (float)Mathf.Max(0, list.Count - 1) * num6; for (int i = 0; i < list.Count; i++) { num7 += GetRowHeight(list[i], num); } Rect r = default(Rect); ((Rect)(ref r))..ctor(num2, num3, num4, num7); Theme.Fill(r, new Color(0.02f, 0.022f, 0.026f, 0.5f)); GUI.Label(new Rect(((Rect)(ref r)).x + 10f * num, ((Rect)(ref r)).y, ((Rect)(ref r)).width - 20f * num, num5), "TEAM STATUS", _shadowStyle); GUI.Label(new Rect(((Rect)(ref r)).x + 10f * num, ((Rect)(ref r)).y, ((Rect)(ref r)).width - 20f * num, num5), "TEAM STATUS", _headerStyle); float num8 = ((Rect)(ref r)).y + num5 + num6; for (int j = 0; j < list.Count; j++) { float rowHeight = GetRowHeight(list[j], num); DrawPlayerRow(new Rect(((Rect)(ref r)).x, num8, ((Rect)(ref r)).width, rowHeight), list[j], num); num8 += rowHeight + num6; } } } private static List BuildPlayers(Character local) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: 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) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) List list = new List(); Vector3 visualCenter = VisualPlayerText.GetVisualCenter(local); bool flag = Object.op_Implicit((Object)(object)local.data) && local.data.dead; float num = Mathf.Max(0f, PlayerStatusHudSettings.MaxDistance); foreach (Character character in GameActions.GetCharacters()) { if (!Object.op_Implicit((Object)(object)character) || !Object.op_Implicit((Object)(object)character.data) || !VisualPlayerText.IsRealPlayer(character)) { continue; } bool flag2 = character == local; if (!flag2 || !PlayerStatusHudSettings.ExcludeSelf) { Vector3 visualCenter2 = VisualPlayerText.GetVisualCenter(character); float num2 = (flag2 ? 0f : Vector3.Distance(visualCenter, visualCenter2)); if (flag || !(num > 0f) || flag2 || !(num2 > num)) { list.Add(new HudPlayer(character, num2, PlayerVitalsRenderer.GetActiveAfflictions(character))); } } } list.Sort((HudPlayer a, HudPlayer b) => a.Distance.CompareTo(b.Distance)); int num3 = Mathf.Clamp(PlayerStatusHudSettings.MaxPlayers, 1, 8); if (list.Count > num3) { list.RemoveRange(num3, list.Count - num3); } return list; } private void DrawPlayerRow(Rect rect, HudPlayer player, float scale) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: 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_0080: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Unknown result type (might be due to invalid IL or missing references) Character character = player.Character; if (Object.op_Implicit((Object)(object)character)) { Color playerColor = PlayerVitalsRenderer.GetPlayerColor(character, Theme.Accent); IReadOnlyList afflictions = player.Afflictions; Theme.Fill(rect, new Color(0.035f, 0.036f, 0.04f, 0.82f)); Theme.Fill(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, 3f * scale, ((Rect)(ref rect)).height), playerColor); DrawOutline(rect, new Color(1f, 1f, 1f, 0.14f), Mathf.Max(1f, scale)); string name = VisualPlayerText.GetName(character); string text = BuildMeta(character, player.Distance); GUI.Label(new Rect(((Rect)(ref rect)).x + 13f * scale, ((Rect)(ref rect)).y + 7f * scale, ((Rect)(ref rect)).width * 0.62f, 18f * scale), name, _nameStyle); GUI.Label(new Rect(((Rect)(ref rect)).x + ((Rect)(ref rect)).width * 0.48f, ((Rect)(ref rect)).y + 7f * scale, ((Rect)(ref rect)).width * 0.47f, 18f * scale), text, _metaStyle); Rect rect2 = default(Rect); ((Rect)(ref rect2))..ctor(((Rect)(ref rect)).x + 13f * scale, ((Rect)(ref rect)).y + 31f * scale, ((Rect)(ref rect)).width - 26f * scale, 16f * scale); PlayerVitalsRenderer.DrawStaminaBar(rect2, character, afflictions, scale, playerColor, showValue: true); PlayerVitalsRenderer.DrawAfflictionBadges(new Rect(((Rect)(ref rect)).x + 13f * scale, ((Rect)(ref rect2)).yMax + 8f * scale, ((Rect)(ref rect)).width - 26f * scale, ((Rect)(ref rect)).yMax - ((Rect)(ref rect2)).yMax - 10f * scale), afflictions, scale); } } private static float GetRowHeight(HudPlayer player, float scale) { float afflictionBadgeHeight = PlayerVitalsRenderer.GetAfflictionBadgeHeight(player.Afflictions, 318f * scale, scale, 2); return 66f * scale + afflictionBadgeHeight; } private static string BuildMeta(Character character, float distance) { string state = GetState(character); string text = ((distance <= 0.01f) ? "self" : (distance.ToString("F0", CultureInfo.InvariantCulture) + "m")); if (!string.IsNullOrEmpty(state)) { return text + " | " + state; } return text; } private static string GetState(Character character) { if (!Object.op_Implicit((Object)(object)character) || !Object.op_Implicit((Object)(object)character.data)) { return string.Empty; } if (character.data.dead) { return "dead"; } if (character.data.fullyPassedOut) { return "downed"; } return string.Empty; } private static void DrawOutline(Rect rect, Color color, float thickness) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: 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_0082: Unknown result type (might be due to invalid IL or missing references) Theme.Fill(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, ((Rect)(ref rect)).width, thickness), color); Theme.Fill(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).yMax - thickness, ((Rect)(ref rect)).width, thickness), color); Theme.Fill(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, thickness, ((Rect)(ref rect)).height), color); Theme.Fill(new Rect(((Rect)(ref rect)).xMax - thickness, ((Rect)(ref rect)).y, thickness, ((Rect)(ref rect)).height), color); } private void EnsureStyles(float scale) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0039: 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) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Expected O, but got Unknown //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Expected O, but got Unknown //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Expected O, but got Unknown //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Expected O, but got Unknown if (_headerStyle == null || _headerStyle.fontSize != Mathf.RoundToInt(11f * scale)) { GUIStyle val = new GUIStyle(GUI.skin.label) { alignment = (TextAnchor)3, clipping = (TextClipping)1, fontSize = Mathf.Max(8, Mathf.RoundToInt(11f * scale)), fontStyle = (FontStyle)1 }; val.normal.textColor = Color.white; _headerStyle = val; GUIStyle val2 = new GUIStyle(GUI.skin.label) { alignment = (TextAnchor)3, clipping = (TextClipping)1, fontSize = Mathf.Max(8, Mathf.RoundToInt(12f * scale)), fontStyle = (FontStyle)1 }; val2.normal.textColor = Color.white; _nameStyle = val2; GUIStyle val3 = new GUIStyle(GUI.skin.label) { alignment = (TextAnchor)5, clipping = (TextClipping)1, fontSize = Mathf.Max(7, Mathf.RoundToInt(10f * scale)) }; val3.normal.textColor = new Color(0.74f, 0.77f, 0.82f, 1f); _metaStyle = val3; GUIStyle val4 = new GUIStyle(_headerStyle); val4.normal.textColor = new Color(0f, 0f, 0f, 0.9f); _shadowStyle = val4; } } } public class PlayerStatusHudMaxPlayers : NumberFeature { public PlayerStatusHudMaxPlayers() { base.Name = "HUD Player Count"; base.Description = "Maximum number of nearby player status bars to show."; base.Min = 1f; base.Max = 20f; base.Value = PlayerStatusHudSettings.MaxPlayers; base.Step = 1f; base.Decimals = 0; } protected override void OnValueChanged(float newValue) { PlayerStatusHudSettings.MaxPlayers = Mathf.Clamp(Mathf.RoundToInt(newValue), 1, 20); } } public class PlayerStatusHudRange : NumberFeature { public PlayerStatusHudRange() { base.Name = "HUD Player Range"; base.Description = "Maximum distance for player status HUD entries. 0 shows every loaded player."; base.Min = 0f; base.Max = 500f; base.Value = PlayerStatusHudSettings.MaxDistance; base.Step = 5f; base.Decimals = 0; base.Unit = "m"; } protected override void OnValueChanged(float newValue) { PlayerStatusHudSettings.MaxDistance = Mathf.Clamp(newValue, base.Min, base.Max); } } internal static class PlayerStatusHudSettings { public static bool ExcludeSelf = true; public static int MaxPlayers = 3; public static float MaxDistance = 30f; public static float Scale = 1f; } internal static class PlayerVitalsRenderer { internal readonly struct AfflictionValue { public readonly string Name; public readonly STATUSTYPE Status; public readonly float Value; public readonly Color Color; public AfflictionValue(string name, STATUSTYPE status, float value, Color color) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) Name = name ?? string.Empty; Status = status; Value = Mathf.Clamp01(value); Color = color; } } private sealed class AfflictionCacheEntry { public Character Character; public readonly List Values = new List(); public float RefreshAt; } private const float AfflictionRefreshInterval = 0.2f; private const float AfflictionPruneInterval = 2f; private static readonly STATUSTYPE[] StatusTypes = (STATUSTYPE[])Enum.GetValues(typeof(STATUSTYPE)); private static readonly Dictionary AfflictionCache = new Dictionary(); private static readonly List StaleAfflictionKeys = new List(); private static Texture2D _stripeTexture; private static GUIStyle _valueStyle; private static GUIStyle _badgeStyle; private static float _styleScale = -1f; private static float _nextAfflictionPruneAt; public static List GetActiveAfflictions(Character character) { //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: 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_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: 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 (!Object.op_Implicit((Object)(object)character)) { return new List(); } int instanceID = ((Object)character).GetInstanceID(); float unscaledTime = Time.unscaledTime; if (AfflictionCache.TryGetValue(instanceID, out var value) && (Object)(object)value.Character == (Object)(object)character && unscaledTime < value.RefreshAt) { return value.Values; } if (value == null) { value = new AfflictionCacheEntry(); AfflictionCache[instanceID] = value; } value.Character = character; value.RefreshAt = unscaledTime + 0.2f; List values = value.Values; values.Clear(); CharacterAfflictions afflictions = GetAfflictions(character); if (!Object.op_Implicit((Object)(object)afflictions)) { PruneAfflictionCacheIfNeeded(unscaledTime); return values; } for (int i = 0; i < StatusTypes.Length; i++) { STATUSTYPE status = StatusTypes[i]; float statusValue = GetStatusValue(afflictions, status); if (!(statusValue <= 0.001f)) { values.Add(new AfflictionValue(GetDisplayName(status), status, Mathf.Clamp01(statusValue), GetAfflictionColor(afflictions, status))); } } PruneAfflictionCacheIfNeeded(unscaledTime); return values; } private static void PruneAfflictionCacheIfNeeded(float now) { if (now < _nextAfflictionPruneAt) { return; } _nextAfflictionPruneAt = now + 2f; StaleAfflictionKeys.Clear(); foreach (KeyValuePair item in AfflictionCache) { if (!Object.op_Implicit((Object)(object)item.Value.Character)) { StaleAfflictionKeys.Add(item.Key); } } for (int i = 0; i < StaleAfflictionKeys.Count; i++) { AfflictionCache.Remove(StaleAfflictionKeys[i]); } } public static void DrawStaminaBar(Rect rect, Character character, IReadOnlyList afflictions, float scale, Color accent, bool showValue) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: 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_0062: 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_006f: 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_0075: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)character) && Object.op_Implicit((Object)(object)character.data)) { EnsureStyles(scale); float num = Mathf.Max(1f, 2f * scale); Theme.Fill(rect, new Color(0.015f, 0.017f, 0.013f, 1f)); DrawOutline(rect, new Color(0f, 0f, 0f, 0.9f), num); Rect val = Inset(rect, num); Theme.Fill(val, new Color(0.08f, 0.09f, 0.07f, 0.95f)); float afflictionTotal = GetAfflictionTotal(afflictions); float num2 = Mathf.Clamp01(afflictionTotal); float num3 = Mathf.Clamp01(1f - num2); float width = ((Rect)(ref val)).width * num3 * GetStaminaPercent(character); DrawClippedFill(val, ((Rect)(ref val)).x, width, new Color(0.28f, 0.72f, 0.08f, 1f), striped: false, scale); DrawAfflictionSegments(val, afflictions, afflictionTotal, num3, scale); DrawExtraStamina(val, character, scale); DrawOutline(rect, new Color(1f, 1f, 1f, 0.36f), Mathf.Max(1f, scale)); if (showValue) { GUI.Label(rect, FormatStaminaText(character), _valueStyle); } } } public static void DrawAfflictionBadges(Rect rect, IReadOnlyList afflictions, float scale) { //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Unknown result type (might be due to invalid IL or missing references) if (afflictions == null || afflictions.Count == 0 || ((Rect)(ref rect)).width <= 1f || ((Rect)(ref rect)).height <= 1f) { return; } EnsureStyles(scale); float num = ((Rect)(ref rect)).x; float num2 = ((Rect)(ref rect)).y; float badgeGap = GetBadgeGap(scale); float badgeRowGap = GetBadgeRowGap(scale); float badgeRowHeight = GetBadgeRowHeight(scale); Rect val = default(Rect); for (int i = 0; i < afflictions.Count; i++) { AfflictionValue affliction = afflictions[i]; string badgeText = GetBadgeText(affliction); float badgeWidth = GetBadgeWidth(badgeText, ((Rect)(ref rect)).width, scale); if (num > ((Rect)(ref rect)).x && num + badgeWidth > ((Rect)(ref rect)).xMax) { num = ((Rect)(ref rect)).x; num2 += badgeRowHeight + badgeRowGap; } if (!(num2 + badgeRowHeight > ((Rect)(ref rect)).yMax)) { ((Rect)(ref val))..ctor(num, num2, Mathf.Min(badgeWidth, ((Rect)(ref rect)).xMax - num), badgeRowHeight); if (!(((Rect)(ref val)).width <= 8f * scale)) { Color color = affliction.Color; Theme.Fill(val, new Color(color.r, color.g, color.b, 0.28f)); Theme.Fill(new Rect(((Rect)(ref val)).x, ((Rect)(ref val)).y, Mathf.Max(2f, 3f * scale), ((Rect)(ref val)).height), color); DrawOutline(val, new Color(1f, 1f, 1f, 0.12f), Mathf.Max(1f, scale)); GUI.Label(new Rect(((Rect)(ref val)).x + 7f * scale, ((Rect)(ref val)).y, ((Rect)(ref val)).width - 10f * scale, ((Rect)(ref val)).height), badgeText, _badgeStyle); num += ((Rect)(ref val)).width + badgeGap; continue; } break; } break; } } public static float GetAfflictionBadgeHeight(IReadOnlyList afflictions, float width, float scale, int maxRows) { if (afflictions == null || afflictions.Count == 0 || width <= 1f) { return 0f; } EnsureStyles(scale); float num = 0f; int num2 = 1; float badgeGap = GetBadgeGap(scale); float badgeRowGap = GetBadgeRowGap(scale); float badgeRowHeight = GetBadgeRowHeight(scale); for (int i = 0; i < afflictions.Count; i++) { float badgeWidth = GetBadgeWidth(GetBadgeText(afflictions[i]), width, scale); if (num > 0f && num + badgeWidth > width) { num2++; if (maxRows > 0 && num2 > maxRows) { num2 = maxRows; break; } num = 0f; } num += badgeWidth + badgeGap; } num2 = Mathf.Max(1, num2); return (float)num2 * badgeRowHeight + (float)Mathf.Max(0, num2 - 1) * badgeRowGap; } public static Color GetPlayerColor(Character character, Color fallback) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) try { if (Object.op_Implicit((Object)(object)character) && Object.op_Implicit((Object)(object)character.refs?.customization)) { return character.refs.customization.PlayerColor; } } catch { } return fallback; } private static void DrawAfflictionSegments(Rect track, IReadOnlyList afflictions, float afflictionTotal, float safeStaminaPercent, float scale) { //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0090: 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_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) if (afflictions == null || afflictions.Count == 0) { return; } float num = ((afflictionTotal > 1f) ? (1f / afflictionTotal) : 1f); float num2 = ((Rect)(ref track)).x + ((Rect)(ref track)).width * safeStaminaPercent; for (int i = 0; i < afflictions.Count; i++) { AfflictionValue afflictionValue = afflictions[i]; if (!(afflictionValue.Value <= 0.001f)) { float num3 = ((Rect)(ref track)).width * Mathf.Clamp01(afflictionValue.Value * num); if (num2 >= ((Rect)(ref track)).xMax) { break; } num3 = Mathf.Min(num3, ((Rect)(ref track)).xMax - num2); Color color = afflictionValue.Color; DrawClippedFill(track, num2, num3, new Color(color.r, color.g, color.b, 0.9f), striped: true, scale); num2 += num3; } } } private static void DrawExtraStamina(Rect track, Character character, float scale) { //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) float num = (Object.op_Implicit((Object)(object)character.data) ? Mathf.Clamp01(character.data.extraStamina) : 0f); if (!(num <= 0.001f)) { float num2 = Mathf.Max(2f, 3f * scale); float num3 = Mathf.Clamp(((Rect)(ref track)).width * num, Mathf.Max(4f, 5f * scale), ((Rect)(ref track)).width); Theme.Fill(new Rect(((Rect)(ref track)).x, ((Rect)(ref track)).yMax - num2, num3, num2), new Color(0.7f, 1f, 0.32f, 0.95f)); } } private static float GetStaminaPercent(Character character) { if (!Object.op_Implicit((Object)(object)character) || !Object.op_Implicit((Object)(object)character.data)) { return 0f; } float num = 1f; try { num = Mathf.Max(0.01f, character.GetMaxStamina()); } catch { num = 1f; } return Mathf.Clamp01(character.data.currentStamina / num); } private static float GetAfflictionTotal(IReadOnlyList afflictions) { if (afflictions == null || afflictions.Count == 0) { return 0f; } float num = 0f; for (int i = 0; i < afflictions.Count; i++) { num += Mathf.Clamp01(afflictions[i].Value); } return num; } private static CharacterAfflictions GetAfflictions(Character character) { if (!Object.op_Implicit((Object)(object)character)) { return null; } try { CharacterAfflictions val = character.refs?.afflictions; if (Object.op_Implicit((Object)(object)val)) { return val; } } catch { } CharacterAfflictions val2 = ((Component)character).GetComponent(); if (!Object.op_Implicit((Object)(object)val2)) { val2 = ((Component)character).GetComponentInChildren(); } return val2; } private static float GetStatusValue(CharacterAfflictions afflictions, STATUSTYPE status) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)afflictions)) { return 0f; } try { return Mathf.Clamp01(afflictions.GetCurrentStatus(status)); } catch { return 0f; } } private static string FormatStaminaText(Character character) { int num = Mathf.RoundToInt(GetStaminaPercent(character) * 100f); if (!Object.op_Implicit((Object)(object)character) || !Object.op_Implicit((Object)(object)character.data) || character.data.extraStamina <= 0.001f) { return num.ToString(CultureInfo.InvariantCulture) + "%"; } int num2 = Mathf.RoundToInt(Mathf.Clamp01(character.data.extraStamina) * 100f); return num.ToString(CultureInfo.InvariantCulture) + "% +" + num2.ToString(CultureInfo.InvariantCulture); } private static string GetBadgeText(AfflictionValue affliction) { return affliction.Name + " " + Mathf.RoundToInt(affliction.Value * 100f).ToString(CultureInfo.InvariantCulture) + "%"; } private static float GetBadgeWidth(string text, float maxWidth, float scale) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown //IL_000b: Unknown result type (might be due to invalid IL or missing references) return Mathf.Min(_badgeStyle.CalcSize(new GUIContent(text)).x + 13f * scale, maxWidth); } private static float GetBadgeGap(float scale) { return Mathf.Max(4f, 6f * scale); } private static float GetBadgeRowGap(float scale) { return Mathf.Max(1f, scale); } private static float GetBadgeRowHeight(float scale) { return Mathf.Max(15f, 18f * scale); } private static string GetDisplayName(STATUSTYPE status) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected I4, but got Unknown return (int)status switch { 0 => "Injury", 1 => "Hunger", 2 => "Cold", 3 => "Poison", 4 => "Crab", 5 => "Curse", 6 => "Drowsy", 7 => "Weight", 8 => "Hot", 9 => "Thorns", 10 => "Spores", 11 => "Web", _ => ((object)(STATUSTYPE)(ref status)).ToString(), }; } private static Color GetAfflictionColor(CharacterAfflictions afflictions, STATUSTYPE status) { //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Expected I4, but got Unknown //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Expected I4, but got Unknown //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_01af: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: 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_01fd: Unknown result type (might be due to invalid IL or missing references) //IL_0217: Unknown result type (might be due to invalid IL or missing references) //IL_0231: Unknown result type (might be due to invalid IL or missing references) //IL_024b: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0049: 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_005c: 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_0068: 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_006e: 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_007e: 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_008a: 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_0090: 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_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: 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_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_0265: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0065: 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_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)afflictions)) { switch ((int)status) { case 0: { Color colorSpores = afflictions.colorInjury; if (IsUsableColor(colorSpores)) { return colorSpores; } break; } case 2: { Color colorSpores = afflictions.colorCold; if (IsUsableColor(colorSpores)) { return colorSpores; } break; } case 3: { Color colorSpores = afflictions.colorPoison; if (IsUsableColor(colorSpores)) { return colorSpores; } break; } case 4: { Color colorSpores = afflictions.colorCrab; if (IsUsableColor(colorSpores)) { return colorSpores; } break; } case 5: { Color colorSpores = afflictions.colorCurse; if (IsUsableColor(colorSpores)) { return colorSpores; } break; } case 6: { Color colorSpores = afflictions.colorDrowsy; if (IsUsableColor(colorSpores)) { return colorSpores; } break; } case 8: { Color colorSpores = afflictions.colorHot; if (IsUsableColor(colorSpores)) { return colorSpores; } break; } case 9: { Color colorSpores = afflictions.colorThorns; if (IsUsableColor(colorSpores)) { return colorSpores; } break; } case 10: { Color colorSpores = afflictions.colorSpores; if (IsUsableColor(colorSpores)) { return colorSpores; } break; } } } return (Color)((int)status switch { 0 => new Color(0.82f, 0.16f, 0.14f, 1f), 1 => new Color(0.95f, 0.64f, 0.18f, 1f), 2 => new Color(0.22f, 0.58f, 0.94f, 1f), 3 => new Color(0.62f, 0.3f, 0.88f, 1f), 4 => new Color(0.9f, 0.32f, 0.22f, 1f), 5 => new Color(0.56f, 0.28f, 0.86f, 1f), 6 => new Color(0.56f, 0.58f, 0.66f, 1f), 7 => new Color(0.86f, 0.68f, 0.28f, 1f), 8 => new Color(0.95f, 0.28f, 0.08f, 1f), 9 => new Color(0.24f, 0.72f, 0.26f, 1f), 10 => new Color(0.32f, 0.74f, 0.52f, 1f), 11 => new Color(0.72f, 0.82f, 0.9f, 1f), _ => new Color(0.55f, 0.55f, 0.55f, 1f), }); } private static bool IsUsableColor(Color color) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) if (color.a > 0.01f) { return color.r + color.g + color.b > 0.01f; } return false; } private static void DrawClippedFill(Rect track, float startX, float width, Color color, bool striped, float scale) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0046: 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_0079: 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_00a3: Unknown result type (might be due to invalid IL or missing references) if (width <= 0f) { return; } float num = Mathf.Max(((Rect)(ref track)).x, startX); float num2 = Mathf.Min(((Rect)(ref track)).xMax, startX + width); if (num2 <= num) { return; } Rect val = default(Rect); ((Rect)(ref val))..ctor(num, ((Rect)(ref track)).y, num2 - num, ((Rect)(ref track)).height); Theme.Fill(val, color); if (striped) { Texture2D stripeTexture = GetStripeTexture(); if (Object.op_Implicit((Object)(object)stripeTexture)) { float num3 = Mathf.Max(2f, 7f * scale); Color color2 = GUI.color; GUI.color = Color.white; GUI.DrawTextureWithTexCoords(val, (Texture)(object)stripeTexture, new Rect(0f, 0f, ((Rect)(ref val)).width / num3, ((Rect)(ref val)).height / num3), true); GUI.color = color2; } } } private static Texture2D GetStripeTexture() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Expected O, but got Unknown //IL_0092: 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) if (Object.op_Implicit((Object)(object)_stripeTexture)) { return _stripeTexture; } Texture2D val = new Texture2D(16, 16, (TextureFormat)4, false) { hideFlags = (HideFlags)61, wrapMode = (TextureWrapMode)0, filterMode = (FilterMode)0, name = "CubeX_PlayerVitalsStripe" }; Color val2 = default(Color); ((Color)(ref val2))..ctor(0f, 0f, 0f, 0f); Color val3 = default(Color); ((Color)(ref val3))..ctor(0f, 0f, 0f, 0.28f); for (int i = 0; i < 16; i++) { for (int j = 0; j < 16; j++) { int num = (j + i) % 8; val.SetPixel(j, i, (num <= 2) ? val3 : val2); } } val.Apply(false, false); return _stripeTexture = val; } private static Rect Inset(Rect rect, float amount) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) return new Rect(((Rect)(ref rect)).x + amount, ((Rect)(ref rect)).y + amount, Mathf.Max(0f, ((Rect)(ref rect)).width - amount * 2f), Mathf.Max(0f, ((Rect)(ref rect)).height - amount * 2f)); } private static void DrawOutline(Rect rect, Color color, float thickness) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: 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_0082: Unknown result type (might be due to invalid IL or missing references) Theme.Fill(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, ((Rect)(ref rect)).width, thickness), color); Theme.Fill(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).yMax - thickness, ((Rect)(ref rect)).width, thickness), color); Theme.Fill(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, thickness, ((Rect)(ref rect)).height), color); Theme.Fill(new Rect(((Rect)(ref rect)).xMax - thickness, ((Rect)(ref rect)).y, thickness, ((Rect)(ref rect)).height), color); } private static void EnsureStyles(float scale) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0062: 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) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Expected O, but got Unknown //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0094: 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_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Expected O, but got Unknown scale = Mathf.Clamp(scale, 0.55f, 2f); if (_valueStyle == null || !Mathf.Approximately(_styleScale, scale)) { _styleScale = scale; GUIStyle val = new GUIStyle(GUI.skin.label) { alignment = (TextAnchor)4, clipping = (TextClipping)1, fontSize = Mathf.Max(8, Mathf.RoundToInt(10f * scale)), fontStyle = (FontStyle)1 }; val.normal.textColor = Color.white; _valueStyle = val; GUIStyle val2 = new GUIStyle(GUI.skin.label) { alignment = (TextAnchor)3, clipping = (TextClipping)1, fontSize = Mathf.Max(8, Mathf.RoundToInt(9f * scale)), fontStyle = (FontStyle)1 }; val2.normal.textColor = Color.white; _badgeStyle = val2; } } } public class SummitRosterOverlay : Feature { private const float MountainHeight = 1920f; private const int MaxVisiblePlayers = 12; private GUIStyle _headerStyle; private GUIStyle _rowStyle; private GUIStyle _mutedStyle; private GUIStyle _rankStyle; public SummitRosterOverlay() { base.Name = "Summit Roster"; base.Description = "Draws a compact ascent roster with each player's height and state."; } public override void OnRender() { //IL_00a6: 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_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_0198: Unknown result type (might be due to invalid IL or missing references) //IL_019d: 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_01f5: Unknown result type (might be due to invalid IL or missing references) //IL_020e: Unknown result type (might be due to invalid IL or missing references) //IL_0237: Unknown result type (might be due to invalid IL or missing references) //IL_023c: 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_02cf: Unknown result type (might be due to invalid IL or missing references) //IL_0301: Unknown result type (might be due to invalid IL or missing references) List list = (from character in GameActions.GetCharacters().Where(VisualPlayerText.IsRealPlayer) orderby (!Object.op_Implicit((Object)(object)character)) ? 0f : ((Component)character).transform.position.y descending select character).Take(12).ToList(); if (list.Count == 0) { return; } EnsureStyles(); GUI.depth = 80; float num = Mathf.Clamp(48f + (float)list.Count * 30f, 88f, 440f); Rect val = default(Rect); ((Rect)(ref val))..ctor(16f, 84f, 284f, num); Theme.Fill(val, new Color(0.035f, 0.036f, 0.04f, 0.82f)); Theme.Fill(new Rect(((Rect)(ref val)).x, ((Rect)(ref val)).y, 3f, ((Rect)(ref val)).height), Theme.Accent); DrawOutline(val, new Color(1f, 1f, 1f, 0.14f), 1f); GUI.Label(new Rect(28f, 92f, 260f, 20f), "SUMMIT ROSTER", _headerStyle); float num2 = 120f; Rect val4 = default(Rect); for (int i = 0; i < list.Count; i++) { Character val2 = list[i]; if (Object.op_Implicit((Object)(object)val2)) { float num3 = Mathf.Max(0f, ((Component)val2).transform.position.y); float num4 = Mathf.Clamp01(num3 / 1920f); float num5 = num2; num2 += 30f; Color playerColor = GetPlayerColor(val2); Rect val3 = new Rect(28f, num5 + 2f, 24f, 18f); ((Rect)(ref val4))..ctor(58f, num5 + 9f, 62f, 5f); Theme.Fill(new Rect(((Rect)(ref val4)).x, ((Rect)(ref val4)).y, ((Rect)(ref val4)).width, ((Rect)(ref val4)).height), new Color(1f, 1f, 1f, 0.14f)); Theme.Fill(new Rect(((Rect)(ref val4)).x, ((Rect)(ref val4)).y, ((Rect)(ref val4)).width * num4, ((Rect)(ref val4)).height), playerColor); string state = GetState(val2); string name = VisualPlayerText.GetName(val2); string text = num3.ToString("F0", CultureInfo.InvariantCulture) + "m"; GUI.Label(val3, (i + 1).ToString(CultureInfo.InvariantCulture), _rankStyle); GUI.Label(new Rect(128f, num5 - 1f, 108f, 20f), name, _rowStyle); GUI.Label(new Rect(238f, num5 - 1f, 50f, 20f), text, _mutedStyle); if (!string.IsNullOrEmpty(state)) { GUI.Label(new Rect(128f, num5 + 12f, 160f, 16f), state, _mutedStyle); } } } } private static string GetState(Character character) { if (!Object.op_Implicit((Object)(object)character) || !Object.op_Implicit((Object)(object)character.data)) { return string.Empty; } if (character.data.dead) { return "dead"; } if (character.data.fullyPassedOut) { return "downed"; } return string.Empty; } private static Color GetPlayerColor(Character character) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) try { if (Object.op_Implicit((Object)(object)character) && Object.op_Implicit((Object)(object)character.refs?.customization)) { return character.refs.customization.PlayerColor; } } catch { } return Theme.Accent; } private static void DrawOutline(Rect rect, Color color, float thickness) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: 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_0082: Unknown result type (might be due to invalid IL or missing references) Theme.Fill(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, ((Rect)(ref rect)).width, thickness), color); Theme.Fill(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).yMax - thickness, ((Rect)(ref rect)).width, thickness), color); Theme.Fill(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, thickness, ((Rect)(ref rect)).height), color); Theme.Fill(new Rect(((Rect)(ref rect)).xMax - thickness, ((Rect)(ref rect)).y, thickness, ((Rect)(ref rect)).height), color); } private void EnsureStyles() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Expected O, but got Unknown //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_0062: 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) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Expected O, but got Unknown //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: 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_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Expected O, but got Unknown //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0100: 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) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Expected O, but got Unknown if (_headerStyle == null) { GUIStyle val = new GUIStyle(GUI.skin.label) { alignment = (TextAnchor)3, clipping = (TextClipping)1, fontSize = 12, fontStyle = (FontStyle)1 }; val.normal.textColor = Color.white; _headerStyle = val; GUIStyle val2 = new GUIStyle(GUI.skin.label) { alignment = (TextAnchor)3, clipping = (TextClipping)1, fontSize = 12, fontStyle = (FontStyle)1 }; val2.normal.textColor = new Color(0.94f, 0.95f, 0.96f, 1f); _rowStyle = val2; GUIStyle val3 = new GUIStyle(GUI.skin.label) { alignment = (TextAnchor)5, clipping = (TextClipping)1, fontSize = 10 }; val3.normal.textColor = new Color(0.72f, 0.75f, 0.78f, 1f); _mutedStyle = val3; GUIStyle val4 = new GUIStyle(GUI.skin.label) { alignment = (TextAnchor)4, clipping = (TextClipping)1, fontSize = 10, fontStyle = (FontStyle)1 }; val4.normal.textColor = new Color(0.72f, 0.75f, 0.78f, 1f); _rankStyle = val4; } } } internal enum EspTargetKind { Player, Food, Item, Luggage, Ghost, Hazard } public class PlayerEsp : Feature { private static class WorldGlowRuntime { private sealed class GlowInstance { private readonly Renderer _source; private readonly GameObject _cloneObject; private readonly Renderer _cloneRenderer; private readonly Material _material; public bool IsValid { get { if (Object.op_Implicit((Object)(object)_source) && Object.op_Implicit((Object)(object)_cloneObject) && Object.op_Implicit((Object)(object)_cloneRenderer)) { return Object.op_Implicit((Object)(object)_material); } return false; } } private GlowInstance(Renderer source, GameObject cloneObject, Renderer cloneRenderer, Material material) { _source = source; _cloneObject = cloneObject; _cloneRenderer = cloneRenderer; _material = material; } public bool IsValidFor(Renderer source) { if (IsValid) { return _source == source; } return false; } public static GlowInstance Create(Renderer source) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown //IL_005b: 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_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)source)) { return null; } Material val = CreateMaterial(Color.white); if (!Object.op_Implicit((Object)(object)val)) { return null; } GameObject val2 = new GameObject("CubeX ESP World Glow"); ((Object)val2).hideFlags = (HideFlags)61; val2.layer = ((Component)source).gameObject.layer; val2.transform.SetParent(((Component)source).transform, false); val2.transform.localPosition = Vector3.zero; val2.transform.localRotation = Quaternion.identity; val2.transform.localScale = Vector3.one * 1.035f; SkinnedMeshRenderer val3 = (SkinnedMeshRenderer)(object)((source is SkinnedMeshRenderer) ? source : null); Renderer val5; if (val3 == null) { MeshRenderer val4 = (MeshRenderer)(object)((source is MeshRenderer) ? source : null); val5 = ((val4 == null) ? null : CreateMeshClone(val2, val4)); } else { val5 = CreateSkinnedClone(val2, val3); } Renderer val6 = val5; if (!Object.op_Implicit((Object)(object)val6)) { Object.Destroy((Object)(object)val2); Object.Destroy((Object)(object)val); return null; } ApplyGlowMaterial(val6, val, source); val6.shadowCastingMode = (ShadowCastingMode)0; val6.receiveShadows = false; val6.allowOcclusionWhenDynamic = false; return new GlowInstance(source, val2, val6, val); } public void Update(Color color) { //IL_0056: Unknown result type (might be due to invalid IL or missing references) if (IsValid) { bool flag = _source.enabled && ((Component)_source).gameObject.activeInHierarchy; if (_cloneObject.activeSelf != flag) { _cloneObject.SetActive(flag); } _cloneRenderer.enabled = flag; SetMaterialColor(_material, color); } } public void Destroy() { if (Object.op_Implicit((Object)(object)_cloneObject)) { Object.Destroy((Object)(object)_cloneObject); } if (Object.op_Implicit((Object)(object)_material)) { Object.Destroy((Object)(object)_material); } } private static Renderer CreateSkinnedClone(GameObject cloneObject, SkinnedMeshRenderer source) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)source.sharedMesh)) { return null; } SkinnedMeshRenderer obj = cloneObject.AddComponent(); obj.sharedMesh = source.sharedMesh; obj.bones = source.bones; obj.rootBone = source.rootBone; ((Renderer)obj).localBounds = ((Renderer)source).localBounds; obj.updateWhenOffscreen = true; obj.quality = source.quality; return (Renderer)(object)obj; } private static Renderer CreateMeshClone(GameObject cloneObject, MeshRenderer source) { MeshFilter component = ((Component)source).GetComponent(); if (!Object.op_Implicit((Object)(object)component) || !Object.op_Implicit((Object)(object)component.sharedMesh)) { return null; } cloneObject.AddComponent().sharedMesh = component.sharedMesh; return (Renderer)(object)cloneObject.AddComponent(); } private static void ApplyGlowMaterial(Renderer cloneRenderer, Material material, Renderer source) { int num = 1; try { Material[] sharedMaterials = source.sharedMaterials; if (sharedMaterials != null && sharedMaterials.Length > 0) { num = source.sharedMaterials.Length; } } catch { } Material[] array = (Material[])(object)new Material[num]; for (int i = 0; i < array.Length; i++) { array[i] = material; } cloneRenderer.sharedMaterials = array; } } private const float OutlineScale = 1.035f; private const float GlowAlpha = 0.44f; private static readonly Dictionary Instances = new Dictionary(); private static readonly HashSet SeenThisFrame = new HashSet(); private static readonly List RemoveBuffer = new List(); public static void BeginFrame() { SeenThisFrame.Clear(); } public static void Track(EspTarget target, Color color) { //IL_0098: Unknown result type (might be due to invalid IL or missing references) if (target == null || !Object.op_Implicit((Object)(object)target.Component)) { return; } Renderer[] renderers = target.Renderers; renderers = ((renderers != null && renderers.Length > 0) ? target.Renderers : target.Component.GetComponentsInChildren(true)); foreach (Renderer val in renderers) { if (!IsUsableRenderer(val)) { continue; } int instanceID = ((Object)val).GetInstanceID(); SeenThisFrame.Add(instanceID); if (!Instances.TryGetValue(instanceID, out var value) || !value.IsValidFor(val)) { value?.Destroy(); value = GlowInstance.Create(val); if (value == null) { continue; } Instances[instanceID] = value; } value.Update(color); } } public static void EndFrame() { RemoveBuffer.Clear(); foreach (KeyValuePair instance in Instances) { if (SeenThisFrame.Contains(instance.Key)) { GlowInstance value = instance.Value; if (value != null && value.IsValid) { continue; } } RemoveBuffer.Add(instance.Key); } foreach (int item in RemoveBuffer) { if (Instances.TryGetValue(item, out var value2)) { value2?.Destroy(); } Instances.Remove(item); } } public static void Clear() { foreach (GlowInstance value in Instances.Values) { value?.Destroy(); } Instances.Clear(); SeenThisFrame.Clear(); } private static Material CreateMaterial(Color color) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Expected O, but got Unknown //IL_00bc: Unknown result type (might be due to invalid IL or missing references) Shader val = Shader.Find("Hidden/Internal-Colored") ?? Shader.Find("Unlit/Color"); if (!Object.op_Implicit((Object)(object)val)) { return null; } Material val2 = new Material(val) { hideFlags = (HideFlags)61, renderQueue = 4000 }; if (val2.HasProperty("_ZWrite")) { val2.SetInt("_ZWrite", 0); } if (val2.HasProperty("_ZTest")) { val2.SetInt("_ZTest", 8); } if (val2.HasProperty("_Cull")) { val2.SetInt("_Cull", 1); } if (val2.HasProperty("_SrcBlend")) { val2.SetInt("_SrcBlend", 5); } if (val2.HasProperty("_DstBlend")) { val2.SetInt("_DstBlend", 10); } SetMaterialColor(val2, color); return val2; } private static void SetMaterialColor(Material material, Color color) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)material)) { Color val = default(Color); ((Color)(ref val))..ctor(color.r, color.g, color.b, 0.44f); if (material.HasProperty("_Color")) { material.SetColor("_Color", val); } if (material.HasProperty("_TintColor")) { material.SetColor("_TintColor", val); } } } } private readonly struct RenderCandidate { public EspTarget Target { get; } public Color Color { get; } public float DistanceSqr { get; } public RenderCandidate(EspTarget target, Color color, float distanceSqr) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) Target = target; Color = color; DistanceSqr = distanceSqr; } } private sealed class EspTarget { public Component Component { get; } public Character Character { get; } public EspTargetKind Kind { get; } public string DisplayName { get; } public Renderer[] Renderers { get; } public string Key { get; } public int Score { get; } public bool HasBounds { get; } public Bounds CachedBounds { get; } public EspTarget(Component component, Character character, EspTargetKind kind, string displayName, Renderer[] renderers, string key, int score, bool hasBounds, Bounds cachedBounds) { //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) Component = component; Character = character; Kind = kind; DisplayName = (string.IsNullOrWhiteSpace(displayName) ? "Unknown" : displayName.Trim()); Renderers = renderers ?? Array.Empty(); Key = key; Score = score; HasBounds = hasBounds; CachedBounds = cachedBounds; } } private const float SceneCharacterScanInterval = 2f; private const float NearPlanePadding = 0.05f; private const float FallbackWidth = 0.7f; private const float FallbackHeight = 2f; private const float BoxThickness = 1.25f; private const float LineThickness = 1.15f; private const float InfoLabelWidth = 240f; private const float InfoLabelHeight = 22f; private const float MaxUsefulBoundsSize = 80f; private const float ScreenMargin = 3f; private static PlayerEsp _instance; private readonly List _targets = new List(); private readonly List _renderCandidates = new List(128); private readonly Dictionary _characterTargetsByKey = new Dictionary(StringComparer.Ordinal); private readonly HashSet _seenEntities = new HashSet(); private readonly HashSet _seenCharacterIds = new HashSet(); private readonly List _candidateCharacters = new List(16); private readonly Vector3[] _corners = (Vector3[])(object)new Vector3[8]; private Camera _camera; private float _nextRefreshAt; private float _nextSceneCharacterScanAt; private PlayerEspTargetFlags _cachedTargetFlags = (PlayerEspTargetFlags)(-1); private float _cachedMaxDistance = -1f; private bool _cachedWorldGlow; private int _lastRenderFrame = -1; private GUIStyle _infoStyle; private GUIStyle _infoShadowStyle; public PlayerEsp() { _instance = this; base.Name = "ESP Boxes"; base.Description = "Draws 2D box outlines for enabled ESP target types."; } protected override void OnEnable() { _nextRefreshAt = 0f; RefreshTargetsIfNeeded(); } public override void OnRender() { RenderShared(); } protected override void OnDisable() { RequestRefresh(); } public override void OnTick() { RefreshTargetsIfNeeded(); } internal static void ClearWorldGlow() { WorldGlowRuntime.Clear(); } internal static void RequestRefresh() { if (_instance != null) { _instance._nextRefreshAt = 0f; _instance._lastRenderFrame = -1; } } internal static void RenderShared() { _instance?.RenderActiveLayers(); } private void RenderActiveLayers() { int frameCount = Time.frameCount; if (_lastRenderFrame != frameCount) { bool enabled = base.Enabled; bool showLines = PlayerEspSettings.ShowLines; bool showInfo = PlayerEspSettings.ShowInfo; bool showWorldGlow = PlayerEspSettings.ShowWorldGlow; if (enabled || showLines || showInfo || showWorldGlow) { _lastRenderFrame = frameCount; RenderEsp(enabled, showLines, showInfo, showWorldGlow); } } } private void RenderEsp(bool drawBoxes, bool drawLines, bool drawInfoLabels, bool drawWorldGlow) { //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0120: 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_0135: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)_camera) || !((Behaviour)_camera).isActiveAndEnabled) { _camera = Camera.main; } Camera camera = _camera; if (!Object.op_Implicit((Object)(object)camera)) { return; } RefreshTargetsIfNeeded(); Character localCharacter = Character.localCharacter; Vector3 origin = (Object.op_Implicit((Object)(object)localCharacter) ? GetCharacterAnchor(localCharacter) : ((Component)camera).transform.position); BuildRenderCandidates(localCharacter, origin); if (drawWorldGlow) { WorldGlowRuntime.BeginFrame(); } try { int num = Mathf.Clamp(PlayerEspSettings.MaxTargets, 1, 256); int num2 = 0; for (int i = 0; i < _renderCandidates.Count && num2 < num; i++) { RenderCandidate renderCandidate = _renderCandidates[i]; EspTarget target = renderCandidate.Target; Color color = renderCandidate.Color; bool flag = false; if (drawWorldGlow) { WorldGlowRuntime.Track(target, color); flag = true; } if (drawBoxes || drawLines || drawInfoLabels) { if (!TryGetScreenRect(camera, target, out var rect)) { if (flag) { num2++; } continue; } if (drawBoxes) { DrawBox(rect, color, 1.25f); } if (drawLines) { DrawLine(new Vector2((float)Screen.width * 0.5f, (float)Screen.height), new Vector2(((Rect)(ref rect)).center.x, ((Rect)(ref rect)).yMax), color, 1.15f); } if (drawInfoLabels) { DrawInfo(rect, target, Mathf.Sqrt(renderCandidate.DistanceSqr)); } flag = true; } if (flag) { num2++; } } } finally { if (drawWorldGlow) { WorldGlowRuntime.EndFrame(); } } } private void BuildRenderCandidates(Character local, Vector3 origin) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //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_0060: Unknown result type (might be due to invalid IL or missing references) _renderCandidates.Clear(); float num = Mathf.Max(1f, PlayerEspSettings.MaxDistance); float num2 = num * num; for (int i = 0; i < _targets.Count; i++) { EspTarget target = _targets[i]; if (ShouldDrawTarget(target, local)) { Vector3 val = GetTargetWorldPosition(target) - origin; float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude; if (!(sqrMagnitude > num2)) { Color targetColor = GetTargetColor(target); _renderCandidates.Add(new RenderCandidate(target, targetColor, sqrMagnitude)); } } } _renderCandidates.Sort((RenderCandidate a, RenderCandidate b) => a.DistanceSqr.CompareTo(b.DistanceSqr)); } private static Color GetTargetColor(EspTarget target) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) if (target == null || target.Kind != 0) { return PlayerEspSettings.EntityColor; } return PlayerEspSettings.PlayerColor; } private void RefreshTargetsIfNeeded() { //IL_0087: 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_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01fb: Unknown result type (might be due to invalid IL or missing references) //IL_022e: Unknown result type (might be due to invalid IL or missing references) float num = Mathf.Max(1f, PlayerEspSettings.MaxDistance); PlayerEspTargetFlags targetFlags = PlayerEspSettings.TargetFlags; bool showWorldGlow = PlayerEspSettings.ShowWorldGlow; if (Time.unscaledTime < _nextRefreshAt && targetFlags == _cachedTargetFlags && Mathf.Abs(num - _cachedMaxDistance) <= 0.01f && showWorldGlow == _cachedWorldGlow) { return; } _targets.Clear(); _characterTargetsByKey.Clear(); _seenEntities.Clear(); Character localCharacter = Character.localCharacter; Vector3 origin = (Object.op_Implicit((Object)(object)localCharacter) ? GetCharacterAnchor(localCharacter) : Vector3.zero); bool hasOrigin = Object.op_Implicit((Object)(object)localCharacter); CollectCandidateCharacters(); for (int i = 0; i < _candidateCharacters.Count; i++) { AddCharacterTarget(_candidateCharacters[i], localCharacter, _characterTargetsByKey, showWorldGlow); } _targets.AddRange(_characterTargetsByKey.Values); int num2; if (!PlayerEspSettings.ShowFood && !PlayerEspSettings.ShowItems && !PlayerEspSettings.ShowLuggage && !PlayerEspSettings.ShowGhosts) { num2 = (PlayerEspSettings.ShowHazards ? 1 : 0); if (num2 == 0) { goto IL_0138; } } else { num2 = 1; } if (PlayerEspSettings.ShowFood || PlayerEspSettings.ShowItems) { AddItemTargets(_seenEntities, origin, hasOrigin, num, PlayerEspSettings.ShowFood, PlayerEspSettings.ShowItems, showWorldGlow); } goto IL_0138; IL_0138: if (num2 != 0 && PlayerEspSettings.ShowLuggage) { AddEntityTargets(_seenEntities, origin, hasOrigin, num, EspTargetKind.Luggage, (Func)((Luggage luggage) => (!Object.op_Implicit((Object)(object)luggage) || string.IsNullOrEmpty(luggage.displayName)) ? "Luggage" : luggage.displayName), showWorldGlow, (Func)null); } if (num2 != 0 && PlayerEspSettings.ShowGhosts) { AddEntityTargets(_seenEntities, origin, hasOrigin, num, EspTargetKind.Ghost, (Func)((PlayerGhost _) => "Player Ghost"), showWorldGlow, (Func)null); } if (num2 != 0 && PlayerEspSettings.ShowHazards) { AddEntityTargets(_seenEntities, origin, hasOrigin, num, EspTargetKind.Hazard, (Func)((Tornado _) => "Tornado"), showWorldGlow, (Func)null); AddEntityTargets(_seenEntities, origin, hasOrigin, num, EspTargetKind.Hazard, (Func)((BeeSwarm _) => "Bee Swarm"), showWorldGlow, (Func)null); AddEntityTargets(_seenEntities, origin, hasOrigin, num, EspTargetKind.Hazard, (Func)((Scoutmaster _) => "Scoutmaster"), showWorldGlow, (Func)null); } _cachedTargetFlags = targetFlags; _cachedMaxDistance = num; _cachedWorldGlow = showWorldGlow; _nextRefreshAt = Time.unscaledTime + Mathf.Clamp(PlayerEspSettings.RefreshInterval, 0.5f, 5f); } private void AddCharacterTarget(Character character, Character local, Dictionary targetsByKey, bool collectRenderers) { //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)character) && (!Object.op_Implicit((Object)(object)local) || character != local) && !IsChickenCharacter(character)) { bool flag = IsPlayerCharacter(character, local); EspTarget espTarget = new EspTarget((Component)(object)character, character, (!flag) ? ClassifyCharacterEntity(character) : EspTargetKind.Player, GetCharacterDisplayName(character, flag), collectRenderers ? ((Component)character).GetComponentsInChildren(true) : Array.Empty(), BuildCharacterTargetKey(character, flag), GetCharacterTargetScore(character, flag), hasBounds: false, default(Bounds)); if (!string.IsNullOrEmpty(espTarget.Key) && (!targetsByKey.TryGetValue(espTarget.Key, out var value) || espTarget.Score > value.Score)) { targetsByKey[espTarget.Key] = espTarget; } } } private void AddEntityTargets(HashSet seen, Vector3 origin, bool hasOrigin, float maxDistance, EspTargetKind kind, Func nameFactory, bool collectRenderers, Func include = null) where T : Component { //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //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) float num = maxDistance * maxDistance; T[] array = Object.FindObjectsByType((FindObjectsSortMode)0); foreach (T val in array) { if (!Object.op_Implicit((Object)(object)val) || (include != null && !include(val)) || Object.op_Implicit((Object)(object)((Component)val).GetComponentInParent())) { continue; } if (hasOrigin) { Vector3 val2 = ((Component)val).transform.position - origin; if (((Vector3)(ref val2)).sqrMagnitude > num) { continue; } } int instanceID = ((Object)(object)val).GetInstanceID(); if (seen.Add(instanceID)) { AddEntityTarget((Component)(object)val, kind, nameFactory?.Invoke(val), "entity-" + instanceID.ToString(CultureInfo.InvariantCulture), collectRenderers); } } } private void AddItemTargets(HashSet seen, Vector3 origin, bool hasOrigin, float maxDistance, bool includeFood, bool includeItems, bool collectRenderers) { //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_005c: 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) float num = maxDistance * maxDistance; int num2 = 0; int num3 = Mathf.Clamp(PlayerEspSettings.MaxTargets, 16, 256); Item[] array = Object.FindObjectsByType((FindObjectsSortMode)0); for (int i = 0; i < array.Length && num2 < num3; i++) { Item val = array[i]; if (!Object.op_Implicit((Object)(object)val) || Object.op_Implicit((Object)(object)((Component)val).GetComponentInParent())) { continue; } if (hasOrigin) { Vector3 val2 = ((Component)val).transform.position - origin; if (((Vector3)(ref val2)).sqrMagnitude > num) { continue; } } bool flag = IsFoodItem(val); if (!(flag ? (!includeFood) : (!includeItems))) { int instanceID = ((Object)val).GetInstanceID(); if (seen.Add(instanceID)) { string displayName = ((!string.IsNullOrEmpty(val.GetName())) ? val.GetName() : (flag ? "Food" : "Item")); AddEntityTarget((Component)(object)val, flag ? EspTargetKind.Food : EspTargetKind.Item, displayName, "item-" + instanceID.ToString(CultureInfo.InvariantCulture), collectRenderers); num2++; } } } } private void AddEntityTarget(Component component, EspTargetKind kind, string displayName, string key, bool collectRenderers) { //IL_006e: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)component)) { if (string.IsNullOrWhiteSpace(displayName)) { displayName = CleanObjectName(((Object)component).name, ((object)component).GetType().Name); } Renderer[] renderers = (collectRenderers ? component.GetComponentsInChildren(true) : Array.Empty()); Bounds bounds; bool hasBounds = TryGetColliderBounds(component.GetComponentsInChildren(true), out bounds) || (collectRenderers && TryGetRendererBounds(renderers, out bounds)); _targets.Add(new EspTarget(component, null, kind, displayName, renderers, key, 0, hasBounds, bounds)); } } private void CollectCandidateCharacters() { _candidateCharacters.Clear(); _seenCharacterIds.Clear(); if (Character.AllCharacters != null) { for (int i = 0; i < Character.AllCharacters.Count; i++) { Character val = Character.AllCharacters[i]; if (Object.op_Implicit((Object)(object)val) && _seenCharacterIds.Add(((Object)val).GetInstanceID())) { _candidateCharacters.Add(val); } } } if (_candidateCharacters.Count > 0 && Time.unscaledTime < _nextSceneCharacterScanAt) { return; } _nextSceneCharacterScanAt = Time.unscaledTime + 2f; Character[] array = Object.FindObjectsByType((FindObjectsSortMode)0); foreach (Character val2 in array) { if (Object.op_Implicit((Object)(object)val2) && _seenCharacterIds.Add(((Object)val2).GetInstanceID())) { _candidateCharacters.Add(val2); } } } private static bool ShouldDrawTarget(EspTarget target, Character local) { if (target == null || !Object.op_Implicit((Object)(object)target.Component)) { return false; } if (Object.op_Implicit((Object)(object)target.Character) && Object.op_Implicit((Object)(object)local) && target.Character == local) { return false; } return target.Kind switch { EspTargetKind.Player => PlayerEspSettings.ShowPlayers, EspTargetKind.Food => PlayerEspSettings.ShowFood, EspTargetKind.Item => PlayerEspSettings.ShowItems, EspTargetKind.Luggage => PlayerEspSettings.ShowLuggage, EspTargetKind.Ghost => PlayerEspSettings.ShowGhosts, EspTargetKind.Hazard => PlayerEspSettings.ShowHazards, _ => false, }; } private bool TryGetScreenRect(Camera camera, EspTarget target, out Rect rect) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) rect = default(Rect); if (!Object.op_Implicit((Object)(object)camera) || target == null || !Object.op_Implicit((Object)(object)target.Component)) { return false; } if (!IsTargetAnchorOnScreen(camera, target)) { return false; } if (Object.op_Implicit((Object)(object)target.Character) && TryGetCharacterScreenRect(camera, target.Character, out rect)) { return true; } if (target.HasBounds && TryGetBoundsScreenRect(camera, target.CachedBounds, _corners, out rect)) { return true; } Bounds bounds = BuildFallbackBounds(target); return TryGetBoundsScreenRect(camera, bounds, _corners, out rect); } private static bool TryGetCharacterScreenRect(Camera camera, Character character, out Rect rect) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003b: 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) //IL_0045: 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_0071: 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) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_004f: 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) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008d: 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_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //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_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) rect = default(Rect); if (!Object.op_Implicit((Object)(object)camera) || !Object.op_Implicit((Object)(object)character)) { return false; } Vector3 val = GetCharacterHead(character); Vector3 val2 = GetCharacterFeet(character, val); if (!IsFinite(val)) { val = val2 + Vector3.up * 2f; } if (!IsFinite(val2) || Vector3.Distance(val, val2) < 0.35f || val2.y > val.y - 0.2f) { val2 = val - Vector3.up * 2f; } Vector3 val3 = camera.WorldToScreenPoint(val2); Vector3 val4 = camera.WorldToScreenPoint(val); if (val3.z <= 0.05f || val4.z <= 0.05f) { return false; } if (!IsScreenPointVisible(val4) && !IsScreenPointVisible(val3)) { return false; } val3.y = (float)Screen.height - val3.y; val4.y = (float)Screen.height - val4.y; float num = Mathf.Abs(val3.y - val4.y); if (num < 8f) { return false; } float num2 = Mathf.Clamp(num * 0.42f, 16f, 260f); float num3 = (val3.x + val4.x) * 0.5f; float num4 = Mathf.Min(val3.y, val4.y); rect = new Rect(num3 - num2 * 0.5f, num4, num2, num); return ClipRectToScreen(ref rect); } private static bool TryGetRendererBounds(Renderer[] renderers, out Bounds bounds) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) bounds = default(Bounds); bool flag = false; if (renderers == null) { return false; } foreach (Renderer val in renderers) { if (!IsUsableRenderer(val)) { continue; } Bounds bounds2 = val.bounds; if (IsUsableBounds(bounds2)) { if (!flag) { bounds = bounds2; flag = true; } else { ((Bounds)(ref bounds)).Encapsulate(bounds2); } } } if (flag) { return IsUsableBounds(bounds); } return false; } private static bool TryGetColliderBounds(Collider[] colliders, out Bounds bounds) { //IL_0001: 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_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_004a: 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) bounds = default(Bounds); if (colliders == null) { return false; } bool flag = false; foreach (Collider val in colliders) { if (!Object.op_Implicit((Object)(object)val) || !val.enabled || !((Component)val).gameObject.activeInHierarchy) { continue; } Bounds bounds2 = val.bounds; if (IsUsableBounds(bounds2)) { if (!flag) { bounds = bounds2; flag = true; } else { ((Bounds)(ref bounds)).Encapsulate(bounds2); } } } if (flag) { return IsUsableBounds(bounds); } return false; } private static bool TryGetBoundsScreenRect(Camera camera, Bounds bounds, Vector3[] corners, out Rect rect) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: 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_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005c: 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_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006e: 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_007a: 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_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0098: 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_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: 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_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: 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_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0165: 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_016d: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01bf: 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_01d3: Unknown result type (might be due to invalid IL or missing references) //IL_01ca: Unknown result type (might be due to invalid IL or missing references) //IL_01de: Unknown result type (might be due to invalid IL or missing references) //IL_0234: Unknown result type (might be due to invalid IL or missing references) //IL_0239: Unknown result type (might be due to invalid IL or missing references) rect = default(Rect); if (!IsUsableBounds(bounds)) { return false; } Vector3 val = camera.WorldToScreenPoint(((Bounds)(ref bounds)).center); if (val.z <= 0.05f) { return false; } if (!IsScreenPointVisible(val)) { return false; } Vector3 min = ((Bounds)(ref bounds)).min; Vector3 max = ((Bounds)(ref bounds)).max; corners[0] = new Vector3(min.x, min.y, min.z); corners[1] = new Vector3(max.x, min.y, min.z); corners[2] = new Vector3(max.x, min.y, max.z); corners[3] = new Vector3(min.x, min.y, max.z); corners[4] = new Vector3(min.x, max.y, min.z); corners[5] = new Vector3(max.x, max.y, min.z); corners[6] = new Vector3(max.x, max.y, max.z); corners[7] = new Vector3(min.x, max.y, max.z); float num = float.MaxValue; float num2 = float.MaxValue; float num3 = float.MinValue; float num4 = float.MinValue; int num5 = 0; foreach (Vector3 val2 in corners) { Vector3 val3 = camera.WorldToScreenPoint(val2); if (!(val3.z <= 0.05f)) { val3.y = (float)Screen.height - val3.y; if (val3.x < num) { num = val3.x; } if (val3.y < num2) { num2 = val3.y; } if (val3.x > num3) { num3 = val3.x; } if (val3.y > num4) { num4 = val3.y; } num5++; } } if (num5 < 2) { return false; } if (num3 < 0f || num > (float)Screen.width || num4 < 0f || num2 > (float)Screen.height) { return false; } rect = Rect.MinMaxRect(num, num2, num3, num4); return ClipRectToScreen(ref rect); } private static Bounds BuildFallbackBounds(EspTarget target) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) Vector3 targetWorldPosition = GetTargetWorldPosition(target); Vector3 val = (Vector3)((target != null && target.Kind == EspTargetKind.Player) ? new Vector3(0.7f, 2f, 0.7f) : Vector3.one); return new Bounds(targetWorldPosition + Vector3.up * (val.y * 0.5f), val); } private static bool ClipRectToScreen(ref Rect rect) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) if (((Rect)(ref rect)).width < 2f || ((Rect)(ref rect)).height < 2f) { return false; } if (!IsFinite(new Vector3(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, ((Rect)(ref rect)).width)) || float.IsNaN(((Rect)(ref rect)).height) || float.IsInfinity(((Rect)(ref rect)).height)) { return false; } float num = Mathf.Clamp(((Rect)(ref rect)).xMin, 0f, (float)Screen.width); float num2 = Mathf.Clamp(((Rect)(ref rect)).xMax, 0f, (float)Screen.width); float num3 = Mathf.Clamp(((Rect)(ref rect)).yMin, 0f, (float)Screen.height); float num4 = Mathf.Clamp(((Rect)(ref rect)).yMax, 0f, (float)Screen.height); if (num2 - num < 2f || num4 - num3 < 2f) { return false; } rect = Rect.MinMaxRect(num, num3, num2, num4); return true; } private static bool IsTargetAnchorOnScreen(Camera camera, EspTarget target) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) Vector3 targetWorldPosition = GetTargetWorldPosition(target); if (!IsFinite(targetWorldPosition)) { return false; } return IsScreenPointVisible(camera.WorldToScreenPoint(targetWorldPosition)); } private static bool IsScreenPointVisible(Vector3 screen) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) if (screen.z > 0.05f && screen.x >= -3f && screen.x <= (float)Screen.width + 3f && screen.y >= -3f) { return screen.y <= (float)Screen.height + 3f; } return false; } private static bool IsUsableRenderer(Renderer renderer) { if (!Object.op_Implicit((Object)(object)renderer) || !renderer.enabled || !((Component)renderer).gameObject.activeInHierarchy) { return false; } if (((Object)((Component)renderer).gameObject).name == "CubeX ESP World Glow") { return false; } string name = ((object)renderer).GetType().Name; if (name.IndexOf("Particle", StringComparison.OrdinalIgnoreCase) >= 0) { return false; } if (string.Equals(name, "TrailRenderer", StringComparison.OrdinalIgnoreCase)) { return false; } return !string.Equals(name, "LineRenderer", StringComparison.OrdinalIgnoreCase); } private static bool IsUsableBounds(Bounds bounds) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_004b: 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) if (!IsFinite(((Bounds)(ref bounds)).center) || !IsFinite(((Bounds)(ref bounds)).size)) { return false; } Vector3 size = ((Bounds)(ref bounds)).size; if (((Vector3)(ref size)).sqrMagnitude <= 0.0001f) { return false; } if (((Bounds)(ref bounds)).size.x > 80f || ((Bounds)(ref bounds)).size.y > 80f || ((Bounds)(ref bounds)).size.z > 80f) { return false; } return true; } private static void DrawBox(Rect rect, Color color, float thickness) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_002e: 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_007a: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) thickness = Mathf.Max(1f, thickness); Color color2 = GUI.color; GUI.color = color; GUI.DrawTexture(new Rect(((Rect)(ref rect)).xMin, ((Rect)(ref rect)).yMin, ((Rect)(ref rect)).width, thickness), (Texture)(object)Texture2D.whiteTexture); GUI.DrawTexture(new Rect(((Rect)(ref rect)).xMin, ((Rect)(ref rect)).yMax - thickness, ((Rect)(ref rect)).width, thickness), (Texture)(object)Texture2D.whiteTexture); GUI.DrawTexture(new Rect(((Rect)(ref rect)).xMin, ((Rect)(ref rect)).yMin, thickness, ((Rect)(ref rect)).height), (Texture)(object)Texture2D.whiteTexture); GUI.DrawTexture(new Rect(((Rect)(ref rect)).xMax - thickness, ((Rect)(ref rect)).yMin, thickness, ((Rect)(ref rect)).height), (Texture)(object)Texture2D.whiteTexture); GUI.color = color2; } private static void DrawLine(Vector2 start, Vector2 end, Color color, float thickness) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0047: 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_005d: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) Vector2 val = end - start; float magnitude = ((Vector2)(ref val)).magnitude; if (!(magnitude <= 0.5f)) { Matrix4x4 matrix = GUI.matrix; Color color2 = GUI.color; GUI.color = color; GUIUtility.RotateAroundPivot(Mathf.Atan2(val.y, val.x) * 57.29578f, start); GUI.DrawTexture(new Rect(start.x, start.y - thickness * 0.5f, magnitude, thickness), (Texture)(object)Texture2D.whiteTexture); GUI.matrix = matrix; GUI.color = color2; } } private void DrawInfo(Rect rect, EspTarget target, float distance) { //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) EnsureInfoStyles(); string text = target.DisplayName + (IsDead(target.Character) ? " [Dead]" : string.Empty) + " - " + distance.ToString("F1", CultureInfo.InvariantCulture) + "m"; Rect val = default(Rect); ((Rect)(ref val))..ctor(((Rect)(ref rect)).center.x - 120f, Mathf.Max(0f, ((Rect)(ref rect)).yMin - 22f - 4f), 240f, 22f); GUI.Label(new Rect(((Rect)(ref val)).x + 1f, ((Rect)(ref val)).y + 1f, ((Rect)(ref val)).width, ((Rect)(ref val)).height), text, _infoShadowStyle); GUI.Label(val, text, _infoStyle); } private void EnsureInfoStyles() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003e: 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_0053: Expected O, but got Unknown //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Expected O, but got Unknown //IL_0083: Unknown result type (might be due to invalid IL or missing references) if (_infoStyle == null || _infoShadowStyle == null) { GUIStyle val = new GUIStyle(GUI.skin.label) { alignment = (TextAnchor)4, fontSize = 13, fontStyle = (FontStyle)1, clipping = (TextClipping)1 }; val.normal.textColor = Color.white; _infoStyle = val; _infoShadowStyle = new GUIStyle(_infoStyle); _infoShadowStyle.normal.textColor = new Color(0f, 0f, 0f, 0.9f); } } private static bool IsPlayerCharacter(Character character, Character local) { if (!Object.op_Implicit((Object)(object)character)) { return false; } if (Object.op_Implicit((Object)(object)local) && character == local) { return true; } if (character.isBot || character.isZombie || character.isScoutmaster) { return false; } PhotonView photonView = VisualPlayerText.GetPhotonView((Component)(object)character); if (Object.op_Implicit((Object)(object)photonView) && (photonView.Controller != null || photonView.Owner != null)) { return true; } if (!VisualPlayerText.IsRealPlayer(character)) { return SafeIsPlayerControlled(character); } return true; } private static EspTargetKind ClassifyCharacterEntity(Character character) { if (!Object.op_Implicit((Object)(object)character)) { return EspTargetKind.Hazard; } if (!character.isScoutmaster && !character.isZombie && !character.isBot) { return EspTargetKind.Item; } return EspTargetKind.Hazard; } private static bool IsFoodItem(Item item) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Invalid comparison between Unknown and I4 if (!Object.op_Implicit((Object)(object)item)) { return false; } return (item.itemTags & 0x2E) > 0; } private static bool SafeIsRegisteredToPlayer(Character character) { try { return Object.op_Implicit((Object)(object)character) && character.IsRegisteredToPlayer; } catch { return false; } } private static bool SafeIsPlayerControlled(Character character) { try { return Object.op_Implicit((Object)(object)character) && character.IsPlayerControlled; } catch { return false; } } private static bool IsDead(Character character) { try { return Object.op_Implicit((Object)(object)character) && Object.op_Implicit((Object)(object)character.data) && character.data.dead; } catch { return false; } } private static string BuildCharacterTargetKey(Character character, bool isPlayer) { if (!Object.op_Implicit((Object)(object)character)) { return null; } PhotonView photonView = VisualPlayerText.GetPhotonView((Component)(object)character); Player val = (Object.op_Implicit((Object)(object)photonView) ? (photonView.Controller ?? photonView.Owner) : null); if (isPlayer) { if (val != null && val.ActorNumber > 0) { return "player-actor-" + val.ActorNumber.ToString(CultureInfo.InvariantCulture); } if (val != null && !string.IsNullOrWhiteSpace(val.UserId)) { return "player-user-" + val.UserId; } } return (isPlayer ? "player-object-" : "character-entity-") + ((Object)character).GetInstanceID().ToString(CultureInfo.InvariantCulture); } private static int GetCharacterTargetScore(Character character, bool isPlayer) { int num = 0; if (isPlayer) { num += 1000; } if (!IsDead(character)) { num += 250; } if (SafeIsRegisteredToPlayer(character)) { num += 120; } if (SafeIsPlayerControlled(character)) { num += 80; } if (Object.op_Implicit((Object)(object)character) && Object.op_Implicit((Object)(object)character.data)) { num += 60; } if (Object.op_Implicit((Object)(object)character) && Object.op_Implicit((Object)(object)character.refs?.view)) { num += 50; } if (Object.op_Implicit((Object)(object)character) && Object.op_Implicit((Object)(object)character.refs?.movement)) { num += 50; } if (Object.op_Implicit((Object)(object)character) && Object.op_Implicit((Object)(object)character.player)) { num += 40; } PhotonView photonView = VisualPlayerText.GetPhotonView((Component)(object)character); if (Object.op_Implicit((Object)(object)photonView) && photonView.Controller != null) { num += 120; } if (Object.op_Implicit((Object)(object)photonView) && photonView.Owner != null) { num += 100; } if (Object.op_Implicit((Object)(object)character) && ((Component)character).gameObject.activeInHierarchy) { num += 25; } return num; } private static Vector3 GetTargetWorldPosition(EspTarget target) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0051: 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) if (target == null || !Object.op_Implicit((Object)(object)target.Component)) { return Vector3.zero; } if (Object.op_Implicit((Object)(object)target.Character)) { return GetCharacterAnchor(target.Character); } if (!target.HasBounds) { return target.Component.transform.position; } Bounds cachedBounds = target.CachedBounds; return ((Bounds)(ref cachedBounds)).center; } private static Vector3 GetCharacterAnchor(Character character) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)character)) { return Vector3.zero; } Vector3 characterHead = GetCharacterHead(character); if (!IsFinite(characterHead) || !(characterHead != Vector3.zero)) { return ((Component)character).transform.position + Vector3.up; } return characterHead; } private static Vector3 GetCharacterHead(Character character) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: 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) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_004b: 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) //IL_0074: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)character)) { return Vector3.zero; } if (VisualPlayerText.TryGetVisualPosition(character, out var position)) { return position + Vector3.up * 2f; } try { Vector3 head = character.Head; if (IsFinite(head) && head != Vector3.zero) { return head; } } catch { } return ((Component)character).transform.position + Vector3.up * 2f; } private static Vector3 GetCharacterFeet(Character character, Vector3 head) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0060: 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) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: 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_00d0: 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_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00af: 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_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) if (VisualPlayerText.TryGetVisualPosition(character, out var position)) { return position; } Vector3 sum = Vector3.zero; float lowestY = float.MaxValue; int count = 0; AddFootCandidate(character, (BodypartType)27, ref sum, ref lowestY, ref count); AddFootCandidate(character, (BodypartType)28, ref sum, ref lowestY, ref count); AddFootCandidate(character, (BodypartType)13, ref sum, ref lowestY, ref count); AddFootCandidate(character, (BodypartType)16, ref sum, ref lowestY, ref count); if (count > 0) { return new Vector3(sum.x / (float)count, lowestY, sum.z / (float)count); } if (TryGetBodypartPosition(character, (BodypartType)0, out var position2)) { return position2 - Vector3.up * 0.95f; } try { Vector3 center = character.Center; if (IsFinite(center)) { return center - Vector3.up * 0.9f; } } catch { } if (!IsFinite(head)) { return ((Component)character).transform.position; } return head - Vector3.up * 2f; } private static void AddFootCandidate(Character character, BodypartType partType, ref Vector3 sum, ref float lowestY, ref int count) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) if (TryGetBodypartPosition(character, partType, out var position)) { sum += position; if (position.y < lowestY) { lowestY = position.y; } count++; } } private static bool TryGetBodypartPosition(Character character, BodypartType partType, out Vector3 position) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_005c: 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_0067: Unknown result type (might be due to invalid IL or missing references) position = default(Vector3); if (!Object.op_Implicit((Object)(object)character)) { return false; } try { CharacterRagdoll val = character.refs?.ragdoll; if (!Object.op_Implicit((Object)(object)val) || val.partDict == null) { return false; } if (!val.partDict.TryGetValue(partType, out var value) || !Object.op_Implicit((Object)(object)value)) { return false; } position = ((Component)value).transform.position; return IsFinite(position); } catch { return false; } } private static string GetCharacterDisplayName(Character character, bool isPlayer) { if (isPlayer) { return VisualPlayerText.GetName(character); } if (character.isScoutmaster) { return "Scoutmaster"; } if (character.isZombie) { return "Zombie"; } if (character.isBot) { return "Bot"; } return CleanObjectName(((Object)character).name, "Entity " + ((Object)character).GetInstanceID().ToString(CultureInfo.InvariantCulture)); } private static bool IsChickenCharacter(Character character) { if (!Object.op_Implicit((Object)(object)character)) { return false; } string obj = ((Object)character).name ?? string.Empty; string name = ((object)character).GetType().Name; if (obj.IndexOf("chicken", StringComparison.OrdinalIgnoreCase) < 0) { return name.IndexOf("chicken", StringComparison.OrdinalIgnoreCase) >= 0; } return true; } private static string CleanObjectName(string name, string fallback) { if (string.IsNullOrWhiteSpace(name)) { return fallback; } int num = name.IndexOf("(Clone)", StringComparison.OrdinalIgnoreCase); if (num >= 0) { name = name.Substring(0, num).Trim(); } if (!string.IsNullOrEmpty(name)) { return name; } return fallback; } private static bool IsFinite(Vector3 value) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) if (!float.IsNaN(value.x) && !float.IsInfinity(value.x) && !float.IsNaN(value.y) && !float.IsInfinity(value.y) && !float.IsNaN(value.z)) { return !float.IsInfinity(value.z); } return false; } } public class PlayerEspEntityColor : ColorFeature { public override int PresetCount => MenuConfig.Presets.Length; public PlayerEspEntityColor() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) base.Name = "ESP Entity Color"; base.Description = "Box, tracer, and glow color used for non-player entity targets."; base.Value = PlayerEspSettings.EntityColor; } public override string GetPresetName(int index) { if (index < 0 || index >= MenuConfig.Presets.Length) { return string.Empty; } return MenuConfig.Presets[index].Name; } public override Color GetPresetColor(int index) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) if (index < 0 || index >= MenuConfig.Presets.Length) { return Color.white; } return MenuConfig.Presets[index].Color; } protected override void OnColorChanged(Color newColor) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) PlayerEspSettings.EntityColor = newColor; } } public class PlayerEspFood : PlayerEspTargetToggle { public PlayerEspFood() { base.Name = "ESP Food"; base.Description = "Includes food-tagged items such as packaged food, berries, and mushrooms."; } protected override void SetEnabled(bool enabled) { PlayerEspSettings.ShowFood = enabled; } } public class PlayerEspGhosts : PlayerEspTargetToggle { public PlayerEspGhosts() { base.Name = "ESP Ghosts"; base.Description = "Includes player ghost entities."; } protected override void SetEnabled(bool enabled) { PlayerEspSettings.ShowGhosts = enabled; } } public class PlayerEspHazards : PlayerEspTargetToggle { public PlayerEspHazards() { base.Name = "ESP Hazards"; base.Description = "Includes Scoutmasters, tornadoes, bee swarms, bots, and zombie-like threats."; } protected override void SetEnabled(bool enabled) { PlayerEspSettings.ShowHazards = enabled; } } public class PlayerEspItems : PlayerEspTargetToggle { public PlayerEspItems() { base.Name = "ESP Items"; base.Description = "Includes non-food world items."; } protected override void SetEnabled(bool enabled) { PlayerEspSettings.ShowItems = enabled; } } public class PlayerEspLuggage : PlayerEspTargetToggle { public PlayerEspLuggage() { base.Name = "ESP Luggage"; base.Description = "Includes luggage containers."; } protected override void SetEnabled(bool enabled) { PlayerEspSettings.ShowLuggage = enabled; } } public class PlayerEspMaxDistance : NumberFeature { public PlayerEspMaxDistance() { base.Name = "ESP Max Distance"; base.Description = "Limits ESP rendering to targets within this many meters."; base.Min = 25f; base.Max = 2000f; base.Value = PlayerEspSettings.MaxDistance; base.Step = 25f; base.Decimals = 0; base.Unit = "m"; } protected override void OnValueChanged(float newValue) { PlayerEspSettings.MaxDistance = Mathf.Clamp(newValue, base.Min, base.Max); PlayerEsp.RequestRefresh(); } } public class PlayerEspMaxTargets : NumberFeature { public PlayerEspMaxTargets() { base.Name = "ESP Max Targets"; base.Description = "Caps how many closest ESP targets can be drawn per pass."; base.Min = 8f; base.Max = 256f; base.Value = PlayerEspSettings.MaxTargets; base.Step = 8f; base.Decimals = 0; } protected override void OnValueChanged(float newValue) { PlayerEspSettings.MaxTargets = Mathf.Clamp(Mathf.RoundToInt(newValue), (int)base.Min, (int)base.Max); } } public class PlayerEspOutlineGlow : Feature { public PlayerEspOutlineGlow() { base.Name = "ESP Glow"; base.Description = "Draws in-world outline glow for enabled ESP targets."; } protected override void OnEnable() { PlayerEspSettings.ShowWorldGlow = true; PlayerEsp.RequestRefresh(); } protected override void OnDisable() { PlayerEspSettings.ShowWorldGlow = false; PlayerEsp.RequestRefresh(); PlayerEsp.ClearWorldGlow(); } public override void OnRender() { PlayerEsp.RenderShared(); } } public class PlayerEspPlayerColor : ColorFeature { public override int PresetCount => MenuConfig.Presets.Length; public PlayerEspPlayerColor() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) base.Name = "ESP Player Color"; base.Description = "Box, tracer, and glow color used for player targets."; base.Value = PlayerEspSettings.PlayerColor; } public override string GetPresetName(int index) { if (index < 0 || index >= MenuConfig.Presets.Length) { return string.Empty; } return MenuConfig.Presets[index].Name; } public override Color GetPresetColor(int index) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) if (index < 0 || index >= MenuConfig.Presets.Length) { return Color.white; } return MenuConfig.Presets[index].Color; } protected override void OnColorChanged(Color newColor) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) PlayerEspSettings.PlayerColor = newColor; } } public class PlayerEspPlayers : PlayerEspTargetToggle { public PlayerEspPlayers() { base.Name = "ESP Players"; base.Description = "Includes remote player characters in ESP layers."; base.Enabled = true; } protected override void SetEnabled(bool enabled) { PlayerEspSettings.ShowPlayers = enabled; } } public class PlayerEspRefreshDelay : NumberFeature { public PlayerEspRefreshDelay() { base.Name = "ESP Refresh Delay"; base.Description = "Controls how often ESP rescans loaded targets. Higher values reduce CPU usage."; base.Min = 0.5f; base.Max = 5f; base.Value = PlayerEspSettings.RefreshInterval; base.Step = 0.1f; base.Decimals = 1; base.Unit = "s"; } protected override void OnValueChanged(float newValue) { PlayerEspSettings.RefreshInterval = Mathf.Clamp(newValue, base.Min, base.Max); PlayerEsp.RequestRefresh(); } } internal static class PlayerEspSettings { public static float MaxDistance = 250f; public static int MaxTargets = 32; public static float RefreshInterval = 1.25f; public static bool ShowPlayers = true; public static bool ShowFood; public static bool ShowItems; public static bool ShowLuggage; public static bool ShowGhosts; public static bool ShowHazards; public static bool ShowLines; public static bool ShowInfo; public static bool ShowWorldGlow; public static Color PlayerColor = MenuConfig.AccentColor; public static Color EntityColor = new Color(1f, 0.72f, 0.18f, 1f); public static PlayerEspTargetFlags TargetFlags { get { PlayerEspTargetFlags playerEspTargetFlags = PlayerEspTargetFlags.None; if (ShowPlayers) { playerEspTargetFlags |= PlayerEspTargetFlags.Players; } if (ShowFood) { playerEspTargetFlags |= PlayerEspTargetFlags.Food; } if (ShowItems) { playerEspTargetFlags |= PlayerEspTargetFlags.Items; } if (ShowLuggage) { playerEspTargetFlags |= PlayerEspTargetFlags.Luggage; } if (ShowGhosts) { playerEspTargetFlags |= PlayerEspTargetFlags.Ghosts; } if (ShowHazards) { playerEspTargetFlags |= PlayerEspTargetFlags.Hazards; } return playerEspTargetFlags; } } } public class PlayerEspShowInfo : Feature { public PlayerEspShowInfo() { base.Name = "ESP Info"; base.Description = "Draws target names and distances above enabled ESP targets."; } protected override void OnEnable() { PlayerEspSettings.ShowInfo = true; PlayerEsp.RequestRefresh(); } protected override void OnDisable() { PlayerEspSettings.ShowInfo = false; PlayerEsp.RequestRefresh(); } public override void OnRender() { PlayerEsp.RenderShared(); } } public class PlayerEspShowLines : Feature { public PlayerEspShowLines() { base.Name = "ESP Lines"; base.Description = "Draws tracer lines from the bottom center of the screen to enabled ESP targets."; } protected override void OnEnable() { PlayerEspSettings.ShowLines = true; PlayerEsp.RequestRefresh(); } protected override void OnDisable() { PlayerEspSettings.ShowLines = false; PlayerEsp.RequestRefresh(); } public override void OnRender() { PlayerEsp.RenderShared(); } } [Flags] internal enum PlayerEspTargetFlags { None = 0, Players = 1, Food = 2, Items = 4, Luggage = 8, Ghosts = 0x10, Hazards = 0x20 } public abstract class PlayerEspTargetToggle : Feature { protected override void OnEnable() { SetEnabled(enabled: true); PlayerEsp.RequestRefresh(); } protected override void OnDisable() { SetEnabled(enabled: false); PlayerEsp.RequestRefresh(); } protected abstract void SetEnabled(bool enabled); } public class PlayerFlagTags : Feature { private GUIStyle _style; private GUIStyle _shadowStyle; public PlayerFlagTags() { base.Name = "Player Flag Tags"; base.Description = "Shows safe custom-property player flags above flagged live players."; } public override void OnRender() { //IL_0072: 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_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007c: 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) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_009c: 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_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) Camera main = Camera.main; Character localCharacter = Character.localCharacter; if (!Object.op_Implicit((Object)(object)main)) { return; } EnsureStyles(); Rect val3 = default(Rect); foreach (Character character in GameActions.GetCharacters()) { if (!Object.op_Implicit((Object)(object)character) || !VisualPlayerText.IsRealPlayer(character) || (Object.op_Implicit((Object)(object)localCharacter) && character == localCharacter)) { continue; } string flagText = PlayerFlagDetector.GetFlagText(GetPhotonPlayer((Component)(object)character)); if (!string.IsNullOrEmpty(flagText)) { Vector3 val = ProfileCardsOverlayAnchor(character); Vector3 val2 = main.WorldToScreenPoint(val); if (!(val2.z <= 0f)) { val2.y = (float)Screen.height - val2.y; string text = flagText.ToUpperInvariant(); ((Rect)(ref val3))..ctor(val2.x - 110f, val2.y - 18f, 220f, 22f); GUI.Label(new Rect(((Rect)(ref val3)).x + 1f, ((Rect)(ref val3)).y + 1f, ((Rect)(ref val3)).width, ((Rect)(ref val3)).height), text, _shadowStyle); GUI.Label(val3, text, _style); } } } } private static Player GetPhotonPlayer(Component component) { PhotonView photonView = VisualPlayerText.GetPhotonView(component); if (!Object.op_Implicit((Object)(object)photonView)) { return null; } return photonView.Controller ?? photonView.Owner; } private static Vector3 ProfileCardsOverlayAnchor(Character character) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0058: 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_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0036: 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) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: 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) if (VisualPlayerText.TryGetVisualPosition(character, out var position)) { return position + Vector3.up * 2.45f; } try { Vector3 head = character.Head; if (head != Vector3.zero) { return head + Vector3.up * 0.82f; } } catch { } return ((Component)character).transform.position + Vector3.up * 2.55f; } private void EnsureStyles() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Expected O, but got Unknown //IL_0066: 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_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Expected O, but got Unknown if (_style == null) { GUIStyle val = new GUIStyle(GUI.skin.label) { alignment = (TextAnchor)4, clipping = (TextClipping)1, fontSize = 12, fontStyle = (FontStyle)1 }; val.normal.textColor = new Color(1f, 0.3f, 0.42f, 1f); _style = val; GUIStyle val2 = new GUIStyle(_style); val2.normal.textColor = new Color(0f, 0f, 0f, 0.95f); _shadowStyle = val2; } } } public class ProfileCardScale : NumberFeature { public ProfileCardScale() { base.Name = "Profile Card Scale"; base.Description = "Controls the size of in-world profile cards."; base.Min = 0.65f; base.Max = 1.5f; base.Value = ProfileCardSettings.Scale; base.Step = 0.05f; base.Decimals = 2; base.Unit = "x"; } protected override void OnValueChanged(float newValue) { ProfileCardSettings.Scale = Mathf.Clamp(newValue, base.Min, base.Max); } } internal static class ProfileCardSettings { public static bool ExcludeSelf = true; public static bool ProfileCardsEnabled; public static bool ShowStaminaBars; public static float MaxDistance = 160f; public static float Scale = 1f; } public class ProfileCardsMaxDistance : NumberFeature { public ProfileCardsMaxDistance() { base.Name = "Profile Card Distance"; base.Description = "Maximum distance for drawing profile cards."; base.Min = 1f; base.Max = 1000f; base.Value = ProfileCardSettings.MaxDistance; base.Step = 10f; base.Decimals = 0; base.Unit = "m"; } protected override void OnValueChanged(float newValue) { ProfileCardSettings.MaxDistance = Mathf.Clamp(newValue, base.Min, base.Max); } } public class ProfileCardsOverlay : Feature { private const int MaxCards = 12; private const float CameraRefreshInterval = 0.5f; private GUIStyle _nameStyle; private GUIStyle _detailStyle; private GUIStyle _tagStyle; private Camera _camera; private float _nextCameraRefreshAt; public ProfileCardsOverlay() { base.Name = "Profile Cards"; base.Description = "Draws compact in-world cards with player name, status, distance, actor, and safe flags."; } protected override void OnEnable() { ProfileCardSettings.ProfileCardsEnabled = true; } protected override void OnDisable() { ProfileCardSettings.ProfileCardsEnabled = false; } public override void OnRender() { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_003f: 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) //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_009d: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: 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_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) Camera camera = GetCamera(); Character localCharacter = Character.localCharacter; if (!Object.op_Implicit((Object)(object)camera)) { return; } EnsureStyles(); int num = 0; Vector3 position = ((Component)camera).transform.position; Vector3 forward = ((Component)camera).transform.forward; Vector3 val = (Object.op_Implicit((Object)(object)localCharacter) ? GetCardAnchor(localCharacter) : Vector3.zero); float num2 = Mathf.Max(0f, ProfileCardSettings.MaxDistance); float num3 = num2 * num2; foreach (Character character in GameActions.GetCharacters()) { if (num >= 12) { break; } if (!ShouldDraw(character, localCharacter)) { continue; } Vector3 cardAnchor = GetCardAnchor(character); Vector3 val2 = cardAnchor - position; if (Vector3.Dot(forward, val2) <= 0f) { continue; } float num4; if (!Object.op_Implicit((Object)(object)localCharacter)) { num4 = 0f; } else { Vector3 val3 = cardAnchor - val; num4 = ((Vector3)(ref val3)).sqrMagnitude; } float num5 = num4; if (!(num5 > num3)) { Vector3 val4 = camera.WorldToScreenPoint(cardAnchor); if (!(val4.z <= 0f)) { val4.y = (float)Screen.height - val4.y; DrawCard(character, val4, Mathf.Sqrt(num5)); num++; } } } } private Camera GetCamera() { if (Object.op_Implicit((Object)(object)_camera) && Time.unscaledTime < _nextCameraRefreshAt) { return _camera; } _camera = Camera.main; _nextCameraRefreshAt = Time.unscaledTime + 0.5f; return _camera; } private static bool ShouldDraw(Character character, Character local) { if (!Object.op_Implicit((Object)(object)character) || !VisualPlayerText.IsRealPlayer(character)) { return false; } if (ProfileCardSettings.ExcludeSelf && Object.op_Implicit((Object)(object)local)) { return character != local; } return true; } private void DrawCard(Character character, Vector3 screen, float distance) { //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: 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_01be: Unknown result type (might be due to invalid IL or missing references) //IL_01d4: Unknown result type (might be due to invalid IL or missing references) //IL_020f: Unknown result type (might be due to invalid IL or missing references) //IL_0214: Unknown result type (might be due to invalid IL or missing references) //IL_0294: Unknown result type (might be due to invalid IL or missing references) //IL_0315: Unknown result type (might be due to invalid IL or missing references) //IL_035e: Unknown result type (might be due to invalid IL or missing references) //IL_036d: 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) float num = Mathf.Clamp(ProfileCardSettings.Scale, 0.65f, 1.5f); bool flag = ProfileCardSettings.ShowStaminaBars && Object.op_Implicit((Object)(object)character.data); IReadOnlyList readOnlyList = (flag ? PlayerVitalsRenderer.GetActiveAfflictions(character) : null); bool flag2 = readOnlyList != null && readOnlyList.Count > 0; float num2 = (flag2 ? 264f : 228f) * num; float num3 = (flag2 ? PlayerVitalsRenderer.GetAfflictionBadgeHeight(readOnlyList, num2 - 24f * num, num, 2) : 0f); float num4 = ((!flag) ? (78f * num) : (flag2 ? (104f * num + num3) : (100f * num))); float num5 = Mathf.Clamp(screen.x - num2 * 0.5f, 8f, Mathf.Max(8f, (float)Screen.width - num2 - 8f)); float num6 = Mathf.Clamp(screen.y - num4 - 24f * num, 8f, Mathf.Max(8f, (float)Screen.height - num4 - 8f)); Rect val = default(Rect); ((Rect)(ref val))..ctor(num5, num6, num2, num4); Player photonPlayer = GetPhotonPlayer((Component)(object)character); string name = VisualPlayerText.GetName(character); string status = GetStatus(character); string text = ((photonPlayer != null && photonPlayer.ActorNumber > 0) ? ("#" + photonPlayer.ActorNumber.ToString(CultureInfo.InvariantCulture)) : "-"); string flagText = PlayerFlagDetector.GetFlagText(photonPlayer); Color playerColor = GetPlayerColor(character); Theme.Fill(val, new Color(0.035f, 0.036f, 0.04f, 0.86f)); Theme.Fill(new Rect(((Rect)(ref val)).x, ((Rect)(ref val)).y, 3f * num, ((Rect)(ref val)).height), playerColor); DrawOutline(val, new Color(1f, 1f, 1f, 0.14f), 1f); Theme.Fill(new Rect(((Rect)(ref val)).x + 12f * num, ((Rect)(ref val)).y + 14f * num, 14f * num, 14f * num), playerColor); _nameStyle.fontSize = Mathf.RoundToInt(13f * num); _detailStyle.fontSize = Mathf.RoundToInt(10f * num); _tagStyle.fontSize = Mathf.RoundToInt(9f * num); GUI.Label(new Rect(((Rect)(ref val)).x + 34f * num, ((Rect)(ref val)).y + 8f * num, ((Rect)(ref val)).width - 44f * num, 20f * num), name, _nameStyle); string text2 = status + " | " + distance.ToString("F0", CultureInfo.InvariantCulture) + "m | " + text; GUI.Label(new Rect(((Rect)(ref val)).x + 12f * num, ((Rect)(ref val)).y + 31f * num, ((Rect)(ref val)).width - 24f * num, 16f * num), text2, _detailStyle); DrawFlagTags(flagText, new Rect(((Rect)(ref val)).x + 12f * num, ((Rect)(ref val)).y + 51f * num, ((Rect)(ref val)).width - 24f * num, 18f * num), num); if (flag) { DrawStaminaBar(character, val, num, playerColor, flag2, readOnlyList); } } internal static void DrawStaminaBar(Character character, Rect box, float scale, Color accent, bool showAfflictionBadges = false, IReadOnlyList afflictions = null) { //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)character) && Object.op_Implicit((Object)(object)character.data)) { if (afflictions == null) { afflictions = PlayerVitalsRenderer.GetActiveAfflictions(character); } bool num = showAfflictionBadges && afflictions.Count > 0; bool flag = ((Rect)(ref box)).height <= 42f * scale; float num2 = (num ? PlayerVitalsRenderer.GetAfflictionBadgeHeight(afflictions, ((Rect)(ref box)).width - 24f * scale, scale, 2) : 0f); float num3 = (flag ? (7f * scale) : (13f * scale)); float num4 = (num ? (((Rect)(ref box)).yMax - num2 - 31f * scale) : (((Rect)(ref box)).yMax - (flag ? 17f : 20f) * scale)); Rect rect = default(Rect); ((Rect)(ref rect))..ctor(((Rect)(ref box)).x + 12f * scale, num4, ((Rect)(ref box)).width - 24f * scale, num3); PlayerVitalsRenderer.DrawStaminaBar(rect, character, afflictions, scale, accent, !flag); if (num) { PlayerVitalsRenderer.DrawAfflictionBadges(new Rect(((Rect)(ref box)).x + 12f * scale, ((Rect)(ref rect)).yMax + 7f * scale, ((Rect)(ref box)).width - 24f * scale, num2), afflictions, scale); } } } private void DrawFlagTags(string flags, Rect rect, float scale) { //IL_000f: 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_004e: Expected O, but got Unknown //IL_0049: 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) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) IReadOnlyList readOnlyList = PlayerFlagDetector.SplitFlagText(flags); if (readOnlyList.Count == 0) { GUI.Label(rect, "No flags", _detailStyle); return; } float num = ((Rect)(ref rect)).x; for (int i = 0; i < readOnlyList.Count && i < 3; i++) { string text = readOnlyList[i].ToUpperInvariant(); float num2 = Mathf.Min(_tagStyle.CalcSize(new GUIContent(text)).x + 12f * scale, ((Rect)(ref rect)).xMax - num); if (!(num2 <= 14f * scale)) { Rect val = new Rect(num, ((Rect)(ref rect)).y, num2, ((Rect)(ref rect)).height); Theme.Fill(val, PlayerFlagDetector.GetTagColor(readOnlyList[i])); GUI.Label(val, text, _tagStyle); num += num2 + 4f * scale; continue; } break; } } private static string GetStatus(Character character) { if (!Object.op_Implicit((Object)(object)character) || !Object.op_Implicit((Object)(object)character.data)) { return "Alive"; } if (character.data.dead) { return "Dead"; } if (character.data.fullyPassedOut) { return "Downed"; } return "Alive"; } private static Player GetPhotonPlayer(Component component) { PhotonView photonView = VisualPlayerText.GetPhotonView(component); if (!Object.op_Implicit((Object)(object)photonView)) { return null; } return photonView.Controller ?? photonView.Owner; } private static Vector3 GetCardAnchor(Character character) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: 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_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_004b: 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) //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_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)character)) { return Vector3.zero; } if (VisualPlayerText.TryGetVisualPosition(character, out var position)) { return position + Vector3.up * 2.05f; } try { Vector3 head = character.Head; if (IsFinite(head) && head != Vector3.zero) { return head + Vector3.up * 0.42f; } } catch { } return ((Component)character).transform.position + Vector3.up * 2.2f; } private static Color GetPlayerColor(Character character) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) try { if (Object.op_Implicit((Object)(object)character) && Object.op_Implicit((Object)(object)character.refs?.customization)) { return character.refs.customization.PlayerColor; } } catch { } return Theme.Accent; } private static bool IsFinite(Vector3 value) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) if (!float.IsNaN(value.x) && !float.IsInfinity(value.x) && !float.IsNaN(value.y) && !float.IsInfinity(value.y) && !float.IsNaN(value.z)) { return !float.IsInfinity(value.z); } return false; } private static void DrawOutline(Rect rect, Color color, float thickness) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: 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_0082: Unknown result type (might be due to invalid IL or missing references) Theme.Fill(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, ((Rect)(ref rect)).width, thickness), color); Theme.Fill(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).yMax - thickness, ((Rect)(ref rect)).width, thickness), color); Theme.Fill(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, thickness, ((Rect)(ref rect)).height), color); Theme.Fill(new Rect(((Rect)(ref rect)).xMax - thickness, ((Rect)(ref rect)).y, thickness, ((Rect)(ref rect)).height), color); } private void EnsureStyles() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Expected O, but got Unknown //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_005a: 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_007b: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Expected O, but got Unknown //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Expected O, but got Unknown if (_nameStyle == null) { GUIStyle val = new GUIStyle(GUI.skin.label) { alignment = (TextAnchor)3, clipping = (TextClipping)1, fontStyle = (FontStyle)1 }; val.normal.textColor = Color.white; _nameStyle = val; GUIStyle val2 = new GUIStyle(GUI.skin.label) { alignment = (TextAnchor)3, clipping = (TextClipping)1 }; val2.normal.textColor = new Color(0.76f, 0.78f, 0.82f, 1f); _detailStyle = val2; GUIStyle val3 = new GUIStyle(GUI.skin.label) { alignment = (TextAnchor)4, clipping = (TextClipping)1, fontStyle = (FontStyle)1 }; val3.normal.textColor = Color.white; _tagStyle = val3; } } } public class ProfileCardsSelectedOnly : Feature { public ProfileCardsSelectedOnly() { base.Name = "Exclude Self"; base.Description = "Hides your local player card while profile cards are enabled."; base.Enabled = true; } protected override void OnEnable() { ProfileCardSettings.ExcludeSelf = true; } protected override void OnDisable() { ProfileCardSettings.ExcludeSelf = false; } } public class DayNightTimeHud : Feature { private const float RefreshInterval = 0.5f; private const float FallbackDayStart = 5f; private const float FallbackDayEnd = 21f; private GUIStyle _iconStyle; private GUIStyle _titleStyle; private GUIStyle _bodyStyle; private float _nextRefreshAt; private float _timeOfDay = 9f; private float _dayStart = 5f; private float _dayEnd = 21f; private bool _hasGameTime; public DayNightTimeHud() { base.Name = "Day/Night Time"; base.Description = "Draws a compact day/night icon with the current in-game day time."; } public override void OnRender() { //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Unknown result type (might be due to invalid IL or missing references) //IL_0226: Unknown result type (might be due to invalid IL or missing references) //IL_0246: 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_025f: 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_0281: Unknown result type (might be due to invalid IL or missing references) //IL_0283: Unknown result type (might be due to invalid IL or missing references) //IL_02a4: Unknown result type (might be due to invalid IL or missing references) //IL_02a9: Unknown result type (might be due to invalid IL or missing references) //IL_02dc: Unknown result type (might be due to invalid IL or missing references) //IL_02e1: Unknown result type (might be due to invalid IL or missing references) //IL_02e8: Unknown result type (might be due to invalid IL or missing references) //IL_02ea: Unknown result type (might be due to invalid IL or missing references) //IL_02f6: Unknown result type (might be due to invalid IL or missing references) //IL_030c: Unknown result type (might be due to invalid IL or missing references) //IL_0340: Unknown result type (might be due to invalid IL or missing references) //IL_0345: Unknown result type (might be due to invalid IL or missing references) //IL_034d: Unknown result type (might be due to invalid IL or missing references) //IL_0351: Unknown result type (might be due to invalid IL or missing references) //IL_0355: Unknown result type (might be due to invalid IL or missing references) //IL_035e: Unknown result type (might be due to invalid IL or missing references) RefreshTimeIfNeeded(); EnsureStyles(); float num = Mathf.Repeat(_timeOfDay, 24f); int num2 = Mathf.FloorToInt(num); int num3 = Mathf.FloorToInt((num - (float)num2) * 60f); bool flag = IsDay(num); float cycleFill = GetCycleFill(num, flag); string activeIcon = (flag ? "☀" : "☾"); string baseIcon = (flag ? "☾" : "☀"); string text = (flag ? "DAY" : "NIGHT"); string text2 = num2.ToString("00", CultureInfo.InvariantCulture) + ":" + num3.ToString("00", CultureInfo.InvariantCulture); if (!_hasGameTime) { text2 += " ?"; } float num4 = 148f; float num5 = 58f; float num6 = Mathf.Max(12f, ((float)Screen.width - num4) * 0.5f); float num7 = 16f; Rect val = default(Rect); ((Rect)(ref val))..ctor(num6, num7, num4, num5); Rect rect = default(Rect); ((Rect)(ref rect))..ctor(((Rect)(ref val)).x + 9f, ((Rect)(ref val)).y + 7f, 44f, 44f); Rect val2 = default(Rect); ((Rect)(ref val2))..ctor(((Rect)(ref val)).x + 61f, ((Rect)(ref val)).y + 8f, ((Rect)(ref val)).width - 76f, 17f); Rect val3 = new Rect(((Rect)(ref val)).x + 61f, ((Rect)(ref val)).y + 25f, ((Rect)(ref val)).width - 76f, 22f); Rect r = default(Rect); ((Rect)(ref r))..ctor(((Rect)(ref val)).xMax - 12f, ((Rect)(ref val)).y + 9f, 4f, ((Rect)(ref val)).height - 18f); Color c = default(Color); ((Color)(ref c))..ctor(0.035f, 0.036f, 0.04f, 0.86f); Color color = default(Color); ((Color)(ref color))..ctor(1f, 1f, 1f, 0.14f); Color c2 = default(Color); ((Color)(ref c2))..ctor(1f, 1f, 1f, 0.07f); Color val4 = (flag ? new Color(1f, 0.78f, 0.2f, 1f) : new Color(0.45f, 0.72f, 1f, 1f)); Color baseColor = (flag ? new Color(0.45f, 0.72f, 1f, 0.25f) : new Color(1f, 0.78f, 0.2f, 0.22f)); Theme.Fill(val, c); Theme.Fill(new Rect(((Rect)(ref val)).x, ((Rect)(ref val)).y, 4f, ((Rect)(ref val)).height), val4); Theme.Fill(new Rect(((Rect)(ref val)).x + 4f, ((Rect)(ref val)).y + 1f, ((Rect)(ref val)).width - 5f, 1f), c2); DrawOutline(val, color, 1f); Theme.Fill(r, new Color(1f, 1f, 1f, 0.12f)); Theme.Fill(new Rect(((Rect)(ref r)).x, ((Rect)(ref r)).yMax - ((Rect)(ref r)).height * cycleFill, ((Rect)(ref r)).width, ((Rect)(ref r)).height * cycleFill), val4); DrawFilledIcon(rect, baseIcon, baseColor, activeIcon, val4, cycleFill); GUI.Label(val2, text, _titleStyle); GUI.Label(val3, text2, _bodyStyle); } private void RefreshTimeIfNeeded() { if (Time.unscaledTime < _nextRefreshAt) { return; } _nextRefreshAt = Time.unscaledTime + 0.5f; DayNightManager val = (Object.op_Implicit((Object)(object)DayNightManager.instance) ? DayNightManager.instance : Object.FindFirstObjectByType()); if (Object.op_Implicit((Object)(object)val)) { _timeOfDay = Mathf.Repeat(val.timeOfDay, 24f); _dayStart = NormalizeHour(val.dayStart); _dayEnd = NormalizeHour(val.dayEnd); if (Mathf.Approximately(_dayStart, _dayEnd)) { _dayStart = 5f; _dayEnd = 21f; } _hasGameTime = true; } else { _timeOfDay = Mathf.Repeat(_timeOfDay + 0.02f, 24f); _hasGameTime = false; } } private bool IsDay(float hour) { return ClockProgress(_dayStart, hour) < ClockDistance(_dayStart, _dayEnd); } private float GetCycleFill(float hour, bool isDay) { float start = (isDay ? _dayStart : _dayEnd); float end = (isDay ? _dayEnd : _dayStart); float num = Mathf.Max(0.001f, ClockDistance(start, end)); float num2 = Mathf.Clamp01(ClockProgress(start, hour) / num); return 1f - num2; } private static float NormalizeHour(float hour) { return Mathf.Repeat(hour, 24f); } private static float ClockDistance(float start, float end) { return Mathf.Repeat(end - start, 24f); } private static float ClockProgress(float start, float hour) { return Mathf.Repeat(hour - start, 24f); } private void EnsureStyles() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown //IL_0043: Expected O, but got Unknown //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0062: 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) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Expected O, but got Unknown //IL_00a1: Expected O, but got Unknown //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Expected O, but got Unknown //IL_00eb: Expected O, but got Unknown if (_iconStyle == null) { _iconStyle = new GUIStyle(GUI.skin.label) { alignment = (TextAnchor)4, fontSize = 30, fontStyle = (FontStyle)1, padding = new RectOffset(0, 0, 0, 0) }; GUIStyle val = new GUIStyle(GUI.skin.label) { alignment = (TextAnchor)3, fontSize = 11, fontStyle = (FontStyle)1 }; val.normal.textColor = new Color(0.72f, 0.74f, 0.78f, 1f); val.padding = new RectOffset(0, 0, 0, 0); _titleStyle = val; GUIStyle val2 = new GUIStyle(GUI.skin.label) { alignment = (TextAnchor)3, fontSize = 19, fontStyle = (FontStyle)1 }; val2.normal.textColor = Color.white; val2.padding = new RectOffset(0, 0, 0, 0); _bodyStyle = val2; } } private void DrawFilledIcon(Rect rect, string baseIcon, Color baseColor, string activeIcon, Color activeColor, float fill) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) Theme.Fill(rect, new Color(0f, 0f, 0f, 0.22f)); DrawOutline(rect, new Color(1f, 1f, 1f, 0.12f), 1f); _iconStyle.normal.textColor = baseColor; GUI.Label(rect, baseIcon, _iconStyle); fill = Mathf.Clamp01(fill); if (!(fill <= 0.001f)) { float num = ((Rect)(ref rect)).height * fill; Rect val = default(Rect); ((Rect)(ref val))..ctor(((Rect)(ref rect)).x, ((Rect)(ref rect)).yMax - num, ((Rect)(ref rect)).width, num); GUI.BeginGroup(val); _iconStyle.normal.textColor = activeColor; GUI.Label(new Rect(((Rect)(ref rect)).x - ((Rect)(ref val)).x, ((Rect)(ref rect)).y - ((Rect)(ref val)).y, ((Rect)(ref rect)).width, ((Rect)(ref rect)).height), activeIcon, _iconStyle); GUI.EndGroup(); } } private static void DrawOutline(Rect rect, Color color, float thickness) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: 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_0082: Unknown result type (might be due to invalid IL or missing references) Theme.Fill(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, ((Rect)(ref rect)).width, thickness), color); Theme.Fill(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).yMax - thickness, ((Rect)(ref rect)).width, thickness), color); Theme.Fill(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, thickness, ((Rect)(ref rect)).height), color); Theme.Fill(new Rect(((Rect)(ref rect)).xMax - thickness, ((Rect)(ref rect)).y, thickness, ((Rect)(ref rect)).height), color); } } [HarmonyPatch(typeof(MainCameraMovement), "GetFov")] internal static class ZoomiesFovPatch { private static bool Prefix(ref float __result) { if (ZoomiesRuntime.TryGetFov(out var fov)) { __result = fov; return false; } if (FovRuntime.TryGetFov(out fov)) { __result = fov; return false; } return true; } } public class ZoomiesHoldZoom : NumberBoolFeature { public ZoomiesHoldZoom() { base.Name = "Zoom"; base.Description = "Toggle hold-to-zoom and adjust the target field of view."; base.Min = 8f; base.Max = 80f; base.Value = ZoomiesRuntime.TargetFov; base.Step = 1f; base.Decimals = 0; base.Unit = " deg"; } protected override void OnEnable() { ZoomiesRuntime.Enabled = true; } protected override void OnDisable() { ZoomiesRuntime.Enabled = false; ZoomiesRuntime.Reset(); } protected override void OnValueChanged(float newValue) { ZoomiesRuntime.TargetFov = Mathf.Clamp(newValue, base.Min, base.Max); } } public class ZoomiesKey : TextFeature { public ZoomiesKey() { base.Name = "Zoom Key"; base.Description = "Key held for camera zoom. Examples: C, Mouse1, LeftAlt."; base.MaxLength = 24; SetText(((object)(KeyCode)(ref ZoomiesRuntime.HoldKey)).ToString()); } protected override void OnTextChanged(string newValue) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) if (Enum.TryParse(newValue, ignoreCase: true, out KeyCode result) && (int)result != 0) { ZoomiesRuntime.HoldKey = result; } } } internal static class ZoomiesRuntime { public static bool Enabled; public static KeyCode HoldKey = (KeyCode)99; public static float TargetFov = 24f; private static float _baseFov; private static float _currentFov; public static void Reset() { _baseFov = 0f; _currentFov = 0f; } public static bool TryGetFov(out float fov) { //IL_0052: Unknown result type (might be due to invalid IL or missing references) fov = 0f; if (!Enabled) { return false; } Camera main = Camera.main; float baseFov = FovRuntime.GetBaseFov(Object.op_Implicit((Object)(object)main) ? main.fieldOfView : 60f); if (_baseFov <= 1f) { _baseFov = Mathf.Clamp(baseFov, 10f, 140f); } if (Input.GetKey(HoldKey)) { if (_currentFov <= 1f) { _currentFov = Mathf.Clamp(baseFov, 10f, 140f); } float num = Mathf.Clamp(TargetFov, 8f, Mathf.Max(8f, _baseFov)); _currentFov = Mathf.Lerp(_currentFov, num, 0.28f); fov = _currentFov; return true; } if (_currentFov <= 1f) { return false; } _currentFov = Mathf.Lerp(_currentFov, _baseFov, 0.22f); if (Mathf.Abs(_currentFov - _baseFov) <= 0.2f) { Reset(); return false; } fov = _currentFov; return true; } } internal static class VisualPlayerText { private readonly struct MemberKey : IEquatable { private readonly Type Type; private readonly string Name; public MemberKey(Type type, string name) { Type = type; Name = name; } public bool Equals(MemberKey other) { if (Type == other.Type) { return string.Equals(Name, other.Name, StringComparison.OrdinalIgnoreCase); } return false; } public override bool Equals(object obj) { if (obj is MemberKey other) { return Equals(other); } return false; } public override int GetHashCode() { int num = ((Type != null) ? Type.GetHashCode() : 0); int num2 = ((Name != null) ? StringComparer.OrdinalIgnoreCase.GetHashCode(Name) : 0); return (num * 397) ^ num2; } } private const BindingFlags ReflectionFlags = BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; private static readonly Dictionary MemberInfoCache = new Dictionary(); public static string GetName(Character character) { PhotonView photonView = GetPhotonView((Component)(object)character); Player val = (Object.op_Implicit((Object)(object)photonView) ? (photonView.Controller ?? photonView.Owner) : null); if (val != null && !string.IsNullOrWhiteSpace(val.NickName)) { return val.NickName.Trim(); } string text = GetString(character, "characterName") ?? GetString(character, "playerName") ?? GetString(character?.data, "characterName") ?? GetString(character?.data, "playerName") ?? GetString(character?.data, "playerNameString"); if (!string.IsNullOrWhiteSpace(text)) { return text.Trim(); } int num = ((val != null) ? val.ActorNumber : (-1)); if (num > 0) { return "Player " + num.ToString(CultureInfo.InvariantCulture); } if (!Object.op_Implicit((Object)(object)character)) { return "Player"; } return "Player " + ((Object)character).GetInstanceID().ToString(CultureInfo.InvariantCulture); } public static bool IsRealPlayer(Character character) { if (!Object.op_Implicit((Object)(object)character) || character.isBot || character.isScoutmaster || character.isZombie) { return false; } try { return character.IsRegisteredToPlayer || Object.op_Implicit((Object)(object)GetPhotonView((Component)(object)character)); } catch { return Object.op_Implicit((Object)(object)GetPhotonView((Component)(object)character)); } } public static PhotonView GetPhotonView(Component component) { if (!Object.op_Implicit((Object)(object)component)) { return null; } return component.GetComponent() ?? component.GetComponentInParent() ?? component.GetComponentInChildren(); } public static bool TryGetVisualPosition(Character character, out Vector3 position) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: 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_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //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_002c: Unknown result type (might be due to invalid IL or missing references) //IL_006f: 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_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0035: 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_0043: Unknown result type (might be due to invalid IL or missing references) position = default(Vector3); if (!Object.op_Implicit((Object)(object)character)) { return false; } if (IsDead(character)) { if (TryGetGhostPosition(character, out position)) { return true; } try { Vector3 lastLivingPosition = character.LastLivingPosition; if (IsFinite(lastLivingPosition) && lastLivingPosition != Vector3.zero) { position = lastLivingPosition; return true; } } catch { } try { Vector3 virtualCenter = character.VirtualCenter; if (IsFinite(virtualCenter) && virtualCenter != Vector3.zero) { position = virtualCenter; return true; } } catch { } } return false; } public static Vector3 GetVisualCenter(Character character) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0028: 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_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_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0031: 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) if (TryGetVisualPosition(character, out var position)) { return position + Vector3.up * 0.9f; } try { Vector3 center = character.Center; if (IsFinite(center)) { return center; } } catch { } if (!Object.op_Implicit((Object)(object)character)) { return Vector3.zero; } return ((Component)character).transform.position + Vector3.up; } public static Vector3 GetVisualHead(Character character) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: 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) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_003e: 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) if (TryGetVisualPosition(character, out var position)) { return position + Vector3.up * 1.75f; } try { Vector3 head = character.Head; if (IsFinite(head) && head != Vector3.zero) { return head; } } catch { } if (!Object.op_Implicit((Object)(object)character)) { return Vector3.zero; } return ((Component)character).transform.position + Vector3.up * 2f; } public static Vector3 GetVisualFeet(Character character) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) if (TryGetVisualPosition(character, out var position)) { return position; } if (!Object.op_Implicit((Object)(object)character)) { return Vector3.zero; } return ((Component)character).transform.position; } public static bool IsFinite(Vector3 value) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) if (!float.IsNaN(value.x) && !float.IsInfinity(value.x) && !float.IsNaN(value.y) && !float.IsInfinity(value.y) && !float.IsNaN(value.z)) { return !float.IsInfinity(value.z); } return false; } private static bool TryGetGhostPosition(Character character, out Vector3 position) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: 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_0047: Unknown result type (might be due to invalid IL or missing references) position = default(Vector3); try { PlayerGhost ghost = character.Ghost; if (Object.op_Implicit((Object)(object)ghost) && Object.op_Implicit((Object)(object)((Component)ghost).transform)) { position = ((Component)ghost).transform.position; return IsFinite(position) && position != Vector3.zero; } } catch { } return false; } private static bool IsDead(Character character) { try { return Object.op_Implicit((Object)(object)character) && Object.op_Implicit((Object)(object)character.data) && character.data.dead; } catch { return false; } } private static string GetString(object target, string name) { return GetMemberValue(target, name) as string; } private static object GetMemberValue(object target, string name) { if (target == null || string.IsNullOrEmpty(name)) { return null; } try { Type type = target.GetType(); MemberKey key = new MemberKey(type, name); if (!MemberInfoCache.TryGetValue(key, out var value)) { value = (MemberInfo)(((object)type.GetField(name, BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) ?? ((object)type.GetProperty(name, BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))); MemberInfoCache[key] = value; } MemberInfo memberInfo = value; if (!(memberInfo is FieldInfo fieldInfo)) { if (memberInfo is PropertyInfo propertyInfo && propertyInfo.GetIndexParameters().Length == 0) { return propertyInfo.GetValue(target, null); } return null; } return fieldInfo.GetValue(target); } catch { return null; } } } [HarmonyPatch(typeof(PointPinger), "ReceivePoint_Rpc")] internal static class GhostPingReceivePatch { private static readonly BindingFlags InstanceFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; private static readonly FieldInfo PingInstanceField = typeof(PointPinger).GetField("pingInstance", InstanceFlags); private static bool Prefix(PointPinger __instance, Vector3 point, Vector3 hitNormal) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) if (!PingVisualRuntime.GhostPing) { return true; } if (!Object.op_Implicit((Object)(object)__instance) || !Object.op_Implicit((Object)(object)__instance.pointPrefab) || !Object.op_Implicit((Object)(object)__instance.character)) { return true; } return !CreateVisiblePing(__instance, point, hitNormal); } private static bool CreateVisiblePing(PointPinger pinger, Vector3 point, Vector3 hitNormal) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0052: 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_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) try { object? obj = PingInstanceField?.GetValue(pinger); GameObject val = (GameObject)((obj is GameObject) ? obj : null); if (Object.op_Implicit((Object)(object)val)) { Object.Destroy((Object)(object)val); } Vector3 val2 = point - pinger.character.Head; if (((Vector3)(ref val2)).sqrMagnitude < 0.001f) { val2 = Vector3.forward; } GameObject val3 = Object.Instantiate(pinger.pointPrefab, point, Quaternion.LookRotation(((Vector3)(ref val2)).normalized, Vector3.up)); if (!Object.op_Implicit((Object)(object)val3)) { return false; } PingInstanceField?.SetValue(pinger, val3); PointPing component = val3.GetComponent(); if (Object.op_Implicit((Object)(object)component)) { component.hitNormal = hitNormal; component.Init(pinger.character); component.pointPinger = pinger; if (Object.op_Implicit((Object)(object)component.renderer) && Object.op_Implicit((Object)(object)pinger.character.refs?.mainRenderer)) { ((Renderer)component.renderer).material = Object.Instantiate(((Renderer)pinger.character.refs.mainRenderer).sharedMaterial); } if (Object.op_Implicit((Object)(object)component.material)) { component.material.SetFloat("_Opacity", 1f); } } Object.Destroy((Object)(object)val3, 2f); return true; } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Ghost Ping] " + ex.GetBaseException().Message)); } return false; } } } [HarmonyPatch(typeof(PointPinger), "Update")] internal static class GhostPingUpdatePatch { private static void Postfix(PointPinger __instance) { PingVisualRuntime.TryGhostPing(__instance); } } [HarmonyPatch(typeof(PointPing), "Update")] internal static class PingPointScalePatch { private readonly struct ScaleState { public Vector3 BaseScale { get; } public Vector3 AppliedScale { get; } public float LastSeen { get; } public ScaleState(Vector3 baseScale, Vector3 appliedScale, float lastSeen) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) BaseScale = baseScale; AppliedScale = appliedScale; LastSeen = lastSeen; } } private const float PruneInterval = 5f; private static readonly Dictionary ScaleStates = new Dictionary(); private static float _nextPruneAt; private static void Postfix(PointPing __instance) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: 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_007e: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00af: 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_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: 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_0092: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: 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) if (!Object.op_Implicit((Object)(object)__instance)) { return; } float num = Mathf.Clamp(PingVisualRuntime.ScaleMultiplier, 0.1f, 12f); int instanceID = ((Object)__instance).GetInstanceID(); Transform transform = ((Component)__instance).transform; Vector3 localScale = transform.localScale; if (Mathf.Approximately(num, 1f)) { if (ScaleStates.TryGetValue(instanceID, out var value) && PingVisualRuntime.Approximately(localScale, value.AppliedScale)) { transform.localScale = value.BaseScale; } ScaleStates.Remove(instanceID); PruneScaleStates(); return; } Vector3 val = localScale; if (ScaleStates.TryGetValue(instanceID, out var value2) && PingVisualRuntime.Approximately(localScale, value2.AppliedScale)) { val = value2.BaseScale; } Vector3 appliedScale = (transform.localScale = val * num); ScaleStates[instanceID] = new ScaleState(val, appliedScale, Time.unscaledTime); PruneScaleStates(); } private static void PruneScaleStates() { float unscaledTime = Time.unscaledTime; if (unscaledTime < _nextPruneAt) { return; } List list = new List(); foreach (KeyValuePair scaleState in ScaleStates) { if (unscaledTime - scaleState.Value.LastSeen > 5f) { list.Add(scaleState.Key); } } for (int i = 0; i < list.Count; i++) { ScaleStates.Remove(list[i]); } _nextPruneAt = unscaledTime + 5f; } } [HarmonyPatch(typeof(MainCameraMovement), "LateUpdate")] internal static class ThirdPersonLateUpdatePatch { private static void Postfix(MainCameraMovement __instance) { ThirdPersonRuntime.Apply(__instance); } } internal static class HdPeakRuntime { public static bool Enabled; public static float LodBias = 2f; public static float RenderDistance = 1500f; } internal static class PerformanceRuntime { public static float RenderDistance = 650f; public static float LodBias = 0.6f; public static int TextureMipmapLimit = 1; public static int TargetFrameRate = 120; } internal static class PingVisualRuntime { private const float GhostPingCooldown = 0.45f; private static readonly Dictionary LastGhostPingByView = new Dictionary(); public static bool ShowDistance; public static bool GhostPing; public static float ScaleMultiplier = 1f; public static void TryGhostPing(PointPinger pinger) { //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_0116: 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) if (!GhostPing || !Object.op_Implicit((Object)(object)pinger) || !Object.op_Implicit((Object)(object)pinger.character)) { return; } Character character = pinger.character; PhotonView val = (Object.op_Implicit((Object)(object)character.refs?.view) ? character.refs.view : ((Component)pinger).GetComponent()); if (!Object.op_Implicit((Object)(object)val) || !val.IsMine || (Object.op_Implicit((Object)(object)character.data) && character.data.fullyConscious) || ((!Object.op_Implicit((Object)(object)character.input) || !character.input.pingWasPressed) && !Input.GetMouseButtonDown(2))) { return; } int viewID = val.ViewID; float unscaledTime = Time.unscaledTime; if (!LastGhostPingByView.TryGetValue(viewID, out var value) || !(unscaledTime - value < 0.45f)) { Camera main = Camera.main; RaycastHit val2 = default(RaycastHit); if (Object.op_Implicit((Object)(object)main) && Physics.Raycast(main.ScreenPointToRay(Input.mousePosition), ref val2, 1000f, -1, (QueryTriggerInteraction)1)) { LastGhostPingByView[viewID] = unscaledTime; val.RPC("ReceivePoint_Rpc", (RpcTarget)0, new object[2] { ((RaycastHit)(ref val2)).point, ((RaycastHit)(ref val2)).normal }); } } } public static bool Approximately(Vector3 left, Vector3 right) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) if (Mathf.Abs(left.x - right.x) <= 0.0001f && Mathf.Abs(left.y - right.y) <= 0.0001f) { return Mathf.Abs(left.z - right.z) <= 0.0001f; } return false; } } internal static class ThirdPersonRuntime { public static bool Enabled; public static float Distance = 3.2f; public static float Height = 0.35f; public static void Apply(MainCameraMovement movement) { //IL_0048: 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_0054: 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_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: 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) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_0110: 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_012c: 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_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) if (!Enabled || !Object.op_Implicit((Object)(object)movement)) { return; } Character localCharacter = Character.localCharacter; Camera main = Camera.main; if (!Object.op_Implicit((Object)(object)localCharacter) || !Object.op_Implicit((Object)(object)main) || !Object.op_Implicit((Object)(object)localCharacter.data) || localCharacter.data.dead) { return; } Vector3 anchor = GetAnchor(localCharacter); Vector3 val = localCharacter.data.lookDirection; if (((Vector3)(ref val)).sqrMagnitude < 0.001f) { val = ((Component)main).transform.forward; } ((Vector3)(ref val)).Normalize(); float num = Mathf.Clamp(Distance, 1.2f, 8f); float num2 = Mathf.Clamp(Height, -1f, 2f); Vector3 val2 = anchor - val * num + Vector3.up * num2; Vector3 val3 = val2 - anchor; float magnitude = ((Vector3)(ref val3)).magnitude; if (magnitude > 0.001f) { int num3 = LayerMask.GetMask(new string[2] { "Terrain", "Map" }); if (num3 == 0) { num3 = -1; } RaycastHit val4 = default(RaycastHit); if (Physics.SphereCast(anchor, 0.08f, ((Vector3)(ref val3)).normalized, ref val4, magnitude, num3, (QueryTriggerInteraction)1)) { val2 = ((RaycastHit)(ref val4)).point + ((RaycastHit)(ref val4)).normal * 0.12f; } } ((Component)main).transform.position = val2; } private static Vector3 GetAnchor(Character character) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: 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) try { return character.Center + Vector3.up * 0.35f; } catch { return ((Component)character).transform.position + Vector3.up * 1.3f; } } } internal static class VisualsRuntimeSettings { public static bool SkipExplosionPlume; } } namespace CubeX.Features.Teleport { public class CampfireLocationDirectory : Feature, IMenuRowProvider, IMenuSidePanelProvider { public sealed class CampfireLocation { public Campfire Campfire { get; } public string DisplayName { get; } public string MenuName { get; } public string SceneName { get; } public Vector3 Position { get; } public float Distance { get; } public CampfireLocation(Campfire campfire, string displayName, string menuName, string sceneName, Vector3 position, float distance) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) Campfire = campfire; DisplayName = displayName; MenuName = menuName; SceneName = sceneName; Position = position; Distance = distance; } } private const string LocationsCategory = "Teleport/Locations"; private const float RefreshInterval = 1f; private static readonly List Campfires = new List(); private static readonly Comparison ByDistanceAsc = (CampfireLocation a, CampfireLocation b) => a.Distance.CompareTo(b.Distance); private static float _nextRefreshAt; private static string _activeSceneName = string.Empty; public CampfireLocationDirectory() { base.Name = "Campfire Location Directory"; base.Description = "Builds active-scene campfire teleport rows."; } public IEnumerable GetRows(string category) { if (!string.Equals(category, "Teleport/Locations", StringComparison.Ordinal)) { return Array.Empty(); } RefreshIfNeeded(); if (Campfires.Count == 0) { return new object[2] { new InfoFeature("Scene", GetSceneDisplayName(), "Active scene used for location filtering."), new InfoFeature("Campfires", "None", "No campfires were found in the active scene.") }; } List list = new List { new InfoFeature("Scene", GetSceneDisplayName(), "Active scene used for location filtering."), new SeparatorFeature() }; for (int i = 0; i < Campfires.Count; i++) { list.Add(new TeleportToCampfireLocation(Campfires[i])); } return list; } public bool TryGetSidePanel(string category, object selectedRow, out MenuSidePanel panel) { //IL_0098: Unknown result type (might be due to invalid IL or missing references) panel = null; if (!string.Equals(category, "Teleport/Locations", StringComparison.Ordinal)) { return false; } if (!(selectedRow is TeleportToCampfireLocation teleportToCampfireLocation) || teleportToCampfireLocation.Location == null) { return false; } CampfireLocation location = teleportToCampfireLocation.Location; panel = new MenuSidePanel("CAMPFIRE", location.DisplayName, new List { new InfoFeature("Scene", location.SceneName), new InfoFeature("Distance", location.Distance.ToString("F1", CultureInfo.InvariantCulture) + " m"), new InfoFeature("Position", FormatPosition(location.Position)) }); return true; } public static void ForceRefresh() { Refresh(); } private static void RefreshIfNeeded() { //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) Scene activeScene = SceneManager.GetActiveScene(); if (!string.Equals(((Scene)(ref activeScene)).IsValid() ? ((Scene)(ref activeScene)).name : string.Empty, _activeSceneName, StringComparison.Ordinal)) { Refresh(); } else if (Time.unscaledTime >= _nextRefreshAt) { Refresh(); } } private static void Refresh() { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0048: 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) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: 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_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) Campfires.Clear(); Scene activeScene = SceneManager.GetActiveScene(); _activeSceneName = (((Scene)(ref activeScene)).IsValid() ? ((Scene)(ref activeScene)).name : string.Empty); string sceneDisplayName = GetSceneDisplayName(); Character localCharacter = Character.localCharacter; Vector3 val = (Object.op_Implicit((Object)(object)localCharacter) ? localCharacter.Head : Vector3.zero); Campfire[] array = Object.FindObjectsByType((FindObjectsSortMode)0); if (Campfires.Capacity < array.Length) { Campfires.Capacity = array.Length; } for (int i = 0; i < array.Length; i++) { Campfire val2 = array[i]; if (Object.op_Implicit((Object)(object)val2) && (!((Scene)(ref activeScene)).IsValid() || !(((Component)val2).gameObject.scene != activeScene))) { Vector3 position = ((Component)val2).transform.position; float distance = (Object.op_Implicit((Object)(object)localCharacter) ? Vector3.Distance(val, position) : 0f); string text = BuildCampfireName(val2, i + 1); string menuName = text + (Object.op_Implicit((Object)(object)localCharacter) ? (" [" + distance.ToString("F1", CultureInfo.InvariantCulture) + "m]") : string.Empty); Campfires.Add(new CampfireLocation(val2, text, menuName, sceneDisplayName, position, distance)); } } Campfires.Sort(ByDistanceAsc); _nextRefreshAt = Time.unscaledTime + 1f; } private static string BuildCampfireName(Campfire campfire, int index) { string text = (Object.op_Implicit((Object)(object)campfire) ? CleanObjectName(((Object)((Component)campfire).gameObject).name) : string.Empty); if (string.IsNullOrEmpty(text) || string.Equals(text, "Campfire", StringComparison.OrdinalIgnoreCase)) { return "Campfire " + index.ToString(CultureInfo.InvariantCulture); } return text + " " + index.ToString(CultureInfo.InvariantCulture); } private static string CleanObjectName(string name) { if (string.IsNullOrEmpty(name)) { return string.Empty; } int num = name.IndexOf("(Clone)", StringComparison.OrdinalIgnoreCase); if (num >= 0) { name = name.Substring(0, num).Trim(); } return name.Trim(); } private static string GetSceneDisplayName() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) if (!string.IsNullOrEmpty(_activeSceneName)) { return _activeSceneName; } Scene activeScene = SceneManager.GetActiveScene(); if (!((Scene)(ref activeScene)).IsValid() || string.IsNullOrEmpty(((Scene)(ref activeScene)).name)) { return "Unknown"; } return ((Scene)(ref activeScene)).name; } private static string FormatPosition(Vector3 position) { return position.x.ToString("F1", CultureInfo.InvariantCulture) + ", " + position.y.ToString("F1", CultureInfo.InvariantCulture) + ", " + position.z.ToString("F1", CultureInfo.InvariantCulture); } } public class RefreshCampfireLocations : ButtonFeature { public RefreshCampfireLocations() { base.Name = "Refresh Campfires"; base.Description = "Reloads campfire locations for the active scene."; base.ButtonLabel = "Refresh"; } public override void Execute() { CampfireLocationDirectory.ForceRefresh(); } } public class TeleportToCampfireLocation : ButtonFeature { public CampfireLocationDirectory.CampfireLocation Location { get; } public TeleportToCampfireLocation(CampfireLocationDirectory.CampfireLocation location) { Location = location; base.Name = location?.MenuName ?? "Campfire"; base.Description = ((location == null) ? "Campfire location is unavailable." : ("Teleport to " + location.DisplayName + " in " + location.SceneName + ".")); base.ButtonLabel = "Warp"; } public override void Execute() { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) if (Location != null) { GameActions.WarpLocalToPosition(GetSafeCampfirePosition(Object.op_Implicit((Object)(object)Location.Campfire) ? ((Component)Location.Campfire).transform.position : Location.Position)); } } private static Vector3 GetSafeCampfirePosition(Vector3 position) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003b: 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) RaycastHit val = default(RaycastHit); if (Physics.Raycast(position + Vector3.up * 4f, Vector3.down, ref val, 8f, -1, (QueryTriggerInteraction)1)) { return ((RaycastHit)(ref val)).point + Vector3.up * 1.15f; } return position + Vector3.up * 1.5f; } } public abstract class CoordinateValueFeature : NumberFeature { protected CoordinateValueFeature() { base.Min = -100000f; base.Max = 100000f; base.Step = 1f; base.Decimals = 1; } } public class TeleportToCoordinates : ButtonFeature { public TeleportToCoordinates() { base.Name = "Teleport to Coordinates"; base.Description = "Warps your local character to the configured coordinates."; base.ButtonLabel = "Teleport"; } public override void Execute() { //IL_000f: Unknown result type (might be due to invalid IL or missing references) GameActions.WarpLocalToPosition(new Vector3(CoordinateTeleportState.X, CoordinateTeleportState.Y, CoordinateTeleportState.Z)); } } public class TeleportX : CoordinateValueFeature { public TeleportX() { base.Name = "X"; base.Description = "Teleport target X coordinate."; base.Value = CoordinateTeleportState.X; } protected override void OnValueChanged(float newValue) { CoordinateTeleportState.X = newValue; } } public class TeleportY : CoordinateValueFeature { public TeleportY() { base.Name = "Y"; base.Description = "Teleport target Y coordinate."; base.Value = CoordinateTeleportState.Y; } protected override void OnValueChanged(float newValue) { CoordinateTeleportState.Y = newValue; } } public class TeleportZ : CoordinateValueFeature { public TeleportZ() { base.Name = "Z"; base.Description = "Teleport target Z coordinate."; base.Value = CoordinateTeleportState.Z; } protected override void OnValueChanged(float newValue) { CoordinateTeleportState.Z = newValue; } } public class UseCurrentCoordinates : ButtonFeature { public UseCurrentCoordinates() { base.Name = "Use Current Position"; base.Description = "Copies your current position into the coordinate teleport fields."; base.ButtonLabel = "Copy"; } public override void Execute() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0020: 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_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) if (GameActions.TryGetLocalCharacter(out var character)) { Vector3 position = ((Component)character).transform.position; CoordinateTeleportState.X = position.x; CoordinateTeleportState.Y = position.y; CoordinateTeleportState.Z = position.z; SyncNumber(position.x); SyncNumber(position.y); SyncNumber(position.z); } } private static void SyncNumber(float value) where TFeature : NumberFeature { if (FeatureManager.Current == null) { return; } foreach (Feature item in FeatureManager.Current.All) { if (item is TFeature val) { val.SetValue(value); break; } } } } public class TeleportNearestCampfire : ButtonFeature { public TeleportNearestCampfire() { base.Name = "Teleport Nearest Campfire"; base.Description = "Warps to the closest campfire in the current scene."; base.ButtonLabel = "Warp"; } public override void Execute() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: 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_0064: 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) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) Character localCharacter = Character.localCharacter; if (!Object.op_Implicit((Object)(object)localCharacter)) { return; } Campfire val = null; float num = float.MaxValue; Scene activeScene = SceneManager.GetActiveScene(); Campfire[] array = Object.FindObjectsByType((FindObjectsSortMode)0); foreach (Campfire val2 in array) { if (Object.op_Implicit((Object)(object)val2) && (!((Scene)(ref activeScene)).IsValid() || !(((Component)val2).gameObject.scene != activeScene))) { float num2 = Vector3.SqrMagnitude(((Component)val2).transform.position - localCharacter.Head); if (!(num2 >= num)) { num = num2; val = val2; } } } if (Object.op_Implicit((Object)(object)val)) { GameActions.WarpLocalToPosition(GetSafePosition(((Component)val).transform.position)); } } private static Vector3 GetSafePosition(Vector3 position) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003b: 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) RaycastHit val = default(RaycastHit); if (Physics.Raycast(position + Vector3.up * 4f, Vector3.down, ref val, 8f, -1, (QueryTriggerInteraction)1)) { return ((RaycastHit)(ref val)).point + Vector3.up * 1.15f; } return position + Vector3.up * 1.5f; } } public class TeleportNearestLuggage : ButtonFeature { public TeleportNearestLuggage() { base.Name = "Teleport Nearest Luggage"; base.Description = "Warps to the closest loaded luggage container."; base.ButtonLabel = "Warp"; } public override void Execute() { //IL_0049: 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) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) Character localCharacter = Character.localCharacter; if (!Object.op_Implicit((Object)(object)localCharacter) || Luggage.ALL_LUGGAGE == null) { return; } Luggage val = null; float num = float.MaxValue; foreach (Luggage item in Luggage.ALL_LUGGAGE) { if (Object.op_Implicit((Object)(object)item) && LuggageDirectory.TryGetLuggagePosition(item, out var position)) { float num2 = Vector3.SqrMagnitude(position - localCharacter.Head); if (!(num2 >= num)) { num = num2; val = item; } } } if (Object.op_Implicit((Object)(object)val) && LuggageDirectory.TryGetLuggagePosition(val, out var position2)) { GameActions.WarpLocalToPosition(position2 + Vector3.up * 1.5f); } } } public class TeleportNearestPlayer : ButtonFeature { public TeleportNearestPlayer() { base.Name = "Teleport Nearest Player"; base.Description = "Warps near the closest other player character."; base.ButtonLabel = "Warp"; } public override void Execute() { //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_0075: 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) //IL_0080: Unknown result type (might be due to invalid IL or missing references) Character localCharacter = Character.localCharacter; if (!Object.op_Implicit((Object)(object)localCharacter)) { return; } Character val = null; float num = float.MaxValue; foreach (Character character in GameActions.GetCharacters()) { if (Object.op_Implicit((Object)(object)character) && character != localCharacter && (!Object.op_Implicit((Object)(object)character.data) || !character.data.dead) && !character.isBot && !character.isZombie && !character.isScoutmaster) { float num2 = Vector3.SqrMagnitude(character.Head - localCharacter.Head); if (!(num2 >= num)) { num = num2; val = character; } } } if (Object.op_Implicit((Object)(object)val)) { Vector3 val2 = ((Component)localCharacter).transform.position - ((Component)val).transform.position; if (((Vector3)(ref val2)).sqrMagnitude < 0.01f) { val2 = -((Component)val).transform.forward; } GameActions.WarpLocalToPosition(((Component)val).transform.position + ((Vector3)(ref val2)).normalized * 1.8f + Vector3.up * 0.25f); } } } public class TeleportToLookPoint : ButtonFeature { public TeleportToLookPoint() { base.Name = "Teleport to Look Point"; base.Description = "Raycasts from the camera and teleports to the point you are looking at."; base.ButtonLabel = "Teleport"; } public override void Execute() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003f: 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) Camera main = Camera.main; RaycastHit val = default(RaycastHit); if (Object.op_Implicit((Object)(object)main) && Physics.Raycast(((Component)main).transform.position, ((Component)main).transform.forward, ref val, 1000f, -1, (QueryTriggerInteraction)1)) { GameActions.WarpLocalToPosition(TeleportToPing.GetSafePoint(((RaycastHit)(ref val)).point, ((RaycastHit)(ref val)).normal)); } } } public class TeleportToPing : Feature { [HarmonyPatch(typeof(PointPinger), "ReceivePoint_Rpc")] private static class PointPingPatch { [HarmonyPostfix] private static void Postfix(Vector3 point, Vector3 hitNormal, PointPinger __instance) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) if (IsActive && Object.op_Implicit((Object)(object)__instance) && WasSentByLocalPlayer(__instance)) { GameActions.WarpLocalToPosition(GetSafePoint(point, hitNormal)); } } } private static TeleportToPing _activeFeature; private static bool IsActive => _activeFeature?.Enabled ?? false; public TeleportToPing() { base.Name = "Auto Teleport to Point"; base.Description = "When enabled, placing your point marker automatically warps you there."; } protected override void OnEnable() { OnTick(); } protected override void OnDisable() { if (_activeFeature == this) { _activeFeature = null; } } public override void OnTick() { _activeFeature = this; } internal static Vector3 GetSafePoint(Vector3 point, Vector3 normal) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) Vector3 val = ((((Vector3)(ref normal)).sqrMagnitude > 0.001f) ? ((Vector3)(ref normal)).normalized : Vector3.up); return point + val * 1.1f + Vector3.up * 0.25f; } private static bool WasSentByLocalPlayer(PointPinger pinger) { Character character = pinger.character; Character localCharacter = Character.localCharacter; if (!Object.op_Implicit((Object)(object)character)) { return false; } if (Object.op_Implicit((Object)(object)localCharacter) && character == localCharacter) { return true; } if (IsLocalPhotonView(((Component)pinger).GetComponent() ?? ((Component)pinger).GetComponentInParent())) { return true; } return IsLocalPhotonView(Object.op_Implicit((Object)(object)character.refs?.view) ? character.refs.view : (((Component)character).GetComponent() ?? ((Component)character).GetComponentInChildren())); } private static bool IsLocalPhotonView(PhotonView view) { if (!Object.op_Implicit((Object)(object)view)) { return false; } if (view.IsMine) { return true; } if (PhotonNetwork.LocalPlayer != null) { if (!object.Equals(view.Owner, PhotonNetwork.LocalPlayer)) { return object.Equals(view.Controller, PhotonNetwork.LocalPlayer); } return true; } return false; } } public class TeleportToPlayer : ButtonFeature { public TeleportToPlayer() { base.Name = "Teleport To Player"; base.Description = "Teleport near the currently selected player."; base.ButtonLabel = "Teleport"; } public override void Execute() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) PlayerDirectory.SelectedPlayerInfo selectedPlayer = PlayerDirectory.SelectedPlayer; if (selectedPlayer != null && GameActions.TryGetLocalCharacter(out var character)) { PlayerDirectory.TryGetSelectedCharacter(out var character2); GameActions.WarpLocalToPosition(GetTeleportPosition(character, character2, selectedPlayer.LastKnownPosition)); } } private static Vector3 GetTeleportPosition(Character local, Character target, Vector3 fallback) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0086: 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) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: 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_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0071: 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) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //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_006d: Unknown result type (might be due to invalid IL or missing references) Vector3 val = (Object.op_Implicit((Object)(object)target) ? target.Center : fallback); Vector3 val2 = Vector3.up; if (Object.op_Implicit((Object)(object)target) && Object.op_Implicit((Object)(object)local)) { Vector3 val3 = ((Component)local).transform.position - ((Component)target).transform.position; val3.y = 0f; if (((Vector3)(ref val3)).sqrMagnitude < 0.01f) { val3 = -((Component)target).transform.forward; } val2 += ((Vector3)(ref val3)).normalized * 1.25f; } return val + val2; } } public class TeleportToSpawn : ButtonFeature { private Character _spawnOwner; private Vector3? _spawnPosition; private Quaternion? _spawnRotation; public override bool TickWhenDisabled => true; public TeleportToSpawn() { base.Name = "Teleport to Spawn"; base.Description = "Instantly return to the starting area."; base.ButtonLabel = "Teleport"; } public override void OnTick() { CacheSpawnPosition(); } public override void Execute() { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: 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_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: 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) Character localCharacter = Character.localCharacter; if (!Object.op_Implicit((Object)(object)localCharacter)) { return; } CacheSpawnPosition(); if (!_spawnPosition.HasValue || GameActions.WarpLocalToPosition(_spawnPosition.Value)) { return; } Rigidbody val = ((Component)localCharacter).GetComponent(); if (!Object.op_Implicit((Object)(object)val)) { val = ((Component)localCharacter).GetComponentInChildren(); } if (Object.op_Implicit((Object)(object)val)) { val.linearVelocity = Vector3.zero; val.angularVelocity = Vector3.zero; val.position = _spawnPosition.Value; if (_spawnRotation.HasValue) { val.rotation = _spawnRotation.Value; } } else { ((Component)localCharacter).transform.SetPositionAndRotation(_spawnPosition.Value, (Quaternion)(((??)_spawnRotation) ?? ((Component)localCharacter).transform.rotation)); } } private void CacheSpawnPosition() { //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) Character localCharacter = Character.localCharacter; if (Object.op_Implicit((Object)(object)localCharacter) && (!Object.op_Implicit((Object)(object)localCharacter.data) || !localCharacter.data.dead)) { if (localCharacter != _spawnOwner) { _spawnOwner = localCharacter; _spawnPosition = null; _spawnRotation = null; } if (!_spawnPosition.HasValue) { _spawnPosition = ((Component)localCharacter).transform.position; _spawnRotation = ((Component)localCharacter).transform.rotation; } } } } internal static class CoordinateTeleportState { public static float X; public static float Y; public static float Z; } } namespace CubeX.Features.Spawn { public class CookAllItems : ButtonFeature { public CookAllItems() { base.Name = "Cook All Items"; base.Description = "Sets cooked amount on every loaded item."; base.ButtonLabel = "Cook"; } public override void Execute() { SpawnFeatureHelpers.RpcAllItems("SetCookedAmountRPC", Mathf.RoundToInt(SpawnState.CookLevel)); } } public class DeleteAllSpawnedEntities : ButtonFeature { public DeleteAllSpawnedEntities() { base.Name = "Delete Spawned Entities"; base.Description = "Deletes all objects tracked by Cube-X spawn actions."; base.ButtonLabel = "Delete All"; } public override void Execute() { int num = 0; int num2 = 0; IReadOnlyList spawnedEntities = SpawnState.GetSpawnedEntities(); for (int i = 0; i < spawnedEntities.Count; i++) { if (SpawnedEntityDeletion.Delete(spawnedEntities[i])) { num++; } else { num2++; } } if (spawnedEntities.Count == 0) { NotificationSystem.Push("Spawned Entities", "No tracked spawned entities.", NotificationKind.Warning); return; } if (num2 == 0) { NotificationSystem.Push("Spawned Entities", "Deleted " + num + " spawned entities.", NotificationKind.Success); return; } NotificationSystem.Push("Spawned Entities", "Deleted " + num + ", failed " + num2 + ".", NotificationKind.Warning); } } public class DenyPickupOnAllItems : ButtonFeature { public DenyPickupOnAllItems() { base.Name = "Deny Pickup On All Items"; base.Description = "Runs DenyPickupRPC on every loaded item."; base.ButtonLabel = "Deny"; } public override void Execute() { SpawnFeatureHelpers.RpcAllItems("DenyPickupRPC"); } } public class DisableSmokeOnAllItems : ButtonFeature { public DisableSmokeOnAllItems() { base.Name = "Disable Smoke On All Items"; base.Description = "Disables cooking smoke on loaded ItemCooking components."; base.ButtonLabel = "Disable"; } public override void Execute() { SpawnFeatureHelpers.RpcAllCooking("EnableCookingSmokeRPC", false); } } public class DrawWithSelectedItem : Feature { private const float SpawnDelay = 0.05f; private const float MinPointSpacing = 0.35f; private float _nextSpawnAt; private Vector3 _lastSpawnPoint; private bool _hasLastSpawnPoint; private GUIStyle _indicatorStyle; private GUIStyle _indicatorShadowStyle; public DrawWithSelectedItem() { base.Name = "Draw With Selected Item"; base.Description = "Hold left mouse to draw with the selected item."; } protected override void OnEnable() { _nextSpawnAt = 0f; _hasLastSpawnPoint = false; } protected override void OnDisable() { _nextSpawnAt = 0f; _hasLastSpawnPoint = false; } public override void OnTick() { //IL_003f: 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_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: 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_0062: 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_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: 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) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)SpawnState.SelectedItem)) { return; } if (!Input.GetMouseButton(0)) { _hasLastSpawnPoint = false; } else { if (Time.unscaledTime < _nextSpawnAt) { return; } Camera main = Camera.main; if (!Object.op_Implicit((Object)(object)main)) { return; } Vector3 val = SpawnFeatureHelpers.GetCameraSpawnPosition(2f); Quaternion rotation = ((Component)main).transform.rotation; RaycastHit val2 = default(RaycastHit); if (Physics.Raycast(((Component)main).transform.position, ((Component)main).transform.forward, ref val2, 25f)) { val = ((RaycastHit)(ref val2)).point + ((RaycastHit)(ref val2)).normal * 0.08f; rotation = Quaternion.LookRotation(((RaycastHit)(ref val2)).normal); } if (!_hasLastSpawnPoint || !(Vector3.Distance(_lastSpawnPoint, val) < 0.35f)) { _nextSpawnAt = Time.unscaledTime + 0.05f; _lastSpawnPoint = val; _hasLastSpawnPoint = true; Item val3 = SpawnFeatureHelpers.SpawnWorldItem(SpawnState.SelectedItem, val, rotation); if (Object.op_Implicit((Object)(object)val3)) { SpawnFeatureHelpers.SetItemKinematic(val3, kinematic: true, ((Component)val3).transform.position, ((Component)val3).transform.rotation); } } } } public override void OnRender() { //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) EnsureIndicatorStyles(); string selectedItemName = SpawnState.GetSelectedItemName(); string text = (string.IsNullOrEmpty(selectedItemName) ? "No item selected" : selectedItemName); Rect val = default(Rect); ((Rect)(ref val))..ctor((float)Screen.width * 0.5f - 130f, (float)Screen.height * 0.5f + 22f, 260f, 24f); GUI.Label(new Rect(((Rect)(ref val)).x + 1f, ((Rect)(ref val)).y + 1f, ((Rect)(ref val)).width, ((Rect)(ref val)).height), text, _indicatorShadowStyle); GUI.Label(val, text, _indicatorStyle); } private void EnsureIndicatorStyles() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Expected O, but got Unknown //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_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Expected O, but got Unknown if (_indicatorStyle == null) { GUIStyle val = new GUIStyle(GUI.skin.label) { alignment = (TextAnchor)4, clipping = (TextClipping)1, fontSize = 12, fontStyle = (FontStyle)1 }; val.normal.textColor = Color.white; _indicatorStyle = val; GUIStyle val2 = new GUIStyle(_indicatorStyle); val2.normal.textColor = new Color(0f, 0f, 0f, 0.95f); _indicatorShadowStyle = val2; } } } public class EnableSmokeOnAllItems : ButtonFeature { public EnableSmokeOnAllItems() { base.Name = "Enable Smoke On All Items"; base.Description = "Enables cooking smoke on loaded ItemCooking components."; base.ButtonLabel = "Enable"; } public override void Execute() { SpawnFeatureHelpers.RpcAllCooking("EnableCookingSmokeRPC", true); } } public class FinishCookingAllItems : ButtonFeature { public FinishCookingAllItems() { base.Name = "Finish Cooking On All Items"; base.Description = "Runs FinishCookingRPC on every loaded item."; base.ButtonLabel = "Finish"; } public override void Execute() { SpawnFeatureHelpers.RpcAllItems("FinishCookingRPC"); } } public class FlagGun : Feature { private GameObject _flagTemplate; public FlagGun() { base.Name = "Flag Gun"; base.Description = "Hold left mouse to plant seagull flags at your aim point."; } protected override void OnEnable() { _flagTemplate = null; } protected override void OnDisable() { if (Object.op_Implicit((Object)(object)_flagTemplate)) { PhotonView photonView = SpawnFeatureHelpers.GetPhotonView((Component)(object)_flagTemplate.GetComponent()); if (Object.op_Implicit((Object)(object)photonView)) { PhotonNetwork.Destroy(photonView); } else { Object.Destroy((Object)(object)_flagTemplate); } _flagTemplate = null; } } public override void OnTick() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) Camera main = Camera.main; RaycastHit val = default(RaycastHit); if (Object.op_Implicit((Object)(object)main) && Input.GetMouseButton(0) && Physics.Raycast(((Component)main).transform.position, ((Component)main).transform.forward, ref val, 100f)) { if (!Object.op_Implicit((Object)(object)_flagTemplate)) { _flagTemplate = PhotonNetwork.Instantiate("0_Items/Flag_Plantable_Seagull", Vector3.zero, Quaternion.identity, (byte)0, (object[])null); } PhotonView photonView = SpawnFeatureHelpers.GetPhotonView((Component)(object)(Object.op_Implicit((Object)(object)_flagTemplate) ? _flagTemplate.GetComponent() : null)); if (Object.op_Implicit((Object)(object)photonView)) { photonView.RPC("CreatePrefabRPC", (RpcTarget)0, new object[2] { ((RaycastHit)(ref val)).point, Quaternion.identity }); } } } } public class FreezeAllItems : Feature { public FreezeAllItems() { base.Name = "Freeze All Items"; base.Description = "Keeps loaded items kinematic at their current positions."; } protected override void OnEnable() { OnTick(); } protected override void OnDisable() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) Item[] array = Object.FindObjectsByType((FindObjectsSortMode)0); foreach (Item val in array) { if (Object.op_Implicit((Object)(object)val)) { SpawnFeatureHelpers.SetItemKinematic(val, kinematic: false, ((Component)val).transform.position, ((Component)val).transform.rotation); } } } public override void OnTick() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) Item[] array = Object.FindObjectsByType((FindObjectsSortMode)0); for (int i = 0; i < array.Length; i++) { SpawnFeatureHelpers.SetItemKinematic(array[i], kinematic: true, ((Component)array[i]).transform.position, ((Component)array[i]).transform.rotation); } } } public class GravityGun : Feature { private const float MinHoldDistance = 1.5f; private const float MaxHoldDistance = 30f; private const float DefaultHoldDistance = 6f; private Item _grabbed; private float _holdDistance; public GravityGun() { base.Name = "Gravity Gun"; base.Description = "Hold F while aiming at an item to hold it in front of your camera. Mouse wheel adjusts distance."; } protected override void OnEnable() { _grabbed = null; _holdDistance = 6f; } protected override void OnDisable() { ReleaseGrabbed(); } public override void OnTick() { //IL_001f: 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_0078: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) if (!Input.GetKey((KeyCode)102)) { ReleaseGrabbed(); return; } Camera main = Camera.main; if (!Object.op_Implicit((Object)(object)main)) { return; } float y = Input.mouseScrollDelta.y; if (!Mathf.Approximately(y, 0f)) { _holdDistance = Mathf.Clamp(_holdDistance + y * 0.75f, 1.5f, 30f); } RaycastHit val = default(RaycastHit); if (!Object.op_Implicit((Object)(object)_grabbed) && Physics.Raycast(((Component)main).transform.position, ((Component)main).transform.forward, ref val, 100f)) { Item val2 = (Object.op_Implicit((Object)(object)((RaycastHit)(ref val)).collider) ? ((Component)((RaycastHit)(ref val)).collider).GetComponentInParent() : null); if (Object.op_Implicit((Object)(object)val2)) { _grabbed = val2; } } if (Object.op_Implicit((Object)(object)_grabbed)) { SpawnFeatureHelpers.SetItemKinematic(_grabbed, kinematic: true, SpawnFeatureHelpers.GetCameraSpawnPosition(_holdDistance), ((Component)_grabbed).transform.rotation); } } private void ReleaseGrabbed() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)_grabbed)) { SpawnFeatureHelpers.SetItemKinematic(_grabbed, kinematic: false, ((Component)_grabbed).transform.position, ((Component)_grabbed).transform.rotation); } _grabbed = null; } } public class ItemCookLevel : NumberFeature { public ItemCookLevel() { base.Name = "Item Cook Level"; base.Description = "Cooked amount sent to loaded item RPCs."; base.Min = 0f; base.Max = 4f; base.Value = SpawnState.CookLevel; base.Step = 1f; base.Decimals = 0; } protected override void OnValueChanged(float newValue) { SpawnState.CookLevel = newValue; } } public class RemoveAllFlags : ButtonFeature { public RemoveAllFlags() { base.Name = "Remove All Flags"; base.Description = "Destroys planted seagull flag PhotonViews."; base.ButtonLabel = "Remove"; } public override void Execute() { AnimationJuice[] array = Object.FindObjectsByType((FindObjectsSortMode)0); foreach (AnimationJuice val in array) { if (Object.op_Implicit((Object)(object)val) && ((Object)((Component)val).gameObject).name.Contains("Flag_planted_seagull")) { PhotonView photonView = SpawnFeatureHelpers.GetPhotonView((Component)(object)val); if (Object.op_Implicit((Object)(object)photonView)) { SpawnFeatureHelpers.TakeOwnership(photonView); PhotonNetwork.Destroy(photonView); } } } } } public class RemoveAllItems : ButtonFeature { public RemoveAllItems() { base.Name = "Remove All Items"; base.Description = "Takes ownership of loaded item PhotonViews and destroys them."; base.ButtonLabel = "Remove"; } public override void Execute() { SpawnFeatureHelpers.ForEachItemView(delegate(PhotonView view) { SpawnFeatureHelpers.TakeOwnership(view); PhotonNetwork.Destroy(view); }); } } public class RemoveAllTornados : RuntimeActionButton { public RemoveAllTornados() : base("Remove All Tornados", "Remove", "Destroys loaded tornado PhotonViews.", CharacterActionRuntime.RemoveAllTornados) { } } public class RemoveMyItems : ButtonFeature { public RemoveMyItems() { base.Name = "Remove My Items"; base.Description = "Destroys loaded item PhotonViews owned by you."; base.ButtonLabel = "Remove"; } public override void Execute() { SpawnFeatureHelpers.ForEachItemView(delegate(PhotonView view) { if (view.IsMine) { PhotonNetwork.Destroy(view); } }); } } internal sealed class SelectSpawnItem : ButtonFeature, IMenuTagProvider { public Item Item { get; } public List Tags { get { //IL_0033: Unknown result type (might be due to invalid IL or missing references) if (!SpawnState.IsSelected(Item)) { return new List(); } return new List(1) { new MenuTag("SELECTED", new Color(0.18f, 0.62f, 0.86f, 1f)) }; } } public SelectSpawnItem(Item item, string name) { Item = item; base.Name = name; base.Description = "Select this item for spawn actions."; base.ButtonLabel = "Select"; } public override void Execute() { SpawnState.SelectedItem = Item; } } internal static class SpawnedEntityDeletion { public static bool Delete(SpawnState.SpawnedEntityEntry entry) { if (entry == null || !Object.op_Implicit((Object)(object)entry.GameObject)) { return false; } try { if (Object.op_Implicit((Object)(object)entry.View)) { SpawnFeatureHelpers.TakeOwnership(entry.View); PhotonNetwork.Destroy(entry.View); } else { Object.Destroy((Object)(object)entry.GameObject); } SpawnState.ForgetSpawnedEntity(entry.Id); return true; } catch { return false; } } } public class SpawnedEntityDirectory : Feature, IMenuRowProvider, IMenuSidePanelProvider { private sealed class DeleteSpawnedEntity : ButtonFeature, IMenuTagProvider { public SpawnState.SpawnedEntityEntry Entry { get; } public List Tags { get; } public DeleteSpawnedEntity(SpawnState.SpawnedEntityEntry entry) { //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) Entry = entry; base.Name = (entry?.Name ?? "Spawned Entity") + " #" + (entry?.Id.ToString(CultureInfo.InvariantCulture) ?? "?"); base.Description = "Delete this tracked spawned entity."; base.ButtonLabel = "Delete"; Tags = new List(1) { new MenuTag((entry != null && entry.Networked) ? "NET" : "LOCAL", (entry != null && entry.Networked) ? new Color(0.22f, 0.5f, 0.9f, 1f) : new Color(0.36f, 0.38f, 0.42f, 1f)) }; } public override void Execute() { if (SpawnedEntityDeletion.Delete(Entry)) { NotificationSystem.Push("Spawned Entity Deleted", Entry?.Name ?? "Spawned entity", NotificationKind.Success); } else { NotificationSystem.Push("Spawned Entity Delete Failed", Entry?.Name ?? "Spawned entity", NotificationKind.Warning); } } } private const string SpawnedEntitiesCategory = "Spawn/Entities/Spawned Entities"; public SpawnedEntityDirectory() { base.Name = "Spawned Entity Directory"; base.Description = "Lists tracked spawned entities for individual deletion."; } public IEnumerable GetRows(string category) { if (category != "Spawn/Entities/Spawned Entities") { return Array.Empty(); } IReadOnlyList spawnedEntities = SpawnState.GetSpawnedEntities(); List list = new List(); for (int i = 0; i < spawnedEntities.Count; i++) { list.Add(new DeleteSpawnedEntity(spawnedEntities[i])); } if (list.Count == 0) { list.Add(new InfoFeature("Spawned Entities", "None", "Spawn an item, object, or entity first.")); } return list; } public bool TryGetSidePanel(string category, object selectedRow, out MenuSidePanel panel) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) panel = null; if (category != "Spawn/Entities/Spawned Entities" || !(selectedRow is DeleteSpawnedEntity deleteSpawnedEntity) || deleteSpawnedEntity.Entry == null) { return false; } SpawnState.SpawnedEntityEntry entry = deleteSpawnedEntity.Entry; Vector3 position = entry.Position; panel = new MenuSidePanel("SPAWNED ENTITY", entry.Name, new List { new InfoFeature("ID", entry.Id.ToString(CultureInfo.InvariantCulture)), new InfoFeature("Type", entry.Networked ? "Networked" : "Local"), new InfoFeature("Position", FormatPosition(position)) }, null, deleteSpawnedEntity.Tags); return true; } private static string FormatPosition(Vector3 value) { return value.x.ToString("F1", CultureInfo.InvariantCulture) + ", " + value.y.ToString("F1", CultureInfo.InvariantCulture) + ", " + value.z.ToString("F1", CultureInfo.InvariantCulture); } } public class SpawnItemDirectory : Feature, IMenuRowProvider, IMenuSidePanelProvider { private const string SelectorCategory = "Spawn/Items/Item Selector"; public SpawnItemDirectory() { base.Name = "Spawn Item Directory"; base.Description = "Builds selectable item rows for the Spawn menu."; } public IEnumerable GetRows(string category) { if (category != "Spawn/Items/Item Selector") { return Array.Empty(); } InventoryState.RefreshItemsIfNeeded(); List list = new List(); foreach (InventoryState.ItemEntry itemEntry in InventoryState.ItemEntries) { if (itemEntry != null && Object.op_Implicit((Object)(object)itemEntry.Item) && MatchesSearch(itemEntry)) { list.Add(new SelectSpawnItem(itemEntry.Item, itemEntry.DisplayName)); } } if (list.Count == 0) { list.Add(new InfoFeature("Items", "None", "No item names matched the current search.")); } return list; } public bool TryGetSidePanel(string category, object selectedRow, out MenuSidePanel panel) { panel = null; if (category != "Spawn/Items/Item Selector") { return false; } if (!(selectedRow is SelectSpawnItem selectSpawnItem) || !Object.op_Implicit((Object)(object)selectSpawnItem.Item)) { return false; } panel = ItemDetails.BuildPanel(selectSpawnItem.Item); return panel != null; } private static bool MatchesSearch(InventoryState.ItemEntry entry) { if (string.IsNullOrWhiteSpace(SpawnState.SearchText)) { return true; } string value = SpawnState.SearchText.ToLowerInvariant(); if (!entry.LowerDisplayName.Contains(value)) { return entry.LowerPrefabName.Contains(value); } return true; } } public class SpawnItemSearch : TextFeature { public SpawnItemSearch() { base.Name = "Search"; base.Description = "Filter spawnable item prefabs by name."; base.EmptyDisplayText = "All items"; base.MaxLength = 48; } protected override void OnTextChanged(string newValue) { SpawnState.SearchText = newValue ?? string.Empty; } } public class SpawnMushroomZombie : RuntimeActionButton { public SpawnMushroomZombie() : base("Spawn MushroomZombie", "Spawn", "Spawns a mushroom zombie at your position.", CharacterActionRuntime.SpawnMushroomZombie) { } } public class SpawnObjectLocal : ButtonFeature { public SpawnObjectLocal() { base.Name = "Spawn Object Local"; base.Description = "Resources-spawns the configured object path locally."; base.ButtonLabel = "Spawn"; } public override void Execute() { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) if (!string.IsNullOrWhiteSpace(SpawnState.ObjectPath)) { GameObject val = Resources.Load(SpawnState.ObjectPath); if (Object.op_Implicit((Object)(object)val)) { GameObject obj = Object.Instantiate(val, SpawnFeatureHelpers.GetCameraSpawnPosition(2f), Quaternion.identity); ((Object)obj).name = SpawnState.ObjectPath; SpawnState.RegisterSpawnedEntity(obj, SpawnState.ObjectPath); } } } } public class SpawnObjectNetworked : ButtonFeature { public SpawnObjectNetworked() { base.Name = "Spawn Object"; base.Description = "Photon-spawns the configured object path."; base.ButtonLabel = "Spawn"; } public override void Execute() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) if (!string.IsNullOrWhiteSpace(SpawnState.ObjectPath)) { SpawnState.RegisterSpawnedEntity(PhotonNetwork.Instantiate(SpawnState.ObjectPath, SpawnFeatureHelpers.GetCameraSpawnPosition(2f), Quaternion.identity, (byte)0, (object[])null), SpawnState.ObjectPath); } } } public class SpawnObjectPath : TextFeature { public SpawnObjectPath() { base.Name = "Object Path"; base.Description = "Photon/Resources prefab path used by Spawn Object actions."; base.EmptyDisplayText = "Prefab path"; base.MaxLength = 120; } protected override void OnTextChanged(string newValue) { SpawnState.ObjectPath = newValue ?? string.Empty; } } public class SpawnPlayerGhost : RuntimeActionButton { public SpawnPlayerGhost() : base("Spawn PlayerGhost", "Spawn", "Spawns a PlayerGhost at your position.", CharacterActionRuntime.SpawnPlayerGhost) { } } public class SpawnScoutmaster : RuntimeActionButton { public SpawnScoutmaster() : base("Spawn Scoutmaster", "Spawn", "Spawns a scoutmaster at your position.", CharacterActionRuntime.SpawnScoutmaster) { } } public class SpawnSelectedItem : ButtonFeature { public SpawnSelectedItem() { base.Name = "Spawn Item"; base.Description = "Spawns the selected item in front of your camera."; base.ButtonLabel = "Spawn"; } public override void Execute() { SpawnFeatureHelpers.SpawnWorldItem(SpawnState.SelectedItem); } } public class SpawnSelectedItemInEmptySlot : ButtonFeature { public SpawnSelectedItemInEmptySlot() { base.Name = "Spawn Item In Empty Slot"; base.Description = "Assigns the selected item to the first empty local inventory slot."; base.ButtonLabel = "Assign"; } public override void Execute() { if (!Object.op_Implicit((Object)(object)SpawnState.SelectedItem)) { return; } Player localPlayer = Player.localPlayer; if (!Object.op_Implicit((Object)(object)localPlayer) || localPlayer.itemSlots == null) { return; } for (int i = 0; i < localPlayer.itemSlots.Length; i++) { if (!Object.op_Implicit((Object)(object)localPlayer.itemSlots[i]?.prefab)) { GameActions.AssignInventoryItem(i, SpawnState.SelectedItem); break; } } } } public class SpawnTornado : RuntimeActionButton { public SpawnTornado() : base("Spawn Tornado", "Spawn", "Spawns a tornado in front of your camera.", CharacterActionRuntime.SpawnTornado) { } } public class SpinAllItems : Feature { public SpinAllItems() { base.Name = "Spin All Items"; base.Description = "Applies a repeated rotation RPC to loaded items."; } protected override void OnEnable() { OnTick(); } protected override void OnDisable() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) Item[] array = Object.FindObjectsByType((FindObjectsSortMode)0); foreach (Item val in array) { if (Object.op_Implicit((Object)(object)val)) { SpawnFeatureHelpers.SetItemKinematic(val, kinematic: false, ((Component)val).transform.position, ((Component)val).transform.rotation); } } } public override void OnTick() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003f: 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_0045: Unknown result type (might be due to invalid IL or missing references) Item[] array = Object.FindObjectsByType((FindObjectsSortMode)0); Quaternion val = Quaternion.Euler(0f, SpawnState.SpinSpeed, 0f); Item[] array2 = array; foreach (Item val2 in array2) { if (Object.op_Implicit((Object)(object)val2)) { SpawnFeatureHelpers.SetItemKinematic(val2, kinematic: true, ((Component)val2).transform.position, ((Component)val2).transform.rotation * val); } } } } public class SpinItemSpeed : NumberFeature { public SpinItemSpeed() { base.Name = "Spin Speed"; base.Description = "Rotation step used by Spin All Items."; base.Min = 0f; base.Max = 100f; base.Value = SpawnState.SpinSpeed; base.Step = 1f; base.Decimals = 0; } protected override void OnValueChanged(float newValue) { SpawnState.SpinSpeed = newValue; } } public class UnfreezeAllItems : ButtonFeature { public UnfreezeAllItems() { base.Name = "Unfreeze All Items"; base.Description = "Releases loaded items from kinematic mode."; base.ButtonLabel = "Unfreeze"; } public override void Execute() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) Item[] array = Object.FindObjectsByType((FindObjectsSortMode)0); foreach (Item val in array) { if (Object.op_Implicit((Object)(object)val)) { SpawnFeatureHelpers.SetItemKinematic(val, kinematic: false, ((Component)val).transform.position, ((Component)val).transform.rotation); } } } } internal static class SpawnFeatureHelpers { public static Item SpawnWorldItem(Item item) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) return SpawnWorldItem(item, GetCameraSpawnPosition(2f), Quaternion.identity); } public static Item SpawnWorldItem(Item item, Vector3 position, Quaternion rotation) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)item)) { return null; } string name = ((Object)item).name; if (string.IsNullOrEmpty(name)) { return null; } GameObject val = PhotonNetwork.Instantiate("0_Items/" + name, position, rotation, (byte)0, (object[])null); Item result = (Object.op_Implicit((Object)(object)val) ? val.GetComponent() : null); if (Object.op_Implicit((Object)(object)val)) { SpawnState.RegisterSpawnedEntity(val, name); } return result; } public static void ForEachItemView(Action action) { if (action == null) { return; } PhotonView[] array = Object.FindObjectsByType((FindObjectsSortMode)0); foreach (PhotonView val in array) { if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)((Component)val).GetComponent())) { action(val); } } } public static void TakeOwnership(PhotonView view) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)view) && PhotonNetwork.LocalPlayer != null) { view.OwnershipTransfer = (OwnershipOption)2; view.OwnerActorNr = PhotonNetwork.LocalPlayer.ActorNumber; view.ControllerActorNr = PhotonNetwork.LocalPlayer.ActorNumber; view.RequestOwnership(); view.TransferOwnership(PhotonNetwork.LocalPlayer); } } public static void RpcAllItems(string rpcName, params object[] args) { Item[] array = Object.FindObjectsByType((FindObjectsSortMode)0); for (int i = 0; i < array.Length; i++) { PhotonView photonView = GetPhotonView((Component)(object)array[i]); if (Object.op_Implicit((Object)(object)photonView)) { photonView.RPC(rpcName, (RpcTarget)0, args ?? Array.Empty()); } } } public static void RpcAllCooking(string rpcName, params object[] args) { ItemCooking[] array = Object.FindObjectsByType((FindObjectsSortMode)0); for (int i = 0; i < array.Length; i++) { PhotonView photonView = GetPhotonView((Component)(object)array[i]); if (Object.op_Implicit((Object)(object)photonView)) { photonView.RPC(rpcName, (RpcTarget)0, args ?? Array.Empty()); } } } public static void SetItemKinematic(Item item, bool kinematic, Vector3 position, Quaternion rotation) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) PhotonView photonView = GetPhotonView((Component)(object)item); if (Object.op_Implicit((Object)(object)photonView)) { photonView.RPC("SetKinematicRPC", (RpcTarget)0, new object[3] { kinematic, position, rotation }); } } public static PhotonView GetPhotonView(Component component) { if (!Object.op_Implicit((Object)(object)component)) { return null; } return component.GetComponent() ?? component.GetComponentInChildren(); } public static Vector3 GetCameraSpawnPosition(float distance) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0025: 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_0030: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) Camera main = Camera.main; if (!Object.op_Implicit((Object)(object)main)) { return Vector3.zero; } return ((Component)main).transform.position + ((Component)main).transform.forward * distance; } } internal static class SpawnState { internal sealed class SpawnedEntityEntry { public int Id { get; } public string Name { get; } public GameObject GameObject { get; } public PhotonView View { get; } public float CreatedAt { get; } public Vector3 Position { get { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)GameObject)) { return Vector3.zero; } return GameObject.transform.position; } } public bool Networked => Object.op_Implicit((Object)(object)View); public SpawnedEntityEntry(int id, string name, GameObject gameObject, PhotonView view, float createdAt) { Id = id; Name = name ?? string.Empty; GameObject = gameObject; View = view; CreatedAt = createdAt; } } public static Item SelectedItem; public static string SearchText = string.Empty; public static string ObjectPath = string.Empty; public static float SpinSpeed = 15f; public static float CookLevel = 4f; private static readonly List SpawnedEntities = new List(); private static int _nextSpawnedEntityId = 1; public static string GetSelectedItemName() { if (!Object.op_Implicit((Object)(object)SelectedItem)) { return string.Empty; } try { string name = SelectedItem.GetName(); if (!string.IsNullOrWhiteSpace(name)) { return name; } } catch { } return ((Object)SelectedItem).name ?? string.Empty; } public static bool IsSelected(Item item) { if (!Object.op_Implicit((Object)(object)item) || !Object.op_Implicit((Object)(object)SelectedItem)) { return false; } if (item == SelectedItem) { return true; } try { if (item.itemID != 0 && item.itemID == SelectedItem.itemID) { return true; } } catch { } return string.Equals(((Object)item).name, ((Object)SelectedItem).name, StringComparison.Ordinal); } public static void RegisterSpawnedEntity(GameObject gameObject, string displayName) { if (Object.op_Implicit((Object)(object)gameObject)) { CleanupSpawnedEntities(); SpawnedEntities.Add(new SpawnedEntityEntry(_nextSpawnedEntityId++, string.IsNullOrWhiteSpace(displayName) ? ((Object)gameObject).name : displayName.Trim(), gameObject, gameObject.GetComponent() ?? gameObject.GetComponentInChildren(), Time.unscaledTime)); } } public static IReadOnlyList GetSpawnedEntities() { CleanupSpawnedEntities(); return SpawnedEntities.ToArray(); } public static void ForgetSpawnedEntity(int id) { SpawnedEntities.RemoveAll((SpawnedEntityEntry entry) => entry == null || entry.Id == id || !Object.op_Implicit((Object)(object)entry.GameObject)); } private static void CleanupSpawnedEntities() { SpawnedEntities.RemoveAll((SpawnedEntityEntry entry) => entry == null || !Object.op_Implicit((Object)(object)entry.GameObject)); } } } namespace CubeX.Features.Settings { public class FeatureKeybindDirectory : Feature, IMenuRowProvider { private const string KeybindsCategory = "Settings/Keybinds"; private const string FeatureKeybindPrefix = "Settings/Keybinds/Feature/"; public static string SelectedFeatureId { get; private set; } public static string SelectedFeatureName { get; private set; } public FeatureKeybindDirectory() { base.Name = "Feature Keybind Directory"; base.Description = "Builds rows for keybinds assigned to menu features."; } public IEnumerable GetRows(string category) { if (string.Equals(category, "Settings/Keybinds", StringComparison.Ordinal)) { return BuildKeybindRows(); } if (category != null && category.StartsWith("Settings/Keybinds/Feature/", StringComparison.Ordinal)) { return BuildKeybindActionRows(category.Substring("Settings/Keybinds/Feature/".Length)); } return Array.Empty(); } private static IEnumerable BuildKeybindRows() { //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_0148: 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) List list = new List(); IReadOnlyDictionary featureBinds = RuntimeKeybinds.GetFeatureBinds(); if (featureBinds.Count == 0) { list.Add(new InfoFeature("Feature Keybinds", "None", "Hover a feature and press F8 to assign a keybind.")); return list; } Dictionary features = (from feature in FeatureManager.Current?.All where feature != null group feature by feature.GetType().FullName).ToDictionary, string, Feature>((IGrouping group) => group.Key, (IGrouping group) => group.First(), StringComparer.Ordinal) ?? new Dictionary(StringComparer.Ordinal); foreach (KeyValuePair item in featureBinds.OrderBy, string>((KeyValuePair pair) => GetFeatureName(features, pair.Key), StringComparer.OrdinalIgnoreCase)) { string featureName = GetFeatureName(features, item.Key); KeyCode value = item.Value; string text = ((object)(KeyCode)(ref value)).ToString(); list.Add(new SubmenuFeature(featureName, "Settings/Keybinds/Feature/" + item.Key, "Manage keybind for " + featureName + ".", new List(1) { new MenuTag(text.ToUpperInvariant(), new Color(0.18f, 0.62f, 0.86f, 1f)) })); } return list; } private static IEnumerable BuildKeybindActionRows(string featureId) { if (string.IsNullOrEmpty(featureId) || !RuntimeKeybinds.TryGetFeatureBind(featureId, out var key)) { SelectedFeatureId = null; SelectedFeatureName = null; return new <>z__ReadOnlySingleElementList(new InfoFeature("Keybind", "Not found", "This keybind is no longer assigned.")); } Feature? obj = FeatureManager.Current?.All.FirstOrDefault((Feature current) => current != null && string.Equals(current.GetType().FullName, featureId, StringComparison.Ordinal)); SelectedFeatureId = featureId; SelectedFeatureName = obj?.Name ?? FormatFeatureId(featureId); return new <>z__ReadOnlyArray(new object[3] { new InfoFeature("Feature", SelectedFeatureName), new InfoFeature("Key", ((object)(KeyCode)(ref key)).ToString()), new RemoveSelectedFeatureKeybind() }); } private static string GetFeatureName(Dictionary features, string featureId) { if (!features.TryGetValue(featureId, out var value) || value == null) { return FormatFeatureId(featureId); } return value.Name; } private static string FormatFeatureId(string featureId) { if (string.IsNullOrWhiteSpace(featureId)) { return "Unknown Feature"; } int num = featureId.LastIndexOf('.'); return string.Concat(((num >= 0 && num + 1 < featureId.Length) ? featureId.Substring(num + 1) : featureId).Select((char c, int i) => (i <= 0 || !char.IsUpper(c)) ? c.ToString() : (" " + c))); } } public class FlightBindSetting : KeybindCaptureFeature { public FlightBindSetting() : base(KeybindTarget.Flight) { base.Name = "Set Flight Bind"; base.Description = "Press Enter, then press the key to use for Fly."; } } public abstract class KeybindCaptureFeature : ButtonFeature { private readonly KeybindTarget _target; public override bool TickWhenDisabled => true; protected KeybindCaptureFeature(KeybindTarget target) { _target = target; base.ButtonLabel = RuntimeKeybinds.GetDisplayName(target); } public override void Execute() { RuntimeKeybinds.BeginCapture(_target); SyncLabel(); } public override void OnTick() { RuntimeKeybinds.TickCapture(); SyncLabel(); } private void SyncLabel() { base.ButtonLabel = RuntimeKeybinds.GetDisplayName(_target); base.Description = (RuntimeKeybinds.IsCapturingTarget(_target) ? "Release Enter, then press any keyboard key, including numpad and function keys." : "Press Enter, then press the key to use for this bind."); } } public class MenuBindSetting : KeybindCaptureFeature { public MenuBindSetting() : base(KeybindTarget.Menu) { base.Name = "Set Menu Bind"; base.Description = "Press Enter, then press the key to use for the menu toggle."; } } public class RemoveSelectedFeatureKeybind : ButtonFeature { public RemoveSelectedFeatureKeybind() { base.Name = "Remove Keybind"; base.Description = "Removes the selected feature keybind."; base.ButtonLabel = "Remove"; } public override void Execute() { string selectedFeatureId = FeatureKeybindDirectory.SelectedFeatureId; string selectedFeatureName = FeatureKeybindDirectory.SelectedFeatureName; RuntimeKeybinds.ClearFeatureBind(selectedFeatureId); NotificationSystem.Push("Keybind Removed", string.IsNullOrWhiteSpace(selectedFeatureName) ? "Feature keybind removed." : selectedFeatureName, NotificationKind.Success); } } public class ToggleFlyWithBind : Feature { public override bool TickWhenDisabled => true; public ToggleFlyWithBind() { base.Name = "Flight Bind Enabled"; base.Description = "Allows the configured flight key to toggle Fly."; base.Enabled = true; } protected override void OnEnable() { } protected override void OnDisable() { } public override void OnTick() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) if (RuntimeKeybinds.IsCapturing || !base.Enabled || !Input.GetKeyDown(RuntimeKeybinds.FlightBind) || FeatureManager.Current == null) { return; } foreach (Feature item in FeatureManager.Current.All) { if (item is Fly fly) { fly.Enabled = !fly.Enabled; break; } } } } public enum KeybindTarget { Menu, Flight } internal static class RuntimeKeybinds { private const string MenuBindKey = "CubeX_menu_bind"; private const string FeatureBindsKey = "CubeX_feature_binds"; private static readonly KeyCode[] CaptureKeys; private static KeybindTarget? _captureTarget; private static Feature _captureFeature; private static bool _captureArmed; private static readonly Dictionary FeatureBinds; public static KeyCode MenuBind { get; private set; } public static KeyCode FlightBind { get; private set; } public static bool IsCapturing { get { if (!_captureTarget.HasValue) { return _captureFeature != null; } return true; } } static RuntimeKeybinds() { //IL_0066: Unknown result type (might be due to invalid IL or missing references) CaptureKeys = (from key in (from KeyCode key in Enum.GetValues(typeof(KeyCode)) where (int)key > 0 select key).Distinct() orderby (int)key select key).ToArray(); FeatureBinds = new Dictionary(StringComparer.Ordinal); MenuBind = ReadKey("CubeX_menu_bind", (KeyCode)277); FlightBind = (KeyCode)0; LoadFeatureBinds(); } public static void BeginCapture(KeybindTarget target) { _captureTarget = target; _captureFeature = null; _captureArmed = false; } public static void BeginCapture(Feature feature) { if (CanBind(feature)) { _captureTarget = null; _captureFeature = feature; _captureArmed = false; } } public static bool IsCapturingTarget(KeybindTarget target) { return _captureTarget == target; } public static void TickCapture() { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) if (!_captureTarget.HasValue && _captureFeature == null) { return; } if (!_captureArmed) { if (!Input.anyKey) { _captureArmed = true; } } else { if (!Input.anyKeyDown) { return; } KeyCode[] captureKeys = CaptureKeys; foreach (KeyCode val in captureKeys) { if (Input.GetKeyDown(val)) { if (_captureFeature != null) { SetFeatureBind(_captureFeature, val); } else if (_captureTarget.Value == KeybindTarget.Menu) { SetMenuBind(val); } _captureTarget = null; _captureFeature = null; _captureArmed = false; break; } } } } public static void TickFeatureBinds(FeatureManager features) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) if (features == null || IsCapturing || FeatureBinds.Count == 0) { return; } foreach (Feature item in features.All) { if (CanBind(item) && FeatureBinds.TryGetValue(GetFeatureId(item), out var value) && Input.GetKeyDown(value)) { ActivateFeature(item); } } } public static string GetFeatureBindDisplay(Feature feature) { if (_captureFeature == feature) { return "Press Key"; } if (feature == null || !FeatureBinds.TryGetValue(GetFeatureId(feature), out var value)) { return string.Empty; } return ((object)(KeyCode)(ref value)).ToString(); } public static string GetFeatureBindDescription(Feature feature) { if (!CanBind(feature)) { return string.Empty; } string featureBindDisplay = GetFeatureBindDisplay(feature); if (!string.IsNullOrEmpty(featureBindDisplay)) { return "Keybinded: " + featureBindDisplay; } return "Set keybind: F8"; } public static void ClearFeatureBind(Feature feature) { if (feature != null) { ClearFeatureBind(GetFeatureId(feature)); } } public static void ClearFeatureBind(string featureId) { if (!string.IsNullOrEmpty(featureId) && FeatureBinds.Remove(featureId)) { SaveFeatureBinds(); } } public static void ClearAllFeatureBinds() { FeatureBinds.Clear(); SaveFeatureBinds(); } public static IReadOnlyDictionary GetFeatureBinds() { return FeatureBinds; } public static bool TryGetFeatureBind(string featureId, out KeyCode key) { key = (KeyCode)0; if (!string.IsNullOrEmpty(featureId)) { return FeatureBinds.TryGetValue(featureId, out key); } return false; } private static void SetMenuBind(KeyCode key) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) MenuBind = key; PlayerPrefs.SetString("CubeX_menu_bind", ((object)(KeyCode)(ref key)).ToString()); PlayerPrefs.Save(); } private static void SetFeatureBind(Feature feature, KeyCode key) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) if (CanBind(feature)) { FeatureBinds[GetFeatureId(feature)] = key; SaveFeatureBinds(); } } public static string GetDisplayName(KeybindTarget target) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) if (IsCapturingTarget(target)) { return "Press Key"; } KeyCode val; if (target != 0) { val = (KeyCode)0; return ((object)(KeyCode)(ref val)).ToString(); } val = MenuBind; return ((object)(KeyCode)(ref val)).ToString(); } private static KeyCode ReadKey(string key, KeyCode fallback) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) if (!Enum.TryParse(PlayerPrefs.GetString(key, ((object)(KeyCode)(ref fallback)).ToString()), ignoreCase: true, out KeyCode result)) { return fallback; } return result; } private static bool CanBind(Feature feature) { if (feature == null) { return false; } if (feature is TextFeature) { return false; } if (feature is ColorFeature) { return false; } if (feature is SeparatorFeature) { return false; } if (feature is InfoFeature) { return false; } if (feature is SubmenuFeature) { return false; } if (feature is IMenuRowProvider) { return false; } if (feature is IMenuSidePanelProvider) { return false; } return true; } private static void ActivateFeature(Feature feature) { try { if (feature is ButtonFeature buttonFeature) { buttonFeature.Execute(); NotifyKeybind(feature, "Executed"); } else if (feature is NumberBoolFeature numberBoolFeature) { numberBoolFeature.Enabled = !numberBoolFeature.Enabled; NotifyKeybind(feature, numberBoolFeature.Enabled ? "Enabled" : "Disabled"); } else if (!(feature is NumberFeature)) { feature.Enabled = !feature.Enabled; NotifyKeybind(feature, feature.Enabled ? "Enabled" : "Disabled"); } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Feature Keybind] " + feature.Name + ": " + ex.Message)); } } } private static string GetFeatureId(Feature feature) { return feature.GetType().FullName; } private static void LoadFeatureBinds() { //IL_007f: Unknown result type (might be due to invalid IL or missing references) FeatureBinds.Clear(); string @string = PlayerPrefs.GetString("CubeX_feature_binds", string.Empty); if (string.IsNullOrWhiteSpace(@string)) { return; } string[] array = @string.Split(new char[1] { '\n' }, StringSplitOptions.RemoveEmptyEntries); foreach (string text in array) { int num = text.LastIndexOf('|'); if (num > 0 && num + 1 < text.Length) { string key = text.Substring(0, num); if (Enum.TryParse(text.Substring(num + 1), ignoreCase: true, out KeyCode result)) { FeatureBinds[key] = result; } } } } private static void SaveFeatureBinds() { string text = string.Join("\n", FeatureBinds.Select(delegate(KeyValuePair pair) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) string key = pair.Key; KeyCode value = pair.Value; return key + "|" + ((object)(KeyCode)(ref value)).ToString(); })); PlayerPrefs.SetString("CubeX_feature_binds", text); PlayerPrefs.Save(); } private static void NotifyKeybind(Feature feature, string action) { if (NotificationSettings.KeybindToggles && feature != null) { string featureBindDisplay = GetFeatureBindDisplay(feature); string text = (string.IsNullOrEmpty(featureBindDisplay) ? action : (action + " by " + featureBindDisplay)); NotificationSystem.Push("Keybind Toggle", feature.Name + " - " + text); } } } } namespace CubeX.Features.Self { public class FreezeAfflictions : Feature { private Character _lastCharacter; private PropertyInfo _statusesLockedProperty; private bool? _originalValue; public FreezeAfflictions() { base.Name = "Freeze Afflictions"; base.Description = "Prevents your character's status afflictions from changing."; } protected override void OnEnable() { OnTick(); } protected override void OnDisable() { RestoreOriginal(); _lastCharacter = null; _statusesLockedProperty = null; _originalValue = null; } public override void OnTick() { Character localCharacter = Character.localCharacter; if (!Object.op_Implicit((Object)(object)localCharacter) || (Object.op_Implicit((Object)(object)localCharacter.data) && localCharacter.data.dead)) { RestoreOriginal(); _lastCharacter = null; _statusesLockedProperty = null; _originalValue = null; return; } if (localCharacter != _lastCharacter) { RestoreOriginal(); _lastCharacter = localCharacter; _statusesLockedProperty = AccessTools.Property(((object)localCharacter).GetType(), "statusesLocked"); _originalValue = null; } if (!(_statusesLockedProperty == null) && _statusesLockedProperty.CanWrite) { bool valueOrDefault = _originalValue.GetValueOrDefault(); if (!_originalValue.HasValue) { valueOrDefault = ReadBool(_statusesLockedProperty, localCharacter); _originalValue = valueOrDefault; } _statusesLockedProperty.SetValue(localCharacter, true, null); } } private void RestoreOriginal() { if (Object.op_Implicit((Object)(object)_lastCharacter) && !(_statusesLockedProperty == null) && _originalValue.HasValue) { _statusesLockedProperty.SetValue(_lastCharacter, _originalValue.Value, null); } } private static bool ReadBool(PropertyInfo property, object target) { try { object value = property.GetValue(target, null); return value is bool && (bool)value; } catch { return false; } } } public class NoWeight : Feature { private const int WeightStatusValue = 7; public NoWeight() { base.Name = "No Weight"; base.Description = "Clears the carried-weight affliction from your character."; } protected override void OnEnable() { OnTick(); } protected override void OnDisable() { } public override void OnTick() { Character localCharacter = Character.localCharacter; if (Object.op_Implicit((Object)(object)localCharacter) && (!Object.op_Implicit((Object)(object)localCharacter.data) || !localCharacter.data.dead)) { CharacterAfflictions val = ((Component)localCharacter).GetComponent(); if (!Object.op_Implicit((Object)(object)val)) { val = ((Component)localCharacter).GetComponentInChildren(); } if (Object.op_Implicit((Object)(object)val)) { val.SetStatus((STATUSTYPE)7, 0f, true); } } } } public class EasyBackpackAccess : Feature { public EasyBackpackAccess() { base.Name = "Easy Backpack"; base.Description = "Press B to open your equipped backpack, or the carried player's backpack when carrying someone."; } protected override void OnEnable() { QualityOfLifeRuntime.EasyBackpack = true; } protected override void OnDisable() { QualityOfLifeRuntime.EasyBackpack = false; QualityOfLifeRuntime.ResetBackpackAccess(); } public override void OnTick() { QualityOfLifeRuntime.TickEasyBackpack(); } } public class PeakKickDropMode : Feature { public PeakKickDropMode() { base.Name = "Kick Animation"; base.Description = "Allows the drop input to count as kick mode while grabbing, matching the PeakKick behavior."; } protected override void OnEnable() { OnTick(); } protected override void OnDisable() { QualityOfLifeRuntime.PeakKick = false; } public override void OnTick() { QualityOfLifeRuntime.PeakKick = true; } } public sealed class ClimbMultiplier : ClimbMultiplierFeature { public ClimbMultiplier() { base.Name = "Climb Multiplier"; base.Description = "Adjusts regular climbing speed."; } } public abstract class ClimbMultiplierFeature : NumberBoolFeature where TComponent : Component { private const string ClimbSpeedFieldName = "climbSpeedMod"; private TComponent _lastComponent; private FieldInfo _climbSpeedField; private float? _originalValue; protected ClimbMultiplierFeature() { base.Min = 0.2f; base.Max = 20f; base.Value = 1f; base.Step = 0.1f; base.Decimals = 1; base.Unit = "x"; } protected override void OnEnable() { OnTick(); } protected override void OnDisable() { RestoreOriginal(); _lastComponent = default(TComponent); _climbSpeedField = null; _originalValue = null; } public override void OnTick() { Character localCharacter = Character.localCharacter; TComponent val = (Object.op_Implicit((Object)(object)localCharacter) ? ((Component)localCharacter).GetComponent() : default(TComponent)); if (!Object.op_Implicit((Object)(object)localCharacter) || !Object.op_Implicit((Object)(object)val)) { RestoreOriginal(); _lastComponent = default(TComponent); _climbSpeedField = null; _originalValue = null; return; } if ((object)val != (object)_lastComponent) { RestoreOriginal(); _lastComponent = val; _climbSpeedField = AccessTools.Field(typeof(TComponent), "climbSpeedMod"); _originalValue = null; } if (!(_climbSpeedField == null)) { float valueOrDefault = _originalValue.GetValueOrDefault(); if (!_originalValue.HasValue) { valueOrDefault = ReadFloat(_climbSpeedField, val); _originalValue = valueOrDefault; } _climbSpeedField.SetValue(val, _originalValue.Value * base.Value); } } protected override void OnValueChanged(float newValue) { if (base.Enabled) { OnTick(); } } private void RestoreOriginal() { if (Object.op_Implicit((Object)(object)_lastComponent) && !(_climbSpeedField == null) && _originalValue.HasValue) { _climbSpeedField.SetValue(_lastComponent, _originalValue.Value); } } private static float ReadFloat(FieldInfo field, object target) { try { return (field.GetValue(target) is float num) ? num : 1f; } catch { return 1f; } } } public sealed class RopeClimbMultiplier : ClimbMultiplierFeature { public RopeClimbMultiplier() { base.Name = "Rope Climb Multiplier"; base.Description = "Adjusts rope climbing speed."; } } public sealed class VineClimbMultiplier : ClimbMultiplierFeature { public VineClimbMultiplier() { base.Name = "Vine Climb Multiplier"; base.Description = "Adjusts vine climbing speed."; } } [HarmonyPatch(typeof(PhotonNetwork), "ExecuteRpc")] internal static class AntiModderIncomingRpcPatch { private static bool Prefix(Hashtable rpcData, Player sender) { return !IncomingRpcGuard.ShouldBlock(rpcData, sender); } } [HarmonyPatch] internal static class AntiModderLocalActionRelayPatch { [HarmonyPatch(typeof(RescueHook), "Fire")] [HarmonyPrefix] private static void RescueHookFirePrefix(RescueHook __instance) { IncomingRpcGuard.NoteLocalRescueHookUse(__instance); } [HarmonyPatch(typeof(RescueHook), "OnPrimaryFinishedCast")] [HarmonyPrefix] private static void RescueHookFinishedCastPrefix(RescueHook __instance) { IncomingRpcGuard.NoteLocalRescueHookUse(__instance); } [HarmonyPatch(typeof(CharacterItems), "DoDropping")] [HarmonyPrefix] private static void CharacterItemsDroppingPrefix(CharacterItems __instance) { IncomingRpcGuard.NoteLocalInventoryMutation((Component)(object)__instance); } } [HarmonyPatch(typeof(PhotonNetwork), "NetworkInstantiate", new Type[] { typeof(InstantiateParameters), typeof(bool), typeof(bool) })] internal static class AntiModderNetworkInstantiatePatch { private static bool Prefix(ref InstantiateParameters parameters, bool instantiateEvent, ref GameObject __result) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) if (!IncomingRpcGuard.ShouldBlockNetworkInstantiate(parameters, instantiateEvent)) { return true; } __result = null; return false; } } [HarmonyPatch(typeof(PhotonNetwork), "OnEvent")] internal static class AntiModderPhotonDestroyPatch { private static bool Prefix(EventData photonEvent) { return !IncomingPhotonDestroyGuard.ShouldBlock(photonEvent); } } internal static class IncomingPhotonDestroyGuard { [CompilerGenerated] private sealed class d__29 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public string reason; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__29(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSecondsRealtime(1f); <>1__state = 1; return true; case 1: <>1__state = -1; ValidateLocalRoomStateAfterDestroy(reason); _validationRoutine = null; 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 d__27 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public string reason; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__27(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = null; <>1__state = 1; return true; case 1: <>1__state = -1; ReassertLocalRoomState(); <>2__current = (object)new WaitForSecondsRealtime(0.25f); <>1__state = 2; return true; case 2: <>1__state = -1; ReassertLocalRoomState(); <>2__current = (object)new WaitForSecondsRealtime(0.75f); <>1__state = 3; return true; case 3: <>1__state = -1; ReassertLocalRoomState(); ValidateLocalRoomStateAfterDestroy(reason); _resyncRoutine = null; 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 const byte DestroyEventCode = 204; private const byte DestroyPlayerEventCode = 207; private const byte DataKey = 0; private const byte AlternateDataKey = 1; private const float DelayedValidationSeconds = 1f; private static Coroutine _resyncRoutine; private static Coroutine _validationRoutine; public static bool ShouldBlock(EventData photonEvent) { if (photonEvent == null) { return false; } if (photonEvent.Code != 204 && photonEvent.Code != 207) { return false; } if (!IsRemoteSender(photonEvent.Sender)) { return false; } if (!TryGetLocalDestroyTarget(photonEvent, out var targetView, out var eventName, out var detail)) { return false; } Player sender = GetSender(photonEvent.Sender); PlayerFlagDetector.MarkDetectedModder(sender); RpcEventNotifications.NotifyProtectionDetected(eventName, sender, targetView); if (!SelfRuntimeSettings.ModderProtections) { ScheduleDelayedLocalRoomValidation("remote destroy was allowed"); return false; } ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Anti Modder Protection] Blocked remote " + eventName + " from " + FormatSender(sender, photonEvent.Sender) + detail)); } RpcEventNotifications.NotifyProtectionBlocked(eventName, sender); ScheduleLocalRoomResync("blocked remote destroy"); return true; } private static bool TryGetLocalDestroyTarget(EventData photonEvent, out PhotonView targetView, out string eventName, out string detail) { targetView = null; eventName = "Photon Destroy"; detail = string.Empty; if (!TryGetEventTarget(photonEvent.CustomData, out var target)) { if (photonEvent.Code != 207) { return false; } target = 0; } if (photonEvent.Code == 207) { eventName = ((target <= 0) ? "Photon DestroyAll" : "Photon DestroyPlayer"); targetView = GetLocalIdentityView(); if (!TargetsLocalActor(target)) { return false; } detail = " targeting local actor " + GetLocalActorNumber().ToString(CultureInfo.InvariantCulture); return true; } PhotonView foundView = FindPhotonView(target); if (!TryGetProtectedLocalView(target, foundView, out targetView)) { return false; } detail = " targeting local-owned PhotonView " + target.ToString(CultureInfo.InvariantCulture); return true; } private static bool TargetsLocalActor(int targetActor) { if (targetActor <= 0) { return true; } int localActorNumber = GetLocalActorNumber(); if (localActorNumber <= 0) { return false; } return targetActor == localActorNumber; } private static bool TryGetProtectedLocalView(int targetViewId, PhotonView foundView, out PhotonView targetView) { targetView = null; if (TargetsLocalIdentityView(targetViewId, foundView)) { targetView = ((Object.op_Implicit((Object)(object)foundView) && IsLocalIdentityView(foundView)) ? foundView : GetLocalIdentityView()); return true; } if (TargetsLocalOwnedView(targetViewId, foundView)) { targetView = (Object.op_Implicit((Object)(object)foundView) ? foundView : GetLocalIdentityView()); return true; } return false; } private static bool TargetsLocalIdentityView(int targetViewId, PhotonView foundView) { if (targetViewId == 0) { return false; } PhotonView localIdentityView = GetLocalIdentityView(); if (Object.op_Implicit((Object)(object)localIdentityView) && MatchesViewId(localIdentityView, targetViewId)) { return true; } if (Object.op_Implicit((Object)(object)foundView)) { return IsLocalIdentityView(foundView); } return false; } private static bool TargetsLocalOwnedView(int targetViewId, PhotonView foundView) { if (Object.op_Implicit((Object)(object)foundView) && IsLocalOwnedView(foundView)) { return true; } return ViewIdBelongsToLocalActor(targetViewId); } private static PhotonView FindPhotonView(int viewId) { if (viewId == 0) { return null; } try { return PhotonView.Find(viewId); } catch { return null; } } private static PhotonView GetLocalIdentityView() { Character val = FindLocalCharacter(); PhotonView val2 = val?.refs?.view; if (Object.op_Implicit((Object)(object)val2)) { return val2; } if (Object.op_Implicit((Object)(object)val)) { val2 = ((Component)val).GetComponent() ?? ((Component)val).GetComponentInChildren(); if (Object.op_Implicit((Object)(object)val2)) { return val2; } } Player localPlayer = Player.localPlayer; if (!Object.op_Implicit((Object)(object)localPlayer)) { return null; } return ((Component)localPlayer).GetComponent() ?? ((Component)localPlayer).GetComponentInChildren(); } private static Character FindLocalCharacter() { Character localCharacter = Character.localCharacter; if (Object.op_Implicit((Object)(object)localCharacter)) { return localCharacter; } try { if (Character.AllCharacters != null) { foreach (Character allCharacter in Character.AllCharacters) { if (Object.op_Implicit((Object)(object)allCharacter) && (SelfPatchHelpers.IsLocal(allCharacter) || IsLocalOwnedView(allCharacter.refs?.view))) { Character.localCharacter = allCharacter; return allCharacter; } } } } catch { } Character[] array; try { array = Object.FindObjectsByType((FindObjectsSortMode)0); } catch { return null; } Character[] array2 = array; foreach (Character val in array2) { if (Object.op_Implicit((Object)(object)val) && (SelfPatchHelpers.IsLocal(val) || IsLocalOwnedView(val.refs?.view))) { Character.localCharacter = val; return val; } } return null; } private static bool IsLocalIdentityView(PhotonView view) { if (!Object.op_Implicit((Object)(object)view)) { return false; } PhotonView localIdentityView = GetLocalIdentityView(); if (Object.op_Implicit((Object)(object)localIdentityView) && view.ViewID == localIdentityView.ViewID) { return true; } if (SelfPatchHelpers.IsLocal(((Component)view).GetComponent())) { return true; } Player component = ((Component)view).GetComponent(); if (Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)Player.localPlayer)) { return component == Player.localPlayer; } return false; } private static bool IsLocalOwnedView(PhotonView view) { if (!Object.op_Implicit((Object)(object)view)) { return false; } int localActorNumber = GetLocalActorNumber(); if (localActorNumber <= 0) { return false; } try { if (view.IsMine) { return true; } if (view.OwnerActorNr == localActorNumber || view.ControllerActorNr == localActorNumber) { return true; } Player owner = view.Owner; if (owner != null && owner.ActorNumber == localActorNumber) { goto IL_0067; } Player controller = view.Controller; if (controller != null && controller.ActorNumber == localActorNumber) { goto IL_0067; } goto end_IL_0017; IL_0067: return true; end_IL_0017:; } catch { } if (!ViewIdBelongsToLocalActor(view.ViewID)) { return ViewIdBelongsToLocalActor(view.InstantiationId); } return true; } private static bool MatchesViewId(PhotonView view, int targetViewId) { if (Object.op_Implicit((Object)(object)view)) { if (view.ViewID != targetViewId) { return view.InstantiationId == targetViewId; } return true; } return false; } private static bool ViewIdBelongsToLocalActor(int viewId) { if (viewId <= 0) { return false; } int localActorNumber = GetLocalActorNumber(); if (localActorNumber <= 0) { return false; } int num; try { num = Mathf.Max(1, PhotonNetwork.MAX_VIEW_IDS); } catch { num = 1000; } return viewId / num == localActorNumber; } private static int GetLocalActorNumber() { try { Player localPlayer = PhotonNetwork.LocalPlayer; return (localPlayer != null) ? localPlayer.ActorNumber : 0; } catch { return 0; } } private static bool IsRemoteSender(int senderActor) { if (senderActor <= 0) { return false; } int localActorNumber = GetLocalActorNumber(); if (localActorNumber != 0) { return senderActor != localActorNumber; } return true; } private static Player GetSender(int senderActor) { if (senderActor <= 0 || PhotonNetwork.CurrentRoom == null) { return null; } try { return PhotonNetwork.CurrentRoom.GetPlayer(senderActor, false); } catch { return null; } } private static bool TryGetEventTarget(object customData, out int target) { target = 0; if (customData == null) { return false; } Hashtable val = (Hashtable)((customData is Hashtable) ? customData : null); if (val != null) { if (!TryGetInt((IDictionary)val, 0, out target)) { return TryGetInt((IDictionary)val, 1, out target); } return true; } if (customData is IDictionary data) { if (!TryGetInt(data, 0, out target)) { return TryGetInt(data, 1, out target); } return true; } return TryConvertToInt(customData, out target); } private static bool TryGetInt(IDictionary data, byte key, out int result) { result = 0; if (data == null) { return false; } object key2 = key; object obj = (data.Contains(key2) ? data[key2] : null); if (obj == null) { object key3 = (int)key; obj = (data.Contains(key3) ? data[key3] : null); } return TryConvertToInt(obj, out result); } private static bool TryConvertToInt(object raw, out int value) { value = 0; if (raw == null) { return false; } try { value = Convert.ToInt32(raw); return true; } catch { return false; } } private static void ScheduleLocalRoomResync(string reason) { if (Object.op_Implicit((Object)(object)Plugin.Instance) && PhotonNetwork.InRoom && _resyncRoutine == null) { _resyncRoutine = ((MonoBehaviour)Plugin.Instance).StartCoroutine(LocalRoomResyncRoutine(reason)); } } [IteratorStateMachine(typeof(d__27))] private static IEnumerator LocalRoomResyncRoutine(string reason) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__27(0) { reason = reason }; } private static void ScheduleDelayedLocalRoomValidation(string reason) { if (Object.op_Implicit((Object)(object)Plugin.Instance) && PhotonNetwork.InRoom && _validationRoutine == null) { _validationRoutine = ((MonoBehaviour)Plugin.Instance).StartCoroutine(DelayedLocalRoomValidationRoutine(reason)); } } [IteratorStateMachine(typeof(d__29))] private static IEnumerator DelayedLocalRoomValidationRoutine(string reason) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__29(0) { reason = reason }; } private static void ReassertLocalRoomState() { if (!PhotonNetwork.InRoom) { return; } RepairLocalOwnership(GetLocalIdentityView()); try { GameActions.SyncLocalInventory(); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Anti Modder Protection] Local inventory re-sync failed: " + ex.Message)); } } try { Player localPlayer = PhotonNetwork.LocalPlayer; Hashtable val = ((localPlayer != null) ? localPlayer.CustomProperties : null); if (val != null && ((Dictionary)(object)val).Count > 0) { localPlayer.SetCustomProperties(CopyHashtable(localPlayer.CustomProperties), (Hashtable)null, (WebFlags)null); } } catch (Exception ex2) { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogWarning((object)("[Anti Modder Protection] Local actor property re-sync failed: " + ex2.Message)); } } try { PhotonNetwork.SendAllOutgoingCommands(); } catch (Exception ex3) { ManualLogSource log3 = Plugin.Log; if (log3 != null) { log3.LogWarning((object)("[Anti Modder Protection] Photon command flush failed: " + ex3.Message)); } } } private static void ValidateLocalRoomStateAfterDestroy(string reason) { if (!PhotonNetwork.InRoom) { return; } int localActorNumber = GetLocalActorNumber(); bool flag = CurrentRoomHasPlayer(localActorNumber); Player player; bool flag2 = TryGetPlayerHandlerLocal(localActorNumber, out player); Character val = FindLocalCharacter(); PhotonView localIdentityView = GetLocalIdentityView(); bool flag3 = IsPhotonViewRegistered(localIdentityView); string text = "roomActor=" + flag + ", playerHandler=" + flag2 + ", handlerPlayer=" + (Object.op_Implicit((Object)(object)player) ? "valid" : "missing") + ", character=" + (Object.op_Implicit((Object)(object)val) ? "valid" : "missing") + ", view=" + (Object.op_Implicit((Object)(object)localIdentityView) ? localIdentityView.ViewID.ToString(CultureInfo.InvariantCulture) : "missing") + ", viewRegistered=" + flag3; if (!flag || !flag2 || !Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)localIdentityView) || !flag3) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Anti Modder Protection] 1s local player validation after " + reason + ": " + text)); } } else { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogInfo((object)("[Anti Modder Protection] 1s local player validation after " + reason + ": " + text)); } } if (flag) { ReassertLocalRoomState(); } } private static bool CurrentRoomHasPlayer(int actorNumber) { if (actorNumber <= 0 || PhotonNetwork.CurrentRoom == null) { return false; } try { return PhotonNetwork.CurrentRoom.GetPlayer(actorNumber, false) != null; } catch { return false; } } private static bool TryGetPlayerHandlerLocal(int actorNumber, out Player player) { player = null; if (actorNumber <= 0) { return false; } try { return PlayerHandler.TryGetPlayer(actorNumber, ref player); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Anti Modder Protection] PlayerHandler validation failed: " + ex.Message)); } return false; } } private static bool IsPhotonViewRegistered(PhotonView view) { if (!Object.op_Implicit((Object)(object)view) || view.ViewID == 0) { return false; } try { return (Object)(object)PhotonView.Find(view.ViewID) == (Object)(object)view; } catch { return false; } } private static void RepairLocalOwnership(PhotonView view) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)view) || PhotonNetwork.LocalPlayer == null || IsLocalOwnedView(view)) { return; } try { view.OwnershipTransfer = (OwnershipOption)2; view.TransferOwnership(PhotonNetwork.LocalPlayer); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Anti Modder Protection] Local ownership repair failed: " + ex.Message)); } } } private static Hashtable CopyHashtable(Hashtable source) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) Hashtable val = new Hashtable(); if (source == null) { return val; } DictionaryEntryEnumerator enumerator = source.GetEnumerator(); try { while (((DictionaryEntryEnumerator)(ref enumerator)).MoveNext()) { DictionaryEntry current = ((DictionaryEntryEnumerator)(ref enumerator)).Current; val[current.Key] = current.Value; } return val; } finally { ((IDisposable)(DictionaryEntryEnumerator)(ref enumerator)).Dispose(); } } private static string FormatSender(Player sender, int senderActor) { if (sender != null) { return (string.IsNullOrWhiteSpace(sender.NickName) ? "player" : sender.NickName) + " #" + sender.ActorNumber.ToString(CultureInfo.InvariantCulture); } return "actor #" + senderActor.ToString(CultureInfo.InvariantCulture); } } [HarmonyPatch(typeof(CharacterAfflictions), "SyncStatusesRPC")] internal static class AntiModderSyncStatusesPatch { private static bool Prefix(CharacterAfflictions __instance) { if (!SelfRuntimeSettings.NoAfflictions) { return true; } return !SelfPatchHelpers.IsLocalComponent((Component)(object)__instance); } } public class AutoMaster : Feature { public AutoMaster() { base.Name = "Auto Master"; base.Description = "Continuously asks Photon to make you master client."; } protected override void OnEnable() { OnTick(); } protected override void OnDisable() { } public override void OnTick() { if (PhotonNetwork.InRoom && PhotonNetwork.LocalPlayer != null && !PhotonNetwork.LocalPlayer.IsMasterClient) { PhotonNetwork.SetMasterClient(PhotonNetwork.LocalPlayer); } } } public class ChickenFeature : Feature { [CompilerGenerated] private sealed class d__8 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public int viewId; public bool chicken; private float 5__2; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__8(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; 5__2 = Time.time + 5f; break; case 1: <>1__state = -1; break; } if (Time.time < 5__2) { Character val = FindCharacterByViewId(viewId); if (Object.op_Implicit((Object)(object)val)) { ApplyChickenState(val, chicken); return false; } <>2__current = null; <>1__state = 1; return true; } Plugin.Log.LogWarning((object)$"[ChickenFeature] Could not find character with ViewID {viewId}."); 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 const byte ChickenStateEventCode = 174; public ChickenFeature() { base.Name = "Chicken"; base.Description = "Toggle between human and chicken appearance. Synced to other players in the session."; } protected override void OnEnable() { PhotonNetwork.AddCallbackTarget((object)this); BecomeChickenNetworked(); } protected override void OnDisable() { BecomeHumanNetworked(); PhotonNetwork.RemoveCallbackTarget((object)this); } private static void BecomeChickenNetworked() { SetChickenStateNetworked(chicken: true); } private static void BecomeHumanNetworked() { SetChickenStateNetworked(chicken: false); } private static void SetChickenStateNetworked(bool chicken) { //IL_0082: 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) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Expected O, but got Unknown //IL_009f: Unknown result type (might be due to invalid IL or missing references) Character localCharacter = Character.localCharacter; if (!Object.op_Implicit((Object)(object)localCharacter)) { Plugin.Log.LogWarning((object)"[ChickenFeature] No local character found."); return; } PhotonView photonView = ((MonoBehaviourPun)localCharacter).photonView; if (!Object.op_Implicit((Object)(object)photonView)) { Plugin.Log.LogWarning((object)"[ChickenFeature] Local character has no PhotonView. Applying locally only."); ApplyChickenState(localCharacter, chicken); return; } int viewID = photonView.ViewID; ApplyChickenState(localCharacter, chicken); if (!PhotonNetwork.InRoom) { Plugin.Log.LogInfo((object)"[ChickenFeature] Not in a Photon room. Applied locally only."); return; } object[] array = new object[2] { viewID, chicken }; RaiseEventOptions val = new RaiseEventOptions { Receivers = (ReceiverGroup)0, CachingOption = (EventCaching)0 }; PhotonNetwork.RaiseEvent((byte)174, (object)array, val, SendOptions.SendReliable); Plugin.Log.LogInfo((object)$"[ChickenFeature] Sent chicken state {chicken} for ViewID {viewID}."); } public void OnEvent(EventData photonEvent) { if (photonEvent.Code != 174 || !(photonEvent.CustomData is object[] array) || array.Length < 2) { return; } object obj = array[0]; if (!(obj is int)) { return; } int viewId = (int)obj; obj = array[1]; if (!(obj is bool)) { return; } bool chicken = (bool)obj; Character val = FindCharacterByViewId(viewId); if (Object.op_Implicit((Object)(object)val)) { ApplyChickenState(val, chicken); return; } Plugin instance = Plugin.Instance; if (instance != null) { ((MonoBehaviour)instance).StartCoroutine(ApplyChickenStateWhenCharacterExists(viewId, chicken)); } } [IteratorStateMachine(typeof(d__8))] private static IEnumerator ApplyChickenStateWhenCharacterExists(int viewId, bool chicken) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__8(0) { viewId = viewId, chicken = chicken }; } private static Character FindCharacterByViewId(int viewId) { if (Character.AllCharacters == null) { return null; } foreach (Character allCharacter in Character.AllCharacters) { if (Object.op_Implicit((Object)(object)allCharacter)) { PhotonView photonView = ((MonoBehaviourPun)allCharacter).photonView; if (Object.op_Implicit((Object)(object)photonView) && photonView.ViewID == viewId) { return allCharacter; } } } return null; } private static void ApplyChickenState(Character character, bool chicken) { if (!Object.op_Implicit((Object)(object)character)) { return; } try { CharacterCustomization val = character.refs?.customization; if (!Object.op_Implicit((Object)(object)val)) { Plugin.Log.LogWarning((object)"[ChickenFeature] Character customization ref missing."); } else if (chicken) { ApplyChicken(character, val); } else { ApplyHuman(character, val); } } catch (Exception arg) { Plugin.Log.LogWarning((object)$"[ChickenFeature] Failed to apply chicken state: {arg}"); } } private static void ApplyChicken(Character character, CharacterCustomization customization) { if (!Object.op_Implicit((Object)(object)customization.chickenParticle) || !customization.chickenParticle.isPlaying) { customization.BecomeChicken(); Plugin.Log.LogInfo((object)("[ChickenFeature] Applied chicken to " + ((Object)character).name + ".")); } } private static void ApplyHuman(Character character, CharacterCustomization customization) { if (Object.op_Implicit((Object)(object)customization.chickenParticle)) { customization.chickenParticle.Stop(true, (ParticleSystemStopBehavior)0); } if (TryCallNoArg(customization, "BecomeHuman") || TryCallNoArg(customization, "BecomeNormal") || TryCallNoArg(customization, "ResetCustomization") || TryCallNoArg(customization, "RefreshCustomization") || TryCallNoArg(customization, "ApplyCustomization") || TryCallNoArg(customization, "UpdateCustomization")) { Plugin.Log.LogInfo((object)("[ChickenFeature] Restored human customization for " + ((Object)character).name + ".")); } else { Plugin.Log.LogWarning((object)"[ChickenFeature] No known human restore method found on CharacterCustomization. Chicken particle was stopped, but you may need to inspect CharacterCustomization for the exact reset method."); } } private static bool TryCallNoArg(object target, string methodName) { if (target == null) { return false; } MethodInfo method = target.GetType().GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null); if (method == null) { return false; } method.Invoke(target, null); return true; } } public class CosmeticSpam : Feature { private float _nextRandomizeTime; private const float RandomizeInterval = 0.25f; public CosmeticSpam() { base.Name = "Cosmetic Spam"; base.Description = "Randomizes local character cosmetics on an interval."; } protected override void OnEnable() { Randomize(); } protected override void OnDisable() { } public override void OnTick() { if (!(Time.time < _nextRandomizeTime)) { _nextRandomizeTime = Time.time + 0.25f; Randomize(); } } private static void Randomize() { Character localCharacter = Character.localCharacter; if (Object.op_Implicit((Object)(object)localCharacter)) { CharacterCustomization val = localCharacter.refs?.customization; if (Object.op_Implicit((Object)(object)val)) { val.RandomizeCosmetics(); } } } } public class DeaggroBees : Feature { public DeaggroBees() { base.Name = "Deaggro Bees"; base.Description = "Disperses bee swarms currently targeting you."; } protected override void OnEnable() { OnTick(); } protected override void OnDisable() { } public override void OnTick() { Character localCharacter = Character.localCharacter; if (!Object.op_Implicit((Object)(object)localCharacter)) { return; } BeeSwarm[] array = Object.FindObjectsByType((FindObjectsSortMode)0); foreach (BeeSwarm val in array) { if (Object.op_Implicit((Object)(object)val) && val.currentAggroCharacter == localCharacter) { PhotonView val2 = ((Component)val).GetComponent() ?? ((Component)val).GetComponentInChildren(); if (Object.op_Implicit((Object)(object)val2)) { val2.RPC("DisperseRPC", (RpcTarget)0, Array.Empty()); } } } } } internal static class IncomingRpcGuard { private const byte ViewIdKey = 0; private const byte MethodNameKey = 3; private const byte ArgumentsKey = 4; private const byte ShortcutKey = 5; private const float InventoryDropRelayWindowSeconds = 5f; private const float LocalInventoryRelayWindowSeconds = 2.5f; private const float LocalRescueFallRelayWindowSeconds = 3.5f; private static readonly HashSet ProtectedRpcNames = new HashSet(StringComparer.Ordinal) { "WarpPlayerRPC", "RPCA_Fall", "RPCA_FallWithScreenShake", "RPCA_PassOut", "RPCA_UnPassOut", "RPCA_Die", "RPCA_Revive", "RPCA_ReviveAtPosition", "RPCA_SetCrouch", "JumpRpc", "MoraleBoost", "SyncStatusesRPC", "DropItemFromSlotRPC", "DestroyHeldItemRpc", "RPCRemoveItemFromSlot", "CharacterDied", "CharacterPassedOut", "RPCA_TriggerBanana", "AttachBug", "RPC_StickToCharacterRemote", "RPC_RequestStickFakeItemToPlayer", "RPCA_UnHang", "StopClimbingRpc", "StopRopeClimbingRpc", "StopVineClimbingRpc", "DisperseRPC", "SetBeesAngryRPC", "TriggerHelicopter", "Extinguish_Rpc", "RPCEndGame", "RPCEndGame_ForceWin", "RPCA_InitGhost", "RPCA_SetTarget", "RPCA_SpawnEruption", "GrowVineRPC", "StartMovingRPC", "RPCA_SyncFog", "RPC_InitFog", "BeginIslandLoadRPC", "BeginAirportLoadRPC", "ShakeBridge_Rpc", "Fall_Rpc", "Detach_Rpc", "ShakeRock_Rpc", "RPCA_StartBreaking", "RPCA_Break" }; private static readonly HashSet SuspiciousNetworkPrefabs = new HashSet(StringComparer.OrdinalIgnoreCase) { "BeeSwarm", "Tornado", "Bingbong_Blow", "Bingbong_Grab", "Bingbong_Push", "Bingbong_Suck", "Bingbong_Push_Gentle" }; private static FieldInfo _rpcShortcutsField; private static FieldInfo _skeletonCharacterField; private static FieldInfo _constructHitField; private static readonly Dictionary RecentValidInventoryDrops = new Dictionary(StringComparer.Ordinal); private static float _localInventoryRelayUntil; private static float _localRescueFallRelayUntil; public static void NoteLocalInventoryMutation(Component source) { if (!Object.op_Implicit((Object)(object)source) || IsLocalInventorySource(source)) { float num = Time.realtimeSinceStartup + 2.5f; if (num > _localInventoryRelayUntil) { _localInventoryRelayUntil = num; } } } public static void NoteLocalRescueHookUse(RescueHook hook) { if (IsLocalRescueHook(hook)) { float num = Time.realtimeSinceStartup + 3.5f; if (num > _localRescueFallRelayUntil) { _localRescueFallRelayUntil = num; } } } public static bool ShouldBlock(Hashtable rpcData, Player sender) { string rpcMethodName = GetRpcMethodName(rpcData); if (string.IsNullOrEmpty(rpcMethodName) || !ProtectedRpcNames.Contains(rpcMethodName)) { return false; } if (!IsRemoteSender(sender)) { return false; } PhotonView rpcView = GetRpcView(rpcData); if (!IsIllegalRpc(rpcMethodName, rpcData, sender, rpcView, out var eventName, out var targetView)) { return false; } return HandleDetectedProtectionEvent(eventName ?? rpcMethodName, sender, Object.op_Implicit((Object)(object)targetView) ? targetView : rpcView, rpcMethodName); } public static bool ShouldBlockNetworkInstantiate(InstantiateParameters parameters, bool instantiateEvent) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) if (!instantiateEvent) { return false; } Player creator = parameters.creator; if (!IsRemoteSender(creator)) { return false; } if (IsMasterClientSender(creator)) { return false; } string text = NormalizePrefabName(parameters.prefabName); if (string.IsNullOrEmpty(text) || !SuspiciousNetworkPrefabs.Contains(text)) { return false; } return HandleDetectedProtectionEvent("Network Instantiate " + text, creator, null, "NetworkInstantiate"); } private static bool HandleDetectedProtectionEvent(string eventName, Player sender, PhotonView targetView, string methodName) { bool flag = string.Equals(methodName, "BeginIslandLoadRPC", StringComparison.Ordinal) && HostOnlyKioskSettings.ShouldEnforceAsHost; if (!flag && IsHighConfidenceModderDetection(methodName)) { PlayerFlagDetector.MarkDetectedModder(sender); RpcEventNotifications.NotifyProtectionDetected(eventName, sender, targetView); } if (!SelfRuntimeSettings.ModderProtections && !flag) { return false; } if (flag) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Host Only Kiosk] Blocked " + eventName + " from " + FormatSender(sender) + ".")); } RpcEventNotifications.NotifyProtectionBlocked(eventName, sender); return true; } string text = (PlayerFlagDetector.IsKnownModClient(sender) ? " [known mod client]" : " [modder]"); ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogWarning((object)("[Anti Modder Protection] Blocked " + eventName + " from " + FormatSender(sender) + text)); } RpcEventNotifications.NotifyProtectionBlocked(eventName, sender); return true; } private static bool IsHighConfidenceModderDetection(string methodName) { return methodName switch { "RPCA_Fall" => false, "RPCA_FallWithScreenShake" => false, "RPCA_SetTarget" => false, "RPCA_SyncFog" => false, "BeginIslandLoadRPC" => false, _ => true, }; } private static bool IsIllegalRpc(string methodName, Hashtable rpcData, Player sender, PhotonView rpcView, out string eventName, out PhotonView targetView) { eventName = GetEventName(methodName, rpcView); targetView = rpcView; switch (methodName) { case "WarpPlayerRPC": return !IsValidWarpPlayer(rpcData, sender, rpcView); case "RPCA_ReviveAtPosition": return !IsValidReviveAtPosition(rpcData, sender, rpcView); case "GrowVineRPC": return !IsValidMagicBeanGrow(rpcData, rpcView); case "RPCA_Revive": return !IsValidRevive(rpcData, sender, rpcView); case "MoraleBoost": return !IsValidMoraleBoost(rpcData, sender, rpcView); case "DisperseRPC": return !IsValidBeeSwarmDisperse(rpcData, sender, rpcView); case "SetBeesAngryRPC": return !IsValidBeeSwarmAnger(rpcData, sender, rpcView); case "Extinguish_Rpc": return !IsValidCampfireExtinguish(rpcData, sender, rpcView); case "RPCEndGame_ForceWin": case "RPCEndGame": if (IsTrustedCharacterFlowSender(sender, rpcView)) { return HasArguments(rpcData); } return true; case "RPCA_SetTarget": return !IsValidSetTarget(rpcData, sender, rpcView); case "RPCRemoveItemFromSlot": return !IsValidRemoveItemFromSlot(rpcData, sender, rpcView); case "DropItemFromSlotRPC": return !IsValidDropItemFromSlot(rpcData, sender, rpcView); case "DestroyHeldItemRpc": return !IsValidDestroyHeldItem(rpcData, sender, rpcView); case "RPCA_TriggerBanana": targetView = GetArgumentPhotonView(rpcData, 0); if (Object.op_Implicit((Object)(object)targetView)) { return !IsViewOwner(targetView, sender); } return false; case "AttachBug": case "RPC_StickToCharacterRemote": case "RPC_RequestStickFakeItemToPlayer": eventName = "Tick Attach"; targetView = GetArgumentPhotonView(rpcData, 0); if (Object.op_Implicit((Object)(object)targetView)) { return !IsViewOwner(targetView, sender); } return false; case "TriggerHelicopter": return !IsValidFlareTrigger(rpcView); case "RPCA_Fall": case "RPCA_FallWithScreenShake": if (IsLocalCharacterView(rpcView) && !HasRecentLocalRescueFallRelay() && !IsMasterClientSender(sender)) { return !IsViewOwner(rpcView, sender); } return false; case "RPCA_SyncFog": return !IsMasterClientSender(sender); case "BeginIslandLoadRPC": return IsBlockedByHostOnlyKiosk(sender, rpcView); case "RPCA_UnHang": targetView = GetFirstArgumentPhotonView(rpcData); if (Object.op_Implicit((Object)(object)targetView)) { return !IsViewOwner(targetView, sender); } return false; default: if (RequiresMaster(methodName)) { return !IsMasterClientSender(sender); } if (RequiresViewOwner(methodName)) { if (Object.op_Implicit((Object)(object)rpcView)) { return !IsViewOwner(rpcView, sender); } return false; } if (RequiresMasterOrViewOwner(methodName)) { if (Object.op_Implicit((Object)(object)rpcView) && !IsMasterClientSender(sender)) { return !IsViewOwner(rpcView, sender); } return false; } return false; } } private static bool RequiresMaster(string methodName) { return methodName switch { "RPCA_SpawnEruption" => true, "StartMovingRPC" => true, "RPC_InitFog" => true, "BeginAirportLoadRPC" => true, _ => false, }; } private static bool RequiresViewOwner(string methodName) { return methodName switch { "RPCA_SetCrouch" => true, "JumpRpc" => true, "CharacterDied" => true, "CharacterPassedOut" => true, "RPCA_InitGhost" => true, "StopClimbingRpc" => true, "StopRopeClimbingRpc" => true, "StopVineClimbingRpc" => true, _ => false, }; } private static bool RequiresMasterOrViewOwner(string methodName) { return methodName switch { "RPCA_Fall" => true, "RPCA_FallWithScreenShake" => true, "RPCA_PassOut" => true, "RPCA_UnPassOut" => true, "RPCA_Die" => true, "SyncStatusesRPC" => true, "RPCA_SyncFog" => true, "ShakeBridge_Rpc" => true, "Fall_Rpc" => true, "Detach_Rpc" => true, "ShakeRock_Rpc" => true, "RPCA_StartBreaking" => true, "RPCA_Break" => true, _ => false, }; } private static string GetEventName(string methodName, PhotonView view) { return methodName switch { "RPCA_TriggerBanana" => "Banana Slip", "DisperseRPC" => "Bee Swarm Disperse", "SetBeesAngryRPC" => "Bee Swarm Anger", "TriggerHelicopter" => "Flare End Trigger", "Extinguish_Rpc" => "Campfire Extinguish", "RPCEndGame" => "Force End Game", "RPCEndGame_ForceWin" => "Force End Game", "RPCA_Die" => "Kill Scout", "RPCA_Revive" => "Revive Scout", "RPCA_ReviveAtPosition" => "Revive Scout", "WarpPlayerRPC" => "Teleport Scout", "RPCA_InitGhost" => "Ghost Initialize", "RPCA_SetTarget" => "Ghost Retarget", "RPCA_SpawnEruption" => "Spawn Eruption", "GrowVineRPC" => "Magic Bean Grow", "StartMovingRPC" => "Fog Start", "RPCA_SyncFog" => "Fog Sync", "RPC_InitFog" => "Fog Init", "BeginIslandLoadRPC" => "Start Expedition", "BeginAirportLoadRPC" => "Return To Airport", "ShakeBridge_Rpc" => "Bridge Shake", "Fall_Rpc" => ViewHasComponent(view) ? "Bridge Fall" : "Icicle Fall", "Detach_Rpc" => "Rope Detach", "ShakeRock_Rpc" => "Icicle Shake", "RPCA_StartBreaking" => "Piton Start Break", "RPCA_Break" => "Piton Break", _ => methodName, }; } private static bool IsRemoteSender(Player sender) { if (sender == null) { return false; } if (sender.IsLocal) { return false; } Player localPlayer = PhotonNetwork.LocalPlayer; if (localPlayer != null) { return sender.ActorNumber != localPlayer.ActorNumber; } return true; } private static bool IsMasterClientSender(Player sender) { Player masterClient = PhotonNetwork.MasterClient; if (sender != null && masterClient != null) { return sender.ActorNumber == masterClient.ActorNumber; } return false; } private static bool IsTrustedMasterClientSender(Player sender) { if (!IsMasterClientSender(sender)) { return false; } if (SelfRuntimeSettings.ModderProtections) { return !PlayerFlagDetector.IsKnownOrDetectedModClient(sender); } return true; } private static bool IsViewOwner(PhotonView view, Player sender) { if (!Object.op_Implicit((Object)(object)view) || sender == null) { return false; } int actorNumber = sender.ActorNumber; if (actorNumber <= 0) { return false; } if (view.OwnerActorNr == actorNumber || view.ControllerActorNr == actorNumber || view.CreatorActorNr == actorNumber) { return true; } if (view.Owner != null && view.Owner.ActorNumber == actorNumber) { return true; } if (view.Controller != null && view.Controller.ActorNumber == actorNumber) { return true; } Character val = ((Component)view).GetComponent() ?? ((Component)view).GetComponentInParent() ?? ((Component)view).GetComponentInChildren(); if (Object.op_Implicit((Object)(object)val)) { PhotonView val2 = val.refs?.view ?? ((Component)val).GetComponent() ?? ((Component)val).GetComponentInParent() ?? ((Component)val).GetComponentInChildren(); if (Object.op_Implicit((Object)(object)val2) && val2 != view && IsViewOwner(val2, sender)) { return true; } Player val3 = null; try { val3 = val.player; } catch { } PhotonView val4 = (Object.op_Implicit((Object)(object)val3) ? (((MonoBehaviourPun)val3).photonView ?? ((Component)val3).GetComponent() ?? ((Component)val3).GetComponentInParent() ?? ((Component)val3).GetComponentInChildren()) : null); if (Object.op_Implicit((Object)(object)val4) && IsViewOwner(val4, sender)) { return true; } } Player val5 = ((Component)view).GetComponent() ?? ((Component)view).GetComponentInParent() ?? ((Component)view).GetComponentInChildren(); if (Object.op_Implicit((Object)(object)val5)) { PhotonView val6 = ((MonoBehaviourPun)val5).photonView ?? ((Component)val5).GetComponent() ?? ((Component)val5).GetComponentInParent() ?? ((Component)val5).GetComponentInChildren(); if (Object.op_Implicit((Object)(object)val6) && val6 != view) { return IsViewOwner(val6, sender); } return false; } return false; } private static bool IsLocalCharacterView(PhotonView view) { if (!Object.op_Implicit((Object)(object)view)) { return false; } Character localCharacter = Character.localCharacter; if (!Object.op_Implicit((Object)(object)localCharacter)) { return false; } Character val = ((Component)view).GetComponent() ?? ((Component)view).GetComponentInParent() ?? ((Component)view).GetComponentInChildren(); if (Object.op_Implicit((Object)(object)val) && val == localCharacter) { return true; } PhotonView val2 = localCharacter.refs?.view ?? ((Component)localCharacter).GetComponent() ?? ((Component)localCharacter).GetComponentInParent() ?? ((Component)localCharacter).GetComponentInChildren(); if (Object.op_Implicit((Object)(object)val2) && val2.ViewID == view.ViewID) { return true; } Player val3 = null; try { val3 = localCharacter.player; } catch { } PhotonView val4 = (Object.op_Implicit((Object)(object)val3) ? (((MonoBehaviourPun)val3).photonView ?? ((Component)val3).GetComponent() ?? ((Component)val3).GetComponentInParent() ?? ((Component)val3).GetComponentInChildren()) : null); if (Object.op_Implicit((Object)(object)val4)) { return val4.ViewID == view.ViewID; } return false; } private static bool IsValidRevive(Hashtable rpcData, Player sender, PhotonView rpcView) { if (!ViewHasComponent(rpcView)) { return false; } object[] arguments = GetArguments(rpcData); if (arguments == null || arguments.Length < 1 || !(arguments[0] is bool)) { return false; } return IsTrustedCharacterFlowSender(sender, rpcView); } private static bool IsValidReviveAtPosition(Hashtable rpcData, Player sender, PhotonView rpcView) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0053: 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) if (!TryGetReviveAtPositionArgs(rpcData, out var revivePosition, out var _, out var segment)) { return false; } if (!IsFinite(revivePosition) || !ViewHasComponent(rpcView)) { return false; } if (segment >= 0) { return IsValidStatueRevive(sender, rpcView, revivePosition, segment); } Character viewCharacter = GetViewCharacter(rpcView); if (!IsDeadOrDown(viewCharacter)) { return false; } if (!IsMasterClientSender(sender) && !IsViewOwner(rpcView, sender) && !IsValidSkeletonRevive(viewCharacter, revivePosition)) { return IsValidScoutEffigyRevive(revivePosition); } return true; } private static bool IsValidStatueRevive(Player sender, PhotonView rpcView, Vector3 revivePosition, int statueSegment) { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: 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_006c: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Invalid comparison between Unknown and I4 if (!IsMasterClientSender(sender) || !Object.op_Implicit((Object)(object)rpcView)) { return false; } if (!IsDeadOrDown(GetViewCharacter(rpcView))) { return false; } RespawnChest[] array = Object.FindObjectsByType((FindObjectsSortMode)0); foreach (RespawnChest val in array) { if (Object.op_Implicit((Object)(object)val) && (statueSegment < 0 || (int)val.SegmentNumber == statueSegment)) { Vector3 val2 = ((Component)val).transform.position + ((Component)val).transform.up * 6f; if (Vector3.Distance(revivePosition, val2) <= 8f) { return true; } } } return false; } private static bool IsValidWarpPlayer(Hashtable rpcData, Player sender, PhotonView rpcView) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) object[] arguments = GetArguments(rpcData); if (arguments == null || arguments.Length < 2 || !(arguments[0] is Vector3 value) || !(arguments[1] is bool)) { return false; } if (!ViewHasComponent(rpcView) || !IsFinite(value) || ((Vector3)(ref value)).sqrMagnitude > 400000000f) { return false; } if (!IsMasterClientSender(sender)) { return IsViewOwner(rpcView, sender); } return true; } private static bool IsValidMoraleBoost(Hashtable rpcData, Player sender, PhotonView rpcView) { object[] arguments = GetArguments(rpcData); if (arguments == null || arguments.Length < 2 || !TryGetFloat(arguments[0], out var result) || !TryGetInt(arguments[1], out var result2)) { return false; } if (!ViewHasComponent(rpcView)) { return false; } if (result >= 0f && result <= 5f && result2 >= 0 && result2 <= 64 && sender != null) { return sender.ActorNumber > 0; } return false; } private static bool TryGetReviveAtPositionArgs(Hashtable rpcData, out Vector3 revivePosition, out bool applyStatus, out int segment) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: 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) //IL_004d: Unknown result type (might be due to invalid IL or missing references) revivePosition = Vector3.zero; applyStatus = false; segment = -1; object[] arguments = GetArguments(rpcData); if (arguments == null || arguments.Length < 3 || !(arguments[0] is Vector3 val) || !(arguments[1] is bool flag)) { return false; } revivePosition = val; applyStatus = flag; segment = ToInt(arguments[2]); return true; } private static bool IsValidSkeletonRevive(Character target, Vector3 revivePosition) { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0048: 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_006f: 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_0071: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)target)) { return false; } Skelleton[] array = Object.FindObjectsByType((FindObjectsSortMode)0); foreach (Skelleton val in array) { if (Object.op_Implicit((Object)(object)val) && GetSkeletonCharacter(val) == target) { Vector3 val2 = (Object.op_Implicit((Object)(object)val.hip) ? (val.hip.position + ((Component)val).transform.up) : (((Component)val).transform.position + ((Component)val).transform.up)); if (Vector3.Distance(revivePosition, val2) <= 6f) { return true; } } } return false; } private static Character GetSkeletonCharacter(Skelleton skeleton) { if (!Object.op_Implicit((Object)(object)skeleton)) { return null; } try { if ((object)_skeletonCharacterField == null) { _skeletonCharacterField = typeof(Skelleton).GetField("spawnedFromCharacter", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } object? obj = _skeletonCharacterField?.GetValue(skeleton); return (Character)((obj is Character) ? obj : null); } catch { return null; } } private static bool IsValidScoutEffigyRevive(Vector3 revivePosition) { //IL_004e: 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_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) ScoutEffigy[] array = Object.FindObjectsByType((FindObjectsSortMode)0); foreach (ScoutEffigy val in array) { if (!Object.op_Implicit((Object)(object)val)) { continue; } if (TryGetConstructHit(val, out var hit)) { Vector3 val2 = ((RaycastHit)(ref hit)).point + Vector3.up; if (IsFinite(val2) && Vector3.Distance(revivePosition, val2) <= 6f) { return true; } } if (Vector3.Distance(revivePosition, ((Component)val).transform.position) <= 10f) { return true; } } return false; } private static bool TryGetConstructHit(ScoutEffigy effigy, out RaycastHit hit) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0050: 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_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) hit = default(RaycastHit); if (!Object.op_Implicit((Object)(object)effigy)) { return false; } try { if ((object)_constructHitField == null) { _constructHitField = typeof(Constructable).GetField("currentConstructHit", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } object obj = _constructHitField?.GetValue(effigy); if (obj is RaycastHit) { RaycastHit val = (RaycastHit)obj; hit = val; return true; } } catch { } return false; } private static bool IsValidMagicBeanGrow(Hashtable rpcData, PhotonView rpcView) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: 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_0047: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) if (!ViewHasComponent(rpcView)) { return false; } object[] arguments = GetArguments(rpcData); if (arguments == null || arguments.Length < 3) { return false; } if (!(arguments[0] is Vector3 value) || !(arguments[1] is Vector3 value2)) { return false; } if (!TryGetFloat(arguments[2], out var result)) { return false; } if (IsFinite(value) && IsFinite(value2) && ((Vector3)(ref value2)).sqrMagnitude > 0.0001f && result > 0f) { return result <= 250f; } return false; } private static bool IsValidBeeSwarmDisperse(Hashtable rpcData, Player sender, PhotonView rpcView) { if (ViewHasComponent(rpcView) && (IsMasterClientSender(sender) || IsViewOwner(rpcView, sender))) { return !HasArguments(rpcData); } return false; } private static bool IsValidBeeSwarmAnger(Hashtable rpcData, Player sender, PhotonView rpcView) { object[] arguments = GetArguments(rpcData); if (ViewHasComponent(rpcView) && (IsMasterClientSender(sender) || IsViewOwner(rpcView, sender)) && arguments != null && arguments.Length >= 1) { return arguments[0] is bool; } return false; } private static bool IsValidCampfireExtinguish(Hashtable rpcData, Player sender, PhotonView rpcView) { if (ViewHasComponent(rpcView) && (IsMasterClientSender(sender) || IsViewOwner(rpcView, sender))) { return !HasArguments(rpcData); } return false; } private static bool IsValidSetTarget(Hashtable rpcData, Player sender, PhotonView rpcView) { object[] arguments = GetArguments(rpcData); if (arguments == null || arguments.Length < 1 || !Object.op_Implicit((Object)(object)rpcView)) { return false; } if (ViewHasComponent(rpcView)) { PhotonView argumentPhotonView = GetArgumentPhotonView(rpcData, 0); if (IsViewOwner(rpcView, sender)) { return ViewHasComponent(argumentPhotonView); } return false; } if (ViewHasComponent(rpcView)) { if (!IsMasterClientSender(sender) && !IsViewOwner(rpcView, sender)) { return false; } int num = ToInt(arguments[0]); if (num != -1) { return ViewHasComponent(PhotonView.Find(num)); } return true; } return false; } private static bool IsValidRemoveItemFromSlot(Hashtable rpcData, Player sender, PhotonView rpcView) { object[] arguments = GetArguments(rpcData); if (arguments == null || arguments.Length < 1 || !TryGetByte(arguments[0], out var result)) { return false; } Player viewPlayer = GetViewPlayer(rpcView); if (!Object.op_Implicit((Object)(object)viewPlayer) || !SlotExists(viewPlayer, result)) { return false; } if (IsRecentLocalInventoryRelay(viewPlayer, null, result)) { return true; } if (!IsMasterClientSender(sender) && !SenderMatchesPlayer(sender, viewPlayer)) { return IsRedundantRecentInventoryDropRelay(viewPlayer, result); } return true; } private static bool IsValidDropItemFromSlot(Hashtable rpcData, Player sender, PhotonView rpcView) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: 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) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) object[] arguments = GetArguments(rpcData); if (arguments == null || arguments.Length < 2 || !TryGetByte(arguments[0], out var result) || !(arguments[1] is Vector3 val)) { return false; } if (!IsFinite(val) || !ViewHasComponent(rpcView)) { return false; } Character viewCharacter = GetViewCharacter(rpcView); Player val2 = (Object.op_Implicit((Object)(object)viewCharacter) ? SafeGetPlayer(viewCharacter) : GetViewPlayer(rpcView)); if (Object.op_Implicit((Object)(object)val2) && !SlotExists(val2, result)) { return false; } if (IsRecentLocalInventoryRelay(val2, viewCharacter, result) && IsDropPositionNearLocal(val)) { NoteValidInventoryDrop(val2, result); return true; } if (!IsMasterClientSender(sender) && !IsViewOwner(rpcView, sender) && ((Object)(object)val2 == (Object)null || !SenderMatchesPlayer(sender, val2))) { return false; } if (Object.op_Implicit((Object)(object)viewCharacter)) { Vector3 center = viewCharacter.Center; if (Vector3.Distance(val, center) > 25f) { return false; } } NoteValidInventoryDrop(val2, result); return true; } private static bool IsValidDestroyHeldItem(Hashtable rpcData, Player sender, PhotonView rpcView) { if (HasArguments(rpcData) || !ViewHasComponent(rpcView)) { return false; } Character viewCharacter = GetViewCharacter(rpcView); Player val = (Object.op_Implicit((Object)(object)viewCharacter) ? SafeGetPlayer(viewCharacter) : GetViewPlayer(rpcView)); if (HasRecentLocalInventoryRelay() && IsLocalCharacterOrPlayer(viewCharacter, val)) { return true; } if (!IsMasterClientSender(sender) && !IsViewOwner(rpcView, sender)) { if ((Object)(object)val != (Object)null) { return SenderMatchesPlayer(sender, val); } return false; } return true; } private static bool IsRecentLocalInventoryRelay(Player targetPlayer, Character targetCharacter, byte slot) { if (!HasRecentLocalInventoryRelay()) { return false; } if (!IsLocalCharacterOrPlayer(targetCharacter, targetPlayer)) { return false; } if (!((Object)(object)targetPlayer == (Object)null)) { return SlotExists(targetPlayer, slot); } return true; } private static bool HasRecentLocalInventoryRelay() { return _localInventoryRelayUntil >= Time.realtimeSinceStartup; } private static bool HasRecentLocalRescueFallRelay() { return _localRescueFallRelayUntil >= Time.realtimeSinceStartup; } private static bool IsDropPositionNearLocal(Vector3 dropPosition) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) Character localCharacter = Character.localCharacter; if (!Object.op_Implicit((Object)(object)localCharacter)) { return false; } try { return Vector3.Distance(dropPosition, localCharacter.Center) <= 35f; } catch { return Vector3.Distance(dropPosition, ((Component)localCharacter).transform.position) <= 35f; } } private static bool IsLocalCharacterOrPlayer(Character character, Player player) { Character localCharacter = Character.localCharacter; if (Object.op_Implicit((Object)(object)character) && Object.op_Implicit((Object)(object)localCharacter) && character == localCharacter) { return true; } Player localPlayer = Player.localPlayer; if (Object.op_Implicit((Object)(object)player) && Object.op_Implicit((Object)(object)localPlayer) && player == localPlayer) { return true; } if (Object.op_Implicit((Object)(object)player) && Object.op_Implicit((Object)(object)localCharacter)) { try { return Object.op_Implicit((Object)(object)player.character) && player.character == localCharacter; } catch { return false; } } return false; } private static bool IsLocalInventorySource(Component source) { if (!Object.op_Implicit((Object)(object)source)) { return true; } Character val = source.GetComponent() ?? source.GetComponentInParent() ?? source.GetComponentInChildren(); if (Object.op_Implicit((Object)(object)val) && IsLocalCharacterOrPlayer(val, null)) { return true; } Player player = source.GetComponent() ?? source.GetComponentInParent() ?? source.GetComponentInChildren(); return IsLocalCharacterOrPlayer(null, player); } private static bool IsLocalRescueHook(RescueHook hook) { if (!Object.op_Implicit((Object)(object)hook)) { return false; } try { if (Object.op_Implicit((Object)(object)((ItemComponent)hook).item) && LocalItemScope.IsLocalHeldOrSlotted(((ItemComponent)hook).item)) { return true; } } catch { } try { Character playerHoldingItem = hook.playerHoldingItem; return Object.op_Implicit((Object)(object)playerHoldingItem) && IsLocalCharacterOrPlayer(playerHoldingItem, null); } catch { return false; } } private static bool SlotExists(Player player, byte slot) { if (!Object.op_Implicit((Object)(object)player)) { return false; } try { return player.GetItemSlot(slot) != null; } catch { return false; } } private static void NoteValidInventoryDrop(Player player, byte slot) { string inventorySlotKey = GetInventorySlotKey(player, slot); if (inventorySlotKey.Length != 0) { PruneRecentValidInventoryDrops(); RecentValidInventoryDrops[inventorySlotKey] = Time.realtimeSinceStartup + 5f; } } private static bool HasRecentValidInventoryDrop(Player player, byte slot) { string inventorySlotKey = GetInventorySlotKey(player, slot); if (inventorySlotKey.Length == 0) { return false; } if (!RecentValidInventoryDrops.TryGetValue(inventorySlotKey, out var value)) { return false; } if (value >= Time.realtimeSinceStartup) { return true; } RecentValidInventoryDrops.Remove(inventorySlotKey); return false; } private static bool IsRedundantRecentInventoryDropRelay(Player player, byte slot) { if (HasRecentValidInventoryDrop(player, slot)) { return SlotIsEmpty(player, slot); } return false; } private static bool SlotIsEmpty(Player player, byte slot) { if (!Object.op_Implicit((Object)(object)player)) { return false; } try { ItemSlot itemSlot = player.GetItemSlot(slot); return itemSlot != null && itemSlot.IsEmpty(); } catch { return false; } } private static void PruneRecentValidInventoryDrops() { if (RecentValidInventoryDrops.Count == 0) { return; } float realtimeSinceStartup = Time.realtimeSinceStartup; List list = null; foreach (KeyValuePair recentValidInventoryDrop in RecentValidInventoryDrops) { if (!(recentValidInventoryDrop.Value >= realtimeSinceStartup)) { if (list == null) { list = new List(); } list.Add(recentValidInventoryDrop.Key); } } if (list != null) { for (int i = 0; i < list.Count; i++) { RecentValidInventoryDrops.Remove(list[i]); } } } private static string GetInventorySlotKey(Player player, byte slot) { if (!Object.op_Implicit((Object)(object)player)) { return string.Empty; } PhotonView val = ((MonoBehaviourPun)player).photonView ?? ((Component)player).GetComponent() ?? ((Component)player).GetComponentInParent() ?? ((Component)player).GetComponentInChildren(); return (Object.op_Implicit((Object)(object)val) ? val.ViewID : ((Object)player).GetInstanceID()) + ":" + slot; } private static Player SafeGetPlayer(Character character) { if (!Object.op_Implicit((Object)(object)character)) { return null; } try { return character.player; } catch { return null; } } private static Player GetViewPlayer(PhotonView view) { if (!Object.op_Implicit((Object)(object)view)) { return null; } Player val = ((Component)view).GetComponent() ?? ((Component)view).GetComponentInParent() ?? ((Component)view).GetComponentInChildren(); if (Object.op_Implicit((Object)(object)val)) { return val; } Character viewCharacter = GetViewCharacter(view); if (!Object.op_Implicit((Object)(object)viewCharacter)) { return null; } try { return viewCharacter.player; } catch { return null; } } private static bool SenderMatchesPlayer(Player sender, Player targetPlayer) { if (sender == null || !Object.op_Implicit((Object)(object)targetPlayer)) { return false; } try { Player val = default(Player); if (PlayerHandler.TryGetPlayer(sender.ActorNumber, ref val) && Object.op_Implicit((Object)(object)val) && val == targetPlayer) { return true; } } catch { } try { PhotonView val2 = targetPlayer.character?.refs?.view; if (Object.op_Implicit((Object)(object)val2) && IsViewOwner(val2, sender)) { return true; } } catch { } return IsViewOwner(((Component)targetPlayer).GetComponent() ?? ((Component)targetPlayer).GetComponentInChildren(), sender); } private static bool IsTrustedCharacterFlowSender(Player sender, PhotonView rpcView) { if (!IsMasterClientSender(sender)) { return IsViewOwner(rpcView, sender); } return true; } private static Character GetViewCharacter(PhotonView view) { if (!Object.op_Implicit((Object)(object)view)) { return null; } return ((Component)view).GetComponent() ?? ((Component)view).GetComponentInParent() ?? ((Component)view).GetComponentInChildren(); } private static bool IsDeadOrDown(Character character) { if (Object.op_Implicit((Object)(object)character) && Object.op_Implicit((Object)(object)character.data)) { if (!character.data.dead) { return character.data.fullyPassedOut; } return true; } return false; } private static bool IsBlockedByHostOnlyKiosk(Player sender, PhotonView rpcView) { if (HostOnlyKioskSettings.ShouldEnforceAsHost && RpcViewIsAirportKiosk(rpcView)) { return !IsMasterClientSender(sender); } return false; } private static bool RpcViewIsAirportKiosk(PhotonView view) { if (!Object.op_Implicit((Object)(object)view)) { return false; } if (!Object.op_Implicit((Object)(object)((Component)view).GetComponent()) && !Object.op_Implicit((Object)(object)((Component)view).GetComponentInParent())) { return Object.op_Implicit((Object)(object)((Component)view).GetComponentInChildren()); } return true; } private static bool IsValidFlareTrigger(PhotonView view) { //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)view)) { return false; } Flare val = ((Component)view).GetComponent() ?? ((Component)view).GetComponentInParent() ?? ((Component)view).GetComponentInChildren(); if (!Object.op_Implicit((Object)(object)val)) { return false; } try { PeakHandler instance = Singleton.Instance; if (Object.op_Implicit((Object)(object)instance) && instance.summonedHelicopter) { return true; } } catch { } try { BoolItemData data = ((ItemComponent)val).GetData((DataEntryKey)3); if (data == null || !data.Value) { return false; } MountainProgressHandler instance2 = Singleton.Instance; return Object.op_Implicit((Object)(object)instance2) && instance2.IsAtPeak(((Component)val).transform.position + new Vector3(0f, 0f, 10f)); } catch { return false; } } private static PhotonView GetRpcView(Hashtable rpcData) { int @int = GetInt(rpcData, 0); if (@int != 0) { return PhotonView.Find(@int); } return null; } private static PhotonView GetArgumentPhotonView(Hashtable rpcData, int index) { object[] arguments = GetArguments(rpcData); if (arguments == null || index < 0 || index >= arguments.Length) { return null; } object obj = arguments[index]; PhotonView val = (PhotonView)((obj is PhotonView) ? obj : null); if (val != null) { return val; } int num = ToInt(arguments[index]); if (num != 0) { return PhotonView.Find(num); } return null; } private static PhotonView GetFirstArgumentPhotonView(Hashtable rpcData) { object[] arguments = GetArguments(rpcData); if (arguments == null) { return null; } object[] array = arguments; foreach (object obj in array) { PhotonView val = (PhotonView)((obj is PhotonView) ? obj : null); if (val != null) { return val; } int num = ToInt(obj); if (num != 0) { return PhotonView.Find(num); } } return null; } private static bool ViewHasComponent(PhotonView view) where T : Component { if (Object.op_Implicit((Object)(object)view)) { if (!Object.op_Implicit((Object)(object)((Component)view).GetComponent()) && !Object.op_Implicit((Object)(object)((Component)view).GetComponentInParent())) { return Object.op_Implicit((Object)(object)((Component)view).GetComponentInChildren()); } return true; } return false; } private static string GetRpcMethodName(Hashtable rpcData) { if (GetValue(rpcData, 3) is string result) { return result; } int @int = GetInt(rpcData, 5); if (@int != 0) { return ResolveRpcShortcut(@int); } return null; } private static string ResolveRpcShortcut(int shortcut) { try { if ((object)_rpcShortcutsField == null) { _rpcShortcutsField = typeof(PhotonNetwork).GetField("rpcShortcuts", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); } if (!(_rpcShortcutsField?.GetValue(null) is Dictionary dictionary)) { return null; } foreach (KeyValuePair item in dictionary) { if (item.Value == shortcut) { return item.Key; } } } catch { } return null; } private static object[] GetArguments(Hashtable rpcData) { return GetValue(rpcData, 4) as object[]; } private static bool HasArguments(Hashtable rpcData) { object[] arguments = GetArguments(rpcData); if (arguments != null) { return arguments.Length != 0; } return false; } private static int GetInt(Hashtable rpcData, byte key) { return ToInt(GetValue(rpcData, key)); } private static object GetValue(Hashtable rpcData, byte key) { if (rpcData == null) { return null; } object obj = key; if (((Dictionary)(object)rpcData).ContainsKey(obj)) { return rpcData[obj]; } object obj2 = (int)key; if (!((Dictionary)(object)rpcData).ContainsKey(obj2)) { return null; } return rpcData[obj2]; } private static int ToInt(object value) { if (value == null) { return 0; } try { return Convert.ToInt32(value); } catch { return 0; } } private static bool TryGetInt(object value, out int result) { result = 0; if (value == null) { return false; } try { result = Convert.ToInt32(value); return true; } catch { return false; } } private static bool TryGetFloat(object value, out float result) { result = 0f; if (value == null) { return false; } try { result = Convert.ToSingle(value); return IsFinite(result); } catch { return false; } } private static bool TryGetByte(object value, out byte result) { result = 0; if (value == null) { return false; } try { result = Convert.ToByte(value); return true; } catch { return false; } } private static bool IsFinite(Vector3 value) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) if (IsFinite(value.x) && IsFinite(value.y)) { return IsFinite(value.z); } return false; } private static bool IsFinite(float value) { if (!float.IsNaN(value)) { return !float.IsInfinity(value); } return false; } private static string NormalizePrefabName(string prefabName) { if (string.IsNullOrWhiteSpace(prefabName)) { return string.Empty; } string text = prefabName.Trim(); int num = text.LastIndexOf('/'); if (num >= 0 && num + 1 < text.Length) { text = text.Substring(num + 1); } if (text.EndsWith("(Clone)", StringComparison.Ordinal)) { text = text.Substring(0, text.Length - "(Clone)".Length).Trim(); } return text; } private static string FormatSender(Player sender) { if (sender == null) { return "unknown"; } return (string.IsNullOrEmpty(sender.NickName) ? "player" : sender.NickName) + " #" + sender.ActorNumber; } } [HarmonyPatch(typeof(Action_ReduceUses), "ReduceUsesRPC")] internal static class InfiniteChargeReduceUsesPatch { private static bool Prefix(Action_ReduceUses __instance) { if (!SelfRuntimeSettings.InfiniteItemCharge) { return true; } Item item = (Object.op_Implicit((Object)(object)__instance) ? (((Component)__instance).GetComponent() ?? ((Component)__instance).GetComponentInParent()) : null); if (!InfiniteItemChargeScope.ShouldHandle(item)) { return true; } return !LocalItemScope.IsLocalHeldOrSlotted(item); } } public class InfiniteItemCharge : Feature { public InfiniteItemCharge() { base.Name = "Infinite Item Charge"; base.Description = "Prevents supported item-use charge and ammo counters from draining."; } protected override void OnEnable() { OnTick(); } protected override void OnDisable() { SelfRuntimeSettings.InfiniteItemCharge = false; } public override void OnTick() { SelfRuntimeSettings.InfiniteItemCharge = true; InfiniteItemChargeRuntime.RefillLocalItems(); } } internal static class InfiniteItemChargeRuntime { public static void RefillLocalItems() { bool flag = false; Character localCharacter = Character.localCharacter; if (Object.op_Implicit((Object)(object)localCharacter) && Object.op_Implicit((Object)(object)localCharacter.data) && InfiniteItemChargeScope.ShouldHandle(localCharacter.data.currentItem)) { GameActions.RechargeHeldItemData(localCharacter.data.currentItem); } Player localPlayer = Player.localPlayer; if (!Object.op_Implicit((Object)(object)localPlayer) || localPlayer.itemSlots == null) { return; } for (int i = 0; i < localPlayer.itemSlots.Length; i++) { if (InfiniteItemChargeScope.ShouldHandle(localPlayer.itemSlots[i]?.prefab)) { flag |= GameActions.RechargeItemSlotData(localPlayer.itemSlots[i], createUseData: true); } } if (flag) { GameActions.SyncLocalInventory(); } } } internal static class InfiniteItemChargeScope { public static bool ShouldHandle(Item item) { if (!Object.op_Implicit((Object)(object)item)) { return false; } try { return !Object.op_Implicit((Object)(object)((Component)item).GetComponent()); } catch { return true; } } } [HarmonyPatch(typeof(Item), "Consume")] internal static class InfiniteItemConsumePatch { private static bool Prefix(Item __instance) { if (!SelfRuntimeSettings.InfiniteItemCharge) { return true; } if (!InfiniteItemChargeScope.ShouldHandle(__instance)) { return true; } return !SelfPatchHelpers.IsLocal(Object.op_Implicit((Object)(object)__instance) ? __instance.holderCharacter : null); } } public class InfiniteJump : Feature { public InfiniteJump() { base.Name = "Infinite Jump"; base.Description = "Press jump again in mid-air to trigger another jump RPC."; } protected override void OnEnable() { } protected override void OnDisable() { } public override void OnTick() { Character localCharacter = Character.localCharacter; if (Object.op_Implicit((Object)(object)localCharacter) && Input.GetKeyDown((KeyCode)32)) { PhotonView val = ((Component)localCharacter).GetComponent() ?? ((Component)localCharacter).GetComponentInChildren(); if (Object.op_Implicit((Object)(object)val)) { val.RPC("JumpRpc", (RpcTarget)0, new object[1] { false }); } } } } [HarmonyPatch(typeof(Lantern), "UpdateFuel")] internal static class InfiniteLanternFuelPatch { private static bool Prefix(Lantern __instance) { if (SelfRuntimeSettings.InfiniteItemCharge) { return !LocalItemScope.IsLocalHeldOrSlotted(((ItemComponent)(__instance?)).item); } return true; } } [HarmonyPatch(typeof(MagicBugle), "StartToot")] internal static class InfiniteMagicBugleStartPatch { private static void Prefix(MagicBugle __instance) { InfiniteMagicBugleFuel.RefillIfLocal(__instance); } } [HarmonyPatch(typeof(MagicBugle), "UpdateToot")] internal static class InfiniteMagicBugleUpdatePatch { private static void Prefix(MagicBugle __instance) { InfiniteMagicBugleFuel.RefillIfLocal(__instance); } private static void Postfix(MagicBugle __instance) { InfiniteMagicBugleFuel.RefillIfLocal(__instance); } } internal static class InfiniteMagicBugleFuel { public static void RefillIfLocal(MagicBugle bugle) { if (SelfRuntimeSettings.InfiniteItemCharge && Object.op_Implicit((Object)(object)bugle) && LocalItemScope.IsLocalHeldOrSlotted(((ItemComponent)bugle).item)) { GameActions.RechargeHeldItemData(((ItemComponent)bugle).item); } } } public class InfiniteRescueHookRange : Feature { public InfiniteRescueHookRange() { base.Name = "Infinite Rescue Hook Range"; base.Description = "Keeps local rescue hooks usable and extends their fire range. Seems to work only after the 1st pull"; } protected override void OnEnable() { SelfRuntimeSettings.InfiniteRescueHookRange = true; } protected override void OnDisable() { SelfRuntimeSettings.InfiniteRescueHookRange = false; } } [HarmonyPatch] internal static class InfiniteRescueHookRangePatch { private const float ExtendedRange = 5000f; private const int RefilledUses = 9999; [HarmonyPatch(typeof(RescueHook), "Fire")] [HarmonyPrefix] private static void FirePrefix(RescueHook __instance) { ApplyFireRange(__instance); } [HarmonyPatch(typeof(RescueHook), "OnPrimaryFinishedCast")] [HarmonyPrefix] private static void OnPrimaryFinishedCastPrefix(RescueHook __instance) { ApplyFireRange(__instance); } [HarmonyPatch(typeof(RescueHook), "RPCA_LetGo")] [HarmonyPrefix] private static void LetGoPrefix(RescueHook __instance) { RefillHookUses(__instance); } [HarmonyPatch(typeof(ItemCooking), "Wreck")] [HarmonyPrefix] private static bool WreckPrefix(ItemCooking __instance) { if (!SelfRuntimeSettings.InfiniteRescueHookRange) { return true; } if (!Object.op_Implicit((Object)(object)__instance)) { return true; } return !CanPatchHook(((Component)__instance).GetComponent()); } private static void ApplyFireRange(RescueHook hook) { if (CanPatchHook(hook)) { hook.range = 5000f; hook.rangeDownward = 5000f; hook.curRange = 5000f; hook.maxLength = 5000f; hook.maxLiftDistance = 5000f; hook.maxScoutHookTime = 5000f; hook.maxWallHookTime = 5000f; } } private static void RefillHookUses(RescueHook hook) { if (CanPatchHook(hook) && Object.op_Implicit((Object)(object)((ItemComponent)hook).item)) { OptionableIntItemData data = ((ItemComponent)hook).item.GetData((DataEntryKey)2); if (data != null) { data.HasData = true; data.Value = Mathf.Max(data.Value, 9999); } } } private static bool CanPatchHook(RescueHook hook) { if (!SelfRuntimeSettings.InfiniteRescueHookRange) { return false; } if (!Object.op_Implicit((Object)(object)hook) || !((Behaviour)hook).isActiveAndEnabled) { return false; } return LocalItemScope.IsLocalHeldOrSlotted(((ItemComponent)hook).item); } } public class InfiniteRope : Feature { public InfiniteRope() { base.Name = "Infinite Rope"; base.Description = "Keeps rope spool fuel available while enabled."; } protected override void OnEnable() { OnTick(); } protected override void OnDisable() { SelfRuntimeSettings.InfiniteRope = false; } public override void OnTick() { SelfRuntimeSettings.InfiniteRope = true; InfiniteRopeRuntime.RefillLocalRopes(); } } internal static class InfiniteRopeRuntime { public static void RefillLocalRopes() { Character localCharacter = Character.localCharacter; if (Object.op_Implicit((Object)(object)localCharacter) && Object.op_Implicit((Object)(object)localCharacter.data) && IsRope(localCharacter.data.currentItem)) { GameActions.RechargeHeldItemData(localCharacter.data.currentItem); } Player localPlayer = Player.localPlayer; if (Object.op_Implicit((Object)(object)localPlayer) && localPlayer.itemSlots != null && localPlayer.itemSlots.Where((ItemSlot slot) => IsRope(slot?.prefab)).Aggregate(seed: false, (bool current, ItemSlot slot) => current | GameActions.RechargeItemSlotData(slot, createUseData: true))) { GameActions.SyncLocalInventory(); } } public static bool IsRope(Item item) { if (!Object.op_Implicit((Object)(object)item)) { return false; } try { return Object.op_Implicit((Object)(object)((Component)item).GetComponent()); } catch { return false; } } } [HarmonyPatch(typeof(Item), "Consume")] internal static class InfiniteRopeConsumePatch { private static bool Prefix(Item __instance, int consumerID) { if (!SelfRuntimeSettings.InfiniteRope || !InfiniteRopeRuntime.IsRope(__instance)) { return true; } if (LocalItemScope.IsLocalHeldOrSlotted(__instance)) { return false; } if (SelfPatchHelpers.IsLocal(((Object)(object)__instance != (Object)null) ? __instance.holderCharacter : null)) { return false; } return !IsLocalConsumer(consumerID); } private static bool IsLocalConsumer(int consumerID) { if (consumerID < 0) { return false; } PhotonView photonView = PhotonNetwork.GetPhotonView(consumerID); return SelfPatchHelpers.IsLocal(((Object)(object)photonView != (Object)null) ? ((Component)photonView).GetComponent() : null); } } [HarmonyPatch(/*Could not decode attribute arguments.*/)] internal static class InfiniteRopeFuelPatch { private static bool Prefix(RopeSpool __instance, ref float __result) { if (!SelfRuntimeSettings.InfiniteRope || !LocalItemScope.IsLocalHeldOrSlotted(((ItemComponent)(__instance?)).item)) { return true; } __result = Mathf.Max(__instance.ropeStartFuel, 2000f); return false; } } [HarmonyPatch(/*Could not decode attribute arguments.*/)] internal static class InfiniteRopeOutPatch { private static bool Prefix(RopeSpool __instance, ref bool __result) { if (!SelfRuntimeSettings.InfiniteRope || !LocalItemScope.IsLocalHeldOrSlotted(((ItemComponent)(__instance?)).item)) { return true; } __result = false; return false; } } [HarmonyPatch(/*Could not decode attribute arguments.*/)] internal static class InfiniteRopeSetFuelPatch { private static bool Prefix(RopeSpool __instance) { if (SelfRuntimeSettings.InfiniteRope) { return !LocalItemScope.IsLocalHeldOrSlotted(((ItemComponent)(__instance?)).item); } return true; } } [HarmonyPatch(/*Could not decode attribute arguments.*/)] internal static class InfiniteRopeShooterAmmoPatch { private static bool Prefix(RopeShooter __instance, ref int __result) { if (!SelfRuntimeSettings.InfiniteItemCharge || !LocalItemScope.IsLocalHeldOrSlotted(((ItemComponent)(__instance?)).item)) { return true; } __result = int.MaxValue; return false; } } [HarmonyPatch(typeof(RopeBoneVisualizer), "LateUpdate")] internal static class InfiniteRopeVisualizerPatch { private static readonly FieldInfo FullPositionDataField = AccessTools.Field(typeof(RopeBoneVisualizer), "fullPositionData"); private static readonly FieldInfo SegmentPositionField = AccessTools.Field(typeof(SegmentData), "position"); private static readonly FieldInfo SegmentRotationField = AccessTools.Field(typeof(SegmentData), "rotation"); private static readonly int RopeCutoff = Shader.PropertyToID("_RopeCutoff"); private static void Postfix(RopeBoneVisualizer __instance) { if (!SelfRuntimeSettings.InfiniteRope || !Object.op_Implicit((Object)(object)__instance)) { return; } List bones = __instance.bones; if (bones != null && bones.Count >= 2 && FullPositionDataField?.GetValue(__instance) is List list && list.Count > bones.Count) { ResampleToBones(bones, list); SkinnedMeshRenderer componentInChildren = ((Component)__instance).GetComponentInChildren(); if (Object.op_Implicit((Object)(object)componentInChildren) && Object.op_Implicit((Object)(object)((Renderer)componentInChildren).sharedMaterial)) { ((Renderer)componentInChildren).sharedMaterial.SetFloat(RopeCutoff, 1f); } } } private static void ResampleToBones(IReadOnlyList bones, IReadOnlyList points) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0058: 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_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: 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) //IL_006e: 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_0077: 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) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) float num = (float)points.Count - 1f; float num2 = (float)bones.Count - 1f; for (int i = 0; i < bones.Count; i++) { float num3 = (float)i / num2 * num; int num4 = Mathf.FloorToInt(num3); int index = Mathf.Min(num4 + 1, points.Count - 1); float num5 = num3 - (float)num4; SegmentData point = points[num4]; SegmentData point2 = points[index]; Vector3 position = GetPosition(point); Vector3 position2 = GetPosition(point2); Quaternion rotation = GetRotation(point); Quaternion rotation2 = GetRotation(point2); Transform obj = bones[i]; obj.localScale = Vector3.one; obj.position = Vector3.Lerp(position, position2, num5); obj.rotation = Quaternion.Slerp(rotation, rotation2, num5); } } private static Vector3 GetPosition(SegmentData point) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) return ToVector3(SegmentPositionField?.GetValue(point)); } private static Quaternion GetRotation(SegmentData point) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) object obj = SegmentRotationField?.GetValue(point); if (obj is Quaternion) { return (Quaternion)obj; } return Quaternion.identity; } private static Vector3 ToVector3(object value) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) if (value == null) { return Vector3.zero; } Type type = value.GetType(); return new Vector3(ReadSingle(type, value, "x"), ReadSingle(type, value, "y"), ReadSingle(type, value, "z")); } private static float ReadSingle(Type type, object value, string fieldName) { FieldInfo field = type.GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (!(field != null)) { return 0f; } return Convert.ToSingle(field.GetValue(value)); } } public class InstantItemUse : Feature { public InstantItemUse() { base.Name = "Instant Item Use"; base.Description = "Finishes supported primary and secondary item casts immediately."; } protected override void OnEnable() { OnTick(); } protected override void OnDisable() { SelfRuntimeSettings.InstantItemUse = false; } public override void OnTick() { SelfRuntimeSettings.InstantItemUse = true; } } [HarmonyPatch(typeof(Item), "ContinueUsePrimary")] internal static class InstantPrimaryUsePatch { private static bool Prefix(Item __instance) { if (!SelfRuntimeSettings.InstantItemUse || !Object.op_Implicit((Object)(object)__instance)) { return true; } if (__instance.isUsingSecondary) { __instance.CancelUseSecondary(); } if (!__instance.isUsingPrimary) { return false; } FinishPrimaryCast(__instance); __instance.OnPrimaryHeld?.Invoke(); return false; } private static void FinishPrimaryCast(Item item) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) if (item.finishedCast) { return; } ItemUseFeedback component = ((Component)item).GetComponent(); if (Object.op_Implicit((Object)(object)component)) { item.holderCharacter.refs.animator.SetBool(component.useAnimation, false); if (Object.op_Implicit((Object)(object)component.sfxUsed)) { component.sfxUsed.Play(((Component)item).transform.position); } } item.finishedCast = true; item.lastFinishedCast = Time.time; item.OnPrimaryFinishedCast?.Invoke(); } } [HarmonyPatch(typeof(Item), "ContinueUseSecondary")] internal static class InstantSecondaryUsePatch { private static bool Prefix(Item __instance) { if (!SelfRuntimeSettings.InstantItemUse || !Object.op_Implicit((Object)(object)__instance)) { return true; } if (__instance.isUsingPrimary) { return false; } if (!__instance.isUsingSecondary) { return false; } __instance.OnSecondaryHeld?.Invoke(); if (!__instance.finishedCast) { __instance.finishedCast = true; __instance.lastFinishedCast = Time.time; __instance.OnSecondaryFinishedCast?.Invoke(); } return false; } } internal static class LocalItemScope { public static bool IsLocalHeldOrSlotted(Item item) { if (!Object.op_Implicit((Object)(object)item)) { return false; } Character localCharacter = Character.localCharacter; try { if (Object.op_Implicit((Object)(object)localCharacter)) { if ((Object)(object)item.holderCharacter == (Object)(object)localCharacter || (Object)(object)item.trueHolderCharacter == (Object)(object)localCharacter) { return true; } if (Object.op_Implicit((Object)(object)localCharacter.data) && (Object)(object)localCharacter.data.currentItem == (Object)(object)item) { return true; } } } catch { } Player localPlayer = Player.localPlayer; if (!Object.op_Implicit((Object)(object)localPlayer) || localPlayer.itemSlots == null) { return false; } bool flag = IsPrefabAsset(item); for (int i = 0; i < localPlayer.itemSlots.Length; i++) { ItemSlot val = localPlayer.itemSlots[i]; if (val != null && Object.op_Implicit((Object)(object)val.prefab)) { if ((Object)(object)val.prefab == (Object)(object)item) { return true; } if (val.data != null && item.data != null && val.data == item.data) { return true; } if (flag && IsSamePrefab(val.prefab, item)) { return true; } } } return false; } private static bool IsPrefabAsset(Item item) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)item) || !Object.op_Implicit((Object)(object)((Component)item).gameObject)) { return false; } Scene scene = ((Component)item).gameObject.scene; if (((Scene)(ref scene)).IsValid()) { return !((Scene)(ref scene)).isLoaded; } return true; } private static bool IsSamePrefab(Item left, Item right) { if (!Object.op_Implicit((Object)(object)left) || !Object.op_Implicit((Object)(object)right)) { return false; } try { if (left.itemID != 0 && left.itemID == right.itemID) { return true; } } catch { } return string.Equals(((Object)left).name, ((Object)right).name, StringComparison.Ordinal); } } public class ModderProtections : Feature { public ModderProtections() { base.Name = "Modder Protections"; base.Description = "Blocks high-impact remote RPC effects and stricter Atlas/Cherry client actions while allowing normal player interactions."; } protected override void OnEnable() { OnTick(); } protected override void OnDisable() { SelfRuntimeSettings.ModderProtections = false; } public override void OnTick() { SelfRuntimeSettings.ModderProtections = true; } } [HarmonyPatch(typeof(CharacterAfflictions), "AddAffliction")] internal static class NoAfflictionAddAfflictionPatch { private static bool Prefix() { return !SelfRuntimeSettings.NoAfflictions; } } [HarmonyPatch(typeof(CharacterAfflictions), "AddStatus")] internal static class NoAfflictionAddStatusPatch { private static bool Prefix() { return !SelfRuntimeSettings.NoAfflictions; } } public class NoAfflictions : Feature { public NoAfflictions() { base.Name = "No Afflictions"; base.Description = "Blocks new afflictions and clears current local status values."; } protected override void OnEnable() { SelfRuntimeSettings.NoAfflictions = true; OnTick(); } protected override void OnDisable() { SelfRuntimeSettings.NoAfflictions = false; } public override void OnTick() { Character localCharacter = Character.localCharacter; CharacterAfflictions val = ((!Object.op_Implicit((Object)(object)localCharacter)) ? null : localCharacter.refs?.afflictions); if (Object.op_Implicit((Object)(object)val) && val.currentStatuses != null) { for (int i = 0; i < val.currentStatuses.Length; i++) { val.currentStatuses[i] = 0f; } } } } [HarmonyPatch(typeof(BananaPeel), "RPCA_TriggerBanana")] internal static class NoBananaSlipPatch { private static bool Prefix(int viewID) { if (!SelfRuntimeSettings.NoSlip) { return true; } Character localCharacter = Character.localCharacter; if (Object.op_Implicit((Object)(object)localCharacter) && !((Object)(object)localCharacter.refs?.view == (Object)null)) { return localCharacter.refs.view.ViewID != viewID; } return true; } } public class Noclip : Feature { private Collider[] _colliders; public Noclip() { base.Name = "Noclip"; base.Description = "Disables local character colliders while enabled."; } protected override void OnEnable() { DisableLocalColliders(); } protected override void OnDisable() { RestoreColliders(); } public override void OnTick() { DisableLocalColliders(); } private void DisableLocalColliders() { Character localCharacter = Character.localCharacter; if (!Object.op_Implicit((Object)(object)localCharacter)) { return; } _colliders = ((Component)localCharacter).GetComponentsInChildren(true); Collider[] colliders = _colliders; foreach (Collider val in colliders) { if (Object.op_Implicit((Object)(object)val)) { val.enabled = false; } } } private void RestoreColliders() { if (_colliders == null) { return; } Collider[] colliders = _colliders; foreach (Collider val in colliders) { if (Object.op_Implicit((Object)(object)val)) { val.enabled = true; } } _colliders = null; } } public class NoDeath : Feature { public NoDeath() { base.Name = "No Death"; base.Description = "Blocks local death calls."; } protected override void OnEnable() { OnTick(); } protected override void OnDisable() { SelfRuntimeSettings.NoDeath = false; } public override void OnTick() { SelfRuntimeSettings.NoDeath = true; } } [HarmonyPatch(typeof(Character), "Die")] internal static class NoDeathPatch { private static bool Prefix() { return !SelfRuntimeSettings.NoDeath; } } [HarmonyPatch(typeof(Character), "RPCA_Die")] internal static class NoDeathRpcPatch { private static bool Prefix(Character __instance) { return !SelfPatchHelpers.ShouldBlockLocalCharacterEffect(__instance, SelfRuntimeSettings.NoDeath); } } public class NoPassout : Feature { public NoPassout() { base.Name = "No Passout"; base.Description = "Blocks local pass-out calls."; } protected override void OnEnable() { OnTick(); } protected override void OnDisable() { SelfRuntimeSettings.NoPassout = false; } public override void OnTick() { SelfRuntimeSettings.NoPassout = true; } } [HarmonyPatch(typeof(Character), "PassOut")] internal static class NoPassoutPatch { private static bool Prefix() { return !SelfRuntimeSettings.NoPassout; } } [HarmonyPatch(typeof(Character), "RPCA_PassOut")] internal static class NoPassoutRpcPatch { private static bool Prefix(Character __instance) { return !SelfPatchHelpers.ShouldBlockLocalCharacterEffect(__instance, SelfRuntimeSettings.NoPassout); } } public class NoRagdoll : Feature { public NoRagdoll() { base.Name = "No Ragdoll"; base.Description = "Blocks local fall ragdoll RPCs and clears fall buildup."; } protected override void OnEnable() { SelfRuntimeSettings.NoRagdoll = true; OnTick(); } protected override void OnDisable() { SelfRuntimeSettings.NoRagdoll = false; } public override void OnTick() { Character localCharacter = Character.localCharacter; if (Object.op_Implicit((Object)(object)localCharacter?.data)) { localCharacter.data.fallSeconds = 0f; } } } [HarmonyPatch(typeof(Character), "RPCA_Fall")] internal static class NoRagdollPatch { private static bool Prefix(Character __instance) { return !SelfPatchHelpers.ShouldBlockLocalCharacterEffect(__instance, SelfRuntimeSettings.NoRagdoll); } } [HarmonyPatch(typeof(Character), "RPCA_FallWithScreenShake")] internal static class NoRagdollScreenShakePatch { private static bool Prefix(Character __instance) { return !SelfPatchHelpers.ShouldBlockLocalCharacterEffect(__instance, SelfRuntimeSettings.NoRagdoll || SelfRuntimeSettings.NoScreenShake); } } public class NoScreenShake : Feature { public NoScreenShake() { base.Name = "No Screen Shake"; base.Description = "Blocks camera shake effects."; } protected override void OnEnable() { OnTick(); } protected override void OnDisable() { SelfRuntimeSettings.NoScreenShake = false; } public override void OnTick() { SelfRuntimeSettings.NoScreenShake = true; } } [HarmonyPatch(typeof(PerlinShake), "AddShake", new Type[] { typeof(float), typeof(float), typeof(float) })] internal static class NoScreenShakePatch { private static bool Prefix() { return !SelfRuntimeSettings.NoScreenShake; } } public class NoSlip : Feature { public NoSlip() { base.Name = "No Slip"; base.Description = "Blocks banana and slippery-object slip triggers."; } protected override void OnEnable() { OnTick(); } protected override void OnDisable() { SelfRuntimeSettings.NoSlip = false; } public override void OnTick() { SelfRuntimeSettings.NoSlip = true; } } [HarmonyPatch(typeof(SlipperyJellyfish), "Trigger")] internal static class NoSlipperyJellyfishPatch { private static bool Prefix() { return !SelfRuntimeSettings.NoSlip; } } internal static class SelfPatchHelpers { public static bool IsLocal(Character character) { if (!Object.op_Implicit((Object)(object)character)) { return false; } if (character.IsLocal) { return true; } Character localCharacter = Character.localCharacter; if (Object.op_Implicit((Object)(object)localCharacter)) { return character == localCharacter; } return false; } public static bool IsLocalComponent(Component component) { if (!Object.op_Implicit((Object)(object)component)) { return false; } if (IsLocal(component.GetComponentInParent())) { return true; } Player componentInParent = component.GetComponentInParent(); if (Object.op_Implicit((Object)(object)componentInParent) && Object.op_Implicit((Object)(object)Player.localPlayer)) { return componentInParent == Player.localPlayer; } return false; } public static bool ShouldBlockLocalCharacterEffect(Character character, bool specificProtection) { if (specificProtection) { return IsLocal(character); } return false; } } public class Fly : Feature { private Character _character; private Rigidbody _rb; private float _cachedLinearDamping; private bool _cachedGravity; private Vector3 _velocity; public static float Speed { get; set; } = 12f; public static float Acceleration { get; set; } = 24f; public Fly() { base.Name = "Fly"; base.Description = "Keyboard or controller movement to fly freely. Jump ascends; right stick down or crouch descends."; } protected override void OnEnable() { TryBindLocalRigidbody(); } protected override void OnDisable() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) _velocity = Vector3.zero; RestoreRigidbody(); } public override void OnTick() { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0094: 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) //IL_0099: 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_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) if (!TryBindLocalRigidbody()) { RestoreRigidbody(); return; } Camera main = Camera.main; if (Object.op_Implicit((Object)(object)main)) { Vector3 flyMove = GetFlyMove(main); if (Object.op_Implicit((Object)(object)_character.data)) { _character.data.isGrounded = true; _character.data.sinceGrounded = 0f; _character.data.sinceJump = 0f; } Vector3 val = ((((Vector3)(ref flyMove)).sqrMagnitude > 0f) ? (((Vector3)(ref flyMove)).normalized * Speed) : Vector3.zero); float num = 1f - Mathf.Exp((0f - Mathf.Max(0.1f, Acceleration)) * Time.deltaTime); _velocity = Vector3.Lerp(_velocity, val, num); _rb.linearVelocity = _velocity; } } private Vector3 GetFlyMove(Camera cam) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: 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_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0064: 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) //IL_006a: 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_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_009d: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) Vector2 planarInput = GetPlanarInput(); Vector3 val = Vector3.ProjectOnPlane(((Component)cam).transform.forward, Vector3.up); Vector3 val2 = Vector3.ProjectOnPlane(((Component)cam).transform.right, Vector3.up); if (((Vector3)(ref val)).sqrMagnitude > 0.0001f) { ((Vector3)(ref val)).Normalize(); } if (((Vector3)(ref val2)).sqrMagnitude > 0.0001f) { ((Vector3)(ref val2)).Normalize(); } Vector3 val3 = val * planarInput.y + val2 * planarInput.x; if (!Input.GetKey((KeyCode)32)) { CharacterInput input = _character.input; if (input == null || !input.jumpIsPressed) { goto IL_00a9; } } val3 += Vector3.up; goto IL_00a9; IL_00a9: if (!Input.GetKey((KeyCode)306) && !Input.GetKey((KeyCode)305)) { CharacterInput input2 = _character.input; if ((input2 == null || !input2.crouchIsPressed) && !IsControllerDescendPressed()) { goto IL_00ed; } } val3 -= Vector3.up; goto IL_00ed; IL_00ed: return val3; } private Vector2 GetPlanarInput() { //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_008e: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) Vector2 val = Vector2.zero; if (Input.GetKey((KeyCode)119)) { val.y += 1f; } if (Input.GetKey((KeyCode)115)) { val.y -= 1f; } if (Input.GetKey((KeyCode)97)) { val.x -= 1f; } if (Input.GetKey((KeyCode)100)) { val.x += 1f; } Vector2 val2 = (Object.op_Implicit((Object)(object)_character.input) ? _character.input.movementInput : Vector2.zero); if (((Vector2)(ref val2)).sqrMagnitude > ((Vector2)(ref val)).sqrMagnitude) { val = val2; } Gamepad val3 = CurrentGamepad(); if (val3 != null) { Vector2 val4 = ((InputControl)(object)val3.leftStick).ReadValue(); if (((Vector2)(ref val4)).sqrMagnitude > ((Vector2)(ref val)).sqrMagnitude) { val = val4; } } return Vector2.ClampMagnitude(val, 1f); } private static bool IsControllerDescendPressed() { //IL_000f: Unknown result type (might be due to invalid IL or missing references) Gamepad val = CurrentGamepad(); if (val != null) { return ((InputControl)(object)val.rightStick).ReadValue().y < -0.45f; } return false; } private static Gamepad CurrentGamepad() { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) Gamepad current = Gamepad.current; if (current != null) { return current; } if (Gamepad.all.Count <= 0) { return null; } return Gamepad.all[0]; } private bool TryBindLocalRigidbody() { //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) Character localCharacter = Character.localCharacter; if (!Object.op_Implicit((Object)(object)localCharacter) || (Object.op_Implicit((Object)(object)localCharacter.data) && localCharacter.data.dead)) { return false; } Rigidbody val = ((Component)localCharacter).GetComponent(); if (!Object.op_Implicit((Object)(object)val)) { val = ((Component)localCharacter).GetComponentInChildren(); } if (!Object.op_Implicit((Object)(object)val)) { return false; } if (localCharacter == _character && val == _rb) { return true; } RestoreRigidbody(); _character = localCharacter; _rb = val; _cachedGravity = _rb.useGravity; _cachedLinearDamping = _rb.linearDamping; _rb.useGravity = false; _rb.linearDamping = 4f; _velocity = Vector3.zero; return true; } private void RestoreRigidbody() { if (Object.op_Implicit((Object)(object)_rb)) { _rb.useGravity = _cachedGravity; _rb.linearDamping = _cachedLinearDamping; } _rb = null; _character = null; } } public class FlyAcceleration : NumberFeature { public FlyAcceleration() { base.Name = "Fly Acceleration"; base.Description = "Adjusts how quickly fly velocity reaches the selected speed."; base.Min = 1f; base.Max = 300f; base.Value = Fly.Acceleration; base.Step = 5f; base.Decimals = 0; } protected override void OnValueChanged(float newValue) { Fly.Acceleration = newValue; } } public class FlySpeed : NumberFeature { public FlySpeed() { base.Name = "Fly Speed"; base.Description = "Adjusts fly movement speed."; base.Min = 2f; base.Max = 100f; base.Value = Fly.Speed; base.Step = 1f; base.Decimals = 0; base.Unit = " u/s"; } protected override void OnValueChanged(float newValue) { Fly.Speed = newValue; } } public class GodMode : Feature { private object _lastData; private FieldInfo _invincibleField; private bool? _originalInvincible; public GodMode() { base.Name = "God Mode"; base.Description = "You won't receive damage."; } protected override void OnEnable() { CacheAndApply(); } protected override void OnDisable() { RestoreOriginal(); } public override void OnTick() { if (!HasValidCharacter()) { RestoreOriginal(); } else { CacheAndApply(); } } private bool HasValidCharacter() { Character localCharacter = Character.localCharacter; if (Object.op_Implicit((Object)(object)localCharacter) && Object.op_Implicit((Object)(object)localCharacter.data)) { return !localCharacter.data.dead; } return false; } private void CacheAndApply() { if (!HasValidCharacter()) { return; } object data = Character.localCharacter.data; if (data != _lastData) { RestoreOriginal(); _lastData = data; _invincibleField = AccessTools.Field(data.GetType(), "isInvincible"); if (_invincibleField == null) { return; } _originalInvincible = (bool)_invincibleField.GetValue(data); } _invincibleField?.SetValue(data, true); } private void RestoreOriginal() { if (_lastData != null && _originalInvincible.HasValue) { _invincibleField?.SetValue(_lastData, _originalInvincible.Value); } _lastData = null; _invincibleField = null; _originalInvincible = null; } } public class InfiniteStamina : Feature { public InfiniteStamina() { base.Name = "Infinite Stamina"; base.Description = "Never run out of stamina."; } protected override void OnEnable() { OnTick(); } protected override void OnDisable() { } public override void OnTick() { Character localCharacter = Character.localCharacter; if (Object.op_Implicit((Object)(object)localCharacter) && Object.op_Implicit((Object)(object)localCharacter.data) && !localCharacter.data.dead) { localCharacter.data.currentStamina = 1f; } } } public class JumpMultiplier : NumberBoolFeature { private Character _lastCharacter; private float? _baseJumpImpulse; private float? _lastAppliedJumpImpulse; public JumpMultiplier() { base.Name = "Jump Multiplier"; base.Description = "Toggle custom jump height and adjust the multiplier."; base.Min = 0.2f; base.Max = 20f; base.Value = 1f; base.Step = 0.1f; base.Decimals = 1; base.Unit = "x"; } protected override void OnEnable() { OnTick(); } protected override void OnDisable() { RestoreOriginal(); _lastCharacter = null; _baseJumpImpulse = null; _lastAppliedJumpImpulse = null; } public override void OnTick() { Character localCharacter = Character.localCharacter; CharacterMovement val = ((!Object.op_Implicit((Object)(object)localCharacter)) ? null : localCharacter.refs?.movement); if (!Object.op_Implicit((Object)(object)localCharacter) || !Object.op_Implicit((Object)(object)val)) { RestoreOriginal(); _lastCharacter = null; _baseJumpImpulse = null; _lastAppliedJumpImpulse = null; return; } if (localCharacter != _lastCharacter) { RestoreOriginal(); _lastCharacter = localCharacter; _baseJumpImpulse = null; _lastAppliedJumpImpulse = null; } float jumpImpulse = val.jumpImpulse; if (!_baseJumpImpulse.HasValue || !_lastAppliedJumpImpulse.HasValue || !Mathf.Approximately(jumpImpulse, _lastAppliedJumpImpulse.Value)) { _baseJumpImpulse = jumpImpulse; } _lastAppliedJumpImpulse = (val.jumpImpulse = _baseJumpImpulse.Value * base.Value); } protected override void OnValueChanged(float newValue) { if (base.Enabled) { OnTick(); } } private void RestoreOriginal() { if (Object.op_Implicit((Object)(object)_lastCharacter) && _baseJumpImpulse.HasValue) { CharacterMovement val = _lastCharacter.refs?.movement; if (Object.op_Implicit((Object)(object)val)) { val.jumpImpulse = _baseJumpImpulse.Value; _lastAppliedJumpImpulse = null; } } } } public class NoFallDamage : Feature { [HarmonyPatch(typeof(CharacterMovement), "CheckFallDamage")] private static class CheckFallDamagePatch { [HarmonyPrefix] private static bool Prefix(CharacterMovement __instance) { return CheckFallDamagePrefix(__instance); } } private static NoFallDamage _activeFeature; private Character _localCharacter; public NoFallDamage() { base.Name = "No Fall Damage"; base.Description = "Cancel fall damage."; } protected override void OnEnable() { TryBindLocalCharacter(); _activeFeature = this; } protected override void OnDisable() { if (_activeFeature == this) { _activeFeature = null; } _localCharacter = null; } public override void OnTick() { TryBindLocalCharacter(); } private void TryBindLocalCharacter() { Character localCharacter = Character.localCharacter; if (!Object.op_Implicit((Object)(object)localCharacter) || (Object.op_Implicit((Object)(object)localCharacter.data) && localCharacter.data.dead)) { _localCharacter = null; } else { _localCharacter = localCharacter; } } private bool IsLocalCharacter(Character character) { if (!Object.op_Implicit((Object)(object)character)) { return false; } if (character.IsLocal) { return true; } if (Object.op_Implicit((Object)(object)_localCharacter)) { return character == _localCharacter; } return false; } private static bool CheckFallDamagePrefix(CharacterMovement instance) { NoFallDamage activeFeature = _activeFeature; if (activeFeature == null || !activeFeature.Enabled) { return true; } if (!Object.op_Implicit((Object)(object)instance)) { return true; } Character componentInParent = ((Component)instance).GetComponentInParent(); if (!activeFeature.IsLocalCharacter(componentInParent)) { return true; } return false; } } public class PullDistance : NumberBoolFeature { public PullDistance() { base.Name = "Pull Distance"; base.Description = "Extends the local friend pull/grab distance for pulling climbing players."; base.Min = 2f; base.Max = 50f; base.Value = PullDistanceRuntime.Distance; base.Step = 1f; base.Decimals = 0; base.Unit = "m"; } protected override void OnEnable() { PullDistanceRuntime.Enabled = true; PullDistanceRuntime.Distance = base.Value; PullDistanceRuntime.Apply(); } protected override void OnDisable() { PullDistanceRuntime.Enabled = false; PullDistanceRuntime.Restore(); } protected override void OnValueChanged(float newValue) { PullDistanceRuntime.Distance = Mathf.Clamp(newValue, base.Min, base.Max); if (base.Enabled) { PullDistanceRuntime.Apply(); } } public override void OnTick() { PullDistanceRuntime.Apply(); } } internal static class PullDistanceRuntime { private const BindingFlags CharacterMethodFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; private const float LookConeDegrees = 90f; private const float PullForce = 140f; private static readonly MethodInfo UnStickMethod = typeof(Character).GetMethod("UnStick", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly MethodInfo DragTowardsMethod = typeof(Character).GetMethod("DragTowards", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly MethodInfo LimitFallingMethod = typeof(Character).GetMethod("LimitFalling", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); public static bool Enabled; public static float Distance = 50f; public static void Apply() { Distance = Mathf.Clamp(Distance, 2f, 50f); } public static void Restore() { } public static bool TryRunReach(Character character) { //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: 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_00b7: Unknown result type (might be due to invalid IL or missing references) if (!Enabled || !Object.op_Implicit((Object)(object)character) || !Object.op_Implicit((Object)(object)character.data)) { return false; } float num = Mathf.Max(2f, Distance); if (TryGetLookRaycastTarget(character, num, out var target, out var distance)) { ApplyHelpTarget(character, target, distance); TryNetworkPullTarget(character, target); return true; } Character target2 = null; float num2 = float.MaxValue; foreach (Character allCharacter in Character.AllCharacters) { if (!Object.op_Implicit((Object)(object)allCharacter) || !Object.op_Implicit((Object)(object)allCharacter.data)) { continue; } float num3 = Vector3.Distance(character.Center, allCharacter.Center); if (!(num3 > num) && !(Vector3.Angle(character.data.lookDirection, allCharacter.Center - character.Center) > 90f) && TargetCanBeHelped(character, allCharacter)) { ApplyHelpTarget(character, allCharacter, num3); if (CanNetworkPullTarget(character, allCharacter) && num3 < num2) { target2 = allCharacter; num2 = num3; } } } TryNetworkPullTarget(character, target2); return true; } private static bool TryGetLookRaycastTarget(Character character, float maxDistance, out Character target, out float distance) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003f: 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_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: 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_0058: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) target = null; distance = 0f; Camera main = Camera.main; Vector3 val; Vector3 val2; if (Object.op_Implicit((Object)(object)main)) { val = ((Component)main).transform.position; val2 = ((Component)main).transform.forward; } else { val = character.Center; val2 = character.data.lookDirection; } if (((Vector3)(ref val2)).sqrMagnitude < 0.0001f) { return false; } RaycastHit[] array = Physics.RaycastAll(val, ((Vector3)(ref val2)).normalized, maxDistance, -1, (QueryTriggerInteraction)1); if (array == null || array.Length == 0) { return false; } Array.Sort(array, (RaycastHit a, RaycastHit b) => ((RaycastHit)(ref a)).distance.CompareTo(((RaycastHit)(ref b)).distance)); for (int i = 0; i < array.Length; i++) { RaycastHit hit = array[i]; if (!Object.op_Implicit((Object)(object)((RaycastHit)(ref hit)).collider)) { continue; } if (!TryGetHitCharacter(hit, out var character2)) { return false; } if (!((Object)(object)character2 == (Object)(object)character)) { float num = Vector3.Distance(character.Center, character2.Center); if (num > maxDistance) { return false; } if (!TargetCanBeHelped(character, character2)) { return false; } target = character2; distance = num; return true; } } return false; } private static bool TryGetHitCharacter(RaycastHit hit, out Character character) { character = null; if (Object.op_Implicit((Object)(object)((RaycastHit)(ref hit)).collider) && CharacterRagdoll.TryGetCharacterFromCollider(((RaycastHit)(ref hit)).collider, ref character) && Object.op_Implicit((Object)(object)character)) { return true; } if (Object.op_Implicit((Object)(object)((RaycastHit)(ref hit)).rigidbody)) { character = ((Component)((RaycastHit)(ref hit)).rigidbody).GetComponentInParent(); if (Object.op_Implicit((Object)(object)character)) { return true; } } if (Object.op_Implicit((Object)(object)((RaycastHit)(ref hit)).collider)) { character = ((Component)((RaycastHit)(ref hit)).collider).GetComponentInParent(); if (Object.op_Implicit((Object)(object)character)) { return true; } } return false; } private static void ApplyHelpTarget(Character character, Character target, float distance) { //IL_00f8: Unknown result type (might be due to invalid IL or missing references) if (target.IsStuck() && target.IsLocal) { CallCharacterMethod(UnStickMethod, target); } if (Object.op_Implicit((Object)(object)target.refs?.afflictions)) { target.refs.afflictions.SubtractStatus((STATUSTYPE)11, 1f, false, false); } if (distance < character.data.grabFriendDistance) { character.data.grabFriendDistance = distance; character.data.sinceGrabFriend = 0f; } if (Object.op_Implicit((Object)(object)character.refs?.view) && character.refs.view.IsMine && Object.op_Implicit((Object)(object)GUIManager.instance)) { GUIManager.instance.Grasp(); } if (Object.op_Implicit((Object)(object)target.refs?.view) && target.refs.view.IsMine) { CallCharacterMethod(DragTowardsMethod, target, character.Center, 140f); CallCharacterMethod(LimitFallingMethod, target); if (Object.op_Implicit((Object)(object)GUIManager.instance)) { GUIManager.instance.Grasp(); } } } private static bool CanNetworkPullTarget(Character character, Character target) { if (!Object.op_Implicit((Object)(object)character) || !Object.op_Implicit((Object)(object)target) || !Object.op_Implicit((Object)(object)character.data) || (Object)(object)target == (Object)(object)character) { return false; } if (!character.data.isReaching || Object.op_Implicit((Object)(object)character.data.grabJoint)) { return false; } if (!Object.op_Implicit((Object)(object)character.refs?.view) || !character.refs.view.IsMine) { return false; } if (Object.op_Implicit((Object)(object)target.refs?.view)) { return !target.refs.view.IsMine; } return false; } private static void TryNetworkPullTarget(Character character, Character target) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0067: 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) if (CanNetworkPullTarget(character, target)) { Bodypart pullBodypart = GetPullBodypart(target); if (Object.op_Implicit((Object)(object)pullBodypart)) { Vector3 val = Vector3.ClampMagnitude(character.Center - target.Center, 1f) * 140f; target.refs.view.RPC("RPCA_AddForceToBodyPart", (RpcTarget)0, new object[3] { pullBodypart.partType, Vector3.zero, val }); } } } private static Bodypart GetPullBodypart(Character target) { try { if (!Object.op_Implicit((Object)(object)target) || (Object)(object)target.refs?.ragdoll == (Object)null || target.refs.ragdoll.partDict == null) { return null; } if (target.refs.ragdoll.partDict.TryGetValue((BodypartType)2, out var value) && Object.op_Implicit((Object)(object)value)) { return value; } if (target.refs.ragdoll.partDict.TryGetValue((BodypartType)1, out var value2) && Object.op_Implicit((Object)(object)value2)) { return value2; } if (target.refs.ragdoll.partDict.TryGetValue((BodypartType)0, out var value3) && Object.op_Implicit((Object)(object)value3)) { return value3; } } catch { } return null; } private static bool TargetCanBeHelped(Character character, Character target) { //IL_0078: 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) if (!Object.op_Implicit((Object)(object)target) || (Object)(object)target == (Object)(object)character || !Object.op_Implicit((Object)(object)target.data)) { return false; } if (target.IsStuck() || target.data.sinceUnstuck < 1f) { return true; } if ((Object)(object)target.refs?.afflictions != (Object)null && target.refs.afflictions.isWebbed) { return true; } if (target.data.isClimbing) { return target.Center.y < character.Center.y + 1f; } return false; } private static void CallCharacterMethod(MethodInfo method, Character target, params object[] args) { if (!(method == null) && Object.op_Implicit((Object)(object)target)) { method.Invoke(target, args); } } } public class ReachDistance : NumberBoolFeature { public ReachDistance() { base.Name = "Reach Distance"; base.Description = "Extends local pickup, grab, reach, and interaction distance fields where the game exposes them."; base.Min = 2f; base.Max = 50f; base.Value = ReachDistanceRuntime.Distance; base.Step = 1f; base.Decimals = 0; base.Unit = "m"; } protected override void OnEnable() { ReachDistanceRuntime.Enabled = true; ReachDistanceRuntime.Distance = base.Value; ReachDistanceRuntime.Apply(force: true); } protected override void OnDisable() { ReachDistanceRuntime.Enabled = false; ReachDistanceRuntime.Restore(); } protected override void OnValueChanged(float newValue) { ReachDistanceRuntime.Distance = Mathf.Clamp(newValue, base.Min, base.Max); if (base.Enabled) { ReachDistanceRuntime.Apply(force: true); } } public override void OnTick() { ReachDistanceRuntime.Apply(force: false); } } internal static class ReachDistanceRuntime { private readonly struct MemberKey : IEquatable { public object Target { get; } public MemberInfo Member { get; } public MemberKey(object target, MemberInfo member) { Target = target; Member = member; } public bool Equals(MemberKey other) { if (Target == other.Target) { return object.Equals(Member, other.Member); } return false; } public override bool Equals(object obj) { if (obj is MemberKey other) { return Equals(other); } return false; } public override int GetHashCode() { int num = ((Target != null) ? Target.GetHashCode() : 0); int num2 = ((Member != null) ? Member.GetHashCode() : 0); return (num * 397) ^ num2; } } private const float ScanInterval = 0.75f; private const BindingFlags Flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; private static readonly Dictionary Originals = new Dictionary(); private static readonly HashSet SupportedTypes = new HashSet(); private static float _nextScanAt; public static bool Enabled; public static float Distance = 12f; public static void Apply(bool force) { //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) if (!Enabled || (!force && Time.unscaledTime < _nextScanAt)) { return; } _nextScanAt = Time.unscaledTime + 0.75f; Character localCharacter = Character.localCharacter; if (!Object.op_Implicit((Object)(object)localCharacter)) { return; } ApplyKnownGameReachFields(localCharacter); ApplyToObject(localCharacter); ApplyToObject(localCharacter.data); ApplyToObject(localCharacter.input); ApplyToObject(localCharacter.player); Component[] componentsInChildren = ((Component)localCharacter).GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { ApplyToObject(componentsInChildren[i]); } Camera main = Camera.main; if (Object.op_Implicit((Object)(object)main)) { componentsInChildren = ((Component)main).GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { ApplyToObject(componentsInChildren[i]); } } Item[] array = Object.FindObjectsByType((FindObjectsSortMode)0); foreach (Item val in array) { if (Object.op_Implicit((Object)(object)val)) { Vector3 val2 = ((Component)val).transform.position - ((Component)localCharacter).transform.position; if (!(((Vector3)(ref val2)).sqrMagnitude > 225f)) { ApplyToObject(val); } } } } private static void ApplyKnownGameReachFields(Character local) { ApplyNamedMember(Interaction.instance, "distance"); ApplyNamedMember(local.refs?.grabbing, "kickRange"); ApplyNamedMember(local.refs?.grabbing, "kickDistance"); } public static void Restore() { foreach (KeyValuePair original in Originals) { try { if (original.Key.Target == null || original.Key.Member == null) { continue; } MemberInfo member = original.Key.Member; if (!(member is FieldInfo fieldInfo)) { if (member is PropertyInfo propertyInfo && propertyInfo.CanWrite) { propertyInfo.SetValue(original.Key.Target, original.Value, null); } } else { fieldInfo.SetValue(original.Key.Target, original.Value); } } catch { } } Originals.Clear(); SupportedTypes.Clear(); } private static void ApplyToObject(object target) { if (target == null) { return; } Type type = target.GetType(); if (!IsPotentialReachType(type)) { return; } FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo fieldInfo in fields) { if (IsPotentialReachMember(fieldInfo.Name, fieldInfo.FieldType)) { ApplyMember(target, fieldInfo, fieldInfo.FieldType); } } PropertyInfo[] properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (PropertyInfo propertyInfo in properties) { if (propertyInfo.CanRead && propertyInfo.CanWrite && propertyInfo.GetIndexParameters().Length == 0 && IsPotentialReachMember(propertyInfo.Name, propertyInfo.PropertyType)) { ApplyMember(target, propertyInfo, propertyInfo.PropertyType); } } } private static void ApplyNamedMember(object target, string name) { if (target == null || string.IsNullOrEmpty(name)) { return; } Type type = target.GetType(); FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null && (field.FieldType == typeof(float) || field.FieldType == typeof(int))) { ApplyMember(target, field, field.FieldType); return; } PropertyInfo property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (property != null && property.CanRead && property.CanWrite && property.GetIndexParameters().Length == 0 && (property.PropertyType == typeof(float) || property.PropertyType == typeof(int))) { ApplyMember(target, property, property.PropertyType); } } private static bool IsPotentialReachType(Type type) { if (type == null) { return false; } if (SupportedTypes.Contains(type)) { return true; } if (ContainsAny(type.Name, "Character", "Interact", "Interaction", "Pickup", "Item", "Grab", "Reach", "Carry", "Climb", "Player", "Camera")) { SupportedTypes.Add(type); return true; } return false; } private static bool IsPotentialReachMember(string name, Type valueType) { if (valueType != typeof(float) && valueType != typeof(int)) { return false; } if (ContainsAny(name, "reach", "interact", "interaction", "pickup", "pickUp", "grab", "carry", "climb")) { return ContainsAny(name, "distance", "range", "radius", "length", "dist"); } return false; } private static void ApplyMember(object target, MemberInfo member, Type valueType) { try { object obj = ((member is FieldInfo fieldInfo) ? fieldInfo.GetValue(target) : ((!(member is PropertyInfo propertyInfo)) ? null : propertyInfo.GetValue(target, null))); object obj2 = obj; if (obj2 == null) { return; } float num = Convert.ToSingle(obj2, CultureInfo.InvariantCulture); MemberKey key = new MemberKey(target, member); object value; bool num2 = Originals.TryGetValue(key, out value); float num3 = Distance; if (num2) { float num4 = Convert.ToSingle(value, CultureInfo.InvariantCulture); if (num4 <= 0f) { return; } num3 = Mathf.Max(num4, Distance); } else { if (num <= 0f || num >= Distance) { return; } Originals[key] = obj2; } if (Mathf.Approximately(num, num3)) { return; } object value2 = ((valueType == typeof(int)) ? ((float)Mathf.RoundToInt(num3)) : num3); if (!(member is FieldInfo fieldInfo2)) { if (member is PropertyInfo propertyInfo2) { propertyInfo2.SetValue(target, value2, null); } } else { fieldInfo2.SetValue(target, value2); } } catch { } } private static bool ContainsAny(string value, params string[] needles) { if (!string.IsNullOrEmpty(value)) { return needles.Any((string t) => value.IndexOf(t, StringComparison.OrdinalIgnoreCase) >= 0); } return false; } } public class SpeedMultiplier : NumberBoolFeature { private Character _lastCharacter; private float? _baseMovementModifier; private float? _lastAppliedMovementModifier; public SpeedMultiplier() { base.Name = "Speed Multiplier"; base.Description = "Toggle custom movement speed and adjust the multiplier."; base.Min = 0.2f; base.Max = 10f; base.Value = 1f; base.Step = 0.1f; base.Decimals = 1; base.Unit = "x"; } protected override void OnEnable() { OnTick(); } protected override void OnDisable() { RestoreOriginal(); _lastCharacter = null; _baseMovementModifier = null; _lastAppliedMovementModifier = null; } public override void OnTick() { Character localCharacter = Character.localCharacter; CharacterMovement val = ((!Object.op_Implicit((Object)(object)localCharacter)) ? null : localCharacter.refs?.movement); if (!Object.op_Implicit((Object)(object)localCharacter) || !Object.op_Implicit((Object)(object)val)) { RestoreOriginal(); _lastCharacter = null; _baseMovementModifier = null; _lastAppliedMovementModifier = null; return; } if (localCharacter != _lastCharacter) { RestoreOriginal(); _lastCharacter = localCharacter; _baseMovementModifier = null; _lastAppliedMovementModifier = null; } float movementModifier = val.movementModifier; if (!_baseMovementModifier.HasValue || !_lastAppliedMovementModifier.HasValue || !Mathf.Approximately(movementModifier, _lastAppliedMovementModifier.Value)) { _baseMovementModifier = movementModifier; } _lastAppliedMovementModifier = (val.movementModifier = _baseMovementModifier.Value * base.Value); } protected override void OnValueChanged(float newValue) { if (base.Enabled) { OnTick(); } } private void RestoreOriginal() { if (Object.op_Implicit((Object)(object)_lastCharacter) && _baseMovementModifier.HasValue) { CharacterMovement val = _lastCharacter.refs?.movement; if (Object.op_Implicit((Object)(object)val)) { val.movementModifier = _baseMovementModifier.Value; _lastAppliedMovementModifier = null; } } } } public class SprintMultiplier : NumberBoolFeature { private Character _lastCharacter; private float? _baseSprintModifier; private float? _lastAppliedSprintModifier; public SprintMultiplier() { base.Name = "Sprint Multiplier"; base.Description = "Toggle custom sprint speed and adjust the multiplier."; base.Min = 0.2f; base.Max = 10f; base.Value = 1f; base.Step = 0.1f; base.Decimals = 1; base.Unit = "x"; } protected override void OnEnable() { OnTick(); } protected override void OnDisable() { RestoreOriginal(); _lastCharacter = null; _baseSprintModifier = null; _lastAppliedSprintModifier = null; } public override void OnTick() { Character localCharacter = Character.localCharacter; CharacterMovement val = ((!Object.op_Implicit((Object)(object)localCharacter)) ? null : localCharacter.refs?.movement); if (!Object.op_Implicit((Object)(object)localCharacter) || !Object.op_Implicit((Object)(object)val)) { RestoreOriginal(); _lastCharacter = null; _baseSprintModifier = null; _lastAppliedSprintModifier = null; return; } if (localCharacter != _lastCharacter) { RestoreOriginal(); _lastCharacter = localCharacter; _baseSprintModifier = null; _lastAppliedSprintModifier = null; } float sprintMultiplier = val.sprintMultiplier; if (!_baseSprintModifier.HasValue || !_lastAppliedSprintModifier.HasValue || !Mathf.Approximately(sprintMultiplier, _lastAppliedSprintModifier.Value)) { _baseSprintModifier = sprintMultiplier; } _lastAppliedSprintModifier = (val.sprintMultiplier = _baseSprintModifier.Value * base.Value); } protected override void OnValueChanged(float newValue) { if (base.Enabled) { OnTick(); } } private void RestoreOriginal() { if (Object.op_Implicit((Object)(object)_lastCharacter) && _baseSprintModifier.HasValue) { CharacterMovement val = _lastCharacter.refs?.movement; if (Object.op_Implicit((Object)(object)val)) { val.sprintMultiplier = _baseSprintModifier.Value; _lastAppliedSprintModifier = null; } } } } [HarmonyPatch(typeof(BackpackWheel), "Update")] internal static class EasyBackpackWheelPatch { private static void Prefix(out QualityOfLifeRuntime.BackpackInputState __state) { __state = QualityOfLifeRuntime.HoldEasyBackpackOpen(); } private static void Postfix(QualityOfLifeRuntime.BackpackInputState __state) { QualityOfLifeRuntime.RestoreEasyBackpackInput(__state); } } [HarmonyPatch(/*Could not decode attribute arguments.*/)] internal static class PeakKickDropModePatch { private static bool Prefix(Character ___character, ref bool __result) { if (!QualityOfLifeRuntime.PeakKick) { return true; } return !QualityOfLifeRuntime.TryApplyPeakKickDropInput(___character, out __result); } } internal static class QualityOfLifeRuntime { public readonly struct BackpackInputState { public readonly bool Changed; public readonly bool InteractIsPressed; public BackpackInputState(bool changed, bool interactIsPressed) { Changed = changed; InteractIsPressed = interactIsPressed; } } public static bool EasyBackpack; public static bool PeakKick; private static bool _isAccessingBackpack; private static bool _isAccessingCarriedBackpack; public static bool IsAccessingBackpack => _isAccessingBackpack; public static void TickEasyBackpack() { if (!EasyBackpack) { ResetBackpackAccess(); return; } Character localCharacter = Character.localCharacter; if (!Application.isFocused || !Object.op_Implicit((Object)(object)localCharacter)) { ResetBackpackAccess(); return; } if (_isAccessingCarriedBackpack) { if (!Object.op_Implicit((Object)(object)localCharacter.data) || !Object.op_Implicit((Object)(object)localCharacter.data.carriedPlayer)) { ResetBackpackAccess(); return; } } else if (!CanOpenOwnBackpack(localCharacter)) { ResetBackpackAccess(); return; } if (Input.GetKeyUp((KeyCode)98)) { ResetBackpackAccess(); } else if (Input.GetKeyDown((KeyCode)98)) { if (TryOpenBackpack(localCharacter)) { _isAccessingBackpack = true; _isAccessingCarriedBackpack = false; } else if (TryOpenBackpack(Object.op_Implicit((Object)(object)localCharacter.data) ? localCharacter.data.carriedPlayer : null)) { _isAccessingBackpack = true; _isAccessingCarriedBackpack = true; } } } public static void ResetBackpackAccess() { _isAccessingBackpack = false; _isAccessingCarriedBackpack = false; } public static BackpackInputState HoldEasyBackpackOpen() { if (!EasyBackpack || !_isAccessingBackpack) { return default(BackpackInputState); } Character localCharacter = Character.localCharacter; if (!Object.op_Implicit((Object)(object)localCharacter) || (Object)(object)localCharacter.data == (Object)null || (Object)(object)localCharacter.input == (Object)null) { return default(BackpackInputState); } BackpackInputState result = new BackpackInputState(changed: true, localCharacter.input.interactIsPressed); localCharacter.input.interactIsPressed = true; localCharacter.data.usingBackpackWheel = true; return result; } public static void RestoreEasyBackpackInput(BackpackInputState state) { if (state.Changed) { Character localCharacter = Character.localCharacter; if ((Object)(object)localCharacter?.input != (Object)null) { localCharacter.input.interactIsPressed = state.InteractIsPressed; } } } public static bool TryApplyPeakKickDropInput(Character character, out bool isKickMode) { isKickMode = false; if (!PeakKick || !Object.op_Implicit((Object)(object)character) || (Object)(object)character.data == (Object)null || (Object)(object)character.input == (Object)null) { return false; } bool flag = RunSettings.GetValue((SETTINGTYPE)10200, false) == 1; bool flag2 = (Object)(object)character.data.currentItem == (Object)null; if (flag2 && character.input.dropWasPressed) { character.data.sincePressReach = 0f; } isKickMode = flag || character.data.isKicking || (flag2 && character.input.dropIsPressed); return true; } private static bool CanOpenOwnBackpack(Character character) { if (!Object.op_Implicit((Object)(object)character) || !Object.op_Implicit((Object)(object)character.data)) { return false; } if (character.data.passedOut || character.data.dead) { return false; } return !(character.data.currentItem is Backpack); } private static bool TryOpenBackpack(Character character) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)character) || !Object.op_Implicit((Object)(object)character.player)) { return false; } BackpackSlot backpackSlot = character.player.backpackSlot; if (backpackSlot == null || !backpackSlot.hasBackpack) { return false; } if (!Object.op_Implicit((Object)(object)GUIManager.instance)) { return false; } GUIManager.instance.OpenBackpackWheel(BackpackReference.GetFromEquippedBackpack(character)); return true; } } internal static class SelfRuntimeSettings { public static bool ModderProtections; public static bool InfiniteItemCharge; public static bool InfiniteRope; public static bool InfiniteRescueHookRange; public static bool InstantItemUse; public static bool NoAfflictions; public static bool NoRagdoll; public static bool NoSlip; public static bool NoPassout; public static bool NoDeath; public static bool NoScreenShake; } } namespace CubeX.Features.Search { public class MenuSearchDirectory : Feature, IMenuRowProvider { private readonly struct ScoredResult { public int Score { get; } public MenuSearchResult Result { get; } public ScoredResult(int score, MenuSearchResult result) { Score = score; Result = result; } } private const int MaxResults = 35; public MenuSearchDirectory() { base.Name = "Search Directory"; base.Description = "Builds menu search result rows."; } public IEnumerable GetRows(string category) { if (!string.Equals(category, "Search", StringComparison.Ordinal)) { return Array.Empty(); } string text = (MenuSearchState.Query ?? string.Empty).Trim(); if (text.Length == 0) { return new <>z__ReadOnlySingleElementList(new InfoFeature("Results", "Type above", "Search finds pages, submenus, and menu options.")); } List list = BuildResults(text); if (list.Count == 0) { return new <>z__ReadOnlySingleElementList(new InfoFeature("Results", "0", "No menu entries matched the search text.")); } return list.Cast().ToList(); } private static List BuildResults(string query) { //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) FeatureManager current = FeatureManager.Current; if (current == null) { return new List(); } string needle = query.ToLowerInvariant(); List list = new List(); foreach (string category in current.Categories) { if (!string.Equals(category, "Search", StringComparison.Ordinal)) { string label = "Page > " + category; AddIfMatch(list, needle, label, category, () => new MenuSearchResult(label, "Open the " + category + " page.", category, null, null, null, "PAGE", new Color(0.18f, 0.36f, 0.88f, 1f))); } } foreach (Feature feature in current.All) { if (feature == null || string.Equals(feature.Category, "Search", StringComparison.Ordinal) || feature is SeparatorFeature || feature is IMenuRowProvider || feature is IMenuSidePanelProvider) { continue; } string kind = GetKind(feature); Color tagColor = GetKindColor(kind); string path = FormatPath(feature.Category) + " > " + feature.Name; string searchable = path + " " + feature.Description + " " + kind; SubmenuFeature submenu = feature as SubmenuFeature; if (submenu != null) { AddIfMatch(list, needle, searchable, path, () => new MenuSearchResult(path, submenu.Description, feature.Category, submenu.ChildCategory, null, submenu.Name, kind, tagColor)); } else { AddIfMatch(list, needle, searchable, path, () => new MenuSearchResult(path, feature.Description, feature.Category, null, feature.GetType(), feature.Name, kind, tagColor)); } } return (from result in list.OrderBy((ScoredResult result) => result.Score).ThenBy((ScoredResult result) => result.Result.Name, StringComparer.OrdinalIgnoreCase).Take(35) select result.Result).ToList(); } private static void AddIfMatch(List results, string needle, string searchable, string label, Func build) { if (results != null && build != null && !string.IsNullOrEmpty(needle) && (searchable ?? string.Empty).ToLowerInvariant().Contains(needle)) { string text = (label ?? string.Empty).ToLowerInvariant(); int score = ((!text.Equals(needle, StringComparison.Ordinal)) ? (text.EndsWith("> " + needle, StringComparison.Ordinal) ? 1 : (text.Contains("> " + needle, StringComparison.Ordinal) ? 2 : (text.StartsWith(needle, StringComparison.Ordinal) ? 3 : 4))) : 0); results.Add(new ScoredResult(score, build())); } } private static string FormatPath(string category) { if (!string.IsNullOrEmpty(category)) { return category.Replace("/", " > "); } return "Home"; } private static string GetKind(Feature feature) { if (feature is SubmenuFeature) { return "MENU"; } if (feature is ButtonFeature) { return "ACTION"; } if (feature is NumberFeature) { return "VALUE"; } if (feature is TextFeature) { return "TEXT"; } if (feature is ColorFeature) { return "COLOR"; } return "TOGGLE"; } private static Color GetKindColor(string kind) { //IL_006d: 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_0121: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) return (Color)(kind switch { "PAGE" => new Color(0.18f, 0.36f, 0.88f, 1f), "MENU" => new Color(0.56f, 0.36f, 0.78f, 1f), "ACTION" => new Color(0.18f, 0.58f, 0.48f, 1f), "VALUE" => new Color(0.78f, 0.42f, 0.08f, 1f), "TEXT" => new Color(0.84f, 0.2f, 0.42f, 1f), "COLOR" => new Color(0.063f, 0.808f, 0.851f, 1f), _ => new Color(0.72f, 0.16f, 0.16f, 1f), }); } } internal sealed class MenuSearchResult : ButtonFeature, IMenuNavigationTarget, IMenuTagProvider { public string TargetCategory { get; } public string TargetChildCategory { get; } public Type TargetFeatureType { get; } public string TargetRowName { get; } public List Tags { get; } public MenuSearchResult(string name, string description, string targetCategory, string targetChildCategory, Type targetFeatureType, string targetRowName, string kind, Color tagColor) { //IL_0057: Unknown result type (might be due to invalid IL or missing references) base.Name = name; base.Description = (string.IsNullOrEmpty(description) ? "Open this menu entry." : description); base.ButtonLabel = "Go"; TargetCategory = targetCategory; TargetChildCategory = targetChildCategory; TargetFeatureType = targetFeatureType; TargetRowName = targetRowName; Tags = new List(1) { new MenuTag(kind, tagColor) }; } public override void Execute() { } } public class MenuSearchText : TextFeature { public override bool RefreshRowsWhileEditing => true; public MenuSearchText() { base.Name = "Search"; base.Description = "Type part of an option, submenu, or page name."; base.EmptyDisplayText = "Type to search"; base.MaxLength = 80; } protected override void OnTextChanged(string newValue) { MenuSearchState.Query = newValue ?? string.Empty; } } internal static class MenuSearchState { public const string Category = "Search"; public static string Query = string.Empty; } } namespace CubeX.Features.Player { public class InviteFriendToLobby : ButtonFeature { public InviteFriendToLobby() { base.Name = "Invite Friend"; base.Description = "Sends the selected Steam friend an invite to your current lobby."; base.ButtonLabel = "Invite"; } public override void Execute() { if (SteamPlayerActions.InviteToCurrentLobby(FriendsDirectory.SelectedFriend.SteamId)) { NotificationSystem.Push("Steam Invite", "Invite sent.", NotificationKind.Success); } else { NotificationSystem.Push("Steam Invite Failed", "No active Steam lobby or Steam rejected the invite.", NotificationKind.Warning); } } } public class OpenFriendSteamProfile : ButtonFeature { public OpenFriendSteamProfile() { base.Name = "Open Steam Profile"; base.Description = "Opens the selected Steam friend's profile."; base.ButtonLabel = "Open"; } public override void Execute() { SteamPlayerActions.OpenProfile(FriendsDirectory.SelectedFriend.SteamId); } } public class CopyFriendSteamId : ButtonFeature { public CopyFriendSteamId() { base.Name = "Copy Steam ID"; base.Description = "Copies the selected Steam friend's Steam ID."; base.ButtonLabel = "Copy"; } public override void Execute() { GUIUtility.systemCopyBuffer = FriendsDirectory.SelectedFriend.SteamId.ToString(CultureInfo.InvariantCulture); NotificationSystem.Push("Steam ID Copied", GUIUtility.systemCopyBuffer, NotificationKind.Success); } } public class JoinFriendGame : ButtonFeature { private readonly ulong _lobbyId; public JoinFriendGame(ulong lobbyId) { _lobbyId = lobbyId; base.Name = "Join Friend Game"; base.Description = "Joins this friend's current PEAK Steam lobby."; base.ButtonLabel = "Join"; } public override void Execute() { if (SteamPlayerActions.JoinLobby(_lobbyId)) { NotificationSystem.Push("Steam Join", "Join request sent.", NotificationKind.Success); } else { NotificationSystem.Push("Steam Join Failed", "Friend lobby join was not available.", NotificationKind.Warning); } } } public class FriendsDirectory : Feature, IMenuRowProvider, IMenuSidePanelProvider { private const string FriendsCategory = "Network/Friends"; private const string FriendCategoryPrefix = "Network/Friends/"; internal static SteamPlayerActions.SteamFriendInfo SelectedFriend { get; private set; } public FriendsDirectory() { base.Name = "Friends Directory"; base.Description = "Builds Steam friend rows for invites and joinable PEAK lobbies."; } public IEnumerable GetRows(string category) { if (category == "Network/Friends") { return BuildFriendRows(); } if (category != null && category.StartsWith("Network/Friends/", StringComparison.Ordinal)) { return BuildFriendDetailRows(category.Substring("Network/Friends/".Length)); } return Array.Empty(); } public bool TryGetSidePanel(string category, object selectedRow, out MenuSidePanel panel) { panel = null; if (!ulong.TryParse(GetPanelFriendId(category, selectedRow), NumberStyles.Integer, CultureInfo.InvariantCulture, out var result)) { return false; } if (!TryFindFriend(result, out var friend)) { return false; } SelectedFriend = friend; panel = new MenuSidePanel("STEAM FRIEND", friend.Name, BuildInfoRows(friend), (Texture)(object)PlayerDirectory.LoadSteamAvatarFromCacheOrSteam(friend.SteamId), BuildTags(friend)); return true; } private static IEnumerable BuildFriendRows() { List list = (from friend in (from friend in SteamPlayerActions.GetFriends() orderby friend.Presence.IsOnline descending, friend.Presence.IsJoinable descending select friend).ThenBy((SteamPlayerActions.SteamFriendInfo friend) => friend.Name, StringComparer.OrdinalIgnoreCase) select new SubmenuFeature(friend.Name, "Network/Friends/" + friend.SteamId.ToString(CultureInfo.InvariantCulture), "Open Steam friend actions for " + friend.Name + ".", BuildTags(friend))).Cast().ToList(); if (list.Count == 0) { list.Add(new InfoFeature("Friends", "None", "Steam friends were not available from the Steamworks API.")); } return list; } private static IEnumerable BuildFriendDetailRows(string id) { if (!ulong.TryParse(id, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result) || !TryFindFriend(result, out var friend)) { return new <>z__ReadOnlySingleElementList(new InfoFeature("Friend", "Not found", "This Steam friend is no longer available.")); } SelectedFriend = friend; List list = new List { new OpenFriendSteamProfile(), new InviteFriendToLobby() }; if (friend.Presence.IsJoinable) { list.Add(new JoinFriendGame(friend.Presence.LobbyId)); } list.Add(new CopyFriendSteamId()); return list; } internal static List BuildTags(SteamPlayerActions.SteamFriendInfo friend) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) List list = new List { new MenuTag("FRIEND", new Color(0.22f, 0.5f, 0.9f, 1f)) }; if (friend.Presence.IsJoinable) { list.Add(new MenuTag("JOINABLE", new Color(0.24f, 0.74f, 0.46f, 1f))); } else if (friend.Presence.IsInPeak) { list.Add(new MenuTag("PEAK", new Color(0.22f, 0.62f, 0.88f, 1f))); } list.Add(friend.Presence.IsOnline ? new MenuTag("ONLINE", new Color(0.18f, 0.62f, 0.86f, 1f)) : new MenuTag("OFFLINE", new Color(0.36f, 0.38f, 0.42f, 1f))); return list; } private static List BuildInfoRows(SteamPlayerActions.SteamFriendInfo friend) { return new List(5) { new InfoFeature("Steam Status", (string.IsNullOrWhiteSpace(friend.Presence.PersonaState) || friend.Presence.PersonaState == "-") ? "Unknown" : friend.Presence.PersonaState), new InfoFeature("Game", friend.Presence.GameText), new InfoFeature("Joinable", friend.Presence.IsJoinable ? "Yes" : "No"), new InfoFeature("Lobby", friend.Presence.IsJoinable ? friend.Presence.LobbyId.ToString(CultureInfo.InvariantCulture) : "-"), new InfoFeature("Steam", friend.SteamId.ToString(CultureInfo.InvariantCulture)) }; } private static bool TryFindFriend(ulong steamId, out SteamPlayerActions.SteamFriendInfo friend) { foreach (SteamPlayerActions.SteamFriendInfo friend2 in SteamPlayerActions.GetFriends()) { if (friend2.SteamId == steamId) { friend = friend2; return true; } } friend = default(SteamPlayerActions.SteamFriendInfo); return false; } private static string GetPanelFriendId(string category, object selectedRow) { if (selectedRow is SubmenuFeature submenuFeature && submenuFeature.ChildCategory != null && submenuFeature.ChildCategory.StartsWith("Network/Friends/", StringComparison.Ordinal)) { return submenuFeature.ChildCategory.Substring("Network/Friends/".Length); } if (category != null && category.StartsWith("Network/Friends/", StringComparison.Ordinal)) { return category.Substring("Network/Friends/".Length); } return null; } } public class AddRecentPlayerToBlacklist : ButtonFeature { public AddRecentPlayerToBlacklist() { base.Name = "Add To Blacklist"; base.Description = "Adds the selected recent player to the persistent blacklist."; base.ButtonLabel = "Add"; } public override void Execute() { RecentPlayerRecord selectedRecentPlayer = RecentPlayersDirectory.SelectedRecentPlayer; if (selectedRecentPlayer != null && PlayerBlacklistStore.Add(selectedRecentPlayer)) { NotificationSystem.Push("Added To Blacklist", selectedRecentPlayer.DisplayName, NotificationKind.Success); PlayerBlacklistStore.EnforceCurrentRoomBlacklist(); } } } public class AddSelectedPlayerToBlacklist : ButtonFeature { public AddSelectedPlayerToBlacklist() { base.Name = "Add To Blacklist"; base.Description = "Adds the selected player to the persistent blacklist."; base.ButtonLabel = "Add"; } public override void Execute() { PlayerDirectory.SelectedPlayerInfo selectedPlayer = PlayerDirectory.SelectedPlayer; if (selectedPlayer != null) { if (selectedPlayer.IsLocal) { NotificationSystem.Push("Blacklist", "You cannot blacklist yourself.", NotificationKind.Warning); } else if (PlayerBlacklistStore.Add(PlayerBlacklistStore.BuildRecord(selectedPlayer))) { NotificationSystem.Push("Added To Blacklist", selectedPlayer.DisplayName, NotificationKind.Success); PlayerBlacklistStore.EnforceCurrentRoomBlacklist(); } } } } public class ClearPlayerBlacklist : ButtonFeature { public ClearPlayerBlacklist() { base.Name = "Clear Blacklist"; base.Description = "Removes every saved player from blacklisted_players.json."; base.ButtonLabel = "Clear"; } public override void Execute() { PlayerBlacklistStore.Clear(); PlayerBlacklistDirectory.SelectedBlacklistedPlayer = null; NotificationSystem.Push("Blacklist Cleared", string.Empty, NotificationKind.Success); } } public class CopyBlacklistedPlayerSteamId : ButtonFeature { public CopyBlacklistedPlayerSteamId() { base.Name = "Copy Steam ID"; base.Description = "Copies this blacklisted player's Steam ID to the clipboard."; base.ButtonLabel = "Copy"; } public override void Execute() { RecentPlayerRecord selectedBlacklistedPlayer = PlayerBlacklistDirectory.SelectedBlacklistedPlayer; if (selectedBlacklistedPlayer == null || selectedBlacklistedPlayer.SteamId == 0L) { NotificationSystem.Push("Blacklist", "No Steam ID saved for this player.", NotificationKind.Warning); return; } GUIUtility.systemCopyBuffer = selectedBlacklistedPlayer.SteamId.ToString(CultureInfo.InvariantCulture); NotificationSystem.Push("Steam ID Copied", selectedBlacklistedPlayer.DisplayName, NotificationKind.Success); } } public class OpenBlacklistedPlayerSteamProfile : ButtonFeature { public OpenBlacklistedPlayerSteamProfile() { base.Name = "Open Steam Profile"; base.Description = "Opens this blacklisted player's Steam profile."; base.ButtonLabel = "Open"; } public override void Execute() { RecentPlayerRecord selectedBlacklistedPlayer = PlayerBlacklistDirectory.SelectedBlacklistedPlayer; if (selectedBlacklistedPlayer == null || selectedBlacklistedPlayer.SteamId == 0L) { NotificationSystem.Push("Blacklist", "No Steam ID saved for this player.", NotificationKind.Warning); } else if (!SteamPlayerActions.OpenProfile(selectedBlacklistedPlayer.SteamId)) { NotificationSystem.Push("Steam Profile", "Steam overlay/profile URL was not available.", NotificationKind.Warning); } } } public class PlayerBlacklistDirectory : Feature, IMenuRowProvider, IMenuSidePanelProvider { private const string BlacklistCategory = "Network/Blacklist"; private const string BlacklistCategoryPrefix = "Network/Blacklist/"; public static RecentPlayerRecord SelectedBlacklistedPlayer { get; internal set; } internal static RecentPlayersSortMode SortMode { get; set; } = RecentPlayersSortMode.Name; public PlayerBlacklistDirectory() { base.Name = "Player Blacklist Directory"; base.Description = "Builds saved blacklist rows for the Network menu."; } public IEnumerable GetRows(string category) { if (category == "Network/Blacklist") { return BuildBlacklistRows(); } if (category != null && category.StartsWith("Network/Blacklist/", StringComparison.Ordinal)) { return BuildBlacklistDetailRows(category.Substring("Network/Blacklist/".Length)); } return Array.Empty(); } public bool TryGetSidePanel(string category, object selectedRow, out MenuSidePanel panel) { panel = null; string panelBlacklistedPlayerId = GetPanelBlacklistedPlayerId(category, selectedRow); if (string.IsNullOrEmpty(panelBlacklistedPlayerId)) { return false; } RecentPlayerRecord recentPlayerRecord = PlayerBlacklistStore.Find(panelBlacklistedPlayerId); if (recentPlayerRecord == null) { return false; } SelectedBlacklistedPlayer = recentPlayerRecord; panel = new MenuSidePanel("BLACKLISTED PLAYER", recentPlayerRecord.DisplayName, BuildInfoRows(recentPlayerRecord), (Texture)(object)PlayerDirectory.LoadSteamAvatarFromCacheOrSteam(recentPlayerRecord.SteamId), BuildTags(recentPlayerRecord)); return true; } private static IEnumerable BuildBlacklistRows() { IReadOnlyList readOnlyList = SortRecords(PlayerBlacklistStore.GetAll()); List list = new List(); if (readOnlyList.Count > 0) { list.Add(new ClearPlayerBlacklist()); list.Add(new SeparatorFeature()); } foreach (RecentPlayerRecord item in readOnlyList) { list.Add(new SubmenuFeature(item.DisplayName, "Network/Blacklist/" + item.Id, "Open saved blacklist details for " + item.DisplayName + ".", BuildTags(item))); } if (readOnlyList.Count == 0) { list.Add(new InfoFeature("Blacklist", "None", "Blacklisted players will be kicked when you are master client.")); } return list; } private static IReadOnlyList SortRecords(IReadOnlyList records) { if (records == null || records.Count == 0) { return Array.Empty(); } return (SortMode switch { RecentPlayersSortMode.LastSeen => records.OrderByDescending((RecentPlayerRecord record) => ParseUtc(record.LastSeenUtc)).ThenBy((RecentPlayerRecord record) => record.DisplayName, StringComparer.OrdinalIgnoreCase), RecentPlayersSortMode.FirstSeen => records.OrderByDescending((RecentPlayerRecord record) => ParseUtc(record.FirstSeenUtc)).ThenBy((RecentPlayerRecord record) => record.DisplayName, StringComparer.OrdinalIgnoreCase), RecentPlayersSortMode.SeenCount => records.OrderByDescending((RecentPlayerRecord record) => record.TimesSeen).ThenBy((RecentPlayerRecord record) => record.DisplayName, StringComparer.OrdinalIgnoreCase), RecentPlayersSortMode.Region => records.OrderBy((RecentPlayerRecord record) => PlayerRegionLabels.FormatTag(record.Region), StringComparer.OrdinalIgnoreCase).ThenBy((RecentPlayerRecord record) => record.DisplayName, StringComparer.OrdinalIgnoreCase), RecentPlayersSortMode.Online => records.OrderByDescending(IsOnline).ThenByDescending(IsJoinable).ThenBy((RecentPlayerRecord record) => record.DisplayName, StringComparer.OrdinalIgnoreCase), _ => records.OrderBy((RecentPlayerRecord record) => record.DisplayName, StringComparer.OrdinalIgnoreCase).ThenByDescending((RecentPlayerRecord record) => ParseUtc(record.LastSeenUtc)), }).ToList(); } private static bool IsOnline(RecentPlayerRecord record) { return SteamPlayerActions.GetFriendPresence(record?.SteamId ?? 0).IsOnline; } private static bool IsJoinable(RecentPlayerRecord record) { return SteamPlayerActions.GetFriendPresence(record?.SteamId ?? 0).IsJoinable; } private static DateTime ParseUtc(string value) { if (!DateTime.TryParse(value, CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal, out var result)) { return DateTime.MinValue; } return result; } private static IEnumerable BuildBlacklistDetailRows(string id) { RecentPlayerRecord recentPlayerRecord = PlayerBlacklistStore.Find(id); if (recentPlayerRecord == null) { SelectedBlacklistedPlayer = null; return new <>z__ReadOnlySingleElementList(new InfoFeature("Player", "Not found", "This player is no longer blacklisted.")); } SelectedBlacklistedPlayer = recentPlayerRecord; return new <>z__ReadOnlyArray(new object[3] { new RemoveBlacklistedPlayer(), new OpenBlacklistedPlayerSteamProfile(), new CopyBlacklistedPlayerSteamId() }); } private static List BuildInfoRows(RecentPlayerRecord record) { List list = RecentPlayersDirectory.BuildInfoRows(record); list.Insert(0, new InfoFeature("Blacklist", "Blocked", "This player is denied re-entry while you are master client.")); return list; } private static List BuildTags(RecentPlayerRecord record) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) List list = new List(); list.Add(new MenuTag("BLACKLIST", new Color(0.82f, 0.18f, 0.16f, 1f))); list.AddRange(RecentPlayersDirectory.BuildTags(record)); return list; } private static string GetPanelBlacklistedPlayerId(string category, object selectedRow) { if (selectedRow is SubmenuFeature submenuFeature && submenuFeature.ChildCategory != null && submenuFeature.ChildCategory.StartsWith("Network/Blacklist/", StringComparison.Ordinal)) { return submenuFeature.ChildCategory.Substring("Network/Blacklist/".Length); } if (category != null && category.StartsWith("Network/Blacklist/", StringComparison.Ordinal)) { return category.Substring("Network/Blacklist/".Length); } return null; } } internal sealed class PlayerBlacklistFile { public int version; public List players; } public class PlayerBlacklistSortBy : NumberFeature { private static readonly string[] SortNames = new string[6] { "Name", "Last Seen", "First Seen", "Seen Count", "Region", "Online" }; public override bool AllowTextInput => false; public PlayerBlacklistSortBy() { base.Name = "Sort By"; base.Description = "Changes the order of saved blacklisted players."; base.Min = 0f; base.Max = SortNames.Length - 1; base.Value = ToValue(PlayerBlacklistDirectory.SortMode); base.Step = 1f; base.Decimals = 0; } public override string GetDisplayValue() { int num = Mathf.Clamp(Mathf.RoundToInt(base.Value), 0, SortNames.Length - 1); return SortNames[num]; } protected override void OnValueChanged(float newValue) { PlayerBlacklistDirectory.SortMode = FromValue(Mathf.Clamp(Mathf.RoundToInt(newValue), 0, SortNames.Length - 1)); } private static float ToValue(RecentPlayersSortMode mode) { return mode switch { RecentPlayersSortMode.LastSeen => 1f, RecentPlayersSortMode.FirstSeen => 2f, RecentPlayersSortMode.SeenCount => 3f, RecentPlayersSortMode.Region => 4f, RecentPlayersSortMode.Online => 5f, _ => 0f, }; } private static RecentPlayersSortMode FromValue(int index) { return index switch { 1 => RecentPlayersSortMode.LastSeen, 2 => RecentPlayersSortMode.FirstSeen, 3 => RecentPlayersSortMode.SeenCount, 4 => RecentPlayersSortMode.Region, 5 => RecentPlayersSortMode.Online, _ => RecentPlayersSortMode.Name, }; } } public static class PlayerBlacklistStore { private struct BlockResult { public bool GameKicked; public bool CleanedObjects; } [CompilerGenerated] private sealed class d__26 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public int actorNumber; private int 5__2; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__26(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Expected O, but got Unknown int num = <>1__state; RecentPlayerRecord record; if (num != 0) { if (num != 1) { return false; } <>1__state = -1; Player val = FindRoomPlayer(actorNumber); if (val != null && TryFindMatch(val, out record)) { if (!PhotonNetwork.IsMasterClient) { CleanupBlockedActorObjects(actorNumber); 5__2++; goto IL_00de; } TryGameHostKick(val, "after-master-request"); } goto IL_00ea; } <>1__state = -1; 5__2 = 1; goto IL_00de; IL_00de: if (5__2 <= 5) { Player val = FindRoomPlayer(actorNumber); if (val != null && TryFindMatch(val, out record)) { CleanupBlockedActorObjects(actorNumber); if (!PhotonNetwork.IsMasterClient) { TryRequestMasterClient(5__2); <>2__current = (object)new WaitForSeconds(0.45f); <>1__state = 1; return true; } TryGameHostKick(val, "after-master-request"); } } goto IL_00ea; IL_00ea: Player val2 = FindRoomPlayer(actorNumber); if (val2 != null && TryFindMatch(val2, out record)) { CleanupBlockedPlayer(val2); } PendingBlockActors.Remove(actorNumber); 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 const int FileVersion = 1; private const int MaxRecords = 500; private const int MasterKickAttempts = 5; private const float MasterKickInterval = 0.45f; private const string BlacklistFolderName = "Blacklist"; private static readonly string DirectoryPath = AppDataPaths.DirectoryPath("Blacklist"); private static readonly string FilePath = Path.Combine(DirectoryPath, "blacklisted_players.json"); private static readonly List Records = new List(); private static readonly HashSet PendingBlockActors = new HashSet(); private static bool _loaded; public static IReadOnlyList GetAll() { EnsureLoaded(); return (from record in Records orderby record.DisplayName, record.Id select record.Clone()).ToList(); } public static RecentPlayerRecord Find(string id) { EnsureLoaded(); if (!string.IsNullOrEmpty(id)) { return (from t in Records where string.Equals(t.Id, id, StringComparison.Ordinal) select t.Clone()).FirstOrDefault(); } return null; } public static bool Contains(RecentPlayerRecord record) { if (record != null) { return ContainsIdentity(record.SteamId, record.PhotonUserId, record.DisplayName, record.ActorText); } return false; } public static bool ContainsIdentity(ulong steamId, string photonUserId, string displayName, string actorText) { EnsureLoaded(); RecentPlayerRecord record; return TryFindIdentityMatch(steamId, photonUserId, displayName, actorText, out record); } public static bool Add(RecentPlayerRecord source) { RecentPlayerRecord recentPlayerRecord = NormalizeRecord(source); if (recentPlayerRecord == null) { return false; } EnsureLoaded(); int num = FindIndex(recentPlayerRecord.Id); if (num >= 0) { Records[num] = MergeRecords(Records[num], recentPlayerRecord); } else { Records.Add(recentPlayerRecord); } Prune(); Save(); return true; } public static bool Remove(string id) { EnsureLoaded(); if (Records.RemoveAll((RecentPlayerRecord record) => string.Equals(record.Id, id, StringComparison.Ordinal)) <= 0) { return false; } Save(); return true; } public static bool RemoveIdentity(ulong steamId, string photonUserId, string displayName, string actorText) { EnsureLoaded(); if (TryFindIdentityMatch(steamId, photonUserId, displayName, actorText, out var record)) { return Remove(record.Id); } return false; } public static void Clear() { EnsureLoaded(); if (Records.Count != 0) { Records.Clear(); Save(); } } public static bool TryBlock(Player player) { if (!TryFindMatch(player, out var record)) { return false; } string text = BuildPlayerName(player); BlockResult blockResult = EnforceBlockedPlayer(player, text); if (!PhotonNetwork.IsMasterClient) { ScheduleMasterKickAttempts(player); } if (blockResult.GameKicked) { NotificationSystem.Push("Blacklisted Player Game-Kicked", record.DisplayName, NotificationKind.Warning); } else if (blockResult.CleanedObjects) { NotificationSystem.Push("Blacklisted Player Cleaned Up", record.DisplayName, NotificationKind.Warning); } else { NotificationSystem.Push("Blacklist Match", text + " joined; cleanup queued.", NotificationKind.Warning); } return true; } public static int EnforceCurrentRoomBlacklist() { if (!PhotonNetwork.InRoom) { return 0; } Player[] playerListOthers; try { playerListOthers = PhotonNetwork.PlayerListOthers; } catch { return 0; } if (playerListOthers == null || playerListOthers.Length == 0) { return 0; } return playerListOthers.Count(TryBlock); } internal static RecentPlayerRecord BuildRecord(PlayerDirectory.SelectedPlayerInfo target) { if (target == null) { return null; } RecentPlayerRecord recentPlayerRecord = RecentPlayersStore.BuildRecord(target.DisplayName, target.ActorText, target.SteamId, target.PhotonUserId, target.RoomName, target.Region, target.ModFlags); object obj; if (recentPlayerRecord != null) { obj = RecentPlayersStore.Find(recentPlayerRecord.Id); if (obj == null) { return recentPlayerRecord; } } else { obj = null; } return (RecentPlayerRecord)obj; } private static bool TryFindMatch(Player player, out RecentPlayerRecord record) { record = null; if (player == null || player.IsLocal) { return false; } string playerName = RecentPlayersStore.GetPlayerName(player); string actorText = ((player.ActorNumber > 0) ? player.ActorNumber.ToString(CultureInfo.InvariantCulture) : string.Empty); return TryFindIdentityMatch(RecentPlayersStore.TryGetSteamId(player), player.UserId, playerName, actorText, out record); } private static BlockResult EnforceBlockedPlayer(Player player, string playerName) { BlockResult result = default(BlockResult); if (player == null || player.IsLocal) { return result; } if (PhotonNetwork.IsMasterClient) { result.GameKicked |= TryGameHostKick(player, "host"); return result; } result.CleanedObjects |= CleanupBlockedPlayer(player); if (!result.GameKicked && !result.CleanedObjects) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Blacklist] No block method succeeded for " + playerName + ".")); } } return result; } private static bool TryGameHostKick(Player player, string phase) { if (player == null || player.IsLocal || player.ActorNumber <= 0 || !PhotonNetwork.InRoom) { return false; } if (!PhotonNetwork.IsMasterClient) { return false; } try { PlayerHandler.Kick(player.ActorNumber); ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)("[Blacklist] Used PlayerHandler.Kick during " + phase + " for " + BuildPlayerName(player) + ".")); } return true; } catch (Exception ex) { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogWarning((object)("[Blacklist] PlayerHandler.Kick failed during " + phase + ": " + ex.Message)); } return false; } } private static bool TryRequestMasterClient(int attempt) { if (!PhotonNetwork.InRoom || PhotonNetwork.LocalPlayer == null) { return false; } if (PhotonNetwork.IsMasterClient) { return true; } try { bool flag = PhotonNetwork.SetMasterClient(PhotonNetwork.LocalPlayer); ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)("[Blacklist] Requested master client for blacklist kick (" + attempt.ToString(CultureInfo.InvariantCulture) + "/" + 5.ToString(CultureInfo.InvariantCulture) + ").")); } return PhotonNetwork.IsMasterClient || flag; } catch (Exception ex) { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogWarning((object)("[Blacklist] Failed to request master client: " + ex.Message)); } return false; } } private static void ScheduleMasterKickAttempts(Player player) { if (player != null && player.ActorNumber > 0 && Object.op_Implicit((Object)(object)Plugin.Instance) && PendingBlockActors.Add(player.ActorNumber)) { ((MonoBehaviour)Plugin.Instance).StartCoroutine(MasterKickAttemptsRoutine(player.ActorNumber)); } } [IteratorStateMachine(typeof(d__26))] private static IEnumerator MasterKickAttemptsRoutine(int actorNumber) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__26(0) { actorNumber = actorNumber }; } private static bool CleanupBlockedPlayer(Player player) { if (player == null || player.IsLocal) { return false; } bool flag = false; int actorNumber = player.ActorNumber; flag |= TryDestroyPlayerObjects(player); if (actorNumber > 0) { flag |= CleanupBlockedActorObjects(actorNumber); } return flag; } private static bool TryDestroyPlayerObjects(Player player) { if (player == null || player.ActorNumber <= 0) { return false; } bool result = false; try { PhotonNetwork.DestroyPlayerObjects(player); result = true; } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Blacklist] DestroyPlayerObjects(player) failed: " + ex.Message)); } } try { PhotonNetwork.DestroyPlayerObjects(player.ActorNumber); result = true; } catch (Exception ex2) { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogWarning((object)("[Blacklist] DestroyPlayerObjects(actor) failed: " + ex2.Message)); } } try { PhotonNetwork.DestroyPlayerObjects(player.ActorNumber, true); result = true; } catch (Exception ex3) { ManualLogSource log3 = Plugin.Log; if (log3 != null) { log3.LogWarning((object)("[Blacklist] local DestroyPlayerObjects cleanup failed: " + ex3.Message)); } } return result; } private static bool CleanupBlockedActorObjects(int actorNumber) { if (actorNumber <= 0) { return false; } bool flag = false; HashSet seen = new HashSet(); if (Character.AllCharacters != null) { foreach (Character allCharacter in Character.AllCharacters) { flag |= CleanupBlockedCharacter(allCharacter, actorNumber, seen); } } Character[] array; try { array = Object.FindObjectsByType((FindObjectsSortMode)0); } catch { array = Array.Empty(); } Character[] array2 = array; foreach (Character character in array2) { flag |= CleanupBlockedCharacter(character, actorNumber, seen); } PhotonView[] source; try { source = Object.FindObjectsByType((FindObjectsSortMode)0); } catch { source = Array.Empty(); } return source.Where((PhotonView view) => ViewBelongsToActor(view, actorNumber)).Aggregate(flag, (bool current, PhotonView view) => current | DestroyPhotonView(view)); } private static bool CleanupBlockedCharacter(Character character, int actorNumber, HashSet seen) { if (!Object.op_Implicit((Object)(object)character)) { return false; } int instanceID = ((Object)character).GetInstanceID(); if (seen != null && !seen.Add(instanceID)) { return false; } PhotonView view = (Object.op_Implicit((Object)(object)character.refs?.view) ? character.refs.view : GetPhotonView((Component)(object)character)); if (!ViewBelongsToActor(view, actorNumber)) { return false; } bool result = DestroyPhotonView(view); try { if (Object.op_Implicit((Object)(object)character.Ghost)) { Object.Destroy((Object)(object)((Component)character.Ghost).gameObject); } } catch { } try { Object.Destroy((Object)(object)((Component)character).gameObject); result = true; } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Blacklist] Local character cleanup failed: " + ex.Message)); } } return result; } private static bool DestroyPhotonView(PhotonView view) { if (!Object.op_Implicit((Object)(object)view)) { return false; } bool result = false; TryTakeOwnership(view); try { PhotonNetwork.Destroy(view); result = true; } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Blacklist] PhotonNetwork.Destroy(view) failed: " + ex.Message)); } } try { if (Object.op_Implicit((Object)(object)view)) { Object.Destroy((Object)(object)((Component)view).gameObject); result = true; } } catch (Exception ex2) { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogWarning((object)("[Blacklist] Local PhotonView cleanup failed: " + ex2.Message)); } } return result; } private static bool TryTakeOwnership(PhotonView view) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)view) || PhotonNetwork.LocalPlayer == null) { return false; } try { view.OwnershipTransfer = (OwnershipOption)2; view.OwnerActorNr = PhotonNetwork.LocalPlayer.ActorNumber; view.ControllerActorNr = PhotonNetwork.LocalPlayer.ActorNumber; view.RequestOwnership(); view.TransferOwnership(PhotonNetwork.LocalPlayer); return true; } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Blacklist] Take ownership failed: " + ex.Message)); } return false; } } private static bool ViewBelongsToActor(PhotonView view, int actorNumber) { if (!Object.op_Implicit((Object)(object)view) || actorNumber <= 0) { return false; } try { if (view.OwnerActorNr == actorNumber || view.ControllerActorNr == actorNumber) { return true; } } catch { } try { if (view.Owner != null && view.Owner.ActorNumber == actorNumber) { return true; } } catch { } try { return view.Controller != null && view.Controller.ActorNumber == actorNumber; } catch { return false; } } private static PhotonView GetPhotonView(Component component) { if (!Object.op_Implicit((Object)(object)component)) { return null; } return component.GetComponent() ?? component.GetComponentInParent() ?? component.GetComponentInChildren(); } private static bool IsPlayerStillInRoom(Player player) { if (player != null) { return FindRoomPlayer(player.ActorNumber) != null; } return false; } private static Player FindRoomPlayer(int actorNumber) { if (actorNumber <= 0 || !PhotonNetwork.InRoom) { return null; } Player[] playerListOthers; try { playerListOthers = PhotonNetwork.PlayerListOthers; } catch { return null; } return playerListOthers?.FirstOrDefault((Func)((Player player) => player != null && player.ActorNumber == actorNumber)); } private static bool TryFindIdentityMatch(ulong steamId, string photonUserId, string displayName, string actorText, out RecentPlayerRecord record) { EnsureLoaded(); record = null; string currentId = RecentPlayersStore.BuildRecordId(steamId, photonUserId, displayName, actorText); if (!string.IsNullOrEmpty(currentId)) { int num = FindIndex(currentId); if (num >= 0) { record = Records[num].Clone(); return true; } } using (IEnumerator enumerator = Records.Where((RecentPlayerRecord t) => MatchesIdentity(t, steamId, photonUserId, displayName, currentId)).GetEnumerator()) { if (enumerator.MoveNext()) { RecentPlayerRecord current = enumerator.Current; record = current.Clone(); return true; } } return false; } private static bool MatchesIdentity(RecentPlayerRecord record, ulong steamId, string photonUserId, string displayName, string currentId) { if (record == null) { return false; } if (!string.IsNullOrEmpty(currentId) && string.Equals(record.Id, currentId, StringComparison.Ordinal)) { return true; } if (record.SteamId != 0L && steamId != 0L && record.SteamId == steamId) { return true; } if (!string.IsNullOrWhiteSpace(record.PhotonUserId) && !string.IsNullOrWhiteSpace(photonUserId) && string.Equals(record.PhotonUserId, photonUserId, StringComparison.Ordinal)) { return true; } if (record.SteamId == 0L && string.IsNullOrWhiteSpace(record.PhotonUserId) && !string.IsNullOrWhiteSpace(record.DisplayName) && !string.IsNullOrWhiteSpace(displayName)) { return string.Equals(record.DisplayName.Trim(), displayName.Trim(), StringComparison.OrdinalIgnoreCase); } return false; } private static RecentPlayerRecord NormalizeRecord(RecentPlayerRecord source) { if (source == null) { return null; } string text = (string.IsNullOrEmpty(source.Id) ? RecentPlayersStore.BuildRecordId(source.SteamId, source.PhotonUserId, source.DisplayName, source.ActorText) : source.Id); if (string.IsNullOrEmpty(text)) { return null; } string text2 = DateTime.UtcNow.ToString("o", CultureInfo.InvariantCulture); string displayName = (string.IsNullOrWhiteSpace(source.DisplayName) ? "Unknown Player" : source.DisplayName.Trim()); string firstSeenUtc = ((!string.IsNullOrEmpty(source.FirstSeenUtc)) ? source.FirstSeenUtc : (string.IsNullOrEmpty(source.LastSeenUtc) ? text2 : source.LastSeenUtc)); string lastSeenUtc = (string.IsNullOrEmpty(source.LastSeenUtc) ? text2 : source.LastSeenUtc); string text3 = source.ModFlags ?? string.Empty; return new RecentPlayerRecord { Id = text, DisplayName = displayName, SteamId = source.SteamId, PhotonUserId = (source.PhotonUserId ?? string.Empty), ActorText = (source.ActorText ?? string.Empty), RoomName = (source.RoomName ?? string.Empty), SteamLobbyId = source.SteamLobbyId, Region = (source.Region ?? string.Empty), Modded = (source.Modded || !string.IsNullOrWhiteSpace(text3)), ModFlags = text3, SpoofedName = source.SpoofedName, FirstSeenUtc = firstSeenUtc, LastSeenUtc = lastSeenUtc, TimesSeen = Math.Max(0, source.TimesSeen) }; } private static RecentPlayerRecord MergeRecords(RecentPlayerRecord existing, RecentPlayerRecord incoming) { if (existing == null) { return incoming; } if (incoming == null) { return existing; } existing.DisplayName = (string.IsNullOrWhiteSpace(incoming.DisplayName) ? existing.DisplayName : incoming.DisplayName); if (incoming.SteamId != 0L) { existing.SteamId = incoming.SteamId; } if (!string.IsNullOrWhiteSpace(incoming.PhotonUserId)) { existing.PhotonUserId = incoming.PhotonUserId; } if (!string.IsNullOrWhiteSpace(incoming.ActorText)) { existing.ActorText = incoming.ActorText; } if (!string.IsNullOrWhiteSpace(incoming.RoomName)) { existing.RoomName = incoming.RoomName; } if (incoming.SteamLobbyId != 0L) { existing.SteamLobbyId = incoming.SteamLobbyId; } if (!string.IsNullOrWhiteSpace(incoming.Region)) { existing.Region = incoming.Region; } if (string.IsNullOrEmpty(existing.FirstSeenUtc)) { existing.FirstSeenUtc = incoming.FirstSeenUtc; } if (!string.IsNullOrEmpty(incoming.LastSeenUtc)) { existing.LastSeenUtc = incoming.LastSeenUtc; } existing.TimesSeen = Math.Max(existing.TimesSeen, incoming.TimesSeen); existing.ModFlags = MergeFlags(existing.ModFlags, incoming.ModFlags); existing.Modded = existing.Modded || incoming.Modded || !string.IsNullOrEmpty(existing.ModFlags); existing.SpoofedName = existing.SpoofedName || incoming.SpoofedName; return existing; } private static string MergeFlags(string existing, string incoming) { SortedSet sortedSet = new SortedSet(StringComparer.OrdinalIgnoreCase); AddFlags(sortedSet, existing); AddFlags(sortedSet, incoming); if (sortedSet.Count != 0) { return string.Join(", ", sortedSet.ToArray()); } return string.Empty; } private static void AddFlags(SortedSet flags, string value) { if (flags == null || string.IsNullOrWhiteSpace(value)) { return; } string[] array = value.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < array.Length; i++) { string text = array[i].Trim(); if (!string.IsNullOrEmpty(text)) { flags.Add(text); } } } private static void EnsureLoaded() { if (_loaded) { return; } _loaded = true; try { AppDataPaths.MigrateFileToDirectory("blacklisted_players.json", "Blacklist"); if (!File.Exists(FilePath)) { return; } PlayerBlacklistFile playerBlacklistFile = JsonConvert.DeserializeObject(File.ReadAllText(FilePath)); if (playerBlacklistFile?.players == null) { return; } Records.Clear(); foreach (RecentPlayerRecord item in from record in playerBlacklistFile.players.Select(NormalizeRecord) where record != null select record) { Records.Add(item); } Prune(); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogError((object)("Failed to load player blacklist: " + ex)); } } } private static void Save() { try { Directory.CreateDirectory(DirectoryPath); PlayerBlacklistFile playerBlacklistFile = new PlayerBlacklistFile { version = 1, players = (from record in (from record in Records orderby record.DisplayName, record.Id select record).Take(500) select record.Clone()).ToList() }; File.WriteAllText(FilePath, JsonConvert.SerializeObject((object)playerBlacklistFile, (Formatting)1)); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogError((object)("Failed to save player blacklist: " + ex)); } } } private static int FindIndex(string id) { if (string.IsNullOrEmpty(id)) { return -1; } for (int i = 0; i < Records.Count; i++) { if (string.Equals(Records[i].Id, id, StringComparison.Ordinal)) { return i; } } return -1; } private static void Prune() { Records.Sort((RecentPlayerRecord a, RecentPlayerRecord b) => string.Compare(a.DisplayName, b.DisplayName, StringComparison.OrdinalIgnoreCase)); if (Records.Count > 500) { Records.RemoveRange(500, Records.Count - 500); } } private static string BuildPlayerName(Player player) { if (player == null) { return "Unknown Player"; } string playerName = RecentPlayersStore.GetPlayerName(player); if (player.ActorNumber <= 0) { return playerName; } return playerName + " #" + player.ActorNumber.ToString(CultureInfo.InvariantCulture); } } public class RemoveBlacklistedPlayer : ButtonFeature { public RemoveBlacklistedPlayer() { base.Name = "Remove From Blacklist"; base.Description = "Removes this player from the persistent blacklist."; base.ButtonLabel = "Remove"; } public override void Execute() { RecentPlayerRecord selectedBlacklistedPlayer = PlayerBlacklistDirectory.SelectedBlacklistedPlayer; if (selectedBlacklistedPlayer != null && PlayerBlacklistStore.Remove(selectedBlacklistedPlayer.Id)) { NotificationSystem.Push("Removed From Blacklist", selectedBlacklistedPlayer.DisplayName, NotificationKind.Success); } } } public class RemoveRecentPlayerFromBlacklist : ButtonFeature { public RemoveRecentPlayerFromBlacklist() { base.Name = "Remove From Blacklist"; base.Description = "Removes the selected recent player from the persistent blacklist."; base.ButtonLabel = "Remove"; } public override void Execute() { RecentPlayerRecord selectedRecentPlayer = RecentPlayersDirectory.SelectedRecentPlayer; if (selectedRecentPlayer != null && (PlayerBlacklistStore.Remove(selectedRecentPlayer.Id) || PlayerBlacklistStore.RemoveIdentity(selectedRecentPlayer.SteamId, selectedRecentPlayer.PhotonUserId, selectedRecentPlayer.DisplayName, selectedRecentPlayer.ActorText))) { NotificationSystem.Push("Removed From Blacklist", selectedRecentPlayer.DisplayName, NotificationKind.Success); } } } public class RemoveSelectedPlayerFromBlacklist : ButtonFeature { public RemoveSelectedPlayerFromBlacklist() { base.Name = "Remove From Blacklist"; base.Description = "Removes the selected player from the persistent blacklist."; base.ButtonLabel = "Remove"; } public override void Execute() { PlayerDirectory.SelectedPlayerInfo selectedPlayer = PlayerDirectory.SelectedPlayer; if (selectedPlayer != null && PlayerBlacklistStore.RemoveIdentity(selectedPlayer.SteamId, selectedPlayer.PhotonUserId, selectedPlayer.DisplayName, selectedPlayer.ActorText)) { NotificationSystem.Push("Removed From Blacklist", selectedPlayer.DisplayName, NotificationKind.Success); } } } public class PlayerDirectory : Feature, IMenuRowProvider, IMenuSidePanelProvider, IDisposable { public sealed class SelectedPlayerInfo { public string Id { get; } public Character Character { get; } public string DisplayName { get; } public string MenuName { get; } public string ActorText { get; } public bool IsHost { get; } public bool IsLocal { get; } public bool IsDead { get; } public ulong SteamId { get; } public string PhotonUserId { get; } public string RoomName { get; } public string Region { get; } public string ModFlags { get; } public Vector3 LastKnownPosition { get; } public bool IsValid => (Object)(object)Character != (Object)null; public Vector3 Position { get { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)Character)) { return LastKnownPosition; } return ((Component)Character).transform.position; } } public SelectedPlayerInfo(string id, Character character, string displayName, string menuName, string actorText, bool isHost, bool isLocal, bool isDead, ulong steamId, string photonUserId, string roomName, string region, string modFlags, Vector3 lastKnownPosition) { //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) Id = id; Character = character; DisplayName = displayName; MenuName = menuName; ActorText = actorText; IsHost = isHost; IsLocal = isLocal; IsDead = isDead; SteamId = steamId; PhotonUserId = photonUserId ?? string.Empty; RoomName = roomName ?? string.Empty; Region = region ?? string.Empty; ModFlags = modFlags ?? string.Empty; LastKnownPosition = lastKnownPosition; base..ctor(); } } private sealed class WarpSelectedPlayerToPlayerButton : ButtonFeature, IMenuTagProvider { private readonly PlayerInfo _source; private readonly PlayerInfo _destination; public List Tags { get; } public WarpSelectedPlayerToPlayerButton(PlayerInfo source, PlayerInfo destination, List tags) { _source = source; _destination = destination; Tags = tags ?? new List(); base.Name = destination?.DisplayName ?? "Unknown Player"; base.Description = "Warps " + (source?.DisplayName ?? "the selected player") + " near this player."; base.ButtonLabel = "Warp"; } public override void Execute() { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) Character val = _source?.Character; if (!Object.op_Implicit((Object)(object)val)) { NotificationSystem.Push("Teleport Failed", "Selected player is no longer available.", NotificationKind.Warning); return; } Vector3 destinationPosition = GetDestinationPosition(_destination); if (!IsFinite(destinationPosition)) { NotificationSystem.Push("Teleport Failed", "Destination player position is not available.", NotificationKind.Warning); } else if (GameActions.WarpCharacter(val, destinationPosition)) { NotificationSystem.Push("Player Teleport", "Warped " + _source.DisplayName + " to " + _destination.DisplayName + ".", NotificationKind.Success); } else { NotificationSystem.Push("Teleport Failed", "Could not warp selected player.", NotificationKind.Warning); } } private static Vector3 GetDestinationPosition(PlayerInfo destination) { //IL_0012: 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_007e: 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_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004f: 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_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: 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_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) if (destination == null) { return new Vector3(float.NaN, float.NaN, float.NaN); } Character character = destination.Character; if (Object.op_Implicit((Object)(object)character)) { Vector3 right = ((Component)character).transform.right; if (((Vector3)(ref right)).sqrMagnitude < 0.01f) { right = Vector3.right; } return character.Head + ((Vector3)(ref right)).normalized * 1.35f + Vector3.up * 0.75f; } return destination.Position + Vector3.up; } private static bool IsFinite(Vector3 value) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) if (!float.IsNaN(value.x) && !float.IsInfinity(value.x) && !float.IsNaN(value.y) && !float.IsInfinity(value.y) && !float.IsNaN(value.z)) { return !float.IsInfinity(value.z); } return false; } } private sealed class PlayerInfo { public string Id; public Character Character; public string DisplayName; public string MenuName; public string ActorText; public bool IsCurrentLocal; public bool IsRegisteredToPlayer; public bool IsHost; public bool IsLocal; public bool IsDead; public float? Stamina; public float? StaminaMax; public float? PassOut; public float? TotalStamina; public float? ExtraStamina; public float? StaminaDelta; public float? StaminaMod; public float? FallSeconds; public bool? IsGrounded; public bool? IsClimbing; public bool? IsRopeClimbing; public bool? IsVineClimbing; public bool? PassedOut; public bool? FullyPassedOut; public bool? ShouldPassOut; public bool? IsWebbed; public int? JumpsRemaining; public float? MovementModifier; public float? SprintMultiplier; public float? JumpImpulse; public float? CurrentMovementForce; public float? Speed; public float? StatusSum; public List Statuses; public float? Distance; public Vector3 Position; public ulong SteamId; public string PhotonUserId; public string ConnectionState; public string Region; public string PingText; public string RoomName; public string RoomPlayersText; public string MasterClientText; public bool HasExternalClientMarker; public bool CherryUser; public string ModFlags; public bool HasPhotonView; public string VoiceServerAddress; public string VoicePingText; } private sealed class StatusInfo { public readonly string Name; public readonly float? Value; public StatusInfo(string name, float? value) { Name = name; Value = value; base..ctor(); } } private struct AvatarCacheEntry { public Texture2D Texture; public ulong SteamId; public bool IsDead; } private readonly struct MemberKey : IEquatable { private readonly Type Type; private readonly string Name; public MemberKey(Type type, string name) { Type = type; Name = name; } public bool Equals(MemberKey other) { if (Type == other.Type) { return string.Equals(Name, other.Name, StringComparison.OrdinalIgnoreCase); } return false; } public override bool Equals(object obj) { if (obj is MemberKey other) { return Equals(other); } return false; } public override int GetHashCode() { int num = ((Type != null) ? Type.GetHashCode() : 0); int num2 = ((Name != null) ? StringComparer.OrdinalIgnoreCase.GetHashCode(Name) : 0); return (num * 397) ^ num2; } } [CompilerGenerated] private sealed class d__72 : IEnumerable, IEnumerable, IEnumerator, IEnumerator, IDisposable { private int <>1__state; private Character <>2__current; private int <>l__initialThreadId; private HashSet 5__2; private Character[] 5__3; private int 5__4; Character IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__72(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { 5__2 = null; 5__3 = null; <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; 5__2 = new HashSet(); if (Character.AllCharacters != null && Character.AllCharacters.Count > 0) { 5__4 = 0; goto IL_009d; } goto IL_00af; case 1: <>1__state = -1; goto IL_008d; case 2: { <>1__state = -1; goto IL_0104; } IL_008d: 5__4++; goto IL_009d; IL_00af: 5__3 = Object.FindObjectsByType((FindObjectsSortMode)0); 5__4 = 0; goto IL_0114; IL_009d: if (5__4 < Character.AllCharacters.Count) { Character val = Character.AllCharacters[5__4]; if (Object.op_Implicit((Object)(object)val) && 5__2.Add(((Object)val).GetInstanceID())) { <>2__current = val; <>1__state = 1; return true; } goto IL_008d; } goto IL_00af; IL_0114: if (5__4 < 5__3.Length) { Character val2 = 5__3[5__4]; if (Object.op_Implicit((Object)(object)val2) && 5__2.Add(((Object)val2).GetInstanceID())) { <>2__current = val2; <>1__state = 2; return true; } goto IL_0104; } return false; IL_0104: 5__4++; goto IL_0114; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; return this; } return new d__72(0); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)this).GetEnumerator(); } } private const string PlayersCategory = "Network/Players"; private const string PlayerCategoryPrefix = "Network/Players/"; private const string TeleportCategory = "Teleport"; private const string TeleportDestinationCategory = "Teleport/To Player"; private const string RecoveryCategory = "Recovery"; private const string MovementCategory = "Movement"; private const string HazardsCategory = "Events"; private const string InventoryCategory = "Inventory"; private const string StatusCategory = "Status"; private const string EmotesCategory = "Emotes"; private const string LobbyControlCategory = "Lobby Control"; private const float PlayerListRefreshInterval = 0.25f; private const int AvatarSize = 184; private static readonly string AvatarCacheDir = AppDataPaths.DirectoryPath("Cache"); private const BindingFlags ReflectionFlags = BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; private readonly List _players = new List(); private readonly Dictionary _avatarCache = new Dictionary(); private readonly Dictionary _memberInfoCache = new Dictionary(); private static PlayerDirectory ActiveInstance; private float _nextRefreshAt; public static SelectedPlayerInfo SelectedPlayer { get; private set; } public PlayerDirectory() { base.Name = "Player Directory"; base.Description = "Builds live player rows for the Players menu."; ActiveInstance = this; } public IEnumerable GetRows(string category) { RefreshPlayersIfNeeded(); if (category == "Network/Players") { return BuildPlayerListRows(); } if (category != null && category.StartsWith("Network/Players/", StringComparison.Ordinal)) { return BuildPlayerDetailRows(category.Substring("Network/Players/".Length)); } return Array.Empty(); } private IEnumerable BuildPlayerListRows() { List list = _players.Select((PlayerInfo player) => new SubmenuFeature(player.DisplayName, "Network/Players/" + player.Id, "View stats for " + player.DisplayName + ".", BuildPlayerTags(player))).Cast().ToList(); if (_players.Count == 0) { list.Add(new InfoFeature("Players", "None", "No live players were found.")); } return list; } private IEnumerable BuildPlayerDetailRows(string path) { string text = ExtractPlayerId(path); PlayerInfo playerInfo = FindPlayer(text); if (playerInfo == null) { if (SelectedPlayer != null && SelectedPlayer.Id == text) { SelectedPlayer = null; } return new <>z__ReadOnlySingleElementList(new InfoFeature("Player", "Not found", "This player is no longer available.")); } SetSelectedPlayer(playerInfo); string text2 = ExtractPlayerActionGroup(path); if (!string.IsNullOrEmpty(text2)) { if (text2.StartsWith("Teleport/To Player", StringComparison.Ordinal)) { return BuildTeleportDestinationRows(playerInfo); } return BuildPlayerActionRows(playerInfo, text2); } return new List { PlayerSpectate.Instance, PlayerActionSubmenu(playerInfo, "Teleport", "Teleport to this player or bring them to you."), PlayerActionSubmenu(playerInfo, "Recovery", "Support and recovery actions."), PlayerActionSubmenu(playerInfo, "Movement", "Movement and control actions."), PlayerActionSubmenu(playerInfo, "Events", "Player event actions."), PlayerActionSubmenu(playerInfo, "Inventory", "Inventory, slot, and pickup actions."), PlayerActionSubmenu(playerInfo, "Status", "Affliction and status value actions."), PlayerActionSubmenu(playerInfo, "Emotes", "Remote emote actions."), PlayerActionSubmenu(playerInfo, "Lobby Control", "Lobby and player control actions."), new SeparatorFeature(), PlayerBlacklistStore.ContainsIdentity(playerInfo.SteamId, playerInfo.PhotonUserId, playerInfo.DisplayName, playerInfo.ActorText) ? ((ButtonFeature)new RemoveSelectedPlayerFromBlacklist()) : ((ButtonFeature)new AddSelectedPlayerToBlacklist()), new SeparatorFeature(), new InfoFeature("Target", playerInfo.DisplayName, "Currently selected player action target.") }; } private IEnumerable BuildPlayerActionRows(PlayerInfo player, string actionGroup) { return actionGroup switch { "Teleport" => new <>z__ReadOnlyArray(new object[3] { new TeleportToPlayer(), new WarpSelectedPlayerToMe(), PlayerActionSubmenu(player, "To Player", "Warp the selected player to another live player.", null, null, "Teleport/To Player") }), "Recovery" => new <>z__ReadOnlyArray(new object[5] { new ReviveTpSelectedPlayer(), new ReviveSelectedPlayerWithStatuses(), new UnpassOutSelectedPlayer(), new FullStaminaSelectedPlayer(), new SeparatorFeature() }), "Movement" => new <>z__ReadOnlyArray(new object[10] { new JumpSelectedPlayer(), new FlingSelectedPlayer(), new CrouchSelectedPlayer(), new PassOutSelectedPlayer(), new FallSelectedPlayer(), new ShakeScreenSelectedPlayer(), new StopClimbingSelectedPlayer(), new UnhangSelectedPlayer(), new CarrySelectedPlayer(), new SeparatorFeature() }), "Events" => new <>z__ReadOnlyArray(new object[8] { new SlipSelectedPlayer(), new BlowdartHitSelectedPlayer(), new ExplodeSelectedPlayer(), new SwarmBeesSelectedPlayer(), new GrowVineSelectedPlayer(), new ForceScoutmastersSelectedPlayer(), new SpawnScoutmasterForSelectedPlayer(), new SeparatorFeature() }), "Inventory" => new <>z__ReadOnlyArray(new object[11] { new RequestPickupSelectedPlayer(), new DropHeldItemSelectedPlayer(), new EmptySlot1SelectedPlayer(), new EmptySlot2SelectedPlayer(), new EmptySlot3SelectedPlayer(), new EmptyAllSlotsSelectedPlayer(), new DropSlot1SelectedPlayer(), new DropSlot2SelectedPlayer(), new DropSlot3SelectedPlayer(), new DropAllSlotsSelectedPlayer(), new SeparatorFeature() }), "Status" => new <>z__ReadOnlyArray(new object[5] { new AfflictionIndex(), new AddAfflictionSelectedPlayer(), new RemoveAfflictionSelectedPlayer(), new ClearAfflictionsSelectedPlayer(), new SeparatorFeature() }), "Emotes" => new <>z__ReadOnlyArray(new object[9] { new SaluteSelectedPlayer(), new ThumbsUpSelectedPlayer(), new ThinkSelectedPlayer(), new NoNoSelectedPlayer(), new PlayDeadSelectedPlayer(), new ShrugSelectedPlayer(), new CrossedArmsSelectedPlayer(), new DanceSelectedPlayer(), new SeparatorFeature() }), "Lobby Control" => new <>z__ReadOnlyArray(new object[11] { new AddSelectedPlayerOnSteam(), new KillSelectedPlayer(), new KickSelectedPlayer(), new ForceEndScreenClosedSelectedPlayer(), new TakeOwnershipSelectedPlayer(), new DestroySelectedPlayer(), new RenderPassedOutSelectedPlayer(), new RenderDeadSelectedPlayer(), new RefreshCharacterWeightSelectedPlayer(), new SeparatorFeature(), new InfoFeature("Host", "Required", "Most lobby control actions require master-client control.") }), _ => BuildPlayerDetailRows(player.Id), }; } private IEnumerable BuildTeleportDestinationRows(PlayerInfo source) { List list = new List(); foreach (PlayerInfo player in _players) { if (player != null && !string.Equals(player.Id, source.Id, StringComparison.Ordinal)) { list.Add(new WarpSelectedPlayerToPlayerButton(source, player, BuildPlayerTags(player))); } } if (list.Count == 0) { list.Add(new InfoFeature("Players", "None", "No other live players were found.")); } return list; } private static SubmenuFeature PlayerActionSubmenu(PlayerInfo player, string category, string description, string tagText = null, Color? tagColor = null, string childCategory = null) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) List tags = null; if (!string.IsNullOrEmpty(tagText) && tagColor.HasValue) { tags = new List { new MenuTag(tagText, tagColor.Value) }; } return new SubmenuFeature(category, "Network/Players/" + player.Id + "/" + (childCategory ?? category), description, tags); } public bool TryGetSidePanel(string category, object selectedRow, out MenuSidePanel panel) { panel = null; RefreshPlayersIfNeeded(); string panelPlayerId = GetPanelPlayerId(category, selectedRow); if (string.IsNullOrEmpty(panelPlayerId)) { return false; } PlayerInfo playerInfo = FindPlayer(panelPlayerId); if (playerInfo == null) { return false; } SetSelectedPlayer(playerInfo); panel = BuildSidePanel(playerInfo); return true; } private static string GetPanelPlayerId(string category, object selectedRow) { if (selectedRow is SubmenuFeature submenuFeature && submenuFeature.ChildCategory != null && submenuFeature.ChildCategory.StartsWith("Network/Players/", StringComparison.Ordinal)) { return ExtractPlayerId(submenuFeature.ChildCategory.Substring("Network/Players/".Length)); } if (category != null && category.StartsWith("Network/Players/", StringComparison.Ordinal)) { return ExtractPlayerId(category.Substring("Network/Players/".Length)); } return null; } private static string ExtractPlayerId(string path) { if (string.IsNullOrEmpty(path)) { return null; } int num = path.IndexOf('/'); if (num < 0) { return path; } return path.Substring(0, num); } private static string ExtractPlayerActionGroup(string path) { if (string.IsNullOrEmpty(path)) { return null; } int num = path.IndexOf('/'); if (num < 0 || num + 1 >= path.Length) { return null; } return path.Substring(num + 1); } public static bool TryGetSelectedCharacter(out Character character) { character = null; SelectedPlayerInfo selectedPlayer = SelectedPlayer; if (selectedPlayer == null) { return false; } if (IsSelectedCharacterStillValid(selectedPlayer)) { character = selectedPlayer.Character; return true; } PlayerInfo playerInfo = ActiveInstance?.ResolveSelectedPlayer(selectedPlayer); if (playerInfo != null) { SetSelectedPlayer(playerInfo); character = playerInfo.Character; return Object.op_Implicit((Object)(object)character); } character = selectedPlayer.Character; return Object.op_Implicit((Object)(object)character); } private static bool IsSelectedCharacterStillValid(SelectedPlayerInfo selected) { Character val = selected?.Character; if (!Object.op_Implicit((Object)(object)val)) { return false; } if (!Object.op_Implicit((Object)(object)((Component)val).gameObject)) { return false; } PhotonView val2 = ((Component)val).GetComponent() ?? ((Component)val).GetComponentInParent() ?? ((Component)val).GetComponentInChildren(); if (Object.op_Implicit((Object)(object)val2) && val2.Owner != null) { if (!string.IsNullOrWhiteSpace(selected.ActorText) && int.TryParse(selected.ActorText, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result) && val2.Owner.ActorNumber != result) { return false; } if (!string.IsNullOrWhiteSpace(selected.PhotonUserId) && !string.Equals(val2.Owner.UserId, selected.PhotonUserId, StringComparison.Ordinal)) { return false; } } return true; } private PlayerInfo ResolveSelectedPlayer(SelectedPlayerInfo selected) { if (selected == null) { return null; } RefreshPlayers(force: true); PlayerInfo playerInfo = FindPlayerInCache(selected.Id); if (playerInfo != null) { return playerInfo; } if (!string.IsNullOrWhiteSpace(selected.ActorText)) { playerInfo = _players.FirstOrDefault((PlayerInfo p) => string.Equals(p.ActorText, selected.ActorText, StringComparison.Ordinal)); if (playerInfo != null) { return playerInfo; } } if (selected.SteamId != 0L) { playerInfo = _players.FirstOrDefault((PlayerInfo p) => p.SteamId == selected.SteamId); if (playerInfo != null) { return playerInfo; } } if (!string.IsNullOrWhiteSpace(selected.PhotonUserId)) { playerInfo = _players.FirstOrDefault((PlayerInfo p) => string.Equals(p.PhotonUserId, selected.PhotonUserId, StringComparison.Ordinal)); if (playerInfo != null) { return playerInfo; } } if (!string.IsNullOrWhiteSpace(selected.DisplayName)) { playerInfo = _players.FirstOrDefault((PlayerInfo p) => string.Equals(p.DisplayName, selected.DisplayName, StringComparison.OrdinalIgnoreCase)); if (playerInfo != null) { return playerInfo; } } return null; } private static void SetSelectedPlayer(PlayerInfo player) { //IL_0052: Unknown result type (might be due to invalid IL or missing references) SelectedPlayer = ((player == null) ? null : new SelectedPlayerInfo(player.Id, player.Character, player.DisplayName, player.MenuName, player.ActorText, player.IsHost, player.IsLocal, player.IsDead, player.SteamId, player.PhotonUserId, player.RoomName, player.Region, player.ModFlags, player.Position)); } private MenuSidePanel BuildSidePanel(PlayerInfo player) { Texture steamAvatar = GetSteamAvatar(player); List rows = new List { new InfoFeature("Status", player.IsDead ? "Dead" : "Alive"), new InfoFeature("Session", BuildSessionText(player)), new InfoFeature("Stamina", FormatPercent(player.Stamina, player.StaminaMax)), new InfoFeature("Steam", FormatSteamId(player.SteamId)), new InfoFeature("Region", PlayerRegionLabels.FormatInfo(player.Region)), new InfoFeature("IP", BuildIpInfoText(player)), new InfoFeature("Voice Ping", FormatInfoText(player.VoicePingText)), new InfoFeature("Ping", player.PingText), new InfoFeature("Flags", string.IsNullOrEmpty(player.ModFlags) ? "-" : player.ModFlags), new InfoFeature("Distance", BuildDistanceVisual(player.Distance)), new InfoFeature("Speed", FormatSpeed(player.Speed)) }; if (player.Statuses != null) { foreach (StatusInfo status in player.Statuses) { AddStatusRow(rows, status.Name, status.Value); } } return new MenuSidePanel("PLAYER INFORMATION", player.DisplayName, rows, steamAvatar, BuildPlayerTags(player)); } private static List BuildPlayerTags(PlayerInfo player) { //IL_002d: 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_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_015e: 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_018f: Unknown result type (might be due to invalid IL or missing references) List list = new List(); if (player == null) { return list; } if (player.IsLocal) { list.Add(new MenuTag("YOU", new Color(0.18f, 0.58f, 0.48f, 1f))); } if (player.IsHost) { list.Add(new MenuTag("HOST", new Color(0.18f, 0.36f, 0.88f, 1f))); } if (!player.IsLocal && PlayerBlacklistStore.ContainsIdentity(player.SteamId, player.PhotonUserId, player.DisplayName, player.ActorText)) { list.Add(new MenuTag("BLACKLIST", new Color(0.82f, 0.18f, 0.16f, 1f))); } if (!player.IsLocal && SteamPlayerActions.IsFriend(player.SteamId)) { list.Add(new MenuTag("FRIEND", new Color(0.22f, 0.5f, 0.9f, 1f))); } if (!player.IsLocal && IsStoredNameSpoofed(player)) { list.Add(new MenuTag("NAME SPOOF", new Color(0.9f, 0.4f, 0.14f, 1f))); } string text = PlayerRegionLabels.FormatTag(player.Region); if (!string.IsNullOrEmpty(text)) { list.Add(new MenuTag(text, new Color(0.18f, 0.58f, 0.48f, 1f))); } if (player.IsDead) { list.Add(new MenuTag("DEAD", new Color(0.72f, 0.16f, 0.16f, 1f))); } list.AddRange(PlayerFlagDetector.BuildTags(player.ModFlags)); return list; } private static bool IsStoredNameSpoofed(PlayerInfo player) { if (player == null) { return false; } return RecentPlayersStore.Find(RecentPlayersStore.BuildRecordId(player.SteamId, player.PhotonUserId, player.DisplayName, player.ActorText))?.SpoofedName ?? false; } private static string BuildSessionText(PlayerInfo player) { string obj = (player.IsHost ? "Host" : "Client"); string text = (player.IsLocal ? "Local" : "Remote"); return obj + " • " + text; } private static string BuildIpInfoText(PlayerInfo player) { if (player == null) { return "-"; } if (!string.IsNullOrWhiteSpace(player.VoiceServerAddress)) { return player.VoiceServerAddress; } if (!player.IsLocal) { return "No voice data"; } return "Voice disconnected"; } private static string FormatInfoText(string value) { if (!string.IsNullOrWhiteSpace(value)) { return value; } return "-"; } private static string FormatSteamId(ulong steamId) { if (steamId == 0L) { return "-"; } return steamId.ToString(CultureInfo.InvariantCulture); } private Texture GetSteamAvatar(PlayerInfo player) { if (player == null) { return null; } if (_avatarCache.TryGetValue(player.Id, out var value) && Object.op_Implicit((Object)(object)value.Texture) && value.SteamId == player.SteamId && value.IsDead == player.IsDead) { return (Texture)(object)value.Texture; } if (Object.op_Implicit((Object)(object)value.Texture)) { Object.Destroy((Object)(object)value.Texture); } Texture2D val = LoadSteamAvatarFromCacheOrSteam(player.SteamId); if (!Object.op_Implicit((Object)(object)val)) { val = BuildFallbackAvatar(player); } _avatarCache[player.Id] = new AvatarCacheEntry { Texture = val, SteamId = player.SteamId, IsDead = player.IsDead }; return (Texture)(object)val; } internal static Texture2D LoadSteamAvatarFromCacheOrSteam(ulong steamId) { if (steamId == 0L) { return null; } try { AppDataPaths.MigrateLegacyDirectory("Cache"); Directory.CreateDirectory(AvatarCacheDir); } catch { } string text = Path.Combine(AvatarCacheDir, "steam_" + steamId.ToString(CultureInfo.InvariantCulture) + ".CubeXpfp"); Texture2D val = TryLoadRawAvatarFromDisk(text, steamId); if (Object.op_Implicit((Object)(object)val)) { return val; } return TryBuildSteamAvatarTexture(steamId, text); } private static Texture2D TryLoadRawAvatarFromDisk(string filePath, ulong steamId) { if (string.IsNullOrEmpty(filePath) || !File.Exists(filePath)) { return null; } try { byte[] array = File.ReadAllBytes(filePath); if (array.Length < 12) { return null; } if (array[0] != 76 || array[1] != 88 || array[2] != 80 || array[3] != 70) { return null; } int num = BitConverter.ToInt32(array, 4); int num2 = BitConverter.ToInt32(array, 8); if (num <= 0 || num2 <= 0) { return null; } int num3 = num * num2 * 4; if (array.Length != 12 + num3) { return null; } byte[] array2 = new byte[num3]; Buffer.BlockCopy(array, 12, array2, 0, num3); return BuildTextureFromRgba(num, num2, array2, "CubeX_SteamPfp_Cached_" + steamId.ToString(CultureInfo.InvariantCulture)); } catch { return null; } } private static void SaveRawAvatarToDisk(string filePath, int width, int height, byte[] rgba) { if (string.IsNullOrEmpty(filePath) || rgba == null || width <= 0 || height <= 0) { return; } try { byte[] array = new byte[12 + rgba.Length]; array[0] = 76; array[1] = 88; array[2] = 80; array[3] = 70; Buffer.BlockCopy(BitConverter.GetBytes(width), 0, array, 4, 4); Buffer.BlockCopy(BitConverter.GetBytes(height), 0, array, 8, 4); Buffer.BlockCopy(rgba, 0, array, 12, rgba.Length); File.WriteAllBytes(filePath, array); } catch { } } private static Texture2D BuildTextureFromRgba(int width, int height, byte[] rgba, string textureName) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown //IL_0059: 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) if (rgba == null || rgba.Length != width * height * 4) { return null; } Texture2D val = new Texture2D(width, height, (TextureFormat)4, false) { hideFlags = (HideFlags)61, wrapMode = (TextureWrapMode)1, filterMode = (FilterMode)1, name = textureName }; Color32[] array = (Color32[])(object)new Color32[width * height]; int num = 0; int num2 = 0; while (num < rgba.Length) { array[num2] = new Color32(rgba[num], rgba[num + 1], rgba[num + 2], rgba[num + 3]); num += 4; num2++; } val.SetPixels32(array); val.Apply(false, false); return val; } private static Texture2D TryBuildSteamAvatarTexture(ulong steamId, string cachePath) { try { Type type = FindType("Steamworks.CSteamID"); Type type2 = FindType("Steamworks.SteamFriends"); Type type3 = FindType("Steamworks.SteamUtils"); if (type == null || type2 == null || type3 == null) { return null; } object obj = Activator.CreateInstance(type, steamId); if (obj == null) { return null; } int num = InvokeSteamAvatarMethod(type2, "GetLargeFriendAvatar", type, obj); if (num <= 0) { num = InvokeSteamAvatarMethod(type2, "GetMediumFriendAvatar", type, obj); } if (num <= 0) { num = InvokeSteamAvatarMethod(type2, "GetSmallFriendAvatar", type, obj); } if (num <= 0) { return null; } MethodInfo method = type3.GetMethod("GetImageSize", BindingFlags.Static | BindingFlags.Public, null, new Type[3] { typeof(int), typeof(uint).MakeByRefType(), typeof(uint).MakeByRefType() }, null); if (method == null) { return null; } object[] array = new object[3] { num, 0u, 0u }; object obj2 = method.Invoke(null, array); if (!(obj2 is bool) || !(bool)obj2) { return null; } uint num2 = (uint)array[1]; uint num3 = (uint)array[2]; if (num2 == 0 || num3 == 0) { return null; } byte[] array2 = new byte[num2 * num3 * 4]; MethodInfo method2 = type3.GetMethod("GetImageRGBA", BindingFlags.Static | BindingFlags.Public, null, new Type[3] { typeof(int), typeof(byte[]), typeof(int) }, null); if (method2 == null) { return null; } object obj3 = method2.Invoke(null, new object[3] { num, array2, array2.Length }); if (!(obj3 is bool) || !(bool)obj3) { return null; } int num4 = (int)num2; int num5 = (int)num3; byte[] array3 = new byte[array2.Length]; for (int i = 0; i < num5; i++) { int num6 = i * num4 * 4; int num7 = (num5 - 1 - i) * num4 * 4; for (int j = 0; j < num4; j++) { int num8 = num6 + j * 4; int num9 = num7 + j * 4; array3[num9] = array2[num8]; array3[num9 + 1] = array2[num8 + 1]; array3[num9 + 2] = array2[num8 + 2]; array3[num9 + 3] = array2[num8 + 3]; } } SaveRawAvatarToDisk(cachePath, num4, num5, array3); return BuildTextureFromRgba(num4, num5, array3, "CubeX_SteamPfp_" + steamId.ToString(CultureInfo.InvariantCulture)); } catch { return null; } } private static Type FindType(string fullName) { Type type = Type.GetType(fullName); if (type != null) { return type; } Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { try { type = assembly.GetType(fullName); if (type != null) { return type; } } catch { } } return null; } private static int InvokeSteamAvatarMethod(Type steamFriendsType, string methodName, Type cSteamIdType, object steamId) { try { MethodInfo method = steamFriendsType.GetMethod(methodName, BindingFlags.Static | BindingFlags.Public, null, new Type[1] { cSteamIdType }, null); if (method == null) { return -1; } return (method.Invoke(null, new object[1] { steamId }) is int num) ? num : (-1); } catch { return -1; } } private static Texture2D BuildFallbackAvatar(PlayerInfo player) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: 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) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0131: 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_0166: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) Texture2D val = new Texture2D(184, 184, (TextureFormat)4, false) { hideFlags = (HideFlags)61, wrapMode = (TextureWrapMode)1, filterMode = (FilterMode)1, name = "CubeX_FallbackPfp_" + player.Id }; Color32[] array = (Color32[])(object)new Color32[33856]; Color32 a = default(Color32); ((Color32)(ref a))..ctor((byte)20, (byte)22, (byte)28, byte.MaxValue); Color32 b = default(Color32); ((Color32)(ref b))..ctor((byte)34, (byte)37, (byte)46, byte.MaxValue); Color32 color = default(Color32); ((Color32)(ref color))..ctor((byte)8, (byte)10, (byte)14, byte.MaxValue); Color32 color2 = (Color32)(player.IsDead ? new Color32((byte)150, (byte)40, (byte)45, byte.MaxValue) : ColorFromPlayerId(player.Id)); for (int i = 0; i < 184; i++) { float t = (float)i / 183f; Color32 val2 = LerpColor(a, b, t); int num = i * 184; for (int j = 0; j < 184; j++) { array[num + j] = val2; } } DrawCircle(array, 184, 184, 92, 100, 58, color2); DrawCircle(array, 184, 184, 92, 100, 39, new Color32((byte)28, (byte)31, (byte)38, byte.MaxValue)); DrawRect(array, 184, 184, 0, 166, 184, 18, color2); DrawBorder(array, 184, 184, 3, color); if (player.IsDead) { ApplyDeadTint(array); } FlipPixelsVertical(array, 184, 184); val.SetPixels32(array); val.Apply(false); return val; } private void PruneStaleAvatarCache() { if (_avatarCache.Count == 0) { return; } HashSet hashSet = new HashSet(); for (int i = 0; i < _players.Count; i++) { hashSet.Add(_players[i].Id); } List list = null; foreach (KeyValuePair item in _avatarCache) { if (!hashSet.Contains(item.Key) || !Object.op_Implicit((Object)(object)item.Value.Texture)) { (list ?? (list = new List())).Add(item.Key); } } if (list == null) { return; } foreach (string item2 in list) { if (_avatarCache.TryGetValue(item2, out var value) && Object.op_Implicit((Object)(object)value.Texture)) { Object.Destroy((Object)(object)value.Texture); } _avatarCache.Remove(item2); } } public void Dispose() { if (ActiveInstance == this) { ActiveInstance = null; } DisposeAvatars(); } private void DisposeAvatars() { foreach (AvatarCacheEntry item in _avatarCache.Values.Where((AvatarCacheEntry entry) => Object.op_Implicit((Object)(object)entry.Texture))) { Object.Destroy((Object)(object)item.Texture); } _avatarCache.Clear(); } private static void DrawRect(Color32[] px, int w, int h, int x, int y, int rw, int rh, Color32 color) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) int num = Math.Max(0, x); int num2 = Math.Max(0, y); int num3 = Math.Min(w, x + rw); int num4 = Math.Min(h, y + rh); for (int i = num2; i < num4; i++) { int num5 = i * w; for (int j = num; j < num3; j++) { px[num5 + j] = color; } } } private static void FlipPixelsVertical(Color32[] pixels, int width, int height) { if (pixels != null && width > 0 && height > 1) { Color32[] array = (Color32[])(object)new Color32[width]; for (int i = 0; i < height / 2; i++) { int num = i * width; int num2 = (height - 1 - i) * width; Array.Copy(pixels, num, array, 0, width); Array.Copy(pixels, num2, pixels, num, width); Array.Copy(array, 0, pixels, num2, width); } } } private static void DrawBorder(Color32[] px, int w, int h, int thickness, Color32 color) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) DrawRect(px, w, h, 0, 0, w, thickness, color); DrawRect(px, w, h, 0, h - thickness, w, thickness, color); DrawRect(px, w, h, 0, 0, thickness, h, color); DrawRect(px, w, h, w - thickness, 0, thickness, h, color); } private static void DrawCircle(Color32[] px, int w, int h, int cx, int cy, int r, Color32 color) { //IL_0067: 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 (r <= 0) { return; } int num = r * r; int num2 = Math.Max(0, cx - r); int num3 = Math.Min(w - 1, cx + r); int num4 = Math.Max(0, cy - r); int num5 = Math.Min(h - 1, cy + r); for (int i = num4; i <= num5; i++) { int num6 = i - cy; int num7 = num6 * num6; int num8 = i * w; for (int j = num2; j <= num3; j++) { int num9 = j - cx; if (num9 * num9 + num7 <= num) { px[num8 + j] = color; } } } } private static void ApplyDeadTint(Color32[] px) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < px.Length; i++) { Color32 val = px[i]; val.r = (byte)(val.r * 75 / 100); val.g = (byte)(val.g * 60 / 100); val.b = (byte)(val.b * 60 / 100); px[i] = val; } } private static Color32 LerpColor(Color32 a, Color32 b, float t) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0039: 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) t = Mathf.Clamp01(t); return new Color32((byte)Mathf.Lerp((float)(int)a.r, (float)(int)b.r, t), (byte)Mathf.Lerp((float)(int)a.g, (float)(int)b.g, t), (byte)Mathf.Lerp((float)(int)a.b, (float)(int)b.b, t), byte.MaxValue); } private static Color32 ColorFromPlayerId(string id) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0065: 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) int num = 0; if (!string.IsNullOrEmpty(id)) { for (int i = 0; i < id.Length; i++) { num = num * 31 + id[i]; } } Color val = Color.HSVToRGB((float)(Math.Abs(num) % 1000) / 1000f, 0.55f, 0.72f); return new Color32((byte)(val.r * 255f), (byte)(val.g * 255f), (byte)(val.b * 255f), byte.MaxValue); } private PlayerInfo FindPlayer(string id) { PlayerInfo playerInfo = FindPlayerInCache(id); if (playerInfo != null) { return playerInfo; } RefreshPlayers(force: true); return FindPlayerInCache(id); } private PlayerInfo FindPlayerInCache(string id) { if (string.IsNullOrWhiteSpace(id)) { return null; } for (int i = 0; i < _players.Count; i++) { if (_players[i].Id == id) { return _players[i]; } } return null; } private void RefreshPlayersIfNeeded() { if (!(Time.unscaledTime < _nextRefreshAt)) { RefreshPlayers(force: false); } } private void RefreshPlayers(bool force) { if (!force && Time.unscaledTime < _nextRefreshAt) { return; } Character localCharacter = Character.localCharacter; _players.Clear(); Dictionary dictionary = new Dictionary(); foreach (Character candidateCharacter in GetCandidateCharacters()) { if (Object.op_Implicit((Object)(object)candidateCharacter) && IsPlayerCharacter(candidateCharacter, localCharacter)) { PlayerInfo playerInfo = CreatePlayerInfo(candidateCharacter, localCharacter); RecentPlayersStore.RecordLivePlayer(playerInfo.DisplayName, playerInfo.ActorText, playerInfo.SteamId, playerInfo.PhotonUserId, playerInfo.RoomName, playerInfo.Region, playerInfo.IsLocal, playerInfo.ModFlags); if (!dictionary.TryGetValue(playerInfo.Id, out var value) || ShouldReplace(value, playerInfo)) { dictionary[playerInfo.Id] = playerInfo; } } } _players.AddRange(dictionary.Values); _players.Sort(ComparePlayers); _nextRefreshAt = Time.unscaledTime + 0.25f; PruneStaleAvatarCache(); } private static int ComparePlayers(PlayerInfo a, PlayerInfo b) { int num = BoolSortDescending(a.IsHost, b.IsHost); if (num != 0) { return num; } int num2 = BoolSortDescending(a.IsLocal, b.IsLocal); if (num2 != 0) { return num2; } return string.Compare(a.DisplayName, b.DisplayName, StringComparison.OrdinalIgnoreCase); } private static int BoolSortDescending(bool a, bool b) { return (b ? 1 : 0) - (a ? 1 : 0); } private static bool ShouldReplace(PlayerInfo existing, PlayerInfo candidate) { if (candidate.IsCurrentLocal && !existing.IsCurrentLocal) { return true; } if (candidate.IsRegisteredToPlayer && !existing.IsRegisteredToPlayer) { return true; } if (candidate.IsLocal && !existing.IsLocal) { return true; } if (!candidate.IsDead && existing.IsDead) { return true; } if (candidate.HasPhotonView && !existing.HasPhotonView) { return true; } return false; } [IteratorStateMachine(typeof(d__72))] private static IEnumerable GetCandidateCharacters() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__72(-2); } private static bool IsPlayerCharacter(Character character, Character local) { if (!Object.op_Implicit((Object)(object)character)) { return false; } if (Object.op_Implicit((Object)(object)local) && (Object)(object)character == (Object)(object)local) { return true; } if (character.isBot || character.isZombie || character.isScoutmaster) { return false; } if (SafeIsRegisteredToPlayer(character)) { return true; } PhotonView val = ((Component)character).GetComponent() ?? ((Component)character).GetComponentInParent() ?? ((Component)character).GetComponentInChildren(); if (Object.op_Implicit((Object)(object)val) && (val.Owner != null || val.Controller != null)) { return true; } return character.IsPlayerControlled; } private PlayerInfo CreatePlayerInfo(Character character, Character local) { //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_0454: Unknown result type (might be due to invalid IL or missing references) //IL_0459: Unknown result type (might be due to invalid IL or missing references) //IL_04bb: Unknown result type (might be due to invalid IL or missing references) //IL_04bd: Unknown result type (might be due to invalid IL or missing references) //IL_04e0: Unknown result type (might be due to invalid IL or missing references) //IL_04e5: Unknown result type (might be due to invalid IL or missing references) PhotonView val = ((Component)character).GetComponent() ?? ((Component)character).GetComponentInChildren(); Player val2 = (Object.op_Implicit((Object)(object)val) ? (val.Controller ?? val.Owner) : null); int num = ((val2 != null) ? val2.ActorNumber : (-1)); ulong steamId = TryGetSteamId(val); string id = ((num > 0) ? ("actor-" + num) : ("object-" + ((Object)character).GetInstanceID())); string displayName = GetDisplayName(character, val, num); bool flag = Object.op_Implicit((Object)(object)local) && (Object)(object)character == (Object)(object)local; bool flag2 = flag || character.IsLocal || (Object.op_Implicit((Object)(object)val) && val.IsMine); bool isRegisteredToPlayer = SafeIsRegisteredToPlayer(character); bool isHost = IsHost(val); bool isDead = Object.op_Implicit((Object)(object)character.data) && character.data.dead; Vector3 position = ((Component)character).transform.position; object customProperties = ((val2 != null) ? GetMemberValue(val2, "CustomProperties") : null); string text = ((val2 != null) ? PlayerFlagDetector.GetFlagText(val2, includeDetectedModder: true) : PlayerFlagDetector.GetFlagText(customProperties)); string voiceServerAddress = string.Empty; string text2 = string.Empty; float? distance = ((Object.op_Implicit((Object)(object)local) && !flag2) ? new float?(Vector3.Distance(((Component)local).transform.position, position)) : null); float? stamina = (Object.op_Implicit((Object)(object)character.data) ? new float?(character.data.currentStamina) : null); float? staminaMax = (Object.op_Implicit((Object)(object)character) ? new float?(character.GetMaxStamina()) : null); float? passOut = (Object.op_Implicit((Object)(object)character.data) ? new float?(character.data.passOutValue) : null); object data = character.data; CharacterAfflictions afflictions = GetAfflictions(character); CharacterMovement val3 = ((!Object.op_Implicit((Object)(object)character)) ? null : character.refs?.movement); Rigidbody val4 = ((Component)character).GetComponent() ?? ((Component)character).GetComponentInChildren(); if (flag2) { string localVoiceServerAddress = GetLocalVoiceServerAddress(); if (!string.IsNullOrEmpty(localVoiceServerAddress)) { voiceServerAddress = localVoiceServerAddress; } if (string.IsNullOrEmpty(text2)) { text2 = PhotonNetwork.GetPing().ToString(CultureInfo.InvariantCulture) + " ms"; } } PlayerInfo obj = new PlayerInfo { Id = id, Character = character, DisplayName = displayName, MenuName = displayName, ActorText = ((num > 0) ? num.ToString(CultureInfo.InvariantCulture) : string.Empty), IsCurrentLocal = flag, IsRegisteredToPlayer = isRegisteredToPlayer, IsHost = isHost, IsLocal = flag2, IsDead = isDead, Stamina = stamina, StaminaMax = staminaMax, PassOut = passOut, TotalStamina = GetFloat(data, "TotalStamina"), ExtraStamina = GetFloat(data, "extraStamina"), StaminaDelta = GetFloat(data, "staminaDelta"), StaminaMod = GetFloat(data, "staminaMod"), FallSeconds = GetFloat(data, "fallSeconds"), IsGrounded = GetBool(data, "isGrounded"), IsClimbing = GetBool(data, "isClimbing"), IsRopeClimbing = GetBool(data, "isRopeClimbing"), IsVineClimbing = GetBool(data, "isVineClimbing"), PassedOut = GetBool(data, "passedOut"), FullyPassedOut = GetBool(data, "fullyPassedOut"), JumpsRemaining = GetInt(data, "jumpsRemaining"), MovementModifier = (Object.op_Implicit((Object)(object)val3) ? new float?(val3.movementModifier) : null), SprintMultiplier = (Object.op_Implicit((Object)(object)val3) ? new float?(val3.sprintMultiplier) : null), JumpImpulse = (Object.op_Implicit((Object)(object)val3) ? new float?(val3.jumpImpulse) : null), CurrentMovementForce = GetFloat(val3, "CurrentMovementForce") }; float? speed; if (!Object.op_Implicit((Object)(object)val4)) { speed = null; } else { Vector3 linearVelocity = val4.linearVelocity; speed = ((Vector3)(ref linearVelocity)).magnitude; } obj.Speed = speed; obj.StatusSum = GetFloat(afflictions, "statusSum"); obj.ShouldPassOut = GetBool(afflictions, "shouldPassOut"); obj.IsWebbed = GetBool(afflictions, "isWebbed"); obj.Statuses = BuildStatusList(afflictions); obj.Distance = distance; obj.Position = position; obj.SteamId = steamId; obj.PhotonUserId = ((val2 != null) ? val2.UserId : string.Empty); ClientState networkClientState = PhotonNetwork.NetworkClientState; obj.ConnectionState = ((object)(ClientState)(ref networkClientState)).ToString(); obj.Region = (string.IsNullOrEmpty(PhotonNetwork.CloudRegion) ? "-" : PhotonNetwork.CloudRegion); obj.PingText = PhotonNetwork.GetPing().ToString(CultureInfo.InvariantCulture) + " ms"; obj.RoomName = ((PhotonNetwork.CurrentRoom != null) ? PhotonNetwork.CurrentRoom.Name : "-"); obj.RoomPlayersText = ((PhotonNetwork.CurrentRoom != null) ? (PhotonNetwork.CurrentRoom.PlayerCount.ToString(CultureInfo.InvariantCulture) + "/" + PhotonNetwork.CurrentRoom.MaxPlayers.ToString(CultureInfo.InvariantCulture)) : "-"); obj.MasterClientText = ((PhotonNetwork.MasterClient != null) ? (PhotonNetwork.MasterClient.NickName + " #" + PhotonNetwork.MasterClient.ActorNumber.ToString(CultureInfo.InvariantCulture)) : "-"); obj.HasExternalClientMarker = PlayerFlagDetector.HasFlag(text, "Atlas"); obj.CherryUser = PlayerFlagDetector.HasFlag(text, "Cherry"); obj.ModFlags = text; obj.HasPhotonView = Object.op_Implicit((Object)(object)val) && val.Owner != null; obj.VoiceServerAddress = voiceServerAddress; obj.VoicePingText = text2; return obj; } private static string GetLocalVoiceServerAddress() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Invalid comparison between Unknown and I4 try { PunVoiceClient instance = PunVoiceClient.Instance; if (!Object.op_Implicit((Object)(object)instance) || ((VoiceConnection)instance).Client == null || (int)((VoiceConnection)instance).ClientState != 9) { return string.Empty; } return NormalizeVoiceEndpoint(((LoadBalancingClient)((VoiceConnection)instance).Client).GameServerAddress); } catch { return string.Empty; } } private static string NormalizeVoiceEndpoint(object value) { string text = value?.ToString()?.Trim(); if (string.IsNullOrEmpty(text)) { return string.Empty; } if (string.Equals(text, "Unknown", StringComparison.OrdinalIgnoreCase)) { return string.Empty; } if (string.Equals(text, "Disconnected", StringComparison.OrdinalIgnoreCase)) { return string.Empty; } return text; } private static string FormatVoicePing(object value) { string text = value?.ToString()?.Trim(); if (string.IsNullOrEmpty(text)) { return string.Empty; } if (int.TryParse(text, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result)) { return result.ToString(CultureInfo.InvariantCulture) + " ms"; } if (!text.EndsWith("ms", StringComparison.OrdinalIgnoreCase)) { return text + " ms"; } return text; } private static bool SafeIsRegisteredToPlayer(Character character) { if (!Object.op_Implicit((Object)(object)character)) { return false; } try { return character.IsRegisteredToPlayer; } catch { return false; } } private static bool IsHost(PhotonView view) { Player val = (Object.op_Implicit((Object)(object)view) ? (view.Controller ?? view.Owner) : null); if (val == null || PhotonNetwork.MasterClient == null) { return false; } return val.ActorNumber == PhotonNetwork.MasterClient.ActorNumber; } private ulong TryGetSteamId(PhotonView view) { Player player = (Object.op_Implicit((Object)(object)view) ? (view.Controller ?? view.Owner) : null); return TryGetSteamId(player); } private ulong TryGetSteamId(Player player) { if (player == null) { return 0uL; } if (!string.IsNullOrWhiteSpace(player.UserId) && ulong.TryParse(player.UserId, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result)) { return result; } if (TryGetSteamIdFromDictionaryLikeObject(GetMemberValue(player, "CustomProperties"), out result)) { return result; } object obj = GetMemberValue(player, "steamId") ?? GetMemberValue(player, "SteamId") ?? GetMemberValue(player, "SteamID") ?? GetMemberValue(player, "m_SteamID"); if (obj != null && ulong.TryParse(obj.ToString(), NumberStyles.Integer, CultureInfo.InvariantCulture, out result)) { return result; } return 0uL; } private static bool TryGetSteamIdFromDictionaryLikeObject(object source, out ulong steamId) { steamId = 0uL; if (source == null) { return false; } string[] array = new string[4] { "steamid", "steamId", "SteamId", "SteamID" }; string[] array2; if (source is IDictionary dictionary) { array2 = array; foreach (string key in array2) { object obj = null; try { if (dictionary.Contains(key)) { obj = dictionary[key]; } } catch { } if (obj != null && ulong.TryParse(obj.ToString(), NumberStyles.Integer, CultureInfo.InvariantCulture, out steamId)) { return true; } } } Type type = source.GetType(); MethodInfo methodInfo = type.GetMethod("ContainsKey", new Type[1] { typeof(object) }) ?? type.GetMethod("ContainsKey", new Type[1] { typeof(string) }) ?? type.GetMethod("Contains", new Type[1] { typeof(object) }) ?? type.GetMethod("Contains", new Type[1] { typeof(string) }); PropertyInfo propertyInfo = type.GetProperty("Item", new Type[1] { typeof(object) }) ?? type.GetProperty("Item", new Type[1] { typeof(string) }); if (methodInfo == null || propertyInfo == null) { return false; } array2 = array; foreach (string text in array2) { try { object obj3 = methodInfo.Invoke(source, new object[1] { text }); if (obj3 is bool && (bool)obj3) { object value = propertyInfo.GetValue(source, new object[1] { text }); if (value != null && ulong.TryParse(value.ToString(), NumberStyles.Integer, CultureInfo.InvariantCulture, out steamId)) { return true; } } } catch { } } return false; } private static object GetDictionaryLikeValue(object source, string key) { if (source == null || string.IsNullOrEmpty(key)) { return null; } if (source is IDictionary dictionary) { try { return dictionary.Contains(key) ? dictionary[key] : null; } catch { return null; } } Type type = source.GetType(); MethodInfo methodInfo = type.GetMethod("ContainsKey", new Type[1] { typeof(object) }) ?? type.GetMethod("ContainsKey", new Type[1] { typeof(string) }) ?? type.GetMethod("Contains", new Type[1] { typeof(object) }) ?? type.GetMethod("Contains", new Type[1] { typeof(string) }); PropertyInfo propertyInfo = type.GetProperty("Item", new Type[1] { typeof(object) }) ?? type.GetProperty("Item", new Type[1] { typeof(string) }); if (methodInfo == null || propertyInfo == null) { return null; } try { object obj2 = methodInfo.Invoke(source, new object[1] { key }); if (!(obj2 is bool) || !(bool)obj2) { return null; } return propertyInfo.GetValue(source, new object[1] { key }); } catch { return null; } } private string GetDisplayName(Character character, PhotonView view, int actorNumber) { Player val = (Object.op_Implicit((Object)(object)view) ? (view.Controller ?? view.Owner) : null); if (val != null && !string.IsNullOrEmpty(val.NickName)) { return val.NickName; } string text = GetString(character, "characterName") ?? GetString(character, "playerName") ?? GetString(character.data, "characterName") ?? GetString(character.data, "playerName") ?? GetString(character.data, "playerNameString"); if (!string.IsNullOrEmpty(text)) { return text; } if (actorNumber > 0) { return "Player " + actorNumber.ToString(CultureInfo.InvariantCulture); } return "Player " + ((Object)character).GetInstanceID().ToString(CultureInfo.InvariantCulture); } private static CharacterAfflictions GetAfflictions(Character character) { if (!Object.op_Implicit((Object)(object)character)) { return null; } CharacterAfflictions val = ((Component)character).GetComponent(); if (!Object.op_Implicit((Object)(object)val)) { val = ((Component)character).GetComponentInChildren(); } return val; } private static List BuildStatusList(CharacterAfflictions afflictions) { List list = new List(); if (!Object.op_Implicit((Object)(object)afflictions)) { return list; } Array values = Enum.GetValues(typeof(STATUSTYPE)); list.AddRange(from status in values.Cast().Select((Func)((object t, int i) => (STATUSTYPE)values.GetValue(i))) select new StatusInfo(((object)(STATUSTYPE)(ref status)).ToString(), TryGetStatusValue(afflictions, status))); return list; } private static float? TryGetStatusValue(CharacterAfflictions afflictions, STATUSTYPE status) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)afflictions)) { return null; } try { return afflictions.GetCurrentStatus(status); } catch { return null; } } private static void AddStatusRow(List rows, string name, float? value) { if (value.HasValue && !(Mathf.Abs(value.Value) <= 0.001f)) { rows.Add(new InfoFeature(name, FormatStatusValue(value.Value))); } } private static string FormatPercent(float? value, float? max) { if (!value.HasValue) { return "--"; } float num = ((max.HasValue && max.Value > 0.001f) ? max.Value : 1f); return Mathf.RoundToInt(Mathf.Clamp01(value.Value / num) * 100f).ToString(CultureInfo.InvariantCulture) + "%"; } private static string FormatStatusValue(float value) { if (Mathf.Abs(value) <= 1.001f) { return Mathf.RoundToInt(Mathf.Clamp01(value) * 100f).ToString(CultureInfo.InvariantCulture) + "%"; } return value.ToString("F1", CultureInfo.InvariantCulture); } private static string BuildDistanceVisual(float? distance) { if (!distance.HasValue) { return "Self"; } string text = ((distance.Value < 10f) ? "Close" : ((distance.Value < 35f) ? "Mid" : "Far")); return distance.Value.ToString("F1", CultureInfo.InvariantCulture) + " m • " + text; } private static string FormatSpeed(float? speed) { if (!speed.HasValue) { return "-"; } return speed.Value.ToString("F1", CultureInfo.InvariantCulture) + " u/s"; } private float? GetFloat(object target, string name) { return ConvertToFloat(GetMemberValue(target, name)); } private int? GetInt(object target, string name) { object memberValue = GetMemberValue(target, name); if (memberValue == null) { return null; } if (memberValue is int) { return (int)memberValue; } try { return Convert.ToInt32(memberValue, CultureInfo.InvariantCulture); } catch { return null; } } private bool? GetBool(object target, string name) { object memberValue = GetMemberValue(target, name); if (memberValue == null) { return null; } if (memberValue is bool) { return (bool)memberValue; } if (bool.TryParse(memberValue.ToString(), out var result)) { return result; } return null; } private static float? ConvertToFloat(object value) { if (value == null) { return null; } if (value is float) { return (float)value; } if (value is double num) { return (float)num; } if (value is int num2) { return num2; } try { return Convert.ToSingle(value, CultureInfo.InvariantCulture); } catch { return null; } } private string GetString(object target, string name) { return GetMemberValue(target, name) as string; } private object GetMemberValue(object target, string name) { if (target == null || string.IsNullOrEmpty(name)) { return null; } Type type = target.GetType(); MemberKey key = new MemberKey(type, name); if (!_memberInfoCache.TryGetValue(key, out var value)) { value = (MemberInfo)(((object)type.GetField(name, BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) ?? ((object)type.GetProperty(name, BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))); _memberInfoCache[key] = value; } if (value == null) { return null; } try { MemberInfo memberInfo = value; if (!(memberInfo is FieldInfo fieldInfo)) { if (memberInfo is PropertyInfo propertyInfo && propertyInfo.GetIndexParameters().Length == 0) { return propertyInfo.GetValue(target, null); } return null; } return fieldInfo.GetValue(target); } catch { return null; } } } internal static class PlayerFlagDetector { private readonly struct FlagDefinition { public string PropertyKey { get; } public string DisplayName { get; } public string TagText { get; } public Color Color { get; } public FlagDefinition(string propertyKey, string displayName, string tagText, Color color) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) PropertyKey = propertyKey; DisplayName = displayName; TagText = tagText; Color = color; } } private static readonly object DetectedModderLock = new object(); private static readonly HashSet DetectedModderActors = new HashSet(StringComparer.Ordinal); private static readonly HashSet DetectedModderUserIds = new HashSet(StringComparer.Ordinal); private static readonly FlagDefinition[] KnownFlags = new FlagDefinition[4] { new FlagDefinition("AtlOwner", "Atlas Owner", "ATLAS OWNER", new Color(0.64f, 0.42f, 0.86f, 1f)), new FlagDefinition("AtlUser", "Atlas", "ATLAS", new Color(0.56f, 0.36f, 0.78f, 1f)), new FlagDefinition("CherryOwner", "Cherry Owner", "CHERRY OWNER", new Color(0.92f, 0.24f, 0.48f, 1f)), new FlagDefinition("CherryUser", "Cherry", "CHERRY", new Color(0.84f, 0.2f, 0.42f, 1f)) }; public static string GetFlagText(Player player, bool includeDetectedModder = false) { if (player == null) { return string.Empty; } object customProperties = null; try { customProperties = player.CustomProperties; } catch { } string flagText = GetFlagText(customProperties); if (includeDetectedModder && string.IsNullOrEmpty(flagText) && IsDetectedModder(player)) { return "Modder"; } return flagText; } public static string GetFlagText(object customProperties) { if (customProperties == null) { return string.Empty; } return FormatFlags(KnownFlags.Where(delegate(FlagDefinition flag) { object source = customProperties; FlagDefinition flagDefinition2 = flag; return HasDictionaryLikeKey(source, flagDefinition2.PropertyKey); }).Select(delegate(FlagDefinition flag) { FlagDefinition flagDefinition = flag; return flagDefinition.DisplayName; }).ToList()); } public static void MarkDetectedModder(Player player) { if (player == null || HasKnownModFlag(player)) { return; } lock (DetectedModderLock) { string actorScopeKey = GetActorScopeKey(player); if (!string.IsNullOrEmpty(actorScopeKey)) { DetectedModderActors.Add(actorScopeKey); } if (!string.IsNullOrWhiteSpace(player.UserId)) { DetectedModderUserIds.Add(player.UserId); } } } public static bool IsKnownModClient(Player player) { return HasKnownModFlag(player); } public static bool IsKnownOrDetectedModClient(Player player) { if (!HasKnownModFlag(player)) { return IsDetectedModder(player); } return true; } public static IReadOnlyList SplitFlagText(string flagText) { if (string.IsNullOrWhiteSpace(flagText)) { return Array.Empty(); } return (from flag in flagText.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries) select flag.Trim() into flag where !string.IsNullOrEmpty(flag) select flag).Distinct(StringComparer.OrdinalIgnoreCase).OrderBy((string flag) => flag, StringComparer.OrdinalIgnoreCase).ToArray(); } public static bool HasFlag(string flagText, string flagPrefix) { if (!string.IsNullOrWhiteSpace(flagPrefix)) { return SplitFlagText(flagText).Any((string flag) => flag.StartsWith(flagPrefix, StringComparison.OrdinalIgnoreCase)); } return false; } public static List BuildTags(string flagText, int maxTags = 3) { return (from flag in SplitFlagText(flagText).Take(Mathf.Max(0, maxTags)) select new MenuTag(GetTagText(flag), GetTagColor(flag))).ToList(); } public static Color GetTagColor(string flag) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrWhiteSpace(flag)) { return new Color(0.86f, 0.22f, 0.2f, 1f); } FlagDefinition[] knownFlags = KnownFlags; for (int i = 0; i < knownFlags.Length; i++) { FlagDefinition flagDefinition = knownFlags[i]; if (string.Equals(flag, flagDefinition.DisplayName, StringComparison.OrdinalIgnoreCase)) { return flagDefinition.Color; } } return new Color(0.86f, 0.22f, 0.2f, 1f); } private static string GetTagText(string flag) { if (string.IsNullOrWhiteSpace(flag)) { return "MOD"; } if (string.Equals(flag, "Modder", StringComparison.OrdinalIgnoreCase)) { return "MODDER"; } FlagDefinition[] knownFlags = KnownFlags; for (int i = 0; i < knownFlags.Length; i++) { FlagDefinition flagDefinition = knownFlags[i]; if (string.Equals(flag, flagDefinition.DisplayName, StringComparison.OrdinalIgnoreCase)) { return flagDefinition.TagText; } } return flag.ToUpperInvariant(); } private static string FormatFlags(IEnumerable flags) { if (flags == null) { return string.Empty; } string[] array = (from flag in flags where !string.IsNullOrWhiteSpace(flag) select flag.Trim()).Distinct(StringComparer.OrdinalIgnoreCase).OrderBy((string flag) => flag, StringComparer.OrdinalIgnoreCase).ToArray(); if (array.Length != 0) { return string.Join(", ", array); } return string.Empty; } public static bool IsDetectedModder(Player player) { if (player == null) { return false; } lock (DetectedModderLock) { string actorScopeKey = GetActorScopeKey(player); if (!string.IsNullOrEmpty(actorScopeKey) && DetectedModderActors.Contains(actorScopeKey)) { return true; } return !string.IsNullOrWhiteSpace(player.UserId) && DetectedModderUserIds.Contains(player.UserId); } } private static bool HasKnownModFlag(Player player) { if (player == null) { return false; } object obj = null; try { obj = player.CustomProperties; } catch { } if (obj == null) { return false; } FlagDefinition[] knownFlags = KnownFlags; foreach (FlagDefinition flagDefinition in knownFlags) { if (HasDictionaryLikeKey(obj, flagDefinition.PropertyKey)) { return true; } } return false; } private static string GetActorScopeKey(Player player) { if (player == null || player.ActorNumber == 0) { return null; } string text = "local"; try { if (PhotonNetwork.CurrentRoom != null && !string.IsNullOrWhiteSpace(PhotonNetwork.CurrentRoom.Name)) { text = PhotonNetwork.CurrentRoom.Name; } } catch { } return text + ":" + player.ActorNumber; } private static bool HasDictionaryLikeKey(object source, string key) { if (source == null || string.IsNullOrEmpty(key)) { return false; } if (!(source is IDictionary dictionary)) { return false; } try { return dictionary.Contains(key); } catch { return false; } } } public class PlayerSpectate : Feature { private sealed class SpectateOrbitDriver : MonoBehaviour { [FormerlySerializedAs("Target")] public Character target; [FormerlySerializedAs("Distance")] public float distance = 1.5f; [FormerlySerializedAs("SnapNextFrame")] public bool snapNextFrame; private float _yaw; private float _pitch = 15f; public void InitializeFromCurrentCamera(Transform cameraTransform, Character target) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_007e: 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_0085: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)cameraTransform) && Object.op_Implicit((Object)(object)target)) { Vector3 lookPoint = GetLookPoint(target); Vector3 val = cameraTransform.position - lookPoint; if (((Vector3)(ref val)).sqrMagnitude < 0.001f) { _yaw = ((Component)target).transform.eulerAngles.y; _pitch = 15f; distance = 1.5f; } else { distance = Mathf.Clamp(((Vector3)(ref val)).magnitude, 1f, 15f); Vector3 normalized = ((Vector3)(ref val)).normalized; _pitch = Mathf.Asin(normalized.y) * 57.29578f; _pitch = Mathf.Clamp(_pitch, -80f, 80f); _yaw = Mathf.Atan2(normalized.x, normalized.z) * 57.29578f; } } } private void LateUpdate() { //IL_00a8: 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_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: 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_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)target)) { float axisRaw = Input.GetAxisRaw("Mouse X"); float axisRaw2 = Input.GetAxisRaw("Mouse Y"); float axisRaw3 = Input.GetAxisRaw("Mouse ScrollWheel"); _yaw += axisRaw * 4f; _pitch -= axisRaw2 * 4f; _pitch = Mathf.Clamp(_pitch, -80f, 80f); if (Mathf.Abs(axisRaw3) > 0.0001f) { distance = Mathf.Clamp(distance - axisRaw3 * 4f, 1f, 15f); } Vector3 lookPoint = GetLookPoint(target); Vector3 val = Quaternion.Euler(_pitch, _yaw, 0f) * new Vector3(0f, 0f, 0f - distance); Vector3 val2 = lookPoint + val; Quaternion val3 = Quaternion.LookRotation(lookPoint - val2, Vector3.up); float unscaledDeltaTime = Time.unscaledDeltaTime; float num = ((snapNextFrame || unscaledDeltaTime <= 0f) ? 1f : (1f - Mathf.Exp(-22f * unscaledDeltaTime))); ((Component)this).transform.position = Vector3.Lerp(((Component)this).transform.position, val2, num); ((Component)this).transform.rotation = Quaternion.Slerp(((Component)this).transform.rotation, val3, num); snapNextFrame = false; } } } public static readonly PlayerSpectate Instance = new PlayerSpectate(); private const float DefaultDistance = 1.5f; private const float MinDistance = 1f; private const float MaxDistance = 15f; private const float MouseSensitivity = 4f; private const float ScrollSensitivity = 4f; private const float LookHeight = 1.45f; private const float CameraSmoothness = 22f; [CanBeNull] private MainCameraMovement _cameraMovement; [CanBeNull] private Camera _camera; [CanBeNull] private SpectateOrbitDriver _driver; private bool _cameraMovementWasEnabled; private bool _hasCameraMovementState; [CanBeNull] private Transform _originalParent; private Vector3 _originalCameraWorldPosition; private Quaternion _originalCameraWorldRotation; private Vector3 _originalCameraLocalPosition; private Quaternion _originalCameraLocalRotation; private Vector3 _originalCameraLocalScale; private bool _hadOriginalParent; private bool _hasOriginalCameraState; [CanBeNull] private Character _localCharacter; [CanBeNull] private Behaviour _localMovementBehaviour; private bool _localMovementWasEnabled; [CanBeNull] private Rigidbody _localRigidbody; private RigidbodyConstraints _localOriginalConstraints; private bool _localRigidbodyWasKinematic; private bool _hasLocalRigidbodyState; private Vector3 _localFrozenPosition; private Quaternion _localFrozenRotation; public static bool IsManualSpectating { get; private set; } private PlayerSpectate() { base.Name = "Spectate"; base.Description = "Spectate the selected player."; } protected override void OnEnable() { Character validTarget = GetValidTarget(); if (!Object.op_Implicit((Object)(object)validTarget)) { base.Enabled = false; return; } _camera = Camera.main; if (!Object.op_Implicit((Object)(object)_camera)) { _camera = Object.FindFirstObjectByType(); } if (!Object.op_Implicit((Object)(object)_camera)) { base.Enabled = false; return; } StoreCameraState(((Component)_camera).transform); DisableGameCameraMovement(); FreezeLocalCharacter(); _driver = ((Component)_camera).gameObject.GetComponent(); if (!Object.op_Implicit((Object)(object)_driver)) { _driver = ((Component)_camera).gameObject.AddComponent(); } if (Object.op_Implicit((Object)(object)_driver)) { _driver.target = validTarget; _driver.distance = 1.5f; _driver.snapNextFrame = true; _driver.InitializeFromCurrentCamera(((Component)_camera).transform, validTarget); ((Behaviour)_driver).enabled = true; } IsManualSpectating = true; } public override void OnTick() { if (!base.Enabled) { return; } Character validTarget = GetValidTarget(); if (!Object.op_Implicit((Object)(object)validTarget)) { base.Enabled = false; return; } KeepLocalCharacterFrozen(); if (!Object.op_Implicit((Object)(object)_camera)) { _camera = Camera.main; } if (!Object.op_Implicit((Object)(object)_camera)) { base.Enabled = false; return; } if (!Object.op_Implicit((Object)(object)_driver)) { _driver = ((Component)_camera).gameObject.GetComponent(); } if (!Object.op_Implicit((Object)(object)_driver)) { _driver = ((Component)_camera).gameObject.AddComponent(); } if (Object.op_Implicit((Object)(object)_driver) && (Object)(object)_driver.target != (Object)(object)validTarget) { _driver.target = validTarget; _driver.snapNextFrame = true; _driver.InitializeFromCurrentCamera(((Component)_camera).transform, validTarget); } if (Object.op_Implicit((Object)(object)_driver)) { ((Behaviour)_driver).enabled = true; } } protected override void OnDisable() { IsManualSpectating = false; if (Object.op_Implicit((Object)(object)_driver)) { ((Behaviour)_driver).enabled = false; Object.Destroy((Object)(object)_driver); } RestoreLocalCharacter(); RestoreGameCameraMovement(); if (Object.op_Implicit((Object)(object)_camera) && _hasOriginalCameraState) { RestoreCameraState(((Component)_camera).transform); } _driver = null; _camera = null; _cameraMovement = null; _hasCameraMovementState = false; _hasOriginalCameraState = false; _localCharacter = null; _localMovementBehaviour = null; _localRigidbody = null; _hasLocalRigidbodyState = false; } private static Character GetValidTarget() { Character localCharacter = Character.localCharacter; if (!Object.op_Implicit((Object)(object)localCharacter)) { return null; } if (!PlayerDirectory.TryGetSelectedCharacter(out var character)) { return null; } if (!Object.op_Implicit((Object)(object)character)) { return null; } if (!((Object)(object)character == (Object)(object)localCharacter)) { return character; } return null; } private void DisableGameCameraMovement() { _cameraMovement = TryGetCameraMovement(); if (Object.op_Implicit((Object)(object)_cameraMovement)) { _hasCameraMovementState = true; _cameraMovementWasEnabled = ((Behaviour)_cameraMovement).enabled; ((Behaviour)_cameraMovement).enabled = false; } } private void RestoreGameCameraMovement() { MainCameraMovement val = (Object.op_Implicit((Object)(object)_cameraMovement) ? _cameraMovement : TryGetCameraMovement()); if (Object.op_Implicit((Object)(object)val) && _hasCameraMovementState) { ((Behaviour)val).enabled = _cameraMovementWasEnabled; } } private static MainCameraMovement TryGetCameraMovement() { MainCameraMovement val = null; try { val = Singleton.Instance; } catch { } if (!Object.op_Implicit((Object)(object)val)) { val = Object.FindFirstObjectByType(); } return val; } private void FreezeLocalCharacter() { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_003b: 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) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) _localCharacter = Character.localCharacter; if (Object.op_Implicit((Object)(object)_localCharacter)) { _localFrozenPosition = ((Component)_localCharacter).transform.position; _localFrozenRotation = ((Component)_localCharacter).transform.rotation; _localMovementBehaviour = (Behaviour)(object)_localCharacter.refs?.movement; if (Object.op_Implicit((Object)(object)_localMovementBehaviour)) { _localMovementWasEnabled = _localMovementBehaviour.enabled; _localMovementBehaviour.enabled = false; } _localRigidbody = ((Component)_localCharacter).GetComponent() ?? ((Component)_localCharacter).GetComponentInChildren(); if (Object.op_Implicit((Object)(object)_localRigidbody)) { _hasLocalRigidbodyState = true; _localOriginalConstraints = _localRigidbody.constraints; _localRigidbodyWasKinematic = _localRigidbody.isKinematic; _localRigidbody.linearVelocity = Vector3.zero; _localRigidbody.angularVelocity = Vector3.zero; _localRigidbody.constraints = (RigidbodyConstraints)126; } } } private void KeepLocalCharacterFrozen() { //IL_0047: 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_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)_localCharacter)) { if (Object.op_Implicit((Object)(object)_localRigidbody)) { _localRigidbody.linearVelocity = Vector3.zero; _localRigidbody.angularVelocity = Vector3.zero; } ((Component)_localCharacter).transform.position = _localFrozenPosition; ((Component)_localCharacter).transform.rotation = _localFrozenRotation; } } private void RestoreLocalCharacter() { //IL_003a: 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_006b: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)_localMovementBehaviour)) { _localMovementBehaviour.enabled = _localMovementWasEnabled; } if (Object.op_Implicit((Object)(object)_localRigidbody) && _hasLocalRigidbodyState) { _localRigidbody.constraints = _localOriginalConstraints; _localRigidbody.isKinematic = _localRigidbodyWasKinematic; _localRigidbody.linearVelocity = Vector3.zero; _localRigidbody.angularVelocity = Vector3.zero; } } private void StoreCameraState(Transform cameraTransform) { //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_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //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) _hasOriginalCameraState = true; _originalParent = cameraTransform.parent; _hadOriginalParent = Object.op_Implicit((Object)(object)_originalParent); _originalCameraWorldPosition = cameraTransform.position; _originalCameraWorldRotation = cameraTransform.rotation; _originalCameraLocalPosition = cameraTransform.localPosition; _originalCameraLocalRotation = cameraTransform.localRotation; _originalCameraLocalScale = cameraTransform.localScale; } private void RestoreCameraState(Transform cameraTransform) { //IL_0051: 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_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) if (_hadOriginalParent && Object.op_Implicit((Object)(object)_originalParent)) { cameraTransform.SetParent(_originalParent, false); cameraTransform.localPosition = _originalCameraLocalPosition; cameraTransform.localRotation = _originalCameraLocalRotation; cameraTransform.localScale = _originalCameraLocalScale; } else { cameraTransform.SetParent((Transform)null, true); cameraTransform.position = _originalCameraWorldPosition; cameraTransform.rotation = _originalCameraWorldRotation; cameraTransform.localScale = _originalCameraLocalScale; } } private static Vector3 GetLookPoint(Character target) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: 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_005e: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)target)) { return Vector3.zero; } Vector3 head = target.Head; if (IsUsableWorldPoint(head)) { return head; } Vector3 center = target.Center; if (IsUsableWorldPoint(center)) { return center + Vector3.up * 0.35f; } return ((Component)target).transform.position + Vector3.up * 1.45f; } private static bool IsUsableWorldPoint(Vector3 point) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) if (point != Vector3.zero && !float.IsNaN(point.x) && !float.IsNaN(point.y) && !float.IsNaN(point.z) && !float.IsInfinity(point.x) && !float.IsInfinity(point.y)) { return !float.IsInfinity(point.z); } return false; } } public class AddRecentPlayerOnSteam : ButtonFeature { public AddRecentPlayerOnSteam() { base.Name = "Add On Steam"; base.Description = "Opens Steam's add-friend prompt for the selected recent player."; base.ButtonLabel = "Add"; } public override void Execute() { RecentPlayerRecord selectedRecentPlayer = RecentPlayersDirectory.SelectedRecentPlayer; if (selectedRecentPlayer == null || selectedRecentPlayer.SteamId == 0L) { NotificationSystem.Push("Recent Players", "No Steam ID saved for this player.", NotificationKind.Warning); } else if (!SteamPlayerActions.OpenAddFriend(selectedRecentPlayer.SteamId)) { NotificationSystem.Push("Add On Steam", "Steam overlay add-friend prompt was not available.", NotificationKind.Warning); } } } public class ClearRecentPlayers : ButtonFeature { public ClearRecentPlayers() { base.Name = "Clear Recent Players"; base.Description = "Removes every saved recent player from recent_players.json."; base.ButtonLabel = "Clear"; } public override void Execute() { RecentPlayersStore.Clear(); RecentPlayersDirectory.SelectedRecentPlayer = null; NotificationSystem.Push("Recent Players Cleared", string.Empty, NotificationKind.Success); } } public class CopyRecentPlayerSteamId : ButtonFeature { public CopyRecentPlayerSteamId() { base.Name = "Copy Steam ID"; base.Description = "Copies the selected recent player's Steam ID to the clipboard."; base.ButtonLabel = "Copy"; } public override void Execute() { RecentPlayerRecord selectedRecentPlayer = RecentPlayersDirectory.SelectedRecentPlayer; if (selectedRecentPlayer == null || selectedRecentPlayer.SteamId == 0L) { NotificationSystem.Push("Recent Players", "No Steam ID saved for this player.", NotificationKind.Warning); return; } GUIUtility.systemCopyBuffer = selectedRecentPlayer.SteamId.ToString(CultureInfo.InvariantCulture); NotificationSystem.Push("Steam ID Copied", selectedRecentPlayer.DisplayName, NotificationKind.Success); } } public class InviteRecentPlayerToLobby : ButtonFeature { public InviteRecentPlayerToLobby() { base.Name = "Invite To Lobby"; base.Description = "Sends the selected recent Steam player an invite to your current lobby."; base.ButtonLabel = "Invite"; } public override void Execute() { RecentPlayerRecord selectedRecentPlayer = RecentPlayersDirectory.SelectedRecentPlayer; if (selectedRecentPlayer == null || selectedRecentPlayer.SteamId == 0L) { NotificationSystem.Push("Recent Players", "No Steam ID saved for this player.", NotificationKind.Warning); } else if (SteamPlayerActions.InviteToCurrentLobby(selectedRecentPlayer.SteamId)) { NotificationSystem.Push("Invite Sent", selectedRecentPlayer.DisplayName, NotificationKind.Success); } else { NotificationSystem.Push("Invite Failed", "No active Steam lobby or Steam rejected the invite.", NotificationKind.Warning); } } } public class JoinRecentPlayerGame : ButtonFeature { private readonly ulong _lobbyId; public JoinRecentPlayerGame(ulong lobbyId) { _lobbyId = lobbyId; base.Name = "Join Game"; base.Description = "Attempts to join the live Steam lobby currently reported for this recent player."; base.ButtonLabel = "Join"; } public override void Execute() { RecentPlayerRecord selectedRecentPlayer = RecentPlayersDirectory.SelectedRecentPlayer; ulong num = _lobbyId; if (selectedRecentPlayer != null && selectedRecentPlayer.SteamId != 0L && SteamPlayerActions.TryGetJoinableGameLobby(selectedRecentPlayer.SteamId, out var lobbyId)) { num = lobbyId; } if (num == 0L) { NotificationSystem.Push("Recent Players", "Steam no longer reports a joinable PEAK lobby for this player.", NotificationKind.Warning); } else if (SteamPlayerActions.JoinLobby(num)) { NotificationSystem.Push("Joining Game", selectedRecentPlayer?.DisplayName ?? "Recent player", NotificationKind.Success); } else { NotificationSystem.Push("Join Failed", "Steam lobby join API was not available.", NotificationKind.Warning); } } } public class JoinRecentPlayerLobby : ButtonFeature { public JoinRecentPlayerLobby() { base.Name = "Join Saved Lobby"; base.Description = "Attempts to join the Steam lobby saved when this player was last seen."; base.ButtonLabel = "Join"; } public override void Execute() { RecentPlayerRecord selectedRecentPlayer = RecentPlayersDirectory.SelectedRecentPlayer; if (selectedRecentPlayer == null || selectedRecentPlayer.SteamLobbyId == 0L) { NotificationSystem.Push("Recent Players", "No Steam lobby was saved for this player.", NotificationKind.Warning); } else if (SteamPlayerActions.JoinLobby(selectedRecentPlayer.SteamLobbyId)) { NotificationSystem.Push("Joining Lobby", selectedRecentPlayer.DisplayName, NotificationKind.Success); } else { NotificationSystem.Push("Join Failed", "Steam lobby join API was not available.", NotificationKind.Warning); } } } public class OpenRecentPlayerSteamProfile : ButtonFeature { public OpenRecentPlayerSteamProfile() { base.Name = "Open Steam Profile"; base.Description = "Opens the selected recent player's Steam profile."; base.ButtonLabel = "Open"; } public override void Execute() { RecentPlayerRecord selectedRecentPlayer = RecentPlayersDirectory.SelectedRecentPlayer; if (selectedRecentPlayer == null || selectedRecentPlayer.SteamId == 0L) { NotificationSystem.Push("Recent Players", "No Steam ID saved for this player.", NotificationKind.Warning); } else if (!SteamPlayerActions.OpenProfile(selectedRecentPlayer.SteamId)) { NotificationSystem.Push("Steam Profile", "Steam overlay/profile URL was not available.", NotificationKind.Warning); } } } internal static class PlayerRegionLabels { public static string FormatTag(string region) { string fullName = GetFullName(region); if (!string.IsNullOrEmpty(fullName)) { return fullName.ToUpperInvariant(); } return string.Empty; } public static string FormatInfo(string region) { string text = Normalize(region); string fullName = GetFullName(region); if (string.IsNullOrEmpty(fullName)) { return "-"; } if (!string.IsNullOrEmpty(text)) { return fullName + " (" + text + ")"; } return fullName; } private static string GetFullName(string region) { string text = Normalize(region); return text switch { "asia" => "Asia", "au" => "Australia", "cae" => "Canada East", "cn" => "China", "eu" => "Europe", "in" => "India", "jp" => "Japan", "kr" => "South Korea", "ru" => "Russia", "rue" => "Russia East", "sa" => "South America", "tr" => "Turkey", "uae" => "UAE", "us" => "US East", "use" => "US East", "usw" => "US West", "za" => "South Africa", _ => string.IsNullOrEmpty(text) ? string.Empty : text.ToUpperInvariant(), }; } private static string Normalize(string region) { if (!string.IsNullOrWhiteSpace(region) && !(region == "-")) { return region.Trim().ToLowerInvariant(); } return string.Empty; } } public sealed class RecentPlayerRecord { public string Id { get; set; } public string DisplayName { get; set; } public ulong SteamId { get; set; } public string PhotonUserId { get; set; } public string ActorText { get; set; } public string RoomName { get; set; } public ulong SteamLobbyId { get; set; } public string Region { get; set; } public bool Modded { get; set; } public string ModFlags { get; set; } public bool SpoofedName { get; set; } public string FirstSeenUtc { get; set; } public string LastSeenUtc { get; set; } public int TimesSeen { get; set; } public RecentPlayerRecord Clone() { return (RecentPlayerRecord)MemberwiseClone(); } } public class RecentPlayersDirectory : Feature, IMenuRowProvider, IMenuSidePanelProvider { private struct RecentAvatarCacheEntry { public Texture2D Texture; public ulong SteamId; } private const string RecentPlayersCategory = "Network/Recent Players"; private const string RecentPlayerCategoryPrefix = "Network/Recent Players/"; private const int AvatarSize = 184; private readonly Dictionary _avatarCache = new Dictionary(); public static RecentPlayerRecord SelectedRecentPlayer { get; internal set; } internal static RecentPlayersSortMode SortMode { get; set; } public RecentPlayersDirectory() { base.Name = "Recent Players Directory"; base.Description = "Builds saved recent-player rows for the Network menu."; } public IEnumerable GetRows(string category) { if (category == "Network/Recent Players") { return BuildRecentPlayerRows(); } if (category != null && category.StartsWith("Network/Recent Players/", StringComparison.Ordinal)) { return BuildRecentPlayerDetailRows(category.Substring("Network/Recent Players/".Length)); } return Array.Empty(); } public bool TryGetSidePanel(string category, object selectedRow, out MenuSidePanel panel) { panel = null; string panelRecentPlayerId = GetPanelRecentPlayerId(category, selectedRow); if (string.IsNullOrEmpty(panelRecentPlayerId)) { return false; } RecentPlayerRecord recentPlayerRecord = RecentPlayersStore.Find(panelRecentPlayerId); if (recentPlayerRecord == null) { return false; } SelectedRecentPlayer = recentPlayerRecord; panel = new MenuSidePanel("RECENT PLAYER", recentPlayerRecord.DisplayName, BuildInfoRows(recentPlayerRecord), GetRecentAvatar(recentPlayerRecord), BuildTags(recentPlayerRecord)); return true; } private static IEnumerable BuildRecentPlayerRows() { IReadOnlyList readOnlyList = SortRecords(RecentPlayersStore.GetAll()); List list = new List(); if (readOnlyList.Count > 0) { list.Add(new ClearRecentPlayers()); list.Add(new SeparatorFeature()); } list.AddRange(readOnlyList.Select((RecentPlayerRecord record) => new SubmenuFeature(record.DisplayName, "Network/Recent Players/" + record.Id, "Open Steam and saved-session actions for " + record.DisplayName + ".", BuildTags(record)))); if (readOnlyList.Count == 0) { list.Add(new InfoFeature("Recent Players", "None", "Recent players are saved after joining a room with them.")); } return list; } private static IEnumerable BuildRecentPlayerDetailRows(string id) { RecentPlayerRecord recentPlayerRecord = RecentPlayersStore.Find(id); if (recentPlayerRecord == null) { SelectedRecentPlayer = null; return new <>z__ReadOnlySingleElementList(new InfoFeature("Player", "Not found", "This recent player is no longer saved.")); } SelectedRecentPlayer = recentPlayerRecord; ulong lobbyId = 0uL; bool flag = recentPlayerRecord.SteamId != 0L && SteamPlayerActions.TryGetJoinableGameLobby(recentPlayerRecord.SteamId, out lobbyId); List list = new List { new OpenRecentPlayerSteamProfile() }; if (flag) { list.Add(new JoinRecentPlayerGame(lobbyId)); } if (recentPlayerRecord.SteamLobbyId != 0L && (!flag || recentPlayerRecord.SteamLobbyId != lobbyId)) { list.Add(new JoinRecentPlayerLobby()); } list.Add(new AddRecentPlayerOnSteam()); list.Add(new InviteRecentPlayerToLobby()); list.Add(new CopyRecentPlayerSteamId()); list.Add(PlayerBlacklistStore.Contains(recentPlayerRecord) ? ((ButtonFeature)new RemoveRecentPlayerFromBlacklist()) : ((ButtonFeature)new AddRecentPlayerToBlacklist())); list.Add(new RemoveRecentPlayer()); return list; } internal static List BuildInfoRows(RecentPlayerRecord record) { SteamPlayerActions.SteamFriendPresence friendPresence = SteamPlayerActions.GetFriendPresence(record.SteamId); Player livePlayer = FindLivePhotonPlayer(record); return new List(15) { new InfoFeature("Current Room", BuildCurrentRoomText(livePlayer)), new InfoFeature("Steam Status", BuildSteamStatusText(friendPresence)), new InfoFeature("Game", friendPresence.GameText), new InfoFeature("Joinable", BuildJoinableText(record, friendPresence)), new InfoFeature("Live Lobby", friendPresence.IsJoinable ? friendPresence.LobbyId.ToString(CultureInfo.InvariantCulture) : "-"), new InfoFeature("Saved Lobby", (record.SteamLobbyId == 0L) ? "-" : record.SteamLobbyId.ToString(CultureInfo.InvariantCulture)), new InfoFeature("Steam", FormatSteamId(record.SteamId)), new InfoFeature("Photon", FormatLivePhotonUserId(record, livePlayer)), new InfoFeature("Actor", FormatLiveActor(record, livePlayer)), new InfoFeature("Room", FormatLiveRoom(record, livePlayer)), new InfoFeature("Region", PlayerRegionLabels.FormatInfo(record.Region)), new InfoFeature("Flags", string.IsNullOrEmpty(record.ModFlags) ? "-" : record.ModFlags), new InfoFeature("First Seen", FormatUtc(record.FirstSeenUtc)), new InfoFeature("Last Seen", FormatUtc(record.LastSeenUtc)), new InfoFeature("Seen", record.TimesSeen.ToString(CultureInfo.InvariantCulture)) }; } internal static List BuildTags(RecentPlayerRecord record) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_006c: 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_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_0200: Unknown result type (might be due to invalid IL or missing references) List list = new List(); SteamPlayerActions.SteamFriendPresence friendPresence = SteamPlayerActions.GetFriendPresence(record.SteamId); Player val = FindLivePhotonPlayer(record); if (val != null) { list.Add(new MenuTag("ROOM", new Color(0.22f, 0.7f, 0.42f, 1f))); } if (SteamPlayerActions.IsFriend(record.SteamId)) { list.Add(new MenuTag("FRIEND", new Color(0.22f, 0.5f, 0.9f, 1f))); } if (record.SpoofedName) { list.Add(new MenuTag("NAME SPOOF", new Color(0.9f, 0.4f, 0.14f, 1f))); } if (friendPresence.IsJoinable) { list.Add(new MenuTag("JOINABLE", new Color(0.24f, 0.74f, 0.46f, 1f))); } else if (friendPresence.IsInPeak) { list.Add(new MenuTag("PEAK", new Color(0.22f, 0.62f, 0.88f, 1f))); } if (friendPresence.IsOnline || val != null) { list.Add(new MenuTag("ONLINE", new Color(0.18f, 0.62f, 0.86f, 1f))); } else if (friendPresence.HasSteamId) { list.Add(new MenuTag("OFFLINE", new Color(0.36f, 0.38f, 0.42f, 1f))); } if (record.Modded || !string.IsNullOrEmpty(record.ModFlags)) { List list2 = PlayerFlagDetector.BuildTags(record.ModFlags); if (list2.Count == 0) { list.Add(new MenuTag("MOD", new Color(0.86f, 0.22f, 0.2f, 1f))); } else { list.AddRange(list2); } } string text = PlayerRegionLabels.FormatTag(record.Region); if (!string.IsNullOrEmpty(text)) { list.Add(new MenuTag(text, new Color(0.18f, 0.58f, 0.48f, 1f))); } return list; } private static IReadOnlyList SortRecords(IReadOnlyList records) { if (records == null || records.Count == 0) { return Array.Empty(); } return (SortMode switch { RecentPlayersSortMode.Name => records.OrderBy((RecentPlayerRecord record) => record.DisplayName, StringComparer.OrdinalIgnoreCase).ThenByDescending((RecentPlayerRecord record) => ParseUtc(record.LastSeenUtc)), RecentPlayersSortMode.FirstSeen => records.OrderByDescending((RecentPlayerRecord record) => ParseUtc(record.FirstSeenUtc)).ThenBy((RecentPlayerRecord record) => record.DisplayName, StringComparer.OrdinalIgnoreCase), RecentPlayersSortMode.SeenCount => from record in records orderby record.TimesSeen descending, ParseUtc(record.LastSeenUtc) descending select record, RecentPlayersSortMode.Region => records.OrderBy((RecentPlayerRecord record) => PlayerRegionLabels.FormatTag(record.Region), StringComparer.OrdinalIgnoreCase).ThenBy((RecentPlayerRecord record) => record.DisplayName, StringComparer.OrdinalIgnoreCase), RecentPlayersSortMode.Online => records.OrderByDescending(IsOnline).ThenByDescending(IsJoinable).ThenBy((RecentPlayerRecord record) => record.DisplayName, StringComparer.OrdinalIgnoreCase), _ => records.OrderByDescending((RecentPlayerRecord record) => ParseUtc(record.LastSeenUtc)).ThenBy((RecentPlayerRecord record) => record.DisplayName, StringComparer.OrdinalIgnoreCase), }).ToList(); } private static bool IsOnline(RecentPlayerRecord record) { return SteamPlayerActions.GetFriendPresence(record?.SteamId ?? 0).IsOnline; } private static bool IsJoinable(RecentPlayerRecord record) { return SteamPlayerActions.GetFriendPresence(record?.SteamId ?? 0).IsJoinable; } private static DateTime ParseUtc(string value) { if (!DateTime.TryParse(value, CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal, out var result)) { return DateTime.MinValue; } return result; } private static Player FindLivePhotonPlayer(RecentPlayerRecord record) { if (record == null || !PhotonNetwork.InRoom) { return null; } Player[] playerListOthers; try { playerListOthers = PhotonNetwork.PlayerListOthers; } catch { return null; } return playerListOthers?.FirstOrDefault((Func)((Player player) => MatchesLivePlayer(record, player))); } private static bool MatchesLivePlayer(RecentPlayerRecord record, Player player) { if (record == null || player == null || player.IsLocal) { return false; } bool flag = IsCurrentRoomName(record.RoomName); if (record.SteamId != 0L && !string.IsNullOrWhiteSpace(player.UserId) && ulong.TryParse(player.UserId, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result) && result == record.SteamId) { return true; } if (!string.IsNullOrWhiteSpace(record.PhotonUserId) && string.Equals(player.UserId, record.PhotonUserId, StringComparison.Ordinal)) { return true; } if (flag && !string.IsNullOrWhiteSpace(record.ActorText) && int.TryParse(record.ActorText, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result2) && result2 == player.ActorNumber) { return true; } if (flag && !string.IsNullOrWhiteSpace(record.DisplayName) && !string.IsNullOrWhiteSpace(player.NickName)) { return string.Equals(record.DisplayName.Trim(), player.NickName.Trim(), StringComparison.OrdinalIgnoreCase); } return false; } private static bool IsCurrentRoomName(string roomName) { if (PhotonNetwork.CurrentRoom != null && !string.IsNullOrWhiteSpace(roomName)) { return string.Equals(PhotonNetwork.CurrentRoom.Name, roomName, StringComparison.Ordinal); } return false; } private static string BuildCurrentRoomText(Player livePlayer) { if (livePlayer == null) { return "No"; } if (livePlayer.ActorNumber <= 0) { return "Yes"; } return "Yes #" + livePlayer.ActorNumber.ToString(CultureInfo.InvariantCulture); } private static string BuildSteamStatusText(SteamPlayerActions.SteamFriendPresence presence) { if (!presence.HasSteamId) { return "-"; } if (string.IsNullOrWhiteSpace(presence.PersonaState) || presence.PersonaState == "-") { return "Unknown"; } if (!presence.IsOnline) { return "Offline"; } return presence.PersonaState; } private static string BuildJoinableText(RecentPlayerRecord record, SteamPlayerActions.SteamFriendPresence presence) { if (presence.IsJoinable) { return "Yes"; } if (record != null && record.SteamLobbyId != 0L) { return "Saved only"; } if (!presence.HasSteamId) { return "-"; } return "No"; } private static string FormatLivePhotonUserId(RecentPlayerRecord record, Player livePlayer) { if (livePlayer != null && !string.IsNullOrWhiteSpace(livePlayer.UserId)) { return livePlayer.UserId; } if (!string.IsNullOrEmpty(record.PhotonUserId)) { return record.PhotonUserId; } return "-"; } private static string FormatLiveActor(RecentPlayerRecord record, Player livePlayer) { if (livePlayer != null && livePlayer.ActorNumber > 0) { return livePlayer.ActorNumber.ToString(CultureInfo.InvariantCulture); } if (!string.IsNullOrEmpty(record.ActorText)) { return record.ActorText; } return "-"; } private static string FormatLiveRoom(RecentPlayerRecord record, Player livePlayer) { if (livePlayer != null && PhotonNetwork.CurrentRoom != null && !string.IsNullOrEmpty(PhotonNetwork.CurrentRoom.Name)) { return PhotonNetwork.CurrentRoom.Name; } if (!string.IsNullOrEmpty(record.RoomName)) { return record.RoomName; } return "-"; } private Texture GetRecentAvatar(RecentPlayerRecord record) { if (record == null) { return null; } if (_avatarCache.TryGetValue(record.Id, out var value) && Object.op_Implicit((Object)(object)value.Texture) && value.SteamId == record.SteamId) { return (Texture)(object)value.Texture; } if (Object.op_Implicit((Object)(object)value.Texture)) { Object.Destroy((Object)(object)value.Texture); } Texture2D val = PlayerDirectory.LoadSteamAvatarFromCacheOrSteam(record.SteamId); if (!Object.op_Implicit((Object)(object)val)) { val = BuildFallbackAvatar(record); } _avatarCache[record.Id] = new RecentAvatarCacheEntry { Texture = val, SteamId = record.SteamId }; return (Texture)(object)val; } private static Texture2D BuildFallbackAvatar(RecentPlayerRecord record) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Expected O, but got Unknown //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) string text = ((record != null) ? record.Id : "recent"); Texture2D val = new Texture2D(184, 184, (TextureFormat)4, false) { hideFlags = (HideFlags)61, wrapMode = (TextureWrapMode)1, filterMode = (FilterMode)1, name = "CubeX_RecentFallbackPfp_" + text }; Color32[] array = (Color32[])(object)new Color32[33856]; Color32 a = default(Color32); ((Color32)(ref a))..ctor((byte)18, (byte)20, (byte)25, byte.MaxValue); Color32 b = default(Color32); ((Color32)(ref b))..ctor((byte)34, (byte)37, (byte)46, byte.MaxValue); Color32 color = default(Color32); ((Color32)(ref color))..ctor((byte)8, (byte)10, (byte)14, byte.MaxValue); Color32 color2 = ColorFromKey(text); for (int i = 0; i < 184; i++) { float t = (float)i / 183f; Color32 val2 = LerpColor(a, b, t); int num = i * 184; for (int j = 0; j < 184; j++) { array[num + j] = val2; } } DrawCircle(array, 184, 184, 92, 74, 30, color2); DrawCircle(array, 184, 184, 92, 74, 19, new Color32((byte)28, (byte)31, (byte)38, byte.MaxValue)); DrawCircle(array, 184, 184, 92, 144, 58, color2); DrawCircle(array, 184, 184, 92, 144, 39, new Color32((byte)28, (byte)31, (byte)38, byte.MaxValue)); DrawRect(array, 184, 184, 0, 166, 184, 18, color2); DrawBorder(array, 184, 184, 3, color); FlipPixelsVertical(array, 184, 184); val.SetPixels32(array); val.Apply(false); return val; } private static void FlipPixelsVertical(Color32[] pixels, int width, int height) { if (pixels != null && width > 0 && height > 1) { Color32[] array = (Color32[])(object)new Color32[width]; for (int i = 0; i < height / 2; i++) { int num = i * width; int num2 = (height - 1 - i) * width; Array.Copy(pixels, num, array, 0, width); Array.Copy(pixels, num2, pixels, num, width); Array.Copy(array, 0, pixels, num2, width); } } } private static Color32 ColorFromKey(string key) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) int num = 17; if (!string.IsNullOrEmpty(key)) { foreach (char c in key) { num = num * 31 + c; } } Color val = Color.HSVToRGB((float)(Math.Abs(num) % 1000) / 1000f, 0.55f, 0.72f); return new Color32((byte)(val.r * 255f), (byte)(val.g * 255f), (byte)(val.b * 255f), byte.MaxValue); } private static Color32 LerpColor(Color32 a, Color32 b, float t) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0056: 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_0070: Unknown result type (might be due to invalid IL or missing references) t = Mathf.Clamp01(t); return new Color32((byte)Mathf.RoundToInt(Mathf.Lerp((float)(int)a.r, (float)(int)b.r, t)), (byte)Mathf.RoundToInt(Mathf.Lerp((float)(int)a.g, (float)(int)b.g, t)), (byte)Mathf.RoundToInt(Mathf.Lerp((float)(int)a.b, (float)(int)b.b, t)), (byte)Mathf.RoundToInt(Mathf.Lerp((float)(int)a.a, (float)(int)b.a, t))); } private static void DrawRect(Color32[] pixels, int width, int height, int x, int y, int rectWidth, int rectHeight, Color32 color) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) int num = Math.Max(0, x); int num2 = Math.Max(0, y); int num3 = Math.Min(width, x + rectWidth); int num4 = Math.Min(height, y + rectHeight); for (int i = num2; i < num4; i++) { int num5 = i * width; for (int j = num; j < num3; j++) { pixels[num5 + j] = color; } } } private static void DrawBorder(Color32[] pixels, int width, int height, int thickness, Color32 color) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) DrawRect(pixels, width, height, 0, 0, width, thickness, color); DrawRect(pixels, width, height, 0, height - thickness, width, thickness, color); DrawRect(pixels, width, height, 0, 0, thickness, height, color); DrawRect(pixels, width, height, width - thickness, 0, thickness, height, color); } private static void DrawCircle(Color32[] pixels, int width, int height, int centerX, int centerY, int radius, Color32 color) { //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) int num = radius * radius; int num2 = Math.Max(0, centerX - radius); int num3 = Math.Min(width - 1, centerX + radius); int num4 = Math.Max(0, centerY - radius); int num5 = Math.Min(height - 1, centerY + radius); for (int i = num4; i <= num5; i++) { int num6 = i - centerY; int num7 = i * width; for (int j = num2; j <= num3; j++) { int num8 = j - centerX; if (num8 * num8 + num6 * num6 <= num) { pixels[num7 + j] = color; } } } } private static string GetPanelRecentPlayerId(string category, object selectedRow) { if (selectedRow is SubmenuFeature submenuFeature && submenuFeature.ChildCategory != null && submenuFeature.ChildCategory.StartsWith("Network/Recent Players/", StringComparison.Ordinal)) { return submenuFeature.ChildCategory.Substring("Network/Recent Players/".Length); } if (category != null && category.StartsWith("Network/Recent Players/", StringComparison.Ordinal)) { return category.Substring("Network/Recent Players/".Length); } return null; } private static string FormatSteamId(ulong steamId) { if (steamId != 0L) { return steamId.ToString(CultureInfo.InvariantCulture); } return "-"; } private static string FormatUtc(string value) { if (DateTime.TryParse(value, CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal, out var result)) { return result.ToLocalTime().ToString("yyyy-MM-dd HH:mm", CultureInfo.InvariantCulture); } return "-"; } } internal sealed class RecentPlayersFile { public int version; public List players; } public class RecentPlayersSortBy : NumberFeature { private static readonly string[] SortNames = new string[6] { "Last Seen", "Name", "First Seen", "Seen Count", "Region", "Online" }; public override bool AllowTextInput => false; public RecentPlayersSortBy() { base.Name = "Sort By"; base.Description = "Changes the order of saved recent players."; base.Min = 0f; base.Max = SortNames.Length - 1; base.Value = (float)RecentPlayersDirectory.SortMode; base.Step = 1f; base.Decimals = 0; } public override string GetDisplayValue() { int num = Mathf.Clamp(Mathf.RoundToInt(base.Value), 0, SortNames.Length - 1); return SortNames[num]; } protected override void OnValueChanged(float newValue) { RecentPlayersDirectory.SortMode = (RecentPlayersSortMode)Mathf.Clamp(Mathf.RoundToInt(newValue), 0, SortNames.Length - 1); } } internal enum RecentPlayersSortMode { LastSeen, Name, FirstSeen, SeenCount, Region, Online } public static class RecentPlayersStore { private const int FileVersion = 1; private const int MaxRecords = 250; private static readonly TimeSpan SaveRefreshInterval = TimeSpan.FromSeconds(60.0); private const string RecentPlayersFolderName = "RecentPlayers"; private static readonly string DirectoryPath = AppDataPaths.DirectoryPath("RecentPlayers"); private static readonly string FilePath = Path.Combine(DirectoryPath, "recent_players.json"); private static readonly List Records = new List(); private static bool _loaded; public static IReadOnlyList GetAll() { EnsureLoaded(); return (from record in Records orderby ParseUtc(record.LastSeenUtc) descending, record.DisplayName select record.Clone()).ToList(); } public static RecentPlayerRecord Find(string id) { EnsureLoaded(); if (string.IsNullOrEmpty(id)) { return null; } foreach (RecentPlayerRecord record in Records) { if (string.Equals(record.Id, id, StringComparison.Ordinal)) { return record.Clone(); } } return null; } public static void Record(Player player) { if (player != null && !player.IsLocal) { string flagText = PlayerFlagDetector.GetFlagText(player, includeDetectedModder: true); RecordLivePlayer(GetPlayerName(player), (player.ActorNumber > 0) ? player.ActorNumber.ToString(CultureInfo.InvariantCulture) : string.Empty, TryGetSteamId(player), player.UserId, (PhotonNetwork.CurrentRoom != null) ? PhotonNetwork.CurrentRoom.Name : string.Empty, string.IsNullOrEmpty(PhotonNetwork.CloudRegion) ? string.Empty : PhotonNetwork.CloudRegion, isLocal: false, flagText, checkSpoofedName: true, forceSave: true); } } internal static RecentPlayerRecord BuildRecord(string displayName, string actorText, ulong steamId, string photonUserId, string roomName, string region, string modFlags = null) { string text = BuildRecordId(steamId, photonUserId, displayName, actorText); if (string.IsNullOrEmpty(text)) { return null; } string text2 = NormalizeModFlags(modFlags); string text3 = DateTime.UtcNow.ToString("o", CultureInfo.InvariantCulture); SteamPlayerActions.TryGetCurrentLobbyId(out var lobbyId); return new RecentPlayerRecord { Id = text, DisplayName = (string.IsNullOrWhiteSpace(displayName) ? "Unknown Player" : displayName.Trim()), ActorText = (actorText ?? string.Empty), SteamId = steamId, PhotonUserId = (photonUserId ?? string.Empty), RoomName = (roomName ?? string.Empty), Region = (region ?? string.Empty), SteamLobbyId = lobbyId, FirstSeenUtc = text3, LastSeenUtc = text3, TimesSeen = 1, ModFlags = text2, Modded = !string.IsNullOrEmpty(text2) }; } internal static RecentPlayerRecord BuildRecord(Player player) { if (player == null || player.IsLocal) { return null; } return BuildRecord(GetPlayerName(player), (player.ActorNumber > 0) ? player.ActorNumber.ToString(CultureInfo.InvariantCulture) : string.Empty, TryGetSteamId(player), player.UserId, (PhotonNetwork.CurrentRoom != null) ? PhotonNetwork.CurrentRoom.Name : string.Empty, string.IsNullOrEmpty(PhotonNetwork.CloudRegion) ? string.Empty : PhotonNetwork.CloudRegion, PlayerFlagDetector.GetFlagText(player, includeDetectedModder: true)); } internal static string BuildRecordId(ulong steamId, string photonUserId, string displayName, string actorText) { return BuildId(steamId, photonUserId, displayName, actorText); } public static void RecordLivePlayer(string displayName, string actorText, ulong steamId, string photonUserId, string roomName, string region, bool isLocal, string modFlags = null, bool checkSpoofedName = false, bool forceSave = false) { if (isLocal) { return; } EnsureLoaded(); string text = BuildId(steamId, photonUserId, displayName, actorText); if (string.IsNullOrEmpty(text)) { return; } DateTime utcNow = DateTime.UtcNow; string text2 = utcNow.ToString("o", CultureInfo.InvariantCulture); RecentPlayerRecord recentPlayerRecord = FindMutable(text); SteamPlayerActions.TryGetCurrentLobbyId(out var lobbyId); string incoming = NormalizeModFlags(modFlags); bool flag = checkSpoofedName && IsLiveNameSpoofed(displayName, steamId); if (recentPlayerRecord == null) { recentPlayerRecord = new RecentPlayerRecord { Id = text, FirstSeenUtc = text2, TimesSeen = 0 }; Records.Add(recentPlayerRecord); } else { bool flag2 = lobbyId != 0L && recentPlayerRecord.SteamLobbyId != lobbyId; string b = MergeModFlags(recentPlayerRecord.ModFlags, incoming); bool flag3 = !string.Equals(NormalizeModFlags(recentPlayerRecord.ModFlags), b, StringComparison.Ordinal); bool flag4 = checkSpoofedName && recentPlayerRecord.SpoofedName != flag; if (!(forceSave || flag2 || flag3 || flag4) && !(utcNow - ParseUtc(recentPlayerRecord.LastSeenUtc) >= SaveRefreshInterval)) { return; } } recentPlayerRecord.DisplayName = (string.IsNullOrWhiteSpace(displayName) ? "Unknown Player" : displayName.Trim()); recentPlayerRecord.ActorText = actorText ?? string.Empty; recentPlayerRecord.SteamId = steamId; recentPlayerRecord.PhotonUserId = photonUserId ?? string.Empty; recentPlayerRecord.RoomName = roomName ?? string.Empty; recentPlayerRecord.Region = region ?? string.Empty; recentPlayerRecord.LastSeenUtc = text2; recentPlayerRecord.TimesSeen = Math.Max(0, recentPlayerRecord.TimesSeen) + 1; if (lobbyId != 0L) { recentPlayerRecord.SteamLobbyId = lobbyId; } recentPlayerRecord.ModFlags = MergeModFlags(recentPlayerRecord.ModFlags, incoming); recentPlayerRecord.Modded = !string.IsNullOrEmpty(recentPlayerRecord.ModFlags); if (checkSpoofedName) { recentPlayerRecord.SpoofedName = flag; } Prune(); Save(); } public static bool Remove(string id) { EnsureLoaded(); if (Records.RemoveAll((RecentPlayerRecord record) => string.Equals(record.Id, id, StringComparison.Ordinal)) <= 0) { return false; } Save(); return true; } public static void Clear() { EnsureLoaded(); if (Records.Count != 0) { Records.Clear(); Save(); } } private static void EnsureLoaded() { if (_loaded) { return; } _loaded = true; try { AppDataPaths.MigrateFileToDirectory("recent_players.json", "RecentPlayers"); if (!File.Exists(FilePath)) { return; } RecentPlayersFile recentPlayersFile = JsonConvert.DeserializeObject(File.ReadAllText(FilePath)); if (recentPlayersFile?.players == null) { return; } Records.Clear(); foreach (RecentPlayerRecord player in recentPlayersFile.players) { if (player == null) { continue; } player.Id = (string.IsNullOrEmpty(player.Id) ? BuildId(player.SteamId, player.PhotonUserId, player.DisplayName, player.ActorText) : player.Id); if (!string.IsNullOrEmpty(player.Id)) { if (string.IsNullOrWhiteSpace(player.DisplayName)) { player.DisplayName = "Unknown Player"; } if (string.IsNullOrEmpty(player.FirstSeenUtc)) { player.FirstSeenUtc = player.LastSeenUtc; } if (string.IsNullOrEmpty(player.LastSeenUtc)) { player.LastSeenUtc = DateTime.UtcNow.ToString("o", CultureInfo.InvariantCulture); } Records.Add(player); } } Prune(); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogError((object)("Failed to load recent players: " + ex)); } } } private static void Save() { try { Directory.CreateDirectory(DirectoryPath); RecentPlayersFile recentPlayersFile = new RecentPlayersFile { version = 1, players = (from record in Records.OrderByDescending((RecentPlayerRecord record) => ParseUtc(record.LastSeenUtc)).Take(250) select record.Clone()).ToList() }; File.WriteAllText(FilePath, JsonConvert.SerializeObject((object)recentPlayersFile, (Formatting)1)); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogError((object)("Failed to save recent players: " + ex)); } } } private static RecentPlayerRecord FindMutable(string id) { foreach (RecentPlayerRecord record in Records) { if (string.Equals(record.Id, id, StringComparison.Ordinal)) { return record; } } return null; } private static void Prune() { Records.Sort((RecentPlayerRecord a, RecentPlayerRecord b) => ParseUtc(b.LastSeenUtc).CompareTo(ParseUtc(a.LastSeenUtc))); if (Records.Count > 250) { Records.RemoveRange(250, Records.Count - 250); } } private static DateTime ParseUtc(string value) { if (!DateTime.TryParse(value, CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal, out var result)) { return DateTime.MinValue; } return result; } internal static string GetPlayerName(Player player) { if (player == null) { return "Unknown Player"; } if (!string.IsNullOrWhiteSpace(player.NickName)) { return player.NickName.Trim(); } return "Player"; } private static string BuildId(ulong steamId, string photonUserId, string displayName, string actorText) { if (steamId != 0L) { return "steam-" + steamId.ToString(CultureInfo.InvariantCulture); } if (!string.IsNullOrWhiteSpace(photonUserId)) { return "photon-" + SanitizeKey(photonUserId); } string value = (displayName ?? "player") + "-" + (actorText ?? string.Empty); return "name-" + SanitizeKey(value); } private static string SanitizeKey(string value) { if (string.IsNullOrWhiteSpace(value)) { return string.Empty; } StringBuilder stringBuilder = new StringBuilder(value.Length); foreach (char c in value) { stringBuilder.Append(char.IsLetterOrDigit(c) ? c : '_'); } return stringBuilder.ToString().Trim('_'); } internal static ulong TryGetSteamId(Player player) { if (player == null) { return 0uL; } if (!string.IsNullOrWhiteSpace(player.UserId) && ulong.TryParse(player.UserId, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result)) { return result; } object source = null; try { source = player.CustomProperties; } catch { } if (!TryGetSteamIdFromDictionaryLikeObject(source, out result)) { return 0uL; } return result; } private static bool TryGetSteamIdFromDictionaryLikeObject(object source, out ulong steamId) { steamId = 0uL; if (source == null) { return false; } string[] array = new string[4] { "steamid", "steamId", "SteamId", "SteamID" }; if (source is IDictionary dictionary) { string[] array2 = array; foreach (string key in array2) { object obj = null; try { if (dictionary.Contains(key)) { obj = dictionary[key]; } } catch { } if (obj != null && ulong.TryParse(obj.ToString(), NumberStyles.Integer, CultureInfo.InvariantCulture, out steamId)) { return true; } } } return false; } private static void GetModDetections(Player player, out bool atlasUser, out bool cherryUser) { atlasUser = false; cherryUser = false; if (player != null) { object source = null; try { source = player.CustomProperties; } catch { } atlasUser = HasDictionaryLikeKey(source, "AtlUser"); cherryUser = HasDictionaryLikeKey(source, "CherryUser"); } } private static bool HasDictionaryLikeKey(object source, string key) { if (source == null || string.IsNullOrEmpty(key)) { return false; } if (source is IDictionary dictionary) { try { return dictionary.Contains(key); } catch { } } return false; } internal static string BuildModFlags(bool atlasUser, bool cherryUser) { List list = new List(); if (atlasUser) { list.Add("Atlas"); } if (cherryUser) { list.Add("Cherry"); } if (list.Count != 0) { return string.Join(", ", list.ToArray()); } return string.Empty; } private static string MergeModFlags(string existing, string incoming) { SortedSet sortedSet = new SortedSet(StringComparer.OrdinalIgnoreCase); AddModFlags(sortedSet, existing); AddModFlags(sortedSet, incoming); if (sortedSet.Count != 0) { return string.Join(", ", sortedSet.ToArray()); } return string.Empty; } private static string NormalizeModFlags(string value) { return MergeModFlags(null, value); } private static void AddModFlags(SortedSet flags, string value) { if (flags == null || string.IsNullOrWhiteSpace(value)) { return; } string[] array = value.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < array.Length; i++) { string text = array[i].Trim(); if (!string.IsNullOrEmpty(text)) { flags.Add(text); } } } private static bool IsLiveNameSpoofed(string photonName, ulong steamId) { if (steamId == 0L || string.IsNullOrWhiteSpace(photonName)) { return false; } string personaName = SteamPlayerActions.GetPersonaName(steamId); if (string.IsNullOrWhiteSpace(personaName)) { return false; } return !string.Equals(NormalizeComparableName(photonName), NormalizeComparableName(personaName), StringComparison.OrdinalIgnoreCase); } private static string NormalizeComparableName(string value) { if (string.IsNullOrWhiteSpace(value)) { return string.Empty; } string text = StripRichText(value).Trim(); return string.Join(" ", text.Split(new char[4] { ' ', '\t', '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries)); } private static string StripRichText(string value) { if (string.IsNullOrEmpty(value)) { return string.Empty; } List list = new List(value.Length); bool flag = false; foreach (char c in value) { switch (c) { case '<': flag = true; continue; case '>': flag = false; continue; } if (!flag) { list.Add(c); } } return new string(list.ToArray()); } } public class RemoveRecentPlayer : ButtonFeature { public RemoveRecentPlayer() { base.Name = "Remove Recent Player"; base.Description = "Removes the selected recent player from the saved JSON list."; base.ButtonLabel = "Remove"; } public override void Execute() { RecentPlayerRecord selectedRecentPlayer = RecentPlayersDirectory.SelectedRecentPlayer; if (selectedRecentPlayer != null && RecentPlayersStore.Remove(selectedRecentPlayer.Id)) { NotificationSystem.Push("Recent Player Removed", selectedRecentPlayer.DisplayName, NotificationKind.Success); } } } internal static class PiggybackCarryRuntime { private static int _carrierViewId = -1; private static int _targetViewId = -1; public static void Register(Character carrier, Character target) { _carrierViewId = GetViewId(carrier); _targetViewId = GetViewId(target); } public static bool ShouldKeepSelectedCarry(Character carrier) { PhotonView val = ((!Object.op_Implicit((Object)(object)carrier)) ? null : carrier.refs?.view); if (!Object.op_Implicit((Object)(object)carrier) || !Object.op_Implicit((Object)(object)carrier.data) || !Object.op_Implicit((Object)(object)val) || !val.IsMine) { return false; } Character carriedPlayer = carrier.data.carriedPlayer; if (!Object.op_Implicit((Object)(object)carriedPlayer) || !Object.op_Implicit((Object)(object)carriedPlayer.data)) { return false; } if (carrier.data.dead || carrier.data.fullyPassedOut || carriedPlayer.data.dead) { return false; } if (GetViewId(carrier) == _carrierViewId) { return GetViewId(carriedPlayer) == _targetViewId; } return false; } private static int GetViewId(Character character) { if (!Object.op_Implicit((Object)(object)character)) { return -1; } PhotonView val = character.refs?.view; if (!Object.op_Implicit((Object)(object)val)) { val = ((Component)character).GetComponent(); } if (!Object.op_Implicit((Object)(object)val)) { return -1; } return val.ViewID; } } [HarmonyPatch(typeof(CharacterCarrying), "Update")] internal static class PiggybackCarryUpdatePatch { private static bool Prefix(Character ___character) { return !PiggybackCarryRuntime.ShouldKeepSelectedCarry(___character); } } internal static class PlayerActionSettings { public static bool ExcludeSelfFromAllActions = true; } } namespace CubeX.Features.Player.PlayerActions { public class AddSelectedPlayerOnSteam : ButtonFeature { public AddSelectedPlayerOnSteam() { base.Name = "Add On Steam"; base.Description = "Opens Steam's add-friend prompt for the selected player."; base.ButtonLabel = "Add"; } public override void Execute() { PlayerDirectory.SelectedPlayerInfo selectedPlayer = PlayerDirectory.SelectedPlayer; if (selectedPlayer == null || selectedPlayer.SteamId == 0L) { Plugin.Log.LogWarning((object)"[Add On Steam] Selected player has no Steam ID."); } else if (selectedPlayer.IsLocal) { Plugin.Log.LogWarning((object)"[Add On Steam] Cannot add your own Steam account."); } else if (!SteamPlayerActions.OpenAddFriend(selectedPlayer.SteamId)) { Plugin.Log.LogWarning((object)"[Add On Steam] Steam overlay add-friend prompt was not available."); } } } public class ExcludeSelfFromAllActions : Feature { public ExcludeSelfFromAllActions() { base.Name = "Exclude Self"; base.Description = "When enabled, all-player actions leave your local character unchanged."; base.Enabled = true; } protected override void OnEnable() { OnTick(); } protected override void OnDisable() { PlayerActionSettings.ExcludeSelfFromAllActions = false; } public override void OnTick() { PlayerActionSettings.ExcludeSelfFromAllActions = true; } } public class KillAllPlayers : ButtonFeature { public KillAllPlayers() { base.Name = "Down All"; base.Description = "Sets target player characters to a downed state, optionally excluding yourself."; base.ButtonLabel = "Down"; } public override void Execute() { Character localCharacter = Character.localCharacter; foreach (Character character in GameActions.GetCharacters()) { if (Object.op_Implicit((Object)(object)character) && VisualPlayerText.IsRealPlayer(character) && (!PlayerActionSettings.ExcludeSelfFromAllActions || !Object.op_Implicit((Object)(object)localCharacter) || character != localCharacter)) { GameActions.KillCharacter(character); } } } } public class KillSelectedPlayer : ButtonFeature { public KillSelectedPlayer() { base.Name = "Down Player"; base.Description = "Sets the selected player to a downed state."; base.ButtonLabel = "Down"; } public override void Execute() { PlayerDirectory.TryGetSelectedCharacter(out var character); if (Object.op_Implicit((Object)(object)character)) { GameActions.KillCharacter(character); } } } public class ReviveAllPlayers : ButtonFeature { public ReviveAllPlayers() { base.Name = "Revive All"; base.Description = "Revives every player character."; base.ButtonLabel = "Revive"; } public override void Execute() { Character localCharacter = Character.localCharacter; foreach (Character character in GameActions.GetCharacters()) { if (Object.op_Implicit((Object)(object)character) && VisualPlayerText.IsRealPlayer(character) && (!PlayerActionSettings.ExcludeSelfFromAllActions || !Object.op_Implicit((Object)(object)localCharacter) || character != localCharacter)) { GameActions.ReviveCharacter(character); } } } } public class ReviveSelectedPlayer : ButtonFeature { public ReviveSelectedPlayer() { base.Name = "Revive Player"; base.Description = "Revives the selected player."; base.ButtonLabel = "Revive"; } public override void Execute() { PlayerDirectory.TryGetSelectedCharacter(out var character); if (Object.op_Implicit((Object)(object)character)) { GameActions.ReviveCharacter(character); } } } public class SpawnScoutmasterForSelectedPlayer : ButtonFeature { public SpawnScoutmasterForSelectedPlayer() { base.Name = "Spawn Scoutmaster"; base.Description = "Spawns a Scoutmaster near the selected player. Host only."; base.ButtonLabel = "Spawn"; } public override void Execute() { PlayerDirectory.TryGetSelectedCharacter(out var character); if (Object.op_Implicit((Object)(object)character)) { GameActions.SpawnScoutmasterFor(character); } } } public class WarpAllPlayersToMe : ButtonFeature { public WarpAllPlayersToMe() { base.Name = "Warp All To Me"; base.Description = "Warps every other player near your current position."; base.ButtonLabel = "Warp"; } public override void Execute() { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: 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 (!GameActions.TryGetLocalCharacter(out var character)) { return; } Vector3 position = character.Head + Vector3.up * 4f; foreach (Character character2 in GameActions.GetCharacters()) { if (Object.op_Implicit((Object)(object)character2) && VisualPlayerText.IsRealPlayer(character2) && (!PlayerActionSettings.ExcludeSelfFromAllActions || character2 != character)) { GameActions.WarpCharacter(character2, position); } } } } public class WarpSelectedPlayerToMe : ButtonFeature { public WarpSelectedPlayerToMe() { base.Name = "Warp Player To Me"; base.Description = "Warps the selected player near your current position."; base.ButtonLabel = "Warp"; } public override void Execute() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) if (PlayerDirectory.TryGetSelectedCharacter(out var character) && GameActions.TryGetLocalCharacter(out var character2)) { GameActions.WarpCharacter(character, character2.Head + Vector3.up * 4f); } } } } namespace CubeX.Features.Pages { internal static class AllPlayersPageBuilder { public static void Build(FeaturePageBuilder page) { page.AddSubmenu("All Players", delegate(FeaturePageBuilder all) { all.Add(); all.AddSubmenu("Teleport", delegate(FeaturePageBuilder teleport) { teleport.Add(); teleport.Add(); teleport.Add(); }); all.AddSubmenu("Recovery", delegate(FeaturePageBuilder recovery) { recovery.Add(); recovery.Add(); recovery.Add(); recovery.Add(); }); all.AddSubmenu("Movement", delegate(FeaturePageBuilder movement) { movement.Add(); movement.Add(); movement.Add(); movement.Add(); movement.Add(); movement.Add(); movement.Add(); movement.Add(); }); all.AddSubmenu("Events", delegate(FeaturePageBuilder hazards) { hazards.Add(); hazards.Add(); hazards.Add(); hazards.Add(); hazards.Add(); hazards.Add(); }); all.AddSubmenu("Inventory", delegate(FeaturePageBuilder inventory) { inventory.Add(); inventory.Add(); inventory.Add(); inventory.Add(); inventory.Add(); inventory.Add(); inventory.Add(); inventory.Add(); inventory.Add(); inventory.Add(); }); all.AddSubmenu("Status", delegate(FeaturePageBuilder status) { status.Add(); status.Add(); status.Add(); status.Add(); }); all.AddSubmenu("Lobby Control", delegate(FeaturePageBuilder lobby) { lobby.Add(); lobby.Add(); lobby.Add(); lobby.Add(); lobby.Add(); lobby.Add(); lobby.Add(); }); all.AddSubmenu("Emotes", delegate(FeaturePageBuilder emotes) { emotes.Add(); emotes.Add(); emotes.Add(); emotes.Add(); emotes.Add(); emotes.Add(); emotes.Add(); emotes.Add(); emotes.Add(); emotes.Add(); }); }); } } public class HostPage : FeaturePage { public override string Name => "Host"; public override int SortOrder => 2; protected override void Build(FeaturePageBuilder page) { page.AddSubmenu("Authority", delegate(FeaturePageBuilder authority) { authority.Add(); authority.Add(); authority.Add(); }); page.AddSubmenu("More Scouts", delegate(FeaturePageBuilder scouts) { scouts.Add(); scouts.Add(); }); page.AddSubmenu("Kiosk", delegate(FeaturePageBuilder kiosk) { kiosk.Add(); }); page.AddSubmenu("Lobby Control", delegate(FeaturePageBuilder lobby) { lobby.Add(); lobby.Add(); lobby.Add(); lobby.Add(); lobby.Add(); lobby.Add(); }); } } public class InventoryPage : FeaturePage { public override string Name => "Items"; public override int SortOrder => 4; protected override void Build(FeaturePageBuilder page) { page.Add(); page.Add(); page.AddSubmenu("Slot 1", delegate(FeaturePageBuilder slot) { slot.AddSubmenu("Assign Item", delegate(FeaturePageBuilder assign) { assign.Add(); }); slot.Add(); }); page.AddSubmenu("Slot 2", delegate(FeaturePageBuilder slot) { slot.AddSubmenu("Assign Item", delegate(FeaturePageBuilder assign) { assign.Add(); }); slot.Add(); }); page.AddSubmenu("Slot 3", delegate(FeaturePageBuilder slot) { slot.AddSubmenu("Assign Item", delegate(FeaturePageBuilder assign) { assign.Add(); }); slot.Add(); }); } } public class MiscPage : FeaturePage { public override string Name => "Misc"; public override int SortOrder => 98; protected override void Build(FeaturePageBuilder page) { page.AddSubmenu("Startup", delegate(FeaturePageBuilder startup) { startup.Add(); }); page.AddSubmenu("Network", delegate(FeaturePageBuilder network) { network.Add(); network.Add(); }); page.AddSubmenu("Interface", delegate(FeaturePageBuilder ui) { ui.Add(); }); page.AddSubmenu("Audio", delegate(FeaturePageBuilder audio) { audio.Add(); }); page.AddSubmenu("Notifications", delegate(FeaturePageBuilder notifications) { notifications.Add(); notifications.Add(); notifications.Add(); notifications.Add(); }); page.AddSubmenu("Discord Community", delegate(FeaturePageBuilder discord) { discord.Add(); }); } } public class NetworkPage : FeaturePage { public override string Name => "Network"; public override int SortOrder => 1; protected override void Build(FeaturePageBuilder page) { page.AddSubmenu("Players", delegate(FeaturePageBuilder players) { players.Add(); }); AllPlayersPageBuilder.Build(page); page.AddSubmenu("Recent Players", delegate(FeaturePageBuilder recent) { recent.Add(); recent.Add(); }); page.AddSubmenu("Blacklist", delegate(FeaturePageBuilder blacklist) { blacklist.Add(); blacklist.Add(); }); page.AddSubmenu("Friends", delegate(FeaturePageBuilder friends) { friends.Add(); }); page.AddSubmenu("Profile", delegate(FeaturePageBuilder lobby) { lobby.Add(); lobby.Add(); lobby.Add(); }); page.AddSubmenu("Connection", delegate(FeaturePageBuilder lobby) { lobby.Add(); }); page.AddSubmenu("Steam Join", delegate(FeaturePageBuilder steam) { steam.Add(); steam.Add(); }); page.AddSubmenu("Voice Chat", delegate(FeaturePageBuilder voice) { voice.Add(); voice.Add(); }); page.AddSubmenu("Achievements", delegate(FeaturePageBuilder achievements) { achievements.Add(); achievements.Add(); achievements.AddSubmenu("Individual", delegate(FeaturePageBuilder individual) { individual.Add(); }); }); } } public class SearchPage : FeaturePage { public override string Name => "Search"; public override int SortOrder => 100; protected override void Build(FeaturePageBuilder page) { page.Add(); page.Add(); } } public class SelfPage : FeaturePage { public override string Name => "Self"; public override int SortOrder => 0; protected override void Build(FeaturePageBuilder page) { page.AddSubmenu("Protection", delegate(FeaturePageBuilder safety) { safety.Add(); safety.Add(); safety.Add(); safety.Add(); safety.Add(); safety.Add(); safety.Add(); safety.Add(); safety.Add(); safety.Add(); safety.Add(); }); page.AddSubmenu("Movement", delegate(FeaturePageBuilder movement) { movement.AddSubmenu("Stamina", delegate(FeaturePageBuilder stamina) { stamina.Add(); stamina.Add(); }); movement.AddSubmenu("Flight", delegate(FeaturePageBuilder flight) { flight.Add(); flight.Add(); flight.Add(); flight.Add(); }); movement.AddSubmenu("Multipliers", delegate(FeaturePageBuilder multipliers) { multipliers.Add(); multipliers.Add(); multipliers.Add(); multipliers.Add(); multipliers.Add(); multipliers.Add(); }); }); page.AddSubmenu("Items", delegate(FeaturePageBuilder items) { items.AddSubmenu("Access", delegate(FeaturePageBuilder access) { access.Add(); access.Add(); access.Add(); }); items.Add(); items.AddSubmenu("Charges", delegate(FeaturePageBuilder charges) { charges.Add(); charges.Add(); charges.Add(); charges.Add(); }); items.AddSubmenu("Throwing", delegate(FeaturePageBuilder throwing) { throwing.Add(); throwing.Add(); }); }); page.AddSubmenu("Actions", delegate(FeaturePageBuilder actions) { actions.Add(); actions.Add(); actions.Add(); actions.Add(); actions.Add(); actions.Add(); actions.Add(); actions.Add(); actions.Add(); actions.Add(); actions.Add(); actions.Add(); }); page.AddSubmenu("Misc", delegate(FeaturePageBuilder misc) { misc.Add(); misc.Add(); misc.Add(); misc.Add(); }); } } public class SettingsPage : FeaturePage { public override string Name => "Settings"; public override int SortOrder => 99; protected override void Build(FeaturePageBuilder page) { page.AddSubmenu("Config", delegate(FeaturePageBuilder config) { config.Add(); config.Add(); config.AddSubmenu("Custom Saves", delegate(FeaturePageBuilder custom) { custom.Add(); }); config.AddBreak(); config.Add(); config.Add(); }); page.AddSubmenu("Appearance", delegate(FeaturePageBuilder appearance) { appearance.Add(); appearance.Add(); appearance.Add(); }); page.AddSubmenu("Layout", delegate(FeaturePageBuilder layout) { layout.Add(); layout.Add(); layout.Add(); layout.Add(); layout.Add(); layout.Add(); }); page.AddSubmenu("Keybinds", delegate(FeaturePageBuilder keybinds) { keybinds.Add(); keybinds.Add(); }); page.Add(); } } public class SpawnPage : FeaturePage { public override string Name => "Spawn"; public override int SortOrder => 5; protected override void Build(FeaturePageBuilder page) { page.AddSubmenu("Items", delegate(FeaturePageBuilder items) { items.Add(); items.AddSubmenu("Item Selector", delegate(FeaturePageBuilder selector) { selector.Add(); }); items.Add(); items.Add(); }); page.AddSubmenu("Item Tools", delegate(FeaturePageBuilder tools) { tools.Add(); tools.Add(); tools.Add(); tools.Add(); tools.Add(); tools.Add(); tools.Add(); tools.Add(); tools.Add(); tools.Add(); tools.Add(); tools.Add(); }); page.AddSubmenu("Guns", delegate(FeaturePageBuilder guns) { guns.Add(); guns.Add(); guns.Add(); }); page.AddSubmenu("Entities", delegate(FeaturePageBuilder entities) { entities.Add(); entities.Add(); entities.Add(); entities.Add(); entities.Add(); entities.Add(); entities.Add(); entities.Add(); entities.AddSubmenu("Spawned Entities", delegate(FeaturePageBuilder spawned) { spawned.Add(); }); entities.Add(); }); } } public class TeleportPage : FeaturePage { public override string Name => "Teleport"; public override int SortOrder => 2; protected override void Build(FeaturePageBuilder page) { page.Add(); page.Add(); page.Add(); page.Add(); page.Add(); page.Add(); page.AddSubmenu("Locations", delegate(FeaturePageBuilder locations) { locations.Add(); locations.Add(); }); page.AddSubmenu("Coordinates", delegate(FeaturePageBuilder coordinates) { coordinates.Add(); coordinates.Add(); coordinates.Add(); coordinates.Add(); coordinates.Add(); }); } } public class VisualsPage : FeaturePage { public override string Name => "Visuals"; public override int SortOrder => 3; protected override void Build(FeaturePageBuilder page) { page.AddSubmenu("Players", delegate(FeaturePageBuilder players) { players.AddSubmenu("ESP", delegate(FeaturePageBuilder esp) { esp.AddSubmenu("Layers", delegate(FeaturePageBuilder layers) { layers.Add(); layers.Add(); layers.Add(); layers.Add(); }); esp.AddSubmenu("Targets", delegate(FeaturePageBuilder targets) { targets.Add(); targets.Add(); targets.Add(); targets.Add(); targets.Add(); targets.Add(); }); esp.AddSubmenu("Performance", delegate(FeaturePageBuilder performance) { performance.Add(); performance.Add(); performance.Add(); }); esp.AddSubmenu("Colors", delegate(FeaturePageBuilder colors) { colors.Add(); colors.Add(); }); }); players.AddSubmenu("Profile Cards", delegate(FeaturePageBuilder cards) { cards.Add(); cards.Add(); cards.Add(); cards.Add(); cards.Add(); }); players.AddSubmenu("Movement FX", delegate(FeaturePageBuilder movementFx) { movementFx.AddSubmenu("Trails", delegate(FeaturePageBuilder trails) { trails.Add(); trails.Add(); trails.Add(); trails.Add(); }); movementFx.AddSubmenu("Footsteps", delegate(FeaturePageBuilder footsteps) { footsteps.Add(); footsteps.Add(); footsteps.Add(); footsteps.Add(); }); }); players.AddSubmenu("Awareness", delegate(FeaturePageBuilder awareness) { awareness.Add(); awareness.Add(); awareness.Add(); awareness.Add(); }); }); page.AddSubmenu("World Tags", delegate(FeaturePageBuilder world) { world.Add(); world.Add(); }); page.AddSubmenu("Pings", delegate(FeaturePageBuilder pings) { pings.Add(); pings.Add(); pings.Add(); }); page.AddSubmenu("Display", delegate(FeaturePageBuilder display) { display.AddSubmenu("Camera", delegate(FeaturePageBuilder camera) { camera.Add(); camera.Add(); camera.Add(); camera.Add(); camera.AddSubmenu("Zoom", delegate(FeaturePageBuilder zoom) { zoom.Add(); zoom.Add(); }); }); display.AddSubmenu("Quality", delegate(FeaturePageBuilder quality) { quality.Add(); }); display.AddSubmenu("HUD", delegate(FeaturePageBuilder hud) { hud.Add(); hud.Add(); hud.Add(); hud.Add(); }); }); page.AddSubmenu("Performance", delegate(FeaturePageBuilder performance) { performance.AddSubmenu("Preset", delegate(FeaturePageBuilder preset) { preset.Add(); preset.Add(); }); performance.AddSubmenu("Rendering", delegate(FeaturePageBuilder rendering) { rendering.Add(); rendering.Add(); rendering.Add(); rendering.Add(); rendering.Add(); }); performance.AddSubmenu("World Entities", delegate(FeaturePageBuilder entities) { entities.Add(); entities.Add(); entities.Add(); entities.Add(); entities.Add(); }); performance.AddSubmenu("Characters", delegate(FeaturePageBuilder characters) { characters.Add(); characters.Add(); characters.Add(); characters.Add(); characters.Add(); characters.Add(); }); performance.AddSubmenu("Wind", delegate(FeaturePageBuilder wind) { wind.Add(); wind.Add(); }); }); } } public class WorldPage : FeaturePage { public override string Name => "World"; public override int SortOrder => 6; protected override void Build(FeaturePageBuilder page) { page.AddSubmenu("Environment", delegate(FeaturePageBuilder environment) { environment.Add(); environment.Add(); environment.Add(); environment.Add(); environment.Add(); environment.Add(); environment.Add(); environment.Add(); environment.Add(); environment.Add(); environment.Add(); }); page.AddSubmenu("Props", delegate(FeaturePageBuilder props) { props.Add(); props.Add(); props.Add(); props.Add(); }); page.AddSubmenu("Camp Lighting", delegate(FeaturePageBuilder camp) { camp.Add(); camp.Add(); camp.Add(); camp.Add(); }); page.AddSubmenu("Luggage", delegate(FeaturePageBuilder luggage) { luggage.Add(); luggage.Add(); luggage.Add(); luggage.Add(); luggage.Add(); }); page.AddSubmenu("Mouse Tools", delegate(FeaturePageBuilder tools) { tools.Add(); tools.Add(); }); } } } namespace CubeX.Features.Network { public class UnlockAllAchievements : ButtonFeature { public UnlockAllAchievements() { base.Name = "Unlock All Achievements"; base.Description = "Unlocks every PEAK achievement through the game's AchievementManager."; base.ButtonLabel = "Unlock"; } public override void Execute() { AchievementRuntime.UnlockAll(); } } public class LockAllAchievements : ButtonFeature { public LockAllAchievements() { base.Name = "Lock All Achievements"; base.Description = "Clears PEAK achievement state through the game's AchievementManager."; base.ButtonLabel = "Lock"; } public override void Execute() { AchievementRuntime.LockAll(); } } public class AchievementDirectory : Feature, IMenuRowProvider { private sealed class AchievementActionButton : ButtonFeature { private readonly ACHIEVEMENTTYPE _type; private readonly bool _unlock; public AchievementActionButton(ACHIEVEMENTTYPE type, bool unlock) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) _type = type; _unlock = unlock; string text = AchievementRuntime.FormatAchievementName(type); base.Name = (unlock ? "Unlock " : "Lock ") + text; base.Description = (unlock ? "Unlocks " : "Locks ") + text + "."; base.ButtonLabel = (unlock ? "Unlock" : "Lock"); } public override void Execute() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) if (_unlock) { AchievementRuntime.Unlock(_type); } else { AchievementRuntime.Lock(_type); } } } private const string IndividualCategory = "Network/Achievements/Individual"; private const string AchievementPrefix = "Network/Achievements/Individual/"; private const float CacheSeconds = 10f; private static List _cachedRows; private static float _nextRefreshAt; public AchievementDirectory() { base.Name = "Achievement Directory"; base.Description = "Builds individual achievement lock/unlock rows."; } public IEnumerable GetRows(string category) { if (string.Equals(category, "Network/Achievements/Individual", StringComparison.Ordinal)) { return BuildAchievementRows(); } if (category != null && category.StartsWith("Network/Achievements/Individual/", StringComparison.Ordinal)) { return BuildAchievementActionRows(category.Substring("Network/Achievements/Individual/".Length)); } return Array.Empty(); } private static IEnumerable BuildAchievementRows() { if (_cachedRows != null && Time.unscaledTime < _nextRefreshAt) { return _cachedRows; } _cachedRows = ((IEnumerable)AchievementRuntime.AllAchievementTypes()).Select((Func)delegate(ACHIEVEMENTTYPE type) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0007: 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_003a: Unknown result type (might be due to invalid IL or missing references) string text = AchievementRuntime.FormatAchievementName(type); bool flag = AchievementRuntime.IsUnlockedCached(type); List tags = new List { new MenuTag(flag ? "UNLOCKED" : "LOCKED", flag ? new Color(0.18f, 0.58f, 0.34f, 1f) : new Color(0.68f, 0.26f, 0.2f, 1f)) }; return new SubmenuFeature(text, "Network/Achievements/Individual/" + ((object)(ACHIEVEMENTTYPE)(ref type)).ToString(), "Open controls for " + text + ".", tags); }).ToList(); _nextRefreshAt = Time.unscaledTime + 10f; return _cachedRows; } internal static void InvalidateCache() { _cachedRows = null; _nextRefreshAt = 0f; } private static IEnumerable BuildAchievementActionRows(string value) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_006f: 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 (!Enum.TryParse(value, out ACHIEVEMENTTYPE result) || (int)result == 0) { return new <>z__ReadOnlySingleElementList(new InfoFeature("Achievement", "Invalid", "Achievement type was not recognized.")); } string text = AchievementRuntime.FormatAchievementName(result); string text2 = (AchievementRuntime.IsUnlockedCached(result) ? "Unlocked" : "Locked"); return new <>z__ReadOnlyArray(new object[3] { new InfoFeature("Status", text2, text + " is currently " + text2.ToLowerInvariant() + "."), new AchievementActionButton(result, unlock: true), new AchievementActionButton(result, unlock: false) }); } } internal static class AchievementRuntime { private const BindingFlags StaticFlags = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; private const float ManagerCacheSeconds = 5f; private const float UnlockedCacheSeconds = 10f; private const int MaxAscentUnlockLevel = 8; private static readonly ACHIEVEMENTTYPE[] CachedTypes = (from ACHIEVEMENTTYPE type in Enum.GetValues(typeof(ACHIEVEMENTTYPE)) where (int)type > 0 select type).ToArray(); private static readonly Dictionary NameCache = CachedTypes.ToDictionary((ACHIEVEMENTTYPE type) => type, FormatAchievementNameCore); private static readonly Dictionary UnlockedCache = new Dictionary(); private static readonly Dictionary BackendIdCache = new Dictionary(); private static AchievementManager _cachedManager; private static float _nextManagerLookupAt; private static float _nextUnlockedRefreshAt; private static Type _steamUserStatsType; private static bool _steamUserStatsResolved; private static MethodInfo _clearAchievementMethod; private static MethodInfo _giveAscentLevelMethod; public static IReadOnlyList AllAchievementTypes() { return CachedTypes; } public static void UnlockAll() { try { AchievementManager val = FindManagerCached(); if (Object.op_Implicit((Object)(object)val)) { if (!TryInvokeManager(val, "UnlockAll")) { ACHIEVEMENTTYPE[] cachedTypes = CachedTypes; for (int i = 0; i < cachedTypes.Length; i++) { AchievementManager.Grant(cachedTypes[i]); } } UnlockAscentProgress(8, val); } else { ACHIEVEMENTTYPE[] cachedTypes = CachedTypes; for (int i = 0; i < cachedTypes.Length; i++) { AchievementManager.Grant(cachedTypes[i]); } UnlockAscentProgress(8, null); } MarkAllCached(unlocked: true); AchievementDirectory.InvalidateCache(); Notify("Unlock Achievements", "All achievements unlocked.", NotificationKind.Success); } catch (Exception ex) { Notify("Unlock Achievements Failed", GetBaseMessage(ex), NotificationKind.Error); } } public static void LockAll() { try { AchievementManager.ClearAchievements(); MarkAllCached(unlocked: false); AchievementDirectory.InvalidateCache(); Notify("Lock Achievements", "All achievements locked.", NotificationKind.Success); } catch (Exception ex) { Notify("Lock Achievements Failed", GetBaseMessage(ex), NotificationKind.Error); } } public static void Unlock(ACHIEVEMENTTYPE type) { //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_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) if ((int)type == 0) { return; } try { if (!TryUnlockAscent(type)) { AchievementManager.Grant(type); SetUnlockedCached(type, unlocked: true); AchievementDirectory.InvalidateCache(); Notify("Unlock Achievement", FormatAchievementName(type), NotificationKind.Success); } } catch (Exception ex) { Notify("Unlock Achievement Failed", GetBaseMessage(ex), NotificationKind.Error); } } public static void Lock(ACHIEVEMENTTYPE type) { //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_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) if ((int)type == 0) { return; } try { if (TryClearSteamAchievement(type)) { SetUnlockedCached(type, unlocked: false); Notify("Lock Achievement", FormatAchievementName(type), NotificationKind.Success); AchievementDirectory.InvalidateCache(); } else { LockByRebuildingUnlockedSet(type); SetUnlockedCached(type, unlocked: false); AchievementDirectory.InvalidateCache(); Notify("Lock Achievement", FormatAchievementName(type), NotificationKind.Success); } } catch (Exception ex) { Notify("Lock Achievement Failed", GetBaseMessage(ex), NotificationKind.Error); } } public static bool IsUnlockedCached(ACHIEVEMENTTYPE type) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) RefreshUnlockedCacheIfNeeded(); bool value; return UnlockedCache.TryGetValue(type, out value) && value; } public static string FormatAchievementName(ACHIEVEMENTTYPE type) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) if (!NameCache.TryGetValue(type, out var value)) { return FormatAchievementNameCore(type); } return value; } private static string FormatAchievementNameCore(ACHIEVEMENTTYPE type) { string text = ((object)(ACHIEVEMENTTYPE)(ref type)).ToString(); if (text.EndsWith("Badge", StringComparison.Ordinal)) { string text2 = text; int length = "Badge".Length; text = text2.Substring(0, text2.Length - length); } List list = new List(text.Length + 8); for (int i = 0; i < text.Length; i++) { char c = text[i]; if (i > 0 && char.IsUpper(c) && !char.IsUpper(text[i - 1]) && !char.IsDigit(c) && text[i - 1] != ' ') { list.Add(' '); } if (i > 0 && char.IsDigit(c) && !char.IsDigit(text[i - 1])) { list.Add(' '); } list.Add(c); } return new string(list.ToArray()).Trim(); } private static void LockByRebuildingUnlockedSet(ACHIEVEMENTTYPE typeToLock) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) RefreshUnlockedCache(force: true); List list = CachedTypes.Where((ACHIEVEMENTTYPE type) => type != typeToLock && IsUnlockedCached(type)).ToList(); AchievementManager.ClearAchievements(); foreach (ACHIEVEMENTTYPE item in list) { AchievementManager.Grant(item); } } private static bool TryUnlockAscent(ACHIEVEMENTTYPE type) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) int ascentAchievementIndex = GetAscentAchievementIndex(type); if (ascentAchievementIndex < 0) { return false; } AchievementManager manager = FindManagerCached(); int targetMaxAscent = Mathf.Clamp(ascentAchievementIndex + 1, 0, 8); UnlockAscentProgress(targetMaxAscent, manager); AchievementDirectory.InvalidateCache(); Notify("Unlock Achievement", FormatAchievementName(type) + " + ascent level " + targetMaxAscent.ToString(CultureInfo.InvariantCulture), NotificationKind.Success); return true; } private static void UnlockAscentProgress(int targetMaxAscent, AchievementManager manager) { targetMaxAscent = Mathf.Clamp(targetMaxAscent, 0, 8); int num = 0; int num2 = default(int); if (Object.op_Implicit((Object)(object)manager) && manager.GetSteamStatInt((STEAMSTATTYPE)13, ref num2)) { num = Mathf.Max(0, num2); } int num3 = Mathf.Max(num, targetMaxAscent); if (!TryGiveAscentLevel(num3) && Object.op_Implicit((Object)(object)manager)) { manager.SetSteamStat((STEAMSTATTYPE)13, num3); } if (Object.op_Implicit((Object)(object)manager)) { TryInvokeManager(manager, "TestAscentAchievements", num3); } MarkAscentCached(num3); } private static bool TryGiveAscentLevel(int level) { MethodInfo giveAscentLevelMethod = GetGiveAscentLevelMethod(); if (giveAscentLevelMethod == null) { return false; } giveAscentLevelMethod.Invoke(null, new object[1] { level }); return true; } private static MethodInfo GetGiveAscentLevelMethod() { return _giveAscentLevelMethod ?? (_giveAscentLevelMethod = typeof(AchievementManager).GetMethod("GiveAscentLevel", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(int) }, null)); } private static int GetAscentAchievementIndex(ACHIEVEMENTTYPE type) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Invalid comparison between Unknown and I4 //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Invalid comparison between Unknown and I4 //IL_000c: Unknown result type (might be due to invalid IL or missing references) if ((int)type < 33 || (int)type > 39) { return -1; } return Convert.ToInt32(type, CultureInfo.InvariantCulture) - Convert.ToInt32((object)(ACHIEVEMENTTYPE)33, CultureInfo.InvariantCulture) + 1; } private static bool TryClearSteamAchievement(ACHIEVEMENTTYPE type) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) MethodInfo clearAchievementMethod = GetClearAchievementMethod(); if (clearAchievementMethod == null) { return false; } string backendId = GetBackendId(type); object obj = clearAchievementMethod.Invoke(null, new object[1] { backendId }); if (obj is bool) { return (bool)obj; } return false; } private static string GetBackendId(ACHIEVEMENTTYPE type) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) if (BackendIdCache.TryGetValue(type, out var value)) { return value; } AchievementManager val = FindManagerCached(); if (!Object.op_Implicit((Object)(object)val) || val.allAchievements == null) { return ((object)(ACHIEVEMENTTYPE)(ref type)).ToString(); } int num = Convert.ToInt32(type, CultureInfo.InvariantCulture) - 1; if (num >= 0 && num < val.allAchievements.Count) { AchievementData val2 = val.allAchievements[num]; if (Object.op_Implicit((Object)(object)val2) && !string.IsNullOrWhiteSpace(val2.backendID)) { return BackendIdCache[type] = val2.backendID; } } string enumName = ((object)(ACHIEVEMENTTYPE)(ref type)).ToString(); using (IEnumerator enumerator = (from data in val.allAchievements where Object.op_Implicit((Object)(object)data) where string.Equals(((Object)data).name, enumName, StringComparison.OrdinalIgnoreCase) || string.Equals(data.backendID, enumName, StringComparison.OrdinalIgnoreCase) select data).GetEnumerator()) { if (enumerator.MoveNext()) { AchievementData current = enumerator.Current; return BackendIdCache[type] = (string.IsNullOrWhiteSpace(current.backendID) ? enumName : current.backendID); } } return BackendIdCache[type] = ((object)(ACHIEVEMENTTYPE)(ref type)).ToString(); } private static AchievementManager FindManagerCached() { if (Object.op_Implicit((Object)(object)_cachedManager)) { return _cachedManager; } if (Time.unscaledTime < _nextManagerLookupAt) { return null; } _nextManagerLookupAt = Time.unscaledTime + 5f; _cachedManager = Object.FindFirstObjectByType(); return _cachedManager; } private static void RefreshUnlockedCacheIfNeeded() { if (!(Time.unscaledTime < _nextUnlockedRefreshAt) || UnlockedCache.Count <= 0) { RefreshUnlockedCache(force: false); } } private static void RefreshUnlockedCache(bool force) { //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) AchievementManager val = FindManagerCached(); if (!Object.op_Implicit((Object)(object)val)) { if (force) { UnlockedCache.Clear(); } _nextUnlockedRefreshAt = Time.unscaledTime + 5f; return; } ACHIEVEMENTTYPE[] cachedTypes = CachedTypes; foreach (ACHIEVEMENTTYPE val2 in cachedTypes) { try { UnlockedCache[val2] = val.IsAchievementUnlocked(val2); } catch { UnlockedCache[val2] = false; } } _nextUnlockedRefreshAt = Time.unscaledTime + 10f; } private static void SetUnlockedCached(ACHIEVEMENTTYPE type, bool unlocked) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) if ((int)type != 0) { UnlockedCache[type] = unlocked; } _nextUnlockedRefreshAt = Time.unscaledTime + 10f; } private static void MarkAllCached(bool unlocked) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) ACHIEVEMENTTYPE[] cachedTypes = CachedTypes; foreach (ACHIEVEMENTTYPE key in cachedTypes) { UnlockedCache[key] = unlocked; } _nextUnlockedRefreshAt = Time.unscaledTime + 10f; } private static void MarkAscentCached(int maxAscent) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) for (int i = 1; i <= maxAscent - 1 && i <= 7; i++) { if (Enum.TryParse("Ascent" + i.ToString(CultureInfo.InvariantCulture), out ACHIEVEMENTTYPE result)) { UnlockedCache[result] = true; } } _nextUnlockedRefreshAt = Time.unscaledTime + 10f; } private static MethodInfo GetClearAchievementMethod() { if (_clearAchievementMethod != null) { return _clearAchievementMethod; } if (!_steamUserStatsResolved) { _steamUserStatsResolved = true; _steamUserStatsType = FindType("Steamworks.SteamUserStats"); } _clearAchievementMethod = _steamUserStatsType?.GetMethod("ClearAchievement", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(string) }, null); return _clearAchievementMethod; } private static bool TryInvokeManager(AchievementManager manager, string methodName, params object[] args) { MethodInfo methodInfo = ((object)manager)?.GetType().GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (methodInfo == null) { return false; } methodInfo.Invoke(manager, args); return true; } private static Type FindType(string fullName) { return (from assembly in AppDomain.CurrentDomain.GetAssemblies() select assembly.GetType(fullName, throwOnError: false)).FirstOrDefault((Type type) => type != null); } private static void Notify(string title, string description, NotificationKind kind) { NotificationSystem.Push(title, description, kind); } private static string GetBaseMessage(Exception ex) { while (ex is TargetInvocationException && ex.InnerException != null) { ex = ex.InnerException; } return ex.Message; } } public class LeaveLobby : ButtonFeature { public LeaveLobby() { base.Name = "Leave Lobby"; base.ButtonLabel = "Leave"; base.Description = "Safely leaves the current Photon room."; } public override void Execute() { NetworkRoomRuntime.LeaveRoomSafe(); } } internal sealed class NetworkRoomRuntime : MonoBehaviourPunCallbacks { private static NetworkRoomRuntime _instance; private const float LeaveTimeoutSeconds = 15f; private bool _leaving; private float _leaveStartedAt; private static NetworkRoomRuntime Instance { get { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown if (Object.op_Implicit((Object)(object)_instance)) { return _instance; } GameObject val = new GameObject("CubeX_NetworkRoomRuntime"); Object.DontDestroyOnLoad((Object)val); _instance = val.AddComponent(); return _instance; } } private void Awake() { if (Object.op_Implicit((Object)(object)_instance) && (Object)(object)_instance != (Object)(object)this) { Object.Destroy((Object)(object)((Component)this).gameObject); return; } _instance = this; Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject); } private void OnDestroy() { if ((Object)(object)_instance == (Object)(object)this) { _instance = null; } } public static void LeaveRoomSafe() { Instance.BeginLeaveOnly(); } private void BeginLeaveOnly() { try { if (_leaving) { NotificationSystem.Push("Leave Lobby", "A leave request is already running.", NotificationKind.Warning); return; } if (!PhotonNetwork.InRoom) { NotificationSystem.Push("Leave Lobby", "You are not currently in a Photon room.", NotificationKind.Warning); return; } _leaving = true; _leaveStartedAt = Time.realtimeSinceStartup; NotificationSystem.Push("Leave Lobby", "Leaving current room..."); if (!StartLeavingCurrentRoom()) { ResetState(); } } catch (Exception exception) { CubeXDiagnostics.Error("Leave Lobby Failed", "Unexpected error while leaving the room.", exception); ResetState(); } } private static bool StartLeavingCurrentRoom() { if (!PhotonNetwork.InRoom) { return true; } try { Player.LeaveCurrentGame(); return true; } catch (Exception exception) { CubeXDiagnostics.Error("Leave Lobby Failed", "Game leave call failed. Falling back to PhotonNetwork.LeaveRoom().", exception); } if (!PhotonNetwork.InRoom) { return true; } bool num = PhotonNetwork.LeaveRoom(true); if (!num) { NotificationSystem.Push("Leave Lobby Failed", "Photon refused the leave request.", NotificationKind.Error); } return num; } public override void OnLeftRoom() { if (_leaving) { NotificationSystem.Push("Leave Lobby", "Successfully left the current room."); ResetState(); } } public override void OnDisconnected(DisconnectCause cause) { if (_leaving) { NotificationSystem.Push("Leave Lobby Failed", "Disconnected while leaving the room: " + ((object)(DisconnectCause)(ref cause)).ToString(), NotificationKind.Error); ResetState(); } } private void Update() { if (_leaving && !(Time.realtimeSinceStartup - _leaveStartedAt < 15f)) { NotificationSystem.Push("Leave Lobby Failed", "Photon leave request timed out.", NotificationKind.Error); ResetState(); } } private void ResetState() { _leaving = false; _leaveStartedAt = 0f; } } internal static class PhotonJoinFailureMessages { public static string Describe(short returnCode, string photonMessage) { string text = returnCode switch { 32765 => "Lobby/room is full.", 32764 => "Lobby/room is closed.", 32758 => "Lobby/room does not exist or is no longer available.", 32762 => "Game ID already exists.", 32757 => "You are already matched or already joined.", 32756 => "Photon server rejected the operation.", 32755 => "Photon matchmaking rejected the request.", 32742 => "Server/app limit reached.", 32749 => "Inactive joiner/user conflict.", _ => "Photon rejected the join request.", }; string text2 = (string.IsNullOrWhiteSpace(photonMessage) ? string.Empty : (" Photon: " + photonMessage.Trim())); return text + " Code: " + returnCode.ToString(CultureInfo.InvariantCulture) + "." + text2; } } } namespace CubeX.Features.Misc { public class BadgeRemover : Feature { private readonly struct BadgeObjectState { public GameObject GameObject { get; } public bool WasActive { get; } public BadgeObjectState(GameObject gameObject, bool wasActive) { GameObject = gameObject; WasActive = wasActive; } } private readonly Dictionary _states = new Dictionary(); private float _nextScanAt; public BadgeRemover() { base.Name = "Badge Remover"; base.Description = "Hides loaded badge/achievement UI objects locally while enabled and restores them when disabled."; } protected override void OnEnable() { _nextScanAt = 0f; OnTick(); } protected override void OnDisable() { foreach (BadgeObjectState item in _states.Values.Where((BadgeObjectState state) => Object.op_Implicit((Object)(object)state.GameObject))) { item.GameObject.SetActive(item.WasActive); } _states.Clear(); } public override void OnTick() { if (Time.unscaledTime < _nextScanAt) { return; } _nextScanAt = Time.unscaledTime + 1.5f; Transform[] array = Object.FindObjectsByType((FindObjectsInactive)1, (FindObjectsSortMode)0); foreach (Transform val in array) { if (Object.op_Implicit((Object)(object)val) && IsBadgeUiObject(val)) { GameObject gameObject = ((Component)val).gameObject; int instanceID = ((Object)gameObject).GetInstanceID(); if (!_states.ContainsKey(instanceID)) { _states[instanceID] = new BadgeObjectState(gameObject, gameObject.activeSelf); } if (gameObject.activeSelf) { gameObject.SetActive(false); } } } } private static bool IsBadgeUiObject(Transform transform) { if (!Object.op_Implicit((Object)(object)transform)) { return false; } string text = BuildPath(transform); if (text.IndexOf("badge", StringComparison.OrdinalIgnoreCase) < 0 && text.IndexOf("achievement", StringComparison.OrdinalIgnoreCase) < 0) { return false; } if (!Object.op_Implicit((Object)(object)((Component)transform).GetComponent()) && text.IndexOf("canvas", StringComparison.OrdinalIgnoreCase) < 0 && text.IndexOf("hud", StringComparison.OrdinalIgnoreCase) < 0 && text.IndexOf("profile", StringComparison.OrdinalIgnoreCase) < 0) { return text.IndexOf("ui", StringComparison.OrdinalIgnoreCase) >= 0; } return true; } private static string BuildPath(Transform transform) { if (!Object.op_Implicit((Object)(object)transform)) { return string.Empty; } string text = ((Object)transform).name; Transform parent = transform.parent; int num = 0; while (Object.op_Implicit((Object)(object)parent) && num++ < 12) { text = ((Object)parent).name + "/" + text; parent = parent.parent; } return text; } } public class NoMoreAudioFilters : Feature { private readonly struct AudioSourceState { [CompilerGenerated] private readonly AudioSource P; private readonly bool _bypassEffects; private readonly bool _bypassReverbZones; private readonly bool _bypassListenerEffects; private readonly float _minDistance; private readonly float _maxDistance; private readonly float _dopplerLevel; private readonly float _reverbZoneMix; private readonly float _spread; private readonly AudioRolloffMode _rolloffMode; public AudioSourceState(AudioSource source) { //IL_0096: 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) P = source; _bypassEffects = P.bypassEffects; _bypassReverbZones = P.bypassReverbZones; _bypassListenerEffects = P.bypassListenerEffects; _minDistance = P.minDistance; _maxDistance = P.maxDistance; _dopplerLevel = P.dopplerLevel; _reverbZoneMix = P.reverbZoneMix; _spread = P.spread; _rolloffMode = P.rolloffMode; } public void Restore() { //IL_009d: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)P)) { P.bypassEffects = _bypassEffects; P.bypassReverbZones = _bypassReverbZones; P.bypassListenerEffects = _bypassListenerEffects; P.minDistance = _minDistance; P.maxDistance = _maxDistance; P.dopplerLevel = _dopplerLevel; P.reverbZoneMix = _reverbZoneMix; P.spread = _spread; P.rolloffMode = _rolloffMode; } } } private readonly struct BehaviourState { private Behaviour Behaviour { get; } private bool Enabled { get; } public BehaviourState(Behaviour behaviour, bool enabled) { Behaviour = behaviour; Enabled = enabled; } public void Restore() { if (Object.op_Implicit((Object)(object)Behaviour)) { Behaviour.enabled = Enabled; } } } private readonly Dictionary _sourceStates = new Dictionary(); private readonly Dictionary _filterStates = new Dictionary(); private float _nextScanAt; public NoMoreAudioFilters() { base.Name = "Disable Audio Filter"; base.Description = "Clear comms by locally bypassing heavy voice/audio filters and restoring them when disabled."; } protected override void OnEnable() { _nextScanAt = 0f; OnTick(); } protected override void OnDisable() { foreach (AudioSourceState value in _sourceStates.Values) { value.Restore(); } foreach (BehaviourState value2 in _filterStates.Values) { value2.Restore(); } _sourceStates.Clear(); _filterStates.Clear(); } public override void OnTick() { if (Time.unscaledTime < _nextScanAt) { return; } _nextScanAt = Time.unscaledTime + 2f; AudioSource[] array = Object.FindObjectsByType((FindObjectsInactive)0, (FindObjectsSortMode)0); foreach (AudioSource val in array) { if (Object.op_Implicit((Object)(object)val) && ShouldCleanSource(val)) { int instanceID = ((Object)val).GetInstanceID(); if (!_sourceStates.ContainsKey(instanceID)) { _sourceStates[instanceID] = new AudioSourceState(val); } val.bypassEffects = true; val.bypassReverbZones = true; val.bypassListenerEffects = true; val.dopplerLevel = 0f; val.reverbZoneMix = 0f; val.spread = 0f; val.rolloffMode = (AudioRolloffMode)1; val.minDistance = Mathf.Min(val.minDistance, 30f); val.maxDistance = Mathf.Min(Mathf.Max(val.maxDistance, 30f), 300f); DisableFilters(val); } } } private void DisableFilters(AudioSource source) { Behaviour[] components = ((Component)source).GetComponents(); foreach (Behaviour val in components) { if (Object.op_Implicit((Object)(object)val) && IsAudioFilter(val)) { int instanceID = ((Object)val).GetInstanceID(); if (!_filterStates.ContainsKey(instanceID)) { _filterStates[instanceID] = new BehaviourState(val, val.enabled); } val.enabled = false; } } } private static bool ShouldCleanSource(AudioSource source) { if (!Object.op_Implicit((Object)(object)source)) { return false; } if (HasAudioFilter(source)) { return true; } string text = BuildPath(((Component)source).transform); if (text.IndexOf("voice", StringComparison.OrdinalIgnoreCase) < 0 && text.IndexOf("speaker", StringComparison.OrdinalIgnoreCase) < 0 && text.IndexOf("character", StringComparison.OrdinalIgnoreCase) < 0) { return text.IndexOf("player", StringComparison.OrdinalIgnoreCase) >= 0; } return true; } private static bool HasAudioFilter(AudioSource source) { return ((Component)source).GetComponents().Any(IsAudioFilter); } private static bool IsAudioFilter(Behaviour behaviour) { if (!Object.op_Implicit((Object)(object)behaviour)) { return false; } switch (((object)behaviour).GetType().Name) { case "AudioReverbFilter": case "AudioEchoFilter": case "AudioDistortionFilter": case "AudioLowPassFilter": case "AudioHighPassFilter": case "AudioChorusFilter": return true; default: return false; } } private static string BuildPath(Transform transform) { if (!Object.op_Implicit((Object)(object)transform)) { return string.Empty; } string text = ((Object)transform).name; Transform parent = transform.parent; int num = 0; while (Object.op_Implicit((Object)(object)parent) && num++ < 12) { text = ((Object)parent).name + "/" + text; parent = parent.parent; } return text; } } internal static class ClientTimeoutSettings { public static bool DisableClientSideTimeout; } public class DisableClientSideTimeout : Feature { public DisableClientSideTimeout() { base.Name = "Disable Client Timeout"; base.Description = "Skips Photon client-side timeout disconnect handlers while continuing send/receive processing."; } protected override void OnEnable() { ClientTimeoutSettings.DisableClientSideTimeout = true; } protected override void OnDisable() { ClientTimeoutSettings.DisableClientSideTimeout = false; } } internal static class CompatibilitySettings { public static bool VersionCheckCompatibility; } public class VersionCheckCompatibility : Feature { public VersionCheckCompatibility() { base.Name = "Version Check Compatibility"; base.Description = "Skips PEAK's login version rejection while enabled for controlled compatibility testing. Disable to restore the normal check."; } protected override void OnEnable() { CompatibilitySettings.VersionCheckCompatibility = true; } protected override void OnDisable() { CompatibilitySettings.VersionCheckCompatibility = false; } } public class JoinDiscord : ButtonFeature { public JoinDiscord() { base.Name = "Join Discord"; base.Description = "Opens the Cube-X Discord community invite."; base.ButtonLabel = "Join"; } public override void Execute() { DiscordCommunityPrompt.OpenInvite(); NotificationSystem.Push("Discord Community", "Opening Discord invite."); } } public class JoinLeaveNotifications : Feature { public JoinLeaveNotifications() { base.Name = "Notify Player Lifecycle"; base.Description = "Show notifications when players enter or leave the lobby."; base.Enabled = NotificationSettings.JoinLeave; } protected override void OnEnable() { OnTick(); } protected override void OnDisable() { NotificationSettings.JoinLeave = false; } public override void OnTick() { NotificationSettings.JoinLeave = true; } } public class KeybindToggleNotifications : Feature { public KeybindToggleNotifications() { base.Name = "Notify Keybind Toggles"; base.Description = "Show notifications when a feature keybind runs or toggles a feature."; base.Enabled = NotificationSettings.KeybindToggles; } protected override void OnEnable() { NotificationSettings.KeybindToggles = true; } protected override void OnDisable() { NotificationSettings.KeybindToggles = false; } } public class PlayerLifeNotifications : Feature { public PlayerLifeNotifications() { base.Name = "Notify In Game Events"; base.Description = "Show notifications when players die, pass out, or revive."; base.Enabled = NotificationSettings.PlayerLife; } protected override void OnEnable() { OnTick(); } protected override void OnDisable() { NotificationSettings.PlayerLife = false; } public override void OnTick() { NotificationSettings.PlayerLife = true; } } public class RpcNotifications : Feature { public RpcNotifications() { base.Name = "Notify Modder Detections & Protections"; base.Description = "Show notifications for tracked Photon RPCs and blocked modded RPCs."; base.Enabled = NotificationSettings.RpcEvents; } protected override void OnEnable() { OnTick(); } protected override void OnDisable() { NotificationSettings.RpcEvents = false; } public override void OnTick() { NotificationSettings.RpcEvents = true; } } public class SkipIntroOnStartup : Feature { public SkipIntroOnStartup() { base.Name = "Skip Intro on Startup"; base.Description = "Skips the Pretitle splash sequence when the game starts."; } protected override void OnEnable() { OnTick(); } protected override void OnDisable() { StartupSettings.SkipIntroOnStartup = false; } public override void OnTick() { StartupSettings.SkipIntroOnStartup = true; } } public class ReconnectVoiceChat : ButtonFeature { public ReconnectVoiceChat() { base.Name = "Reconnect Voice Chat"; base.Description = "Manually disconnects and reconnects Photon Voice."; base.ButtonLabel = "Reconnect"; } public override void Execute() { VoiceChatFixRuntime.CleanAndReconnect(); } } public class VoiceChatFixer : Feature { public override bool TickWhenDisabled => true; public VoiceChatFixer() { base.Name = "Voice Chat Fixer"; base.Description = "Cleans stale Photon Voice state and reconnects voice after lobby joins or bad voice-room states."; base.Enabled = true; } protected override void OnEnable() { VoiceChatFixRuntime.Enabled = true; VoiceChatFixRuntime.CleanAndReconnect(); } protected override void OnDisable() { VoiceChatFixRuntime.Enabled = false; } public override void OnTick() { VoiceChatFixRuntime.Tick(); } } [HarmonyPatch(typeof(Pretitle), "Start")] internal static class SkipIntroPretitleStartPatch { private static readonly FieldInfo LoadWaitField = typeof(Pretitle).GetField("loadWait", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo AllowedToSwitchField = typeof(Pretitle).GetField("allowedToSwitch", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static void Prefix(Pretitle __instance) { if (StartupSettings.SkipIntroOnStartup && Object.op_Implicit((Object)(object)__instance)) { LoadWaitField?.SetValue(__instance, 0f); AllowedToSwitchField?.SetValue(__instance, true); } } } [HarmonyPatch(typeof(Player), "LeaveCurrentGame")] internal static class VoiceChatLeaveCleanupPatch { private static void Prefix() { VoiceChatFixRuntime.DisconnectVoice(); } } internal static class StartupSettings { public static bool SkipIntroOnStartup; } internal static class VoiceChatFixRuntime { [CompilerGenerated] private sealed class d__9 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__9(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = null; <>1__state = 1; return true; case 1: <>1__state = -1; <>2__current = (object)new WaitForSecondsRealtime(0.25f); <>1__state = 2; return true; case 2: <>1__state = -1; if (!PhotonNetwork.InRoom) { return false; } TryConnect(PunVoiceClient.Instance); 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 const float RetryInterval = 8f; private const float RoomMismatchGrace = 12f; private static float _nextRetryAt; private static float _roomJoinedAt; private static bool _wasInRoom; public static bool Enabled; public static void Tick() { if (!Enabled) { return; } if (!PhotonNetwork.InRoom) { _wasInRoom = false; } else if (!_wasInRoom) { _wasInRoom = true; _roomJoinedAt = Time.unscaledTime; _nextRetryAt = Time.unscaledTime + 2f; CleanAndReconnect(); } else { if (Time.unscaledTime < _nextRetryAt) { return; } PunVoiceClient instance = PunVoiceClient.Instance; if (Object.op_Implicit((Object)(object)instance)) { if (NeedsReconnect(instance)) { CleanAndReconnect(); } _nextRetryAt = Time.unscaledTime + 8f; } } } public static void CleanAndReconnect() { PunVoiceClient instance = PunVoiceClient.Instance; if (Object.op_Implicit((Object)(object)instance)) { try { ((VoiceFollowClient)instance).Disconnect(); } catch { } if (Object.op_Implicit((Object)(object)Plugin.Instance)) { ((MonoBehaviour)Plugin.Instance).StartCoroutine(ReconnectNextFrame()); } else { TryConnect(instance); } } } public static void DisconnectVoice() { PunVoiceClient instance = PunVoiceClient.Instance; if (Object.op_Implicit((Object)(object)instance)) { try { ((VoiceFollowClient)instance).Disconnect(); } catch { } _wasInRoom = false; _nextRetryAt = 0f; } } [IteratorStateMachine(typeof(d__9))] private static IEnumerator ReconnectNextFrame() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__9(0); } private static void TryConnect(PunVoiceClient voice) { if (!Object.op_Implicit((Object)(object)voice) || !PhotonNetwork.InRoom) { return; } try { if (!((VoiceFollowClient)voice).ConnectAndJoinRoom()) { TryJoinVoiceRoom(voice); } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Voice Chat Fixer] " + ex.Message)); } } } private static void TryJoinVoiceRoom(PunVoiceClient voice) { MethodInfo? method = typeof(PunVoiceClient).GetMethod("GetVoiceRoomName", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); MethodInfo method2 = typeof(PunVoiceClient).GetMethod("JoinVoiceRoom", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); string text = method?.Invoke(voice, null) as string; if (!string.IsNullOrEmpty(text)) { method2?.Invoke(voice, new object[1] { text }); } } private static bool NeedsReconnect(PunVoiceClient voice) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Invalid comparison between Unknown and I4 //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Invalid comparison between Unknown and I4 ClientState clientState = ((VoiceConnection)voice).ClientState; if (((int)clientState == 0 || (int)clientState == 14) ? true : false) { return true; } if ((int)clientState != 9) { return false; } if (Time.unscaledTime - _roomJoinedAt < 12f) { return false; } int num = ((PhotonNetwork.CurrentRoom != null) ? PhotonNetwork.CurrentRoom.PlayerCount : 0); LoadBalancingTransport client = ((VoiceConnection)voice).Client; int? obj; if (client == null) { obj = null; } else { Room currentRoom = ((LoadBalancingClient)client).CurrentRoom; obj = ((currentRoom != null) ? new int?(currentRoom.PlayerCount) : null); } int? num2 = obj; int valueOrDefault = num2.GetValueOrDefault(); if (num > 1) { return valueOrDefault <= 1; } return false; } } } namespace CubeX.Features.Misc.PauseMenuFeatures { public class RemovePauseBackground : Feature { private GameObject _background; private bool _originalBackgroundState; private bool _hasOriginalState; public RemovePauseBackground() { base.Name = "Remove Pause Background"; base.Description = "Removes the background image when pausing the game."; base.Enabled = false; } protected override void OnEnable() { CacheBackground(); if (Object.op_Implicit((Object)(object)_background)) { _originalBackgroundState = _background.activeSelf; _hasOriginalState = true; HideBackground(); } } public override void OnTick() { if (Object.op_Implicit((Object)(object)_background) || CacheBackground()) { HideBackground(); } } protected override void OnDisable() { if (Object.op_Implicit((Object)(object)_background) || CacheBackground()) { _background.SetActive(!_hasOriginalState || _originalBackgroundState); _hasOriginalState = false; } } private bool CacheBackground() { GameObject val = GameObject.Find("GUIManager"); if (!Object.op_Implicit((Object)(object)val)) { return false; } Transform val2 = val.transform.Find("PauseMenu"); if (!Object.op_Implicit((Object)(object)val2)) { return false; } Transform val3 = val2.Find("Background"); if (!Object.op_Implicit((Object)(object)val3)) { return false; } _background = ((Component)val3).gameObject; return true; } private void HideBackground() { if (Object.op_Implicit((Object)(object)_background) && _background.activeSelf) { _background.SetActive(false); } } } } namespace CubeX.Features.Inventory { public class HeldItemStats : Feature { private readonly struct StatRow { public string Label { get; } public string Value { get; } public StatIcon Icon { get; } public StatRow(string label, string value, StatIcon icon) { Label = label; Value = value; Icon = icon; } } private sealed class OrderedStatRows { private static readonly string[] DisplayOrder = new string[14] { "Weight", "Hunger", "Stamina", "Cold", "Injury", "Sleepy", "Heat", "Curse", "Spores", "Infinite Stamina", "Speed", "Shield", "Poison", "Thorns" }; private readonly Dictionary _rows = new Dictionary(StringComparer.OrdinalIgnoreCase); public void AddNumeric(string label, float value, StatIcon icon, string suffix) { if (!(Mathf.Abs(value) <= 0.001f)) { if (_rows.TryGetValue(label, out var value2) && TryParseNumber(value2.Value, suffix, out var value3)) { value += value3; } _rows[label] = new StatRow(label, FormatSigned(value) + suffix, icon); } } public void SetText(string label, string value, StatIcon icon) { if (!string.IsNullOrWhiteSpace(label) && !string.IsNullOrWhiteSpace(value)) { _rows[label] = new StatRow(label, value, icon); } } public List ToList() { List list = new List(); string[] displayOrder = DisplayOrder; foreach (string key in displayOrder) { if (_rows.TryGetValue(key, out var value)) { list.Add(value); } } return list; } } private enum StatIcon { Item, Weight, Hunger, Stamina, Cold, Injury, Sleepy, Heat, Curse, Spores, Shield, Poison, Thorns, Uses, Fuel, Tags, Action } [CompilerGenerated] private sealed class d__33 : IEnumerable, IEnumerable, IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; private int <>l__initialThreadId; private Item item; public Item <>3__item; private HashSet 5__2; private IEnumerator <>7__wrap2; private ItemActionBase[] <>7__wrap3; private int <>7__wrap4; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__33(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 1) { try { } finally { <>m__Finally1(); } } 5__2 = null; <>7__wrap2 = null; <>7__wrap3 = null; <>1__state = -2; } private bool MoveNext() { try { ItemActionBase[] componentsInChildren; switch (<>1__state) { default: return false; case 0: <>1__state = -1; if (!Object.op_Implicit((Object)(object)item)) { return false; } 5__2 = new HashSet(); if (GetMemberValue(item, "itemActions") is IEnumerable enumerable) { <>7__wrap2 = enumerable.GetEnumerator(); <>1__state = -3; goto IL_00c8; } goto IL_00e2; case 1: <>1__state = -3; goto IL_00c8; case 2: { <>1__state = -1; goto IL_0145; } IL_00e2: componentsInChildren = ((Component)item).GetComponentsInChildren(true); <>7__wrap3 = componentsInChildren; <>7__wrap4 = 0; goto IL_0153; IL_0153: if (<>7__wrap4 < <>7__wrap3.Length) { ItemActionBase val = <>7__wrap3[<>7__wrap4]; if (Object.op_Implicit((Object)(object)val) && 5__2.Add(((Object)val).GetInstanceID())) { <>2__current = val; <>1__state = 2; return true; } goto IL_0145; } <>7__wrap3 = null; return false; IL_0145: <>7__wrap4++; goto IL_0153; IL_00c8: while (<>7__wrap2.MoveNext()) { object current = <>7__wrap2.Current; if (current != null) { Object val2 = (Object)((current is Object) ? current : null); if (val2 == null || 5__2.Add(val2.GetInstanceID())) { <>2__current = current; <>1__state = 1; return true; } } } <>m__Finally1(); <>7__wrap2 = null; goto IL_00e2; } } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; if (<>7__wrap2 is IDisposable disposable) { disposable.Dispose(); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { d__33 d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; d__ = this; } else { d__ = new d__33(0); } d__.item = <>3__item; return d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)this).GetEnumerator(); } } private const BindingFlags ReflectionFlags = BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; private const float PercentFactor = 100f; private const string UiPrefix = "CubeX_ItemStat_"; private const float RefreshInterval = 0.35f; private const float FontSize = 20f; private static readonly Dictionary HudIconPaths = new Dictionary { { StatIcon.Weight, "GAME/GUIManager/Canvas_HUD/BarGroup/Bar/LayoutGroup/Weight/Icon" }, { StatIcon.Hunger, "GAME/GUIManager/Canvas_HUD/BarGroup/Bar/LayoutGroup/Hunger/Icon" }, { StatIcon.Stamina, "GAME/GUIManager/Canvas_HUD/BarGroup/ExtraStaminaBar/Icon" }, { StatIcon.Cold, "GAME/GUIManager/Canvas_HUD/BarGroup/Bar/LayoutGroup/Cold/Icon" }, { StatIcon.Injury, "GAME/GUIManager/Canvas_HUD/BarGroup/Bar/LayoutGroup/Injury/Icon" }, { StatIcon.Sleepy, "GAME/GUIManager/Canvas_HUD/BarGroup/Bar/LayoutGroup/Sleepy/Icon" }, { StatIcon.Heat, "GAME/GUIManager/Canvas_HUD/BarGroup/Bar/LayoutGroup/Heat/Icon" }, { StatIcon.Curse, "GAME/GUIManager/Canvas_HUD/BarGroup/Bar/LayoutGroup/Curse/Icon" }, { StatIcon.Spores, "GAME/GUIManager/Canvas_HUD/BarGroup/Bar/LayoutGroup/Spores/Icon" }, { StatIcon.Shield, "GAME/GUIManager/Canvas_HUD/BarGroup/Bar/OutlineMask/Outline/ShieldIcon" }, { StatIcon.Poison, "GAME/GUIManager/Canvas_HUD/BarGroup/Bar/LayoutGroup/Poison/Icon" }, { StatIcon.Thorns, "GAME/GUIManager/Canvas_HUD/BarGroup/Bar/LayoutGroup/Thorns/Icon" } }; private static readonly Dictionary UiSignatures = new Dictionary(); private static float _nextRefreshAt; private static bool _runtimeEnabled; public HeldItemStats() { base.Name = "Held Item Stats"; base.Description = "Adds compact item stat icons directly onto PEAK's inventory item UI."; } protected override void OnEnable() { _runtimeEnabled = true; UiSignatures.Clear(); _nextRefreshAt = 0f; ApplyToAllInventoryUi(); } protected override void OnDisable() { _runtimeEnabled = false; UiSignatures.Clear(); CleanupAllInventoryUi(); } public override void OnTick() { if (!(Time.unscaledTime < _nextRefreshAt)) { _nextRefreshAt = Time.unscaledTime + 0.35f; ApplyToAllInventoryUi(); } } private static void ApplyToAllInventoryUi() { GUIManager instance = GUIManager.instance; if (!Object.op_Implicit((Object)(object)instance)) { return; } if (instance.items != null) { InventoryItemUI[] items = instance.items; for (int i = 0; i < items.Length; i++) { ApplyToInventoryUi(items[i]); } } ApplyToInventoryUi(instance.temporaryItem); } private static void CleanupAllInventoryUi() { GUIManager instance = GUIManager.instance; if (Object.op_Implicit((Object)(object)instance)) { if (instance.items != null) { InventoryItemUI[] items = instance.items; for (int i = 0; i < items.Length; i++) { CleanupInventoryUi(items[i]); } } CleanupInventoryUi(instance.temporaryItem); CleanupInventoryUi(instance.backpack); } RectTransform[] array = Object.FindObjectsByType((FindObjectsInactive)1, (FindObjectsSortMode)0); foreach (RectTransform val in array) { if (Object.op_Implicit((Object)(object)val) && ((Object)((Component)val).gameObject).name.StartsWith("CubeX_ItemStat_", StringComparison.Ordinal)) { Object.Destroy((Object)(object)((Component)val).gameObject); } } } internal static void ApplyToInventoryUi(InventoryItemUI ui) { if (!Object.op_Implicit((Object)(object)ui) || !_runtimeEnabled || ui.isBackpack) { CleanupInventoryUi(ui); return; } Item inventoryUiItem = GetInventoryUiItem(ui); if (!Object.op_Implicit((Object)(object)inventoryUiItem) || !IsItemUiVisible(ui)) { CleanupInventoryUi(ui); return; } List list = BuildRows(inventoryUiItem); if (list.Count == 0) { CleanupInventoryUi(ui); return; } string text = BuildUiSignature(ui, inventoryUiItem, list); int instanceID = ((Object)ui).GetInstanceID(); if (UiSignatures.TryGetValue(instanceID, out var value) && string.Equals(value, text, StringComparison.Ordinal)) { return; } CleanupInventoryUi(ui); UiSignatures[instanceID] = text; Transform itemUiStatParent = GetItemUiStatParent(ui); if (Object.op_Implicit((Object)(object)itemUiStatParent)) { int index = 0; for (int i = 0; i < list.Count && i < 14; i++) { StatRow row = list[i]; CreateStatRow(ui, itemUiStatParent, row, ref index); } } } private static Transform GetItemUiStatParent(InventoryItemUI ui) { if (!Object.op_Implicit((Object)(object)ui)) { return null; } if (Object.op_Implicit((Object)(object)ui.fuelBar) && Object.op_Implicit((Object)(object)ui.fuelBar.transform.parent)) { return ui.fuelBar.transform.parent; } return ((Component)ui).transform; } private static bool IsItemUiVisible(InventoryItemUI ui) { if (!Object.op_Implicit((Object)(object)ui) || !((Component)ui).gameObject.activeInHierarchy) { return false; } if (!Object.op_Implicit((Object)(object)ui.nameText)) { return true; } if (((Behaviour)ui.nameText).enabled) { return ((Component)ui.nameText).gameObject.activeInHierarchy; } return false; } private static Item GetInventoryUiItem(InventoryItemUI ui) { if (!Object.op_Implicit((Object)(object)ui)) { return null; } object memberValue = GetMemberValue(ui, "_itemPrefab"); Item val = (Item)((memberValue is Item) ? memberValue : null); if (val != null && Object.op_Implicit((Object)(object)val)) { return val; } return null; } private static string BuildUiSignature(InventoryItemUI ui, Item item, List rows) { List list = new List { ((Object)item).GetInstanceID().ToString(CultureInfo.InvariantCulture), ui.isTemporarySlot ? "temp" : "slot" }; list.AddRange(rows.Select((StatRow t) => t.Label + "=" + t.Value)); return string.Join("|", list.ToArray()); } private static void CreateStatRow(InventoryItemUI ui, Transform parent, StatRow row, ref int index) { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) GameObject hudIconObject = GetHudIconObject(row.Icon); GameObject val = (GameObject)(Object.op_Implicit((Object)(object)hudIconObject) ? ((object)Object.Instantiate(hudIconObject, parent)) : ((object)new GameObject("CubeX_ItemStat_" + SanitizeName(row.Label), new Type[2] { typeof(RectTransform), typeof(TextMeshProUGUI) }))); ((Object)val).name = "CubeX_ItemStat_" + SanitizeName(row.Label); ((Object)val).hideFlags = (HideFlags)61; val.SetActive(true); RectTransform component = val.GetComponent(); if (Object.op_Implicit((Object)(object)component)) { ((Transform)component).localScale = new Vector3(0.66f, 0.66f, 0.66f); ((Transform)component).localPosition = (ui.isTemporarySlot ? new Vector3(20f, 120f + 20f * (float)(index + 1), 0f) : new Vector3(60f, 80f + 20f * (float)(index + 1), 0f)); } Image component2 = val.GetComponent(); if (Object.op_Implicit((Object)(object)component2)) { ((Graphic)component2).raycastTarget = false; } else { ConfigureFallbackIcon(val, row); } EnsureOutline(val); CreateStatText(ui, val.transform, row); index++; } private static void ConfigureFallbackIcon(GameObject iconObject, StatRow row) { //IL_008c: Unknown result type (might be due to invalid IL or missing references) TextMeshProUGUI val = (Object.op_Implicit((Object)(object)iconObject) ? iconObject.GetComponent() : null); if (Object.op_Implicit((Object)(object)val)) { ((TMP_Text)val).text = GetFallbackIconText(row.Icon); ((Behaviour)val).enabled = true; ((Component)val).gameObject.SetActive(true); ((TMP_Text)val).enableAutoSizing = false; ((TMP_Text)val).fontSize = 17f; ((TMP_Text)val).fontStyle = (FontStyles)1; ((TMP_Text)val).alignment = (TextAlignmentOptions)514; ((TMP_Text)val).textWrappingMode = (TextWrappingModes)0; ((TMP_Text)val).overflowMode = (TextOverflowModes)0; ((TMP_Text)val).outlineWidth = 0.1f; ((Graphic)val).raycastTarget = false; ((Graphic)val).color = GetStatColor(row.Icon); } } private static void CreateStatText(InventoryItemUI ui, Transform iconParent, StatRow row) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0052: 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_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0075: 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_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_0075: 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_00a4: Unknown result type (might be due to invalid IL or missing references) object obj = ((Object.op_Implicit((Object)(object)ui) && Object.op_Implicit((Object)(object)ui.nameText)) ? ((object)Object.Instantiate(((Component)ui.nameText).gameObject, iconParent)) : ((object)new GameObject("Text", new Type[2] { typeof(RectTransform), typeof(TextMeshProUGUI) }))); ((Object)obj).name = "Text"; ((Object)obj).hideFlags = (HideFlags)61; RectTransform component = ((GameObject)obj).GetComponent(); if (Object.op_Implicit((Object)(object)component)) { ((Transform)component).localScale = Vector3.one; ((Transform)component).localPosition = new Vector3(-75f, -25f, 0f); component.sizeDelta = new Vector2(180f, 40f); } TextMeshProUGUI component2 = ((GameObject)obj).GetComponent(); if (Object.op_Implicit((Object)(object)component2)) { ((TMP_Text)component2).text = row.Value; ((Behaviour)component2).enabled = true; ((Component)component2).gameObject.SetActive(true); ((TMP_Text)component2).enableAutoSizing = false; ((TMP_Text)component2).fontSize = 20f; ((TMP_Text)component2).fontSizeMin = 20f; ((TMP_Text)component2).fontSizeMax = 20f; ((TMP_Text)component2).alignment = (TextAlignmentOptions)516; ((TMP_Text)component2).textWrappingMode = (TextWrappingModes)0; ((TMP_Text)component2).overflowMode = (TextOverflowModes)0; ((TMP_Text)component2).outlineWidth = 0.1f; ((Graphic)component2).raycastTarget = false; ((Graphic)component2).color = GetStatColor(row.Icon); } } internal static void CleanupInventoryUi(InventoryItemUI ui) { if (!Object.op_Implicit((Object)(object)ui)) { return; } UiSignatures.Remove(((Object)ui).GetInstanceID()); Transform itemUiStatParent = GetItemUiStatParent(ui); if (!Object.op_Implicit((Object)(object)itemUiStatParent)) { return; } for (int num = itemUiStatParent.childCount - 1; num >= 0; num--) { Transform child = itemUiStatParent.GetChild(num); if (Object.op_Implicit((Object)(object)child) && ((Object)((Component)child).gameObject).name.StartsWith("CubeX_ItemStat_", StringComparison.Ordinal)) { Object.Destroy((Object)(object)((Component)child).gameObject); } } } private static void EnsureOutline(GameObject gameObject) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)gameObject) && !Object.op_Implicit((Object)(object)gameObject.GetComponent())) { ((Shadow)gameObject.AddComponent()).effectDistance = new Vector2(1.5f, -1.5f); } } private static GameObject GetHudIconObject(StatIcon icon) { if (HudIconPaths.TryGetValue(icon, out var value)) { return GameObject.Find(value); } return null; } private static Color GetStatColor(StatIcon icon) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) GameObject hudIconObject = GetHudIconObject(icon); Image val = (Object.op_Implicit((Object)(object)hudIconObject) ? hudIconObject.GetComponent() : null); if (!Object.op_Implicit((Object)(object)val)) { return GetFallbackIconColor(icon); } return ((Graphic)val).color; } private static string SanitizeName(string value) { if (string.IsNullOrWhiteSpace(value)) { return "Stat"; } List list = new List(value.Length); list.AddRange(value.Select((char c) => (!char.IsLetterOrDigit(c)) ? '_' : c)); return new string(list.ToArray()).Trim('_'); } private static Item GetHeldItem() { Character localCharacter = Character.localCharacter; if (!Object.op_Implicit((Object)(object)localCharacter) || (Object)(object)localCharacter.data == (Object)null) { return null; } return localCharacter.data.currentItem; } private static List BuildRows(Item item) { OrderedStatRows orderedStatRows = new OrderedStatRows(); float itemCarryWeight = GetItemCarryWeight(item); if (itemCarryWeight > 0.001f) { orderedStatRows.AddNumeric("Weight", itemCarryWeight * 100f / 40f, StatIcon.Weight, "%"); } AddActionStats(orderedStatRows, item); return orderedStatRows.ToList(); } private static float GetItemCarryWeight(Item item) { if (!Object.op_Implicit((Object)(object)item)) { return 0f; } float @float = GetFloat(item, "carryWeight"); if (Mathf.Approximately(@float, 0f)) { @float = GetFloat(item, "CarryWeight"); } return @float + GetAscentsItemWeightModifier(); } private static float GetAscentsItemWeightModifier() { return GetFloat(typeof(Ascents), "itemWeightModifier"); } private static void AddActionStats(OrderedStatRows rows, Item item) { foreach (object itemAction in GetItemActions(item)) { if (itemAction == null) { continue; } Behaviour val = (Behaviour)((itemAction is Behaviour) ? itemAction : null); if (val != null && !val.enabled) { continue; } switch (itemAction.GetType().Name) { case "Action_RestoreHunger": rows.AddNumeric("Hunger", (0f - GetFloat(itemAction, "restorationAmount")) * 100f, StatIcon.Hunger, "%"); break; case "Action_GiveExtraStamina": rows.AddNumeric("Stamina", GetFloat(itemAction, "amount") * 100f, StatIcon.Stamina, "%"); break; case "Action_InflictPoison": rows.AddNumeric("Poison", GetFloat(itemAction, "poisonPerSecond") * GetFloat(itemAction, "inflictionTime") * 100f, StatIcon.Poison, "%"); break; case "Action_AddOrRemoveThorns": rows.AddNumeric("Thorns", GetFloat(itemAction, "thornCount") * 100f / 20f, StatIcon.Thorns, "%"); break; case "Action_ModifyStatus": AddModifyStatusRow(rows, itemAction); break; case "Action_ApplyAffliction": case "Action_ApplyMassAffliction": AddAfflictionStats(rows, GetMemberValue(itemAction, "affliction")); if (!(GetMemberValue(itemAction, "extraAfflictions") is IEnumerable enumerable2)) { break; } foreach (object item2 in enumerable2) { AddAfflictionStats(rows, item2); } break; case "Action_RaycastDart": if (!(GetMemberValue(itemAction, "afflictionsOnHit") is IEnumerable enumerable)) { break; } foreach (object item3 in enumerable) { AddAfflictionStats(rows, item3); } break; } } if (Object.op_Implicit((Object)(object)((Component)item).GetComponent())) { rows.SetText("Shield", "Infinite", StatIcon.Shield); } } [IteratorStateMachine(typeof(d__33))] private static IEnumerable GetItemActions(Item item) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__33(-2) { <>3__item = item }; } private static void AddModifyStatusRow(OrderedStatRows rows, object action) { Character localCharacter = Character.localCharacter; if (!TryGetBool(action, "ifSkeleton", out var value) || !Object.op_Implicit((Object)(object)localCharacter) || !((Object)(object)localCharacter.data != (Object)null) || value == localCharacter.data.isSkeleton) { object memberValue = GetMemberValue(action, "statusType"); StatIcon statusIcon = GetStatusIcon(memberValue); float num = GetFloat(action, "changeAmount") * 100f; if (statusIcon == StatIcon.Curse) { num = 0f - num; } rows.AddNumeric(GetStatusLabel(memberValue, statusIcon), num, statusIcon, "%"); } } private static void AddAfflictionStats(OrderedStatRows rows, object affliction) { if (affliction == null) { return; } string name = affliction.GetType().Name; float @float = GetFloat(affliction, "totalTime"); if (name == null) { return; } object memberValue; StatIcon statusIcon; float num; switch (name.Length) { case 26: switch (name[11]) { case 'I': if (name == "Affliction_InfiniteStamina") { rows.SetText("Infinite Stamina", FormatDuration(@float, includeSpace: false), StatIcon.Stamina); AddAfflictionStats(rows, GetMemberValue(affliction, "drowsyAffliction")); } break; case 'A': if (name == "Affliction_AddBonusStamina") { rows.AddNumeric("Stamina", GetFloat(affliction, "staminaAmount") * 100f, StatIcon.Stamina, "%"); } break; } break; case 21: switch (name[11]) { case 'E': if (name == "Affliction_Exhaustion") { rows.AddNumeric("Sleepy", GetFloat(affliction, "drainAmount") * 100f, StatIcon.Sleepy, "%"); } break; case 'Z': if (name == "Affliction_ZombieBite") { rows.AddNumeric("Poison", GetFloat(affliction, "statusPerSecond") * @float * 100f, StatIcon.Poison, "%"); } break; } break; case 31: switch (name[17]) { default: return; case 'D': if (name == "Affliction_AdjustDrowsyOverTime") { rows.AddNumeric("Sleepy", GetFloat(affliction, "statusPerSecond") * @float * 100f, StatIcon.Sleepy, "%"); } return; case 'S': break; } if (!(name == "Affliction_AdjustStatusOverTime")) { break; } goto IL_02cd; case 25: switch (name[11]) { case 'P': if (name == "Affliction_PoisonOverTime") { rows.AddNumeric("Poison", GetFloat(affliction, "statusPerSecond") * @float * 100f, StatIcon.Poison, "%"); } break; case 'B': if (name == "Affliction_BingBongShield") { rows.SetText("Shield", FormatDuration(@float), StatIcon.Shield); } break; } break; case 20: if (name == "Affliction_FasterBoi") { rows.SetText("Speed", FormatDuration(@float), StatIcon.Stamina); rows.AddNumeric("Sleepy", GetFloat(affliction, "drowsyOnEnd") * 100f, StatIcon.Sleepy, "%"); } break; case 29: if (name == "Affliction_AdjustColdOverTime") { rows.AddNumeric("Cold", GetFloat(affliction, "statusPerSecond") * @float * 100f, StatIcon.Cold, "%"); } break; case 23: if (!(name == "Affliction_AdjustStatus")) { break; } goto IL_02cd; case 24: if (name == "Affliction_Invincibility") { rows.SetText("Shield", FormatDuration(@float), StatIcon.Shield); } break; case 22: case 27: case 28: case 30: break; IL_02cd: memberValue = GetMemberValue(affliction, "statusType"); statusIcon = GetStatusIcon(memberValue); num = GetFloat(affliction, "statusAmount") * 100f; if (Mathf.Approximately(num, 0f)) { num = GetFloat(affliction, "statusPerSecond") * @float * 100f; } rows.AddNumeric(GetStatusLabel(memberValue, statusIcon), num, statusIcon, "%"); break; } } private static string GetActionNames(Item item) { if (!(GetMemberValue(item, "itemActions") is IEnumerable enumerable)) { return string.Empty; } List list = new List(); foreach (object item2 in enumerable) { if (item2 != null) { string text = item2.GetType().Name; if (text.EndsWith("Action", StringComparison.OrdinalIgnoreCase)) { text = text.Substring(0, text.Length - "Action".Length); } if (!string.IsNullOrWhiteSpace(text) && !list.Contains(text)) { list.Add(text); } if (list.Count >= 3) { break; } } } return string.Join(", ", list); } private static float GetFloat(object target, string name) { object memberValue = GetMemberValue(target, name); if (memberValue == null) { return 0f; } if (memberValue is float) { return (float)memberValue; } if (memberValue is double num) { return (float)num; } if (memberValue is int num2) { return num2; } try { return Convert.ToSingle(memberValue, CultureInfo.InvariantCulture); } catch { return 0f; } } private static bool TryGetBool(object target, string name, out bool value) { value = false; if (GetMemberValue(target, name) is bool flag) { value = flag; return true; } return false; } private static bool GetBool(object target, string name) { bool value; return TryGetBool(target, name, out value) && value; } private static string FormatSigned(float value) { return ((value > 0f) ? "+" : string.Empty) + Mathf.Round(value).ToString(CultureInfo.InvariantCulture); } private static string FormatDuration(float seconds, bool includeSpace = true) { if (!(seconds > 0.001f)) { return "-"; } return seconds.ToString("F1", CultureInfo.InvariantCulture) + (includeSpace ? " sec" : "sec"); } private static string FormatAfflictionName(string typeName) { if (string.IsNullOrEmpty(typeName)) { return "Effect"; } if (typeName.StartsWith("Affliction_", StringComparison.Ordinal)) { typeName = typeName.Substring("Affliction_".Length); } return FormatMemberName(typeName); } private static string FormatActionName(string typeName) { if (string.IsNullOrEmpty(typeName)) { return string.Empty; } if (typeName.StartsWith("Action_", StringComparison.Ordinal)) { typeName = typeName.Substring("Action_".Length); } return FormatMemberName(typeName); } private static bool TryParseNumber(string text, string suffix, out float value) { value = 0f; if (string.IsNullOrWhiteSpace(text)) { return false; } if (!string.IsNullOrEmpty(suffix) && !text.EndsWith(suffix, StringComparison.Ordinal)) { return false; } if (!string.IsNullOrEmpty(suffix)) { text = text.Substring(0, text.Length - suffix.Length); } text = text.Trim().TrimStart('+'); return float.TryParse(text, NumberStyles.Float, CultureInfo.InvariantCulture, out value); } private static StatIcon GetStatusIcon(object status) { switch (GetStatusIndex(status)) { case 0: return StatIcon.Injury; case 1: return StatIcon.Hunger; case 2: return StatIcon.Cold; case 3: return StatIcon.Poison; case 5: return StatIcon.Curse; case 6: return StatIcon.Sleepy; case 7: return StatIcon.Weight; case 8: return StatIcon.Heat; case 9: return StatIcon.Thorns; case 10: return StatIcon.Spores; default: { StatIcon result; switch (GetStatusName(status).ToLowerInvariant()) { case "injury": result = StatIcon.Injury; break; case "hunger": result = StatIcon.Hunger; break; case "cold": result = StatIcon.Cold; break; case "poison": result = StatIcon.Poison; break; case "curse": result = StatIcon.Curse; break; case "sleepy": case "drowsy": result = StatIcon.Sleepy; break; case "weight": result = StatIcon.Weight; break; case "heat": result = StatIcon.Heat; break; case "thorns": result = StatIcon.Thorns; break; case "spores": result = StatIcon.Spores; break; default: result = StatIcon.Action; break; } return result; } } } private static string GetStatusLabel(object status, StatIcon fallbackIcon) { string statusName = GetStatusName(status); if (!string.IsNullOrEmpty(statusName) && !int.TryParse(statusName, NumberStyles.Integer, CultureInfo.InvariantCulture, out var _)) { return FormatMemberName(statusName); } return fallbackIcon switch { StatIcon.Injury => "Injury", StatIcon.Hunger => "Hunger", StatIcon.Cold => "Cold", StatIcon.Poison => "Poison", StatIcon.Curse => "Curse", StatIcon.Sleepy => "Sleepy", StatIcon.Weight => "Weight", StatIcon.Heat => "Heat", StatIcon.Thorns => "Thorns", StatIcon.Spores => "Spores", _ => "Status", }; } private static string GetStatusName(object status) { if (status != null) { return status.ToString(); } return string.Empty; } private static int GetStatusIndex(object status) { if (status == null) { return -1; } try { return Convert.ToInt32(status, CultureInfo.InvariantCulture); } catch { return -1; } } private static string FormatMemberName(string name) { if (string.IsNullOrEmpty(name)) { return string.Empty; } name = name.Replace("_", string.Empty); if (name.StartsWith("kBackingField", StringComparison.OrdinalIgnoreCase)) { return string.Empty; } List list = new List(name.Length + 8); for (int i = 0; i < name.Length; i++) { char c = name[i]; if (i > 0 && char.IsUpper(c) && !char.IsUpper(name[i - 1]) && name[i - 1] != ' ') { list.Add(' '); } list.Add(c); } string text = new string(list.ToArray()).Trim(); if (text.Length != 0) { return char.ToUpperInvariant(text[0]) + text.Substring(1); } return name; } private static object GetMemberValue(object target, string name) { if (target == null || string.IsNullOrEmpty(name)) { return null; } try { Type type = (target as Type) ?? target.GetType(); object obj = ((target is Type) ? null : target); MemberInfo memberInfo = FindMember(type, name); if (!(memberInfo is FieldInfo fieldInfo)) { if (memberInfo is PropertyInfo propertyInfo && propertyInfo.GetIndexParameters().Length == 0) { return propertyInfo.GetValue(obj, null); } return null; } return fieldInfo.GetValue(obj); } catch { return null; } } private static MemberInfo FindMember(Type type, string name) { while (type != null) { MemberInfo memberInfo = (MemberInfo)(((object)type.GetField(name, BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)) ?? ((object)type.GetProperty(name, BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic))); if (memberInfo != null) { return memberInfo; } type = type.BaseType; } return null; } private static Color GetFallbackIconColor(StatIcon icon) { //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: 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_0075: 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_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: 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_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Unknown result type (might be due to invalid IL or missing references) return (Color)(icon switch { StatIcon.Hunger => new Color(0.96f, 0.55f, 0.28f, 1f), StatIcon.Stamina => new Color(0.35f, 0.75f, 1f, 1f), StatIcon.Cold => new Color(0.45f, 0.8f, 1f, 1f), StatIcon.Injury => new Color(1f, 0.2f, 0.2f, 1f), StatIcon.Sleepy => new Color(0.68f, 0.55f, 1f, 1f), StatIcon.Heat => new Color(1f, 0.45f, 0.18f, 1f), StatIcon.Curse => new Color(0.74f, 0.35f, 1f, 1f), StatIcon.Poison => new Color(0.35f, 1f, 0.4f, 1f), StatIcon.Thorns => new Color(0.65f, 0.94f, 0.28f, 1f), StatIcon.Spores => new Color(0.55f, 0.86f, 0.64f, 1f), StatIcon.Shield => new Color(0.75f, 0.85f, 1f, 1f), StatIcon.Weight => new Color(0.86f, 0.86f, 0.86f, 1f), _ => Theme.Accent, }); } private static string GetFallbackIconText(StatIcon icon) { return icon switch { StatIcon.Uses => "#", StatIcon.Fuel => "F", StatIcon.Tags => "T", StatIcon.Action => "*", StatIcon.Item => "I", _ => "•", }; } } [HarmonyPatch(typeof(InventoryItemUI), "Clear")] internal static class HeldItemStatsClearPatch { private static void Postfix(InventoryItemUI __instance) { HeldItemStats.CleanupInventoryUi(__instance); } } [HarmonyPatch(typeof(InventoryItemUI), "SetItem")] internal static class HeldItemStatsSetItemPatch { private static void Postfix(InventoryItemUI __instance) { HeldItemStats.ApplyToInventoryUi(__instance); } } [HarmonyPatch(typeof(InventoryItemUI), "OnDisable")] internal static class HeldItemStatsUiDisablePatch { private static void Postfix(InventoryItemUI __instance) { HeldItemStats.CleanupInventoryUi(__instance); } } internal sealed class AssignInventoryItem : ButtonFeature, IMenuTagProvider { private readonly int _slot; private readonly Item _item; public Item Item => _item; public List Tags { get; } public AssignInventoryItem(int slot, Item item, string itemName, List tags = null) { _slot = slot; _item = item; base.Name = itemName; base.Description = "Assign this item to " + InventoryState.GetSlotName(slot) + "."; base.ButtonLabel = "Assign"; Tags = tags ?? new List(); } public override void Execute() { GameActions.AssignInventoryItem(_slot, _item); } } public class InventoryDirectory : Feature, IMenuRowProvider, IMenuSidePanelProvider { private sealed class CachedRows { public int Version { get; } public int SearchVersion { get; } public List Rows { get; } public CachedRows(int version, int searchVersion, List rows) { Version = version; SearchVersion = searchVersion; Rows = rows ?? new List(); base..ctor(); } } private const string ItemsCategory = "Items"; private const string SlotCategoryPrefix = "Items/Slot "; private const string AssignCategorySuffix = "/Assign Item"; private readonly Dictionary _assignRowCache = new Dictionary(); private string _lastCategory; public InventoryDirectory() { base.Name = "Inventory Directory"; base.Description = "Builds inventory slot and item assignment rows."; } public IEnumerable GetRows(string category) { RefreshItemsOnCategoryEnter(category); if (category == "Items") { return new <>z__ReadOnlySingleElementList(new InfoFeature("Known Items", InventoryState.ItemPrefabs.Count.ToString(), "Loaded item prefabs available for assignment.")); } if (TryParseSlotCategory(category, out var slot, out var assignItems, out var groupId)) { if (!assignItems) { return BuildSlotRows(slot); } return GetCachedAssignRows(category, slot, groupId); } return Array.Empty(); } private void RefreshItemsOnCategoryEnter(string category) { if (!string.Equals(category, _lastCategory, StringComparison.Ordinal)) { _lastCategory = category; if (string.Equals(category, "Items", StringComparison.Ordinal)) { InventoryState.RefreshItems(); } } } public bool TryGetSidePanel(string category, object selectedRow, out MenuSidePanel panel) { panel = null; if (!(selectedRow is AssignInventoryItem assignInventoryItem) || !Object.op_Implicit((Object)(object)assignInventoryItem.Item)) { return false; } panel = ItemDetails.BuildPanel(assignInventoryItem.Item); return panel != null; } private IEnumerable GetCachedAssignRows(string category, int slot, string groupId) { if (string.IsNullOrEmpty(category)) { return BuildAssignRows(slot, groupId); } int version = InventoryState.Version; int searchVersion = InventoryState.SearchVersion; if (_assignRowCache.TryGetValue(category, out var value) && value.Version == version && value.SearchVersion == searchVersion) { return value.Rows; } List list = BuildAssignRows(slot, groupId); _assignRowCache[category] = new CachedRows(version, searchVersion, list); return list; } private static IEnumerable BuildSlotRows(int slot) { return new <>z__ReadOnlySingleElementList(new InfoFeature("Current Item", GameActions.GetCurrentSlotItemName(slot), "Item currently equipped in this slot.")); } private static List BuildAssignRows(int slot, string groupId) { List list = new List(); IReadOnlyList itemEntries = InventoryState.ItemEntries; if (itemEntries.Count == 0) { list.Add(new InfoFeature("Items", "None", "No item prefabs were found.")); return list; } list.Add(new SeparatorFeature()); if (string.IsNullOrEmpty(groupId)) { IReadOnlyList itemGroups = InventoryState.ItemGroups; list.AddRange(itemGroups.Select((InventoryState.ItemGroup group) => new SubmenuFeature(group.Name, BuildAssignCategory(slot) + "/" + group.Id, group.Description, BuildGroupTags(slot, group.Id)))); return list; } int num = 0; int num2 = 0; foreach (InventoryState.ItemEntry item2 in itemEntries) { if (item2 == null) { continue; } Item item = item2.Item; if (Object.op_Implicit((Object)(object)item) && (!(item2.GroupId != groupId) || !(groupId != "All"))) { num++; if (InventoryState.MatchesSearch(slot, item)) { num2++; list.Add(new AssignInventoryItem(slot, item, item2.DisplayName, BuildItemTags(item2.GroupId))); } } } if (num2 == 0) { list.Add(new InfoFeature("Matches", "0/" + num, "No item names matched the current search.")); } return list; } private static string BuildAssignCategory(int slot) { return "Items/" + InventoryState.GetSlotName(slot) + "/Assign Item"; } private static List BuildItemTags(string groupId) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) groupId = (string.IsNullOrWhiteSpace(groupId) ? "Misc" : groupId); return new List(1) { new MenuTag(InventoryState.GetGroupTag(groupId), InventoryState.GetGroupColor(groupId)) }; } private static List BuildGroupTags(int slot, string groupId) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: 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) //IL_004f: Unknown result type (might be due to invalid IL or missing references) int num = InventoryState.CountVisibleItems(slot, groupId); Color color = ((num > 0) ? new Color(0.18f, 0.58f, 0.48f, 1f) : new Color(0.36f, 0.38f, 0.42f, 1f)); return new List(1) { new MenuTag(num.ToString(), color) }; } private static bool TryParseSlotCategory(string category, out int slot, out bool assignItems, out string groupId) { slot = -1; assignItems = false; groupId = null; if (string.IsNullOrEmpty(category)) { return false; } if (!category.StartsWith("Items/Slot ", StringComparison.Ordinal)) { return false; } string text = category.Substring("Items/Slot ".Length); int num = text.IndexOf('/'); if (!int.TryParse((num >= 0) ? text.Substring(0, num) : text, out var result)) { return false; } slot = result - 1; int num2 = slot; if ((num2 < 0 || num2 > 2) ? true : false) { return false; } if (num < 0) { return true; } string text2 = text.Substring(num); if (text2 == "/Assign Item") { assignItems = true; return true; } string text3 = "/Assign Item/"; if (text2.StartsWith(text3, StringComparison.Ordinal)) { assignItems = true; groupId = text2.Substring(text3.Length); } return true; } } internal static class InventoryState { public sealed class ItemEntry { public Item Item { get; } public string DisplayName { get; } private string PrefabName { get; } public string GroupId { get; } public string GroupName { get; } public string LowerDisplayName { get; } public string LowerPrefabName { get; } public ItemEntry(Item item, string displayName, string prefabName, string groupId, string groupName) { Item = item; DisplayName = displayName ?? string.Empty; PrefabName = prefabName ?? string.Empty; GroupId = groupId ?? "Misc"; GroupName = groupName ?? "Misc Items"; LowerDisplayName = DisplayName.ToLowerInvariant(); LowerPrefabName = PrefabName.ToLowerInvariant(); } } public sealed class ItemGroup { public string Id { get; } public string Name { get; } public string Description { get; } public ItemGroup(string id, string name, string description) { Id = id; Name = name; Description = description; base..ctor(); } } private const float RefreshInterval = 30f; public static readonly string[] SearchText = new string[3] { string.Empty, string.Empty, string.Empty }; private static readonly List Items = new List(); private static readonly List Entries = new List(); private static readonly Dictionary EntryByItem = new Dictionary(); private static float _nextRefreshAt; private static int _version; private static int _searchVersion; private static readonly ItemGroup[] Groups = new ItemGroup[9] { new ItemGroup("All", "All Items", "Every assignable item prefab."), new ItemGroup("Food", "Food & Drinks", "Berries, mushrooms, packaged food, and edible items."), new ItemGroup("Medicine", "Medicine & Buffs", "Healing, status clears, stamina, and temporary buff items."), new ItemGroup("Climbing", "Climbing Gear", "Ropes, pitons, chalk, and climbing tools."), new ItemGroup("Light", "Light & Fire", "Torches, lanterns, flares, firewood, and fire starters."), new ItemGroup("Tools", "Tools & Utility", "Navigation, traversal, and utility items."), new ItemGroup("Throwables", "Throwables", "Items mainly used by throwing, launching, or exploding."), new ItemGroup("Valuables", "Valuables", "Mystical, collectible, and special objective items."), new ItemGroup("Misc", "Misc Items", "Items that do not fit another category.") }; private const BindingFlags MemberFlags = BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; public static IReadOnlyList ItemPrefabs => Items; public static IReadOnlyList ItemEntries => Entries; public static IReadOnlyList ItemGroups => Groups; public static int Version => _version; public static int SearchVersion => _searchVersion; public static void RefreshItems() { Items.Clear(); Items.AddRange(GameActions.FindItemPrefabs()); RebuildItemEntries(); _nextRefreshAt = Time.unscaledTime + 30f; _version++; } public static void RefreshItemsIfNeeded() { if (!(Time.unscaledTime < _nextRefreshAt)) { RefreshItems(); } } public static string GetSlotName(int slot) { return "Slot " + (slot + 1); } public static void SetSearchText(int slot, string value) { if (slot >= 0 && slot < SearchText.Length) { if (value == null) { value = string.Empty; } if (!(SearchText[slot] == value)) { SearchText[slot] = value; _searchVersion++; } } } public static bool MatchesSearch(int slot, Item item) { if (!Object.op_Implicit((Object)(object)item)) { return false; } if (slot < 0 || slot >= SearchText.Length) { return true; } string text = SearchText[slot]; if (string.IsNullOrWhiteSpace(text)) { return true; } ItemEntry entry = GetEntry(item); if (entry != null) { if (!entry.LowerDisplayName.Contains(text.ToLowerInvariant())) { return entry.LowerPrefabName.Contains(text.ToLowerInvariant()); } return true; } if (GameActions.GetItemName(item).IndexOf(text, StringComparison.OrdinalIgnoreCase) >= 0) { return true; } string name = ((Object)item).name; if (!string.IsNullOrEmpty(name)) { return name.IndexOf(text, StringComparison.OrdinalIgnoreCase) >= 0; } return false; } private static bool MatchesGroup(Item item, string groupId) { if (!Object.op_Implicit((Object)(object)item)) { return false; } if (string.IsNullOrEmpty(groupId) || groupId == "All") { return true; } ItemEntry entry = GetEntry(item); if (entry == null) { return GetItemGroupId(item) == groupId; } return entry.GroupId == groupId; } public static int CountVisibleItems(int slot, string groupId) { int num = 0; foreach (ItemEntry entry in Entries) { if (entry != null && Object.op_Implicit((Object)(object)entry.Item) && MatchesGroup(entry.Item, groupId) && MatchesSearch(slot, entry.Item)) { num++; } } return num; } private static string GetItemGroupId(Item item) { if (!Object.op_Implicit((Object)(object)item)) { return "Misc"; } ItemEntry entry = GetEntry(item); if (entry != null) { return entry.GroupId; } return DetermineItemGroupId(item, GameActions.GetItemName(item)); } public static string GetItemGroupName(Item item) { if (!Object.op_Implicit((Object)(object)item)) { return "Misc Items"; } ItemEntry entry = GetEntry(item); if (entry != null) { return entry.GroupName; } return GetGroupName(GetItemGroupId(item)); } public static string GetItemGroupTag(Item item) { return GetGroupTag(GetItemGroupId(item)); } public static string GetGroupTag(string groupId) { return groupId switch { "Food" => "FOOD", "Medicine" => "MEDICINE", "Climbing" => "CLIMBING", "Light" => "LIGHT", "Tools" => "TOOLS", "Throwables" => "THROWABLES", "Valuables" => "VALUABLES", _ => "MISC", }; } public static Color GetItemGroupColor(Item item) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return GetGroupColor(GetItemGroupId(item)); } public static Color GetGroupColor(string groupId) { //IL_01d8: 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) //IL_01de: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01c1: 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_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) return (Color)(groupId switch { "Food" => new Color(0.24f, 0.68f, 0.36f, 1f), "Medicine" => new Color(0.78f, 0.24f, 0.28f, 1f), "Climbing" => new Color(0.26f, 0.48f, 0.86f, 1f), "Light" => new Color(0.88f, 0.58f, 0.16f, 1f), "Tools" => new Color(0.18f, 0.58f, 0.48f, 1f), "Throwables" => new Color(0.72f, 0.34f, 0.18f, 1f), "Valuables" => new Color(0.66f, 0.42f, 0.86f, 1f), _ => new Color(0.46f, 0.48f, 0.54f, 1f), }); } public static string GetItemDisplayName(Item item) { ItemEntry entry = GetEntry(item); if (entry == null) { return GameActions.GetItemName(item); } return entry.DisplayName; } private static void RebuildItemEntries() { Entries.Clear(); EntryByItem.Clear(); foreach (Item item in Items) { if (Object.op_Implicit((Object)(object)item)) { string itemName = GameActions.GetItemName(item); string text = DetermineItemGroupId(item, itemName); ItemEntry itemEntry = new ItemEntry(item, itemName, ((Object)item).name, text, GetGroupName(text)); Entries.Add(itemEntry); EntryByItem[item] = itemEntry; } } } private static ItemEntry GetEntry(Item item) { if (!Object.op_Implicit((Object)(object)item)) { return null; } if (!EntryByItem.TryGetValue(item, out var value)) { return null; } return value; } private static string DetermineItemGroupId(Item item, string displayName) { if (!Object.op_Implicit((Object)(object)item)) { return "Misc"; } string text = (displayName + " " + ((Object)item).name).ToLowerInvariant(); string text2 = ReadMemberText(item, "itemTags").ToLowerInvariant(); string text3 = ReadActionText(item).ToLowerInvariant(); if (text2.Contains("packagedfood") || text2.Contains("berry") || text2.Contains("mushroom") || ContainsAny(text, "berry", "mushroom", "shroom", "fungus", "banana", "berrynana", "trail mix", "food", "ration", "egg", "honey", "coconut", "drink", "juice", "soda") || text3.Contains("restorehunger")) { return "Food"; } if (ContainsAny(text, "med", "bandage", "antidote", "cure", "remedy", "sunscreen", "tonic", "healing") || ContainsAny(text3, "clearallstatus", "applyinfinitestamina", "giveextrastamina", "modifystatus", "applyaffliction")) { return "Medicine"; } if (ContainsAny(text, "rope", "piton", "chalk", "climb")) { return "Climbing"; } if (ContainsAny(text, "torch", "lantern", "flare", "firewood", "campfire", "match", "lamp")) { return "Light"; } if (ContainsAny(text, "dynamite", "bomb", "stone", "rock", "dart", "cannon", "spear", "snowball")) { return "Throwables"; } if (text2.Contains("mystical") || text2.Contains("bingbong") || text2.Contains("goldenidol") || text2.Contains("bookofbones") || ContainsAny(text, "idol", "gem", "gold", "skull", "bone", "bing bong", "crown")) { return "Valuables"; } if (ContainsAny(text, "compass", "binocular", "map", "guidebook", "passport", "bugle", "parasol", "umbrella", "balloon", "warp")) { return "Tools"; } return "Misc"; } private static string GetGroupName(string id) { ItemGroup[] groups = Groups; foreach (ItemGroup itemGroup in groups) { if (itemGroup.Id == id) { return itemGroup.Name; } } return "Misc Items"; } private static bool ContainsAny(string text, params string[] terms) { if (string.IsNullOrEmpty(text) || terms == null) { return false; } foreach (string value in terms) { if (!string.IsNullOrEmpty(value) && text.Contains(value)) { return true; } } return false; } private static string ReadMemberText(object target, string name) { if (target == null || string.IsNullOrEmpty(name)) { return string.Empty; } try { FieldInfo fieldInfo = FindField(target.GetType(), name); if (fieldInfo != null) { return fieldInfo.GetValue(target)?.ToString() ?? string.Empty; } PropertyInfo propertyInfo = FindProperty(target.GetType(), name); if (propertyInfo != null && propertyInfo.GetIndexParameters().Length == 0) { return propertyInfo.GetValue(target, null)?.ToString() ?? string.Empty; } } catch { } return string.Empty; } private static string ReadActionText(Item item) { object obj = null; try { obj = FindField(((object)item).GetType(), "itemActions")?.GetValue(item); } catch { } if (!(obj is IEnumerable enumerable)) { return string.Empty; } StringBuilder stringBuilder = new StringBuilder(); foreach (object item2 in enumerable) { if (item2 != null) { if (stringBuilder.Length > 0) { stringBuilder.Append(' '); } stringBuilder.Append(item2.GetType().Name); } } return stringBuilder.ToString(); } private static FieldInfo FindField(Type type, string name) { while (type != null) { FieldInfo field = type.GetField(name, BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { return field; } type = type.BaseType; } return null; } private static PropertyInfo FindProperty(Type type, string name) { while (type != null) { PropertyInfo property = type.GetProperty(name, BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (property != null) { return property; } type = type.BaseType; } return null; } } public abstract class ItemSearchFeature : TextFeature { private readonly int _slot; protected ItemSearchFeature(int slot) { _slot = slot; base.Name = "Search"; base.Description = "Filter the assignable item list by item name."; base.EmptyDisplayText = "All items"; base.MaxLength = 48; SetText(InventoryState.SearchText[slot]); } protected override void OnTextChanged(string newValue) { InventoryState.SetSearchText(_slot, newValue); } } public abstract class RechargeSlot : ButtonFeature { private readonly int _slot; protected RechargeSlot(int slot) { _slot = slot; base.Name = "Recharge " + InventoryState.GetSlotName(slot); base.Description = "Recharges the item currently equipped in this slot."; base.ButtonLabel = "Recharge"; } public override void Execute() { GameActions.RechargeInventorySlot(_slot); } } public class RechargeSlot1 : RechargeSlot { public RechargeSlot1() : base(0) { } } public class RechargeSlot2 : RechargeSlot { public RechargeSlot2() : base(1) { } } public class RechargeSlot3 : RechargeSlot { public RechargeSlot3() : base(2) { } } public class Slot1ItemSearch : ItemSearchFeature { public Slot1ItemSearch() : base(0) { } } public class Slot2ItemSearch : ItemSearchFeature { public Slot2ItemSearch() : base(1) { } } public class Slot3ItemSearch : ItemSearchFeature { public Slot3ItemSearch() : base(2) { } } internal static class ItemDetails { private readonly struct ItemEffectInfo { public readonly string Name; public readonly string Value; public ItemEffectInfo(string name, string value) { Name = name; Value = value; } } private const int MaxPanelRows = 24; private const BindingFlags MemberFlags = BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; private static readonly Dictionary PanelCache = new Dictionary(); private static int _panelCacheVersion = -1; private static readonly string[] KnownItemMembers = new string[13] { "itemID", "CarryWeight", "carryWeight", "mass", "totalUses", "itemTags", "canUseOnFriend", "showUseProgress", "blockInteraction", "offsetLuggageSpawn", "throwForceMultiplier", "packLayer", "centerOfMass" }; private static readonly string[] KnownUiMembers = new string[20] { "itemName", "icon", "altIcon", "hasAltIcon", "hasColorBlindIcon", "hasMainInteract", "mainInteractPrompt", "hasSecondInteract", "secondaryInteractPrompt", "hasScrollingInteract", "scrollInteractPrompt", "canDrop", "canPocket", "canBackpack", "canThrow", "isShootable", "hideFuel", "iconPositionOffset", "iconRotationOffset", "iconScaleOffset" }; public static MenuSidePanel BuildPanel(Item item) { if (!Object.op_Implicit((Object)(object)item)) { return null; } if (_panelCacheVersion != InventoryState.Version) { PanelCache.Clear(); _panelCacheVersion = InventoryState.Version; } if (PanelCache.TryGetValue(item, out var value)) { return value; } Texture previewTexture = GetPreviewTexture(item); List list = new List(); HashSet seen = new HashSet(StringComparer.OrdinalIgnoreCase); int hidden = 0; AddRow(list, seen, "Name", GameActions.GetItemName(item), ref hidden); AddRow(list, seen, "Category", InventoryState.GetItemGroupName(item), ref hidden); AddRow(list, seen, "Type", ((object)item).GetType().Name, ref hidden); AddEffectRows(list, seen, item, ref hidden); AddRow(list, seen, "Use", GetUsePrompt(item), ref hidden); AddKnownMembers(list, seen, item, string.Empty, new string[5] { "itemID", "CarryWeight", "mass", "totalUses", "itemTags" }, ref hidden); AddRow(list, seen, "Prefab", ((Object)item).name, ref hidden); if (list.Count < 23) { object memberValue = GetMemberValue(item, "UIData"); AddKnownMembers(list, seen, memberValue, "UI ", new string[4] { "canDrop", "canPocket", "canBackpack", "canThrow" }, ref hidden); } if (hidden > 0 && list.Count < 24) { list.Add(new InfoFeature("More Attributes", "+" + hidden.ToString(CultureInfo.InvariantCulture))); } MenuSidePanel menuSidePanel = new MenuSidePanel("ITEM INFORMATION", GameActions.GetItemName(item), list, previewTexture); PanelCache[item] = menuSidePanel; return menuSidePanel; } private static void AddEffectRows(List rows, HashSet seen, Item item, ref int hidden) { List list = BuildEffects(item); if (list.Count == 0) { AddRow(rows, seen, "Effects", "None", ref hidden); return; } for (int i = 0; i < list.Count; i++) { AddRow(rows, seen, list[i].Name, list[i].Value, ref hidden); } } private static List BuildEffects(Item item) { List list = new List(); if (GetMemberValue(item, "itemActions") is IEnumerable enumerable) { foreach (object item2 in enumerable) { AddActionEffects(list, item2); } } return list; } private static void AddActionEffects(List effects, object action) { if (action == null) { return; } string name = action.GetType().Name; switch (name) { case "Action_RestoreHunger": AddEffect(effects, "Hunger", FormatSigned(GetFloat(action, "restorationAmount"))); break; case "Action_GiveExtraStamina": AddEffect(effects, "Bonus Stamina", FormatSigned(GetFloat(action, "amount"))); break; case "Action_ApplyInfiniteStamina": AddEffect(effects, "Infinite Stamina", FormatDuration(GetFloat(action, "buffTime")) + " ∞"); AddPositiveEffect(effects, "Drowsy", GetFloat(action, "drowsyAmount")); break; case "Action_ModifyStatus": AddEffect(effects, FormatStatusName(GetMemberValue(action, "statusType")), FormatSigned(GetFloat(action, "changeAmount"))); break; case "Action_ClearAllStatus": AddEffect(effects, "Clear Status", "All"); break; case "Action_RandomMushroomEffect": AddEffect(effects, "Random Effect", "Mushroom"); break; case "Action_MoraleBoost": AddEffect(effects, "Morale", "Boost"); break; case "Action_ApplySuperJump": AddEffect(effects, "Jump", "Boost"); break; case "Action_ApplyAntigrav": AddEffect(effects, "Low Gravity", "Boost"); break; } if (!(name == "Action_ApplyAffliction") && !(name == "Action_ApplyMassAffliction")) { return; } AddAfflictionEffects(effects, GetMemberValue(action, "affliction")); if (!(GetMemberValue(action, "extraAfflictions") is IEnumerable enumerable)) { return; } foreach (object item in enumerable) { AddAfflictionEffects(effects, item); } } private static void AddAfflictionEffects(List effects, object affliction) { if (affliction == null) { return; } string name = affliction.GetType().Name; float @float = GetFloat(affliction, "totalTime"); if (name == null) { return; } switch (name.Length) { default: return; case 20: switch (name[11]) { case 'F': if (name == "Affliction_FasterBoi") { AddTimedMultiplier(effects, "Run", @float, GetFloat(affliction, "moveSpeedMod")); AddTimedMultiplier(effects, "Climb", @float, GetFloat(affliction, "climbSpeedMod")); AddPositiveEffect(effects, "Drowsy", GetFloat(affliction, "drowsyOnEnd")); } break; case 'S': if (name == "Affliction_Sunscreen") { AddEffect(effects, "Sunscreen", FormatDuration(@float)); } break; } return; case 26: switch (name[11]) { case 'I': if (name == "Affliction_InfiniteStamina") { AddEffect(effects, "Infinite Stamina", FormatDuration(@float) + " ∞"); AddAfflictionEffects(effects, GetMemberValue(affliction, "drowsyAffliction")); } break; case 'A': if (name == "Affliction_AddBonusStamina") { AddEffect(effects, "Bonus Stamina", FormatSigned(GetFloat(affliction, "staminaAmount")) + FormatDurationSuffix(@float)); } break; } return; case 24: switch (name[11]) { case 'C': if (name == "Affliction_ClimbingChalk") { AddTimedMultiplier(effects, "Climb", @float, GetFloat(affliction, "climbStaminaMultiplier")); } break; case 'I': if (name == "Affliction_Invincibility") { AddEffect(effects, "Invincibility", FormatDuration(@float)); } break; } return; case 23: if (!(name == "Affliction_AdjustStatus")) { return; } goto IL_0230; case 31: if (!(name == "Affliction_AdjustStatusOverTime")) { return; } goto IL_0230; case 19: if (name == "Affliction_NoHunger") { AddEffect(effects, "No Hunger", FormatDuration(@float)); } return; case 21: if (name == "Affliction_LowGravity") { AddEffect(effects, "Low Gravity", FormatDuration(@float)); } return; case 15: if (!(name == "Affliction_Numb")) { return; } break; case 16: if (!(name == "Affliction_Blind")) { return; } break; case 17: case 18: case 22: case 25: case 27: case 28: case 29: case 30: return; IL_0230: AddEffect(effects, FormatStatusName(GetMemberValue(affliction, "statusType")), FormatSigned(GetFloat(affliction, "statusAmount")) + FormatDurationSuffix(@float)); return; } AddEffect(effects, FormatAfflictionName(name), FormatDuration(@float)); } private static void AddTimedMultiplier(List effects, string name, float duration, float multiplier) { if (!(Mathf.Abs(multiplier) <= 0.001f)) { string text = FormatDuration(duration); if (!Mathf.Approximately(multiplier, 1f)) { text = text + " x" + multiplier.ToString("F1", CultureInfo.InvariantCulture); } AddEffect(effects, name, text); } } private static void AddPositiveEffect(List effects, string name, float amount) { if (!(amount <= 0.001f)) { AddEffect(effects, name, FormatSigned(amount)); } } private static void AddEffect(List effects, string name, string value) { if (!string.IsNullOrEmpty(name)) { if (string.IsNullOrEmpty(value)) { value = "-"; } effects.Add(new ItemEffectInfo(name, value)); } } private static string GetUsePrompt(Item item) { object memberValue = GetMemberValue(item, "UIData"); string text = GetMemberValue(memberValue, "mainInteractPrompt") as string; string text2 = GetMemberValue(memberValue, "secondaryInteractPrompt") as string; if (!string.IsNullOrWhiteSpace(text) && !string.IsNullOrWhiteSpace(text2)) { return text + " / " + text2; } if (!string.IsNullOrWhiteSpace(text)) { return text; } if (!string.IsNullOrWhiteSpace(text2)) { return text2; } return "-"; } private static float GetFloat(object target, string name) { object memberValue = GetMemberValue(target, name); if (memberValue == null) { return 0f; } if (memberValue is float) { return (float)memberValue; } if (memberValue is double num) { return (float)num; } if (memberValue is int num2) { return num2; } try { return Convert.ToSingle(memberValue, CultureInfo.InvariantCulture); } catch { return 0f; } } private static string FormatSigned(float value) { if (Mathf.Abs(value) <= 0.001f) { return "0"; } return ((value > 0f) ? "+" : string.Empty) + value.ToString("F1", CultureInfo.InvariantCulture); } private static string FormatDuration(float seconds) { if (seconds <= 0.001f) { return "-"; } return seconds.ToString("F1", CultureInfo.InvariantCulture) + "s"; } private static string FormatDurationSuffix(float seconds) { string text = FormatDuration(seconds); if (!(text == "-")) { return " / " + text; } return string.Empty; } private static string FormatStatusName(object status) { if (status == null) { return "Status"; } string text = status.ToString(); if (!string.IsNullOrEmpty(text)) { return FormatMemberName(text); } return "Status"; } private static string FormatAfflictionName(string typeName) { if (string.IsNullOrEmpty(typeName)) { return "Effect"; } if (typeName.StartsWith("Affliction_", StringComparison.Ordinal)) { typeName = typeName.Substring("Affliction_".Length); } return FormatMemberName(typeName); } private static void AddKnownMembers(List rows, HashSet seen, object target, string prefix, string[] names, ref int hidden) { if (target == null || names == null) { return; } foreach (string text in names) { if (TryGetMemberValue(target, text, out var value)) { AddRow(rows, seen, FormatMemberName(prefix + text), FormatValue(value), ref hidden); } } } private static void AddSimpleMembers(List rows, HashSet seen, object target, string prefix, ref int hidden) { if (target == null) { return; } MemberInfo[] members = target.GetType().GetMembers(BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); Array.Sort(members, (MemberInfo a, MemberInfo b) => string.Compare(a.Name, b.Name, StringComparison.OrdinalIgnoreCase)); MemberInfo[] array = members; foreach (MemberInfo memberInfo in array) { if ((memberInfo.MemberType != MemberTypes.Field && memberInfo.MemberType != MemberTypes.Property) || ShouldSkipMember(memberInfo)) { continue; } object value; try { MemberInfo memberInfo2 = memberInfo; if (!(memberInfo2 is FieldInfo fieldInfo)) { if (!(memberInfo2 is PropertyInfo propertyInfo) || propertyInfo.GetIndexParameters().Length != 0) { continue; } value = propertyInfo.GetValue(target, null); goto IL_00a5; } value = fieldInfo.GetValue(target); goto IL_00a5; } catch { } continue; IL_00a5: if (IsDisplayable(value)) { AddRow(rows, seen, FormatMemberName(prefix + memberInfo.Name), FormatValue(value), ref hidden); } } } private static bool TryGetMemberValue(object target, string name, out object value) { value = null; if (target == null || string.IsNullOrEmpty(name)) { return false; } return TryReadMember(target, name, out value); } private static object GetMemberValue(object target, string name) { TryReadMember(target, name, out var value); return value; } private static bool TryReadMember(object target, string name, out object value) { value = null; if (target == null) { return false; } FieldInfo fieldInfo = FindField(target.GetType(), name); if (fieldInfo != null) { value = fieldInfo.GetValue(target); return true; } PropertyInfo propertyInfo = FindProperty(target.GetType(), name); if (propertyInfo != null && propertyInfo.GetIndexParameters().Length == 0) { value = propertyInfo.GetValue(target, null); return true; } return false; } private static FieldInfo FindField(Type type, string name) { while (type != null) { FieldInfo field = type.GetField(name, BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { return field; } type = type.BaseType; } return null; } private static PropertyInfo FindProperty(Type type, string name) { while (type != null) { PropertyInfo property = type.GetProperty(name, BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (property != null) { return property; } type = type.BaseType; } return null; } private static void AddRow(List rows, HashSet seen, string name, string value, ref int hidden) { if (!string.IsNullOrEmpty(name) && seen.Add(name)) { if (rows.Count >= 23) { hidden++; } else { rows.Add(new InfoFeature(name, string.IsNullOrEmpty(value) ? "-" : value)); } } } private static bool ShouldSkipMember(MemberInfo member) { string name = member.Name; if (string.IsNullOrEmpty(name)) { return true; } if (name.StartsWith("<", StringComparison.Ordinal)) { return true; } if (name.StartsWith("On", StringComparison.Ordinal)) { return true; } if ((name == "mpb" || name == "destroyCancellationToken") ? true : false) { return true; } Type memberType = GetMemberType(member); return typeof(Delegate).IsAssignableFrom(memberType); } private static Type GetMemberType(MemberInfo member) { if (!(member is FieldInfo fieldInfo)) { if (member is PropertyInfo propertyInfo) { return propertyInfo.PropertyType; } return typeof(object); } return fieldInfo.FieldType; } private static bool IsDisplayable(object value) { if (value == null) { return true; } Type type = value.GetType(); if (type.IsPrimitive || type.IsEnum) { return true; } if (value is string) { return true; } if (value is Vector2 || value is Vector3 || value is Vector4 || value is Color) { return true; } if (value is Object) { return true; } if (value is Array) { return true; } if (value is IEnumerable) { return !(value is IDictionary); } return false; } private static string FormatValue(object value) { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: 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_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009f: 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) if (value == null) { return "-"; } if (!(value is string text)) { if (!(value is bool)) { if (!(value is float num)) { if (!(value is double num2)) { if (!(value is Vector2 val)) { if (!(value is Vector3 val2)) { if (!(value is Vector4 val3)) { if (!(value is Color val4)) { Texture val5 = (Texture)((value is Texture) ? value : null); if (val5 == null) { Object val6 = (Object)((value is Object) ? value : null); if (val6 == null) { if (!(value is Array array)) { if (!(value is IEnumerable enumerable)) { if (value is IFormattable formattable) { return formattable.ToString(null, CultureInfo.InvariantCulture); } return value.ToString(); } return CountEnumerable(enumerable).ToString(CultureInfo.InvariantCulture) + " entries"; } return array.Length.ToString(CultureInfo.InvariantCulture) + " " + GetFriendlyTypeName(value.GetType().GetElementType()); } return Object.op_Implicit(val6) ? val6.name : "-"; } return ((Object)val5).name; } return "#" + ColorUtility.ToHtmlStringRGBA(val4); } return val3.x.ToString("F2", CultureInfo.InvariantCulture) + ", " + val3.y.ToString("F2", CultureInfo.InvariantCulture) + ", " + val3.z.ToString("F2", CultureInfo.InvariantCulture) + ", " + val3.w.ToString("F2", CultureInfo.InvariantCulture); } return val2.x.ToString("F2", CultureInfo.InvariantCulture) + ", " + val2.y.ToString("F2", CultureInfo.InvariantCulture) + ", " + val2.z.ToString("F2", CultureInfo.InvariantCulture); } return val.x.ToString("F2", CultureInfo.InvariantCulture) + ", " + val.y.ToString("F2", CultureInfo.InvariantCulture); } return num2.ToString("F2", CultureInfo.InvariantCulture); } return num.ToString("F2", CultureInfo.InvariantCulture); } return ((bool)value) ? "Yes" : "No"; } return string.IsNullOrEmpty(text) ? "-" : text; } private static int CountEnumerable(IEnumerable enumerable) { return enumerable.Cast().Count(); } private static string FormatMemberName(string name) { if (string.IsNullOrEmpty(name)) { return string.Empty; } name = name.Replace("_", string.Empty); if (name.StartsWith("kBackingField", StringComparison.OrdinalIgnoreCase)) { return string.Empty; } List list = new List(name.Length + 8); for (int i = 0; i < name.Length; i++) { char c = name[i]; if (i > 0 && char.IsUpper(c) && !char.IsUpper(name[i - 1]) && name[i - 1] != ' ') { list.Add(' '); } list.Add(c); } string text = new string(list.ToArray()).Trim(); if (text.Length != 0) { return char.ToUpperInvariant(text[0]) + text.Substring(1); } return name; } private static string GetFriendlyTypeName(Type type) { if (!(type == null)) { return type.Name; } return "items"; } private static Texture GetPreviewTexture(Item item) { object memberValue = GetMemberValue(item, "UIData"); if (TryTexture(memberValue, "icon", out var texture)) { return texture; } if (TryTexture(memberValue, "altIcon", out texture)) { return texture; } Renderer val = item.mainRenderer; if (!Object.op_Implicit((Object)(object)val)) { val = ((Component)item).GetComponentInChildren(true); } if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.sharedMaterial) && Object.op_Implicit((Object)(object)val.sharedMaterial.mainTexture)) { return val.sharedMaterial.mainTexture; } return null; } private static bool TryTexture(object target, string memberName, out Texture texture) { texture = null; object memberValue = GetMemberValue(target, memberName); Texture val = (Texture)((memberValue is Texture) ? memberValue : null); if (val != null && Object.op_Implicit((Object)(object)val)) { texture = val; return true; } return false; } } } namespace CubeX.Features.Host { public class HostOnlyKiosk : Feature { public HostOnlyKiosk() { base.Name = "Host Only Kiosk"; base.Description = "Keeps the airport start kiosk locked so only the host can start expeditions."; base.Enabled = HostOnlyKioskSettings.Enabled; } protected override void OnEnable() { HostOnlyKioskSettings.Enabled = true; NotificationSystem.Push("Host Only Kiosk", PhotonNetwork.IsMasterClient ? "Non-host kiosk starts will be blocked." : "Enabled, but it only enforces while you are the host."); } protected override void OnDisable() { HostOnlyKioskSettings.Enabled = false; HostOnlyKioskSettings.ResetHostStartRequest(); } } internal static class HostOnlyKioskSettings { private const float HostStartRequestSeconds = 4f; private const float BlockNotificationCooldownSeconds = 2.5f; private static bool _hostStartRequested; private static float _hostStartRequestedAt = -999f; private static float _lastBlockNotificationAt = -999f; public static bool Enabled = true; public static bool ShouldEnforceAsHost { get { if (Enabled && PhotonNetwork.InRoom) { return PhotonNetwork.IsMasterClient; } return false; } } public static void MarkHostStartRequested() { if (Enabled && PhotonNetwork.IsMasterClient) { _hostStartRequested = true; _hostStartRequestedAt = Time.realtimeSinceStartup; } } public static bool ConsumeHostStartRequest() { bool result = _hostStartRequested && Time.realtimeSinceStartup - _hostStartRequestedAt <= 4f; ResetHostStartRequest(); return result; } public static void ResetHostStartRequest() { _hostStartRequested = false; _hostStartRequestedAt = -999f; } public static void NotifyBlockedLoadMaster() { float realtimeSinceStartup = Time.realtimeSinceStartup; if (!(realtimeSinceStartup - _lastBlockNotificationAt < 2.5f)) { _lastBlockNotificationAt = realtimeSinceStartup; NotificationSystem.Push("Host Only Kiosk", "Blocked a non-host expedition start.", NotificationKind.Warning); } } } public class LightNearbyCampfire : ButtonFeature { public LightNearbyCampfire() { base.Name = "Light Nearby Campfire"; base.Description = "Host-only action that lights the closest unlit campfire within 10 meters."; base.ButtonLabel = "Light"; } public override void Execute() { //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) if (!PhotonNetwork.IsMasterClient) { NotificationSystem.Push("Light Campfire", "Only the host can force-light campfires.", NotificationKind.Warning); return; } Character localCharacter = Character.localCharacter; if (!Object.op_Implicit((Object)(object)localCharacter)) { return; } Campfire val = null; float num = 10f; Campfire[] array = Object.FindObjectsByType((FindObjectsSortMode)0); foreach (Campfire val2 in array) { if (Object.op_Implicit((Object)(object)val2) && !val2.Lit) { float num2 = Vector3.Distance(localCharacter.Center, ((Component)val2).transform.position); if (!(num2 > num)) { val = val2; num = num2; } } } PhotonView photonView = GetPhotonView((Component)(object)val); if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)photonView)) { NotificationSystem.Push("Light Campfire", "No unlit campfire is nearby.", NotificationKind.Warning); return; } photonView.RPC("Light_Rpc", (RpcTarget)0, new object[2] { true, 0f }); NotificationSystem.Push("Light Campfire", "Nearby campfire lit."); } private static PhotonView GetPhotonView(Component component) { if (!Object.op_Implicit((Object)(object)component)) { return null; } return component.GetComponent() ?? component.GetComponentInParent() ?? component.GetComponentInChildren(); } } public class LoadAirport : ButtonFeature { public LoadAirport() { base.Name = "Load Airport"; base.Description = "Host-only action that returns the lobby to the airport using the game's airport load flow."; base.ButtonLabel = "Load"; } public override void Execute() { if (!PhotonNetwork.IsMasterClient) { NotificationSystem.Push("Load Airport", "Only the host can load the airport.", NotificationKind.Warning); return; } GameOverHandler val = Object.FindFirstObjectByType(); if (!Object.op_Implicit((Object)(object)val)) { NotificationSystem.Push("Load Airport", "Game over handler was not found.", NotificationKind.Warning); return; } val.LoadAirportMaster(); NotificationSystem.Push("Load Airport", "Airport load request sent."); } } public class MaxScouts : NumberFeature { public MaxScouts() { base.Name = "Max Scouts"; base.Description = "Maximum scouts allowed in host-created expedition rooms."; base.Min = 1f; base.Max = 30f; base.Value = MoreScoutsRuntime.MaxScouts; base.Step = 1f; base.Decimals = 0; base.Unit = " scouts"; } protected override void OnValueChanged(float newValue) { MoreScoutsRuntime.SetMaxScouts(Mathf.RoundToInt(newValue)); } } public class MoreScouts : Feature { public MoreScouts() { base.Name = "More Scouts"; base.Description = "Lets host-created expedition rooms accept the configured scout limit."; } protected override void OnEnable() { MoreScoutsRuntime.Enabled = true; MoreScoutsRuntime.ApplyCurrentRoomLimit(); NotificationSystem.Push("More Scouts", "Room scout limit set to " + MoreScoutsRuntime.ClampedMaxScouts + "."); } protected override void OnDisable() { MoreScoutsRuntime.Enabled = false; } public override void OnTick() { MoreScoutsRuntime.ApplyCurrentRoomLimit(); } } internal static class MoreScoutsRuntime { public const int VanillaMaxScouts = 4; public const int DefaultMaxScouts = 20; public const int MinMaxScouts = 1; public const int HardMaxScouts = 30; private static readonly HashSet CampfiresWithExtraFood = new HashSet(); private static int _expeditionScoutCount; public static bool Enabled; public static int MaxScouts = 20; public static bool HasCapturedExpeditionScoutCount => _expeditionScoutCount > 0; public static int ExpeditionScoutCount { get { if (_expeditionScoutCount <= 0) { return GetCurrentScoutCount(); } return _expeditionScoutCount; } } public static int ClampedMaxScouts => Mathf.Clamp(MaxScouts, 1, 30); public static void SetMaxScouts(int value) { MaxScouts = Mathf.Clamp(value, 1, 30); ApplyCurrentRoomLimit(); } public static void ApplyCurrentRoomLimit() { if (Enabled && PhotonNetwork.InRoom && PhotonNetwork.IsMasterClient && PhotonNetwork.CurrentRoom != null) { int num = Mathf.Max(PhotonNetwork.CurrentRoom.PlayerCount, 1); PhotonNetwork.CurrentRoom.MaxPlayers = Mathf.Clamp(Mathf.Max(ClampedMaxScouts, num), 1, 30); } } public static void CaptureExpeditionScoutCount() { _expeditionScoutCount = Mathf.Clamp(GetCurrentScoutCount(), 1, 30); CampfiresWithExtraFood.Clear(); } public static void ClearExpeditionScoutCount() { _expeditionScoutCount = 0; CampfiresWithExtraFood.Clear(); } public static void SpawnExtraCampfireFood(GameObject campfireRoot) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0054: 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_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0098: 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_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: 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) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) if (!Enabled || !PhotonNetwork.IsMasterClient || !Object.op_Implicit((Object)(object)campfireRoot)) { return; } int num = Mathf.Max(0, ExpeditionScoutCount - 4); if (num <= 0) { return; } int instanceID = ((Object)campfireRoot).GetInstanceID(); if (CampfiresWithExtraFood.Add(instanceID)) { Vector3 val = campfireRoot.transform.position + Vector3.up * 0.35f; Vector3 val2 = default(Vector3); for (int i = 0; i < num; i++) { float num2 = MathF.PI * 2f * (float)i / (float)Mathf.Max(1, num); ((Vector3)(ref val2))..ctor(Mathf.Cos(num2), 0f, Mathf.Sin(num2)); SpawnNetworkItem("0_Items/Marshmallow", val + val2 * 1.45f + Vector3.up * (0.035f * (float)i)); SpawnNetworkItem("0_Items/Glizzy", val + val2 * 1.85f + Vector3.up * (0.035f * (float)i)); } } } public static int GetCurrentScoutCount() { try { if (PhotonNetwork.InRoom && PhotonNetwork.CurrentRoom != null) { return Mathf.Clamp(PhotonNetwork.CurrentRoom.PlayerCount, 1, 30); } if (PhotonNetwork.PlayerList != null && PhotonNetwork.PlayerList.Length != 0) { return Mathf.Clamp(PhotonNetwork.PlayerList.Length, 1, 30); } } catch { } int num = 0; try { if (Character.AllCharacters != null) { foreach (Character allCharacter in Character.AllCharacters) { if (Object.op_Implicit((Object)(object)allCharacter) && !allCharacter.isBot) { num++; } } } } catch { } return Mathf.Clamp(Mathf.Max(num, 1), 1, 30); } public static int GetCurrentRoomMax() { try { if (PhotonNetwork.InRoom && PhotonNetwork.CurrentRoom != null && PhotonNetwork.CurrentRoom.MaxPlayers > 0) { return PhotonNetwork.CurrentRoom.MaxPlayers; } } catch { } if (!Enabled) { return 4; } return ClampedMaxScouts; } private static void SpawnNetworkItem(string prefabPath, Vector3 position) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) try { PhotonNetwork.Instantiate(prefabPath, position, Quaternion.Euler(0f, Random.Range(0f, 360f), 0f), (byte)0, (object[])null); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[More Scouts] Failed to spawn " + prefabPath + ": " + ex.GetBaseException().Message)); } } } } public class SkipEndScreen : ButtonFeature { public SkipEndScreen() { base.Name = "Skip End Screen"; base.Description = "Host-only action that marks every scout as done with the end screen."; base.ButtonLabel = "Skip"; } public override void Execute() { if (!PhotonNetwork.IsMasterClient) { NotificationSystem.Push("Skip End Screen", "Only the host can skip the end screen.", NotificationKind.Warning); return; } GameOverHandler val = Object.FindFirstObjectByType(); if (!Object.op_Implicit((Object)(object)val)) { NotificationSystem.Push("Skip End Screen", "End screen handler was not found.", NotificationKind.Warning); return; } val.ForceEveryPlayerDoneWithEndScreen(); NotificationSystem.Push("Skip End Screen", "End screen skipped."); } } public class SpawnBackpack : ButtonFeature { public SpawnBackpack() { base.Name = "Spawn Backpack"; base.Description = "Host-only action that spawns a backpack near your camera."; base.ButtonLabel = "Spawn"; } public override void Execute() { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) if (!PhotonNetwork.IsMasterClient) { NotificationSystem.Push("Spawn Backpack", "Only the host can spawn extra backpacks.", NotificationKind.Warning); return; } PhotonNetwork.Instantiate("0_Items/Backpack", SpawnFeatureHelpers.GetCameraSpawnPosition(2f), Quaternion.identity, (byte)0, (object[])null); NotificationSystem.Push("Spawn Backpack", "Backpack spawned."); } } public class SteamLobbyLock : Feature { private float _nextRefreshAt; public SteamLobbyLock() { base.Name = "Steam Lobby Lock"; base.Description = "Locks the Steam lobby so new scouts cannot join until it is unlocked."; } protected override void OnEnable() { if (!PhotonNetwork.IsMasterClient) { NotificationSystem.Push("Steam Lobby Lock", "Only the host can lock the Steam lobby.", NotificationKind.Warning); base.Enabled = false; } else if (SetJoinable(joinable: false)) { NotificationSystem.Push("Steam Lobby Lock", "Steam lobby locked."); } } protected override void OnDisable() { SetJoinable(joinable: true); } public override void OnTick() { if (!PhotonNetwork.IsMasterClient) { base.Enabled = false; } else if (!(Time.unscaledTime < _nextRefreshAt)) { _nextRefreshAt = Time.unscaledTime + 3f; SetJoinable(joinable: false); } } private static bool SetJoinable(bool joinable) { bool num = SteamPlayerActions.SetCurrentLobbyJoinable(joinable); if (!num) { NotificationSystem.Push("Steam Lobby Lock", "Steam lobby was not available.", NotificationKind.Warning); } return num; } } } namespace CubeX.Features.Actions { public class AfflictionIndex : NumberFeature { public AfflictionIndex() { base.Name = "Affliction Index"; base.Description = "0 Injury, 1 Hunger, 2 Cold, 3 Poison, 4 Crab, 5 Curse, 6 Drowsy, 7 Weight, 8 Hot, 9 Thorns, 10 Spores, 11 Web."; base.Min = 0f; base.Max = 11f; base.Value = RuntimeActions.AfflictionIndex; base.Step = 1f; base.Decimals = 0; } protected override void OnValueChanged(float newValue) { RuntimeActions.AfflictionIndex = Mathf.RoundToInt(newValue); } } public class CustomThrowPower : NumberBoolFeature { public CustomThrowPower() { base.Name = "Custom Throw Power"; base.Description = "Toggle custom throw charge and adjust the value."; base.Min = 0f; base.Max = 10f; base.Value = RuntimeActions.ThrowPower; base.Step = 0.1f; base.Decimals = 1; base.Unit = "x"; } protected override void OnEnable() { OnTick(); } protected override void OnDisable() { RuntimeActions.CustomThrowPower = false; } public override void OnTick() { RuntimeActions.CustomThrowPower = true; RuntimeActions.ThrowPower = base.Value; RuntimeActions.TickThrowPower(); } protected override void OnValueChanged(float newValue) { RuntimeActions.ThrowPower = newValue; if (base.Enabled) { RuntimeActions.TickThrowPower(); } } } public class DayTime : NumberFeature { public DayTime() { base.Name = "Day Time"; base.Description = "Time value sent to DayNightManager."; base.Min = 0f; base.Max = 1f; base.Value = RuntimeActions.DayTime; base.Step = 0.05f; base.Decimals = 2; } protected override void OnValueChanged(float newValue) { RuntimeActions.DayTime = newValue; } } public class EmoteName : TextFeature { public EmoteName() { base.Name = "Emote Name"; base.Description = "Emote name used by Play Emote All."; base.MaxLength = 48; base.EmptyDisplayText = RuntimeActions.EmoteName; } protected override void OnTextChanged(string newValue) { RuntimeActions.EmoteName = (string.IsNullOrWhiteSpace(newValue) ? "Wave" : newValue); } } public class InstantThrow : Feature { public InstantThrow() { base.Name = "Instant Throw"; base.Description = "Keeps throw charge full while enabled."; } protected override void OnEnable() { OnTick(); } protected override void OnDisable() { RuntimeActions.InstantThrow = false; } public override void OnTick() { RuntimeActions.InstantThrow = true; RuntimeActions.TickThrowPower(); } } public class JoinLobbyLinkValue : TextFeature { public JoinLobbyLinkValue() { base.Name = "Steam Lobby Link"; base.Description = "Steam lobby URL or numeric lobby ID used by Join From Steam Link."; base.MaxLength = 160; base.EmptyDisplayText = "Steam link"; } protected override void OnTextChanged(string newValue) { CharacterActionRuntime.JoinLobbyLink = newValue ?? string.Empty; } } public class RoomVersionRequirementValue : TextFeature { public RoomVersionRequirementValue() { base.Name = "Room Version Requirement"; base.Description = "Value written to the PeakVersion Steam lobby field."; base.MaxLength = 48; base.EmptyDisplayText = "Version"; } protected override void OnTextChanged(string newValue) { CharacterActionRuntime.RoomVersionRequirement = newValue ?? string.Empty; } } public abstract class RuntimeActionButton : ButtonFeature { private readonly Action _action; protected RuntimeActionButton(string name, string label, string description, Action action) { base.Name = name; base.ButtonLabel = label; base.Description = description; _action = action; } public override void Execute() { _action?.Invoke(); } } public class UsernameValue : TextFeature { public UsernameValue() { base.Name = "Username"; base.Description = "Photon nickname used by username actions."; base.MaxLength = 64; base.EmptyDisplayText = "Name"; } protected override void OnTextChanged(string newValue) { CharacterActionRuntime.Username = newValue ?? string.Empty; } } public class AddAfflictionAll : RuntimeActionButton { public AddAfflictionAll() : base("Apply Status All", "Apply", "Applies 10% of the selected status to target players.", RuntimeActions.AddAfflictionAll) { } } public class AngryBeesAll : RuntimeActionButton { public AngryBeesAll() : base("Bee Swarm All", "Bees", "Spawns bee swarms on target players.", RuntimeActions.AngryBeesAll) { } } public class BlowdartHitAll : RuntimeActionButton { public BlowdartHitAll() : base("Dart Impact All", "Dart", "Uses a healing dart impact RPC on target players.", RuntimeActions.BlowdartHitAll) { } } public class ClearAfflictionsAll : RuntimeActionButton { public ClearAfflictionsAll() : base("Clear Afflictions All", "Clear", "Clears afflictions from target players.", RuntimeActions.ClearAfflictionsAll) { } } public class DropAllHeldItems : RuntimeActionButton { public DropAllHeldItems() : base("Release Held Items All", "Release", "Releases current held items for target players.", RuntimeActions.DropAllHeldItems) { } } public class DropAllSlots : RuntimeActionButton { public DropAllSlots() : base("Release All Slots", "Release", "Releases slots 1, 2, 3, and backpack for target players.", RuntimeActions.DropAllSlots) { } } public class ExplodeAll : RuntimeActionButton { public ExplodeAll() : base("Dynamite Event All", "Event", "Spawns dynamite and triggers its event on target players.", RuntimeActions.ExplodeAll) { } } public class FlingAll : RuntimeActionButton { public FlingAll() : base("Launch All", "Launch", "Runs fall plus repeated jump action.", RuntimeActions.FlingAll) { } } public class GrowVinesAll : RuntimeActionButton { public GrowVinesAll() : base("Grow Vines On All", "Grow", "Grows MagicBean vines on target players.", RuntimeActions.GrowVinesOnAll) { } } public class PlayEmoteAll : RuntimeActionButton { public PlayEmoteAll() : base("Play Emote All", "Emote", "Plays the configured emote on target players.", RuntimeActions.PlayEmoteAll) { } } public class RemoveAfflictionAll : RuntimeActionButton { public RemoveAfflictionAll() : base("Remove Affliction All", "Remove", "Removes 10% of the selected affliction from target players.", RuntimeActions.RemoveAfflictionAll) { } } public class RenderDeadAll : RuntimeActionButton { public RenderDeadAll() : base("Show Downed State All", "Show", "Sends the downed customization RPC to target players.", RuntimeActions.RenderAllDead) { } } public class RenderPassedOutAll : RuntimeActionButton { public RenderPassedOutAll() : base("Render Passed Out All", "Render", "Sends the passed-out customization RPC to target players.", RuntimeActions.RenderAllPassedOut) { } } public class RequestAllItems : RuntimeActionButton { public RequestAllItems() : base("Request All Items", "Pickup", "Requests every loaded item for target players.", RuntimeActions.RequestAllItems) { } } public class ReviveTpAll : RuntimeActionButton { public ReviveTpAll() : base("Revive + TP All To Me", "Bring", "Revives all players and warps them in front of your camera.", RuntimeActions.ReviveAllAndTeleportToMe) { } } public class ShakeAllScreens : RuntimeActionButton { public ShakeAllScreens() : base("Shake All Screens", "Shake", "Shakes target players' screens.", RuntimeActions.ShakeAllScreens) { } } public class SlipAll : RuntimeActionButton { public SlipAll() : base("Stumble All", "Stumble", "Runs stumble action on target players.", RuntimeActions.SlipAll) { } } public class SpawnScoutmastersAll : RuntimeActionButton { public SpawnScoutmastersAll() : base("Spawn Scoutmasters All", "Spawn", "Spawns Scoutmasters near target players. Host only.", CharacterActionRuntime.SpawnScoutmastersForAll) { } } public class StopClimbingAll : RuntimeActionButton { public StopClimbingAll() : base("Stop Climbing All", "Stop", "Stops climbing, rope climbing, and vine climbing for target players.", RuntimeActions.StopClimbingAll) { } } public class UnhangAll : RuntimeActionButton { public UnhangAll() : base("Unhang All", "Unhang", "Unhangs target players from climb handles.", RuntimeActions.UnhangAll) { } } public class CrouchAll : RuntimeActionButton { public CrouchAll() : base("Crouch All", "Crouch", "Runs crouch RPC on target players.", CharacterActionRuntime.CrouchAll) { } } public class DestroyCharactersAll : RuntimeActionButton { public DestroyCharactersAll() : base("Clear Player Objects", "Clear", "Clears target player PhotonViews.", CharacterActionRuntime.DestroyAllCharacters) { } } public class DropAllSlot1 : RuntimeActionButton { public DropAllSlot1() : base("Release All Slot 1", "Release", "Releases slot 1 items for target players.", CharacterActionRuntime.DropAllSlot1) { } } public class DropAllSlot2 : RuntimeActionButton { public DropAllSlot2() : base("Release All Slot 2", "Release", "Releases slot 2 items for target players.", CharacterActionRuntime.DropAllSlot2) { } } public class DropAllSlot3 : RuntimeActionButton { public DropAllSlot3() : base("Release All Slot 3", "Release", "Releases slot 3 items for target players.", CharacterActionRuntime.DropAllSlot3) { } } public class EmptyAllSlot1 : RuntimeActionButton { public EmptyAllSlot1() : base("Clear All Slot 1", "Clear", "Clears slot 1 items from target players.", CharacterActionRuntime.EmptyAllSlot1) { } } public class EmptyAllSlot2 : RuntimeActionButton { public EmptyAllSlot2() : base("Clear All Slot 2", "Clear", "Clears slot 2 items from target players.", CharacterActionRuntime.EmptyAllSlot2) { } } public class EmptyAllSlot3 : RuntimeActionButton { public EmptyAllSlot3() : base("Clear All Slot 3", "Clear", "Clears slot 3 items from target players.", CharacterActionRuntime.EmptyAllSlot3) { } } public class EmptyAllSlots : RuntimeActionButton { public EmptyAllSlots() : base("Clear All Slots", "Clear", "Clears all slot items from target players.", CharacterActionRuntime.EmptyAllSlots) { } } public class FallAll : RuntimeActionButton { public FallAll() : base("Trip All", "Trip", "Runs fall RPC on target players.", CharacterActionRuntime.FallAll) { } } public class ForceEndScreenClosedAll : RuntimeActionButton { public ForceEndScreenClosedAll() : base("Register End Screen Closed All", "Set", "Marks target players as end-screen closed.", CharacterActionRuntime.ForceAllEndScreensClosed) { } } public class FullStaminaAll : RuntimeActionButton { public FullStaminaAll() : base("Full Stamina All", "Stamina", "Runs full-stamina RPC on target players.", CharacterActionRuntime.FullStaminaAll) { } } public class JumpAll : RuntimeActionButton { public JumpAll() : base("Jump All", "Jump", "Runs jump RPC on target players.", CharacterActionRuntime.JumpAll) { } } public class PassOutAll : RuntimeActionButton { public PassOutAll() : base("Tired State All", "State", "Runs pass-out RPC on target players.", CharacterActionRuntime.PassOutAll) { } } public class ReviveAllWithStatuses : RuntimeActionButton { public ReviveAllWithStatuses() : base("Revive All With Hunger & Curse", "Revive", "Revives target players with status restoration enabled.", CharacterActionRuntime.ReviveAllWithStatuses) { } } public class TakeOwnershipAll : RuntimeActionButton { public TakeOwnershipAll() : base("Request Control All", "Control", "Requests control of target player PhotonViews.", CharacterActionRuntime.TakeOwnershipAll) { } } public class UnpassOutAll : RuntimeActionButton { public UnpassOutAll() : base("Wake Up All", "Wake", "Runs wake-up RPC on target players.", CharacterActionRuntime.UnpassOutAll) { } } public class CrossedArmsAllPlayers : RuntimeActionButton { public CrossedArmsAllPlayers() : base("Make All Do Crossed Arms Emote", "Emote", "Plays crossed-arms emote on target players.", delegate { CharacterActionRuntime.PlayAllEmote("A_Scout_Emote_CrossedArms"); }) { } } public class CrossedArmsSelectedPlayer : RuntimeActionButton { public CrossedArmsSelectedPlayer() : base("Do Crossed Arms Emote", "Emote", "Plays crossed-arms emote on selected player.", delegate { CharacterActionRuntime.PlaySelectedEmote("A_Scout_Emote_CrossedArms"); }) { } } public class DanceAllPlayers : RuntimeActionButton { public DanceAllPlayers() : base("Make All Do Dance Emote", "Emote", "Plays dance emote on target players.", delegate { CharacterActionRuntime.PlayAllEmote("A_Scout_Emote_Dance1"); }) { } } public class DanceSelectedPlayer : RuntimeActionButton { public DanceSelectedPlayer() : base("Do Dance Emote", "Emote", "Plays dance emote on selected player.", delegate { CharacterActionRuntime.PlaySelectedEmote("A_Scout_Emote_Dance1"); }) { } } public class NoNoAllPlayers : RuntimeActionButton { public NoNoAllPlayers() : base("Make All Do No-No Emote", "Emote", "Plays no-no emote on target players.", delegate { CharacterActionRuntime.PlayAllEmote("A_Scout_Emote_Nono"); }) { } } public class NoNoSelectedPlayer : RuntimeActionButton { public NoNoSelectedPlayer() : base("Do No-No Emote", "Emote", "Plays no-no emote on selected player.", delegate { CharacterActionRuntime.PlaySelectedEmote("A_Scout_Emote_Nono"); }) { } } public class PlayDeadAllPlayers : RuntimeActionButton { public PlayDeadAllPlayers() : base("Make All Do Play Dead Emote", "Emote", "Plays play-dead emote on target players.", delegate { CharacterActionRuntime.PlayAllEmote("A_Scout_Emote_PlayDead"); }) { } } public class PlayDeadSelectedPlayer : RuntimeActionButton { public PlayDeadSelectedPlayer() : base("Do Play Dead Emote", "Emote", "Plays play-dead emote on selected player.", delegate { CharacterActionRuntime.PlaySelectedEmote("A_Scout_Emote_PlayDead"); }) { } } public class SaluteAllPlayers : RuntimeActionButton { public SaluteAllPlayers() : base("Make All Do Salute Emote", "Emote", "Plays salute emote on target players.", delegate { CharacterActionRuntime.PlayAllEmote("A_Scout_Emote_Salute"); }) { } } public class SaluteSelectedPlayer : RuntimeActionButton { public SaluteSelectedPlayer() : base("Do Salute Emote", "Emote", "Plays salute emote on selected player.", delegate { CharacterActionRuntime.PlaySelectedEmote("A_Scout_Emote_Salute"); }) { } } public class ShrugAllPlayers : RuntimeActionButton { public ShrugAllPlayers() : base("Make All Do Shrug Emote", "Emote", "Plays shrug emote on target players.", delegate { CharacterActionRuntime.PlayAllEmote("A_Scout_Emote_Shrug"); }) { } } public class ShrugSelectedPlayer : RuntimeActionButton { public ShrugSelectedPlayer() : base("Do Shrug Emote", "Emote", "Plays shrug emote on selected player.", delegate { CharacterActionRuntime.PlaySelectedEmote("A_Scout_Emote_Shrug"); }) { } } public class ThinkAllPlayers : RuntimeActionButton { public ThinkAllPlayers() : base("Make All Do Think Emote", "Emote", "Plays think emote on target players.", delegate { CharacterActionRuntime.PlayAllEmote("A_Scout_Emote_Think"); }) { } } public class ThinkSelectedPlayer : RuntimeActionButton { public ThinkSelectedPlayer() : base("Do Think Emote", "Emote", "Plays think emote on selected player.", delegate { CharacterActionRuntime.PlaySelectedEmote("A_Scout_Emote_Think"); }) { } } public class ThumbsUpAllPlayers : RuntimeActionButton { public ThumbsUpAllPlayers() : base("Make All Do Thumbs Up Emote", "Emote", "Plays thumbs-up emote on target players.", delegate { CharacterActionRuntime.PlayAllEmote("A_Scout_Emote_ThumbsUp"); }) { } } public class ThumbsUpSelectedPlayer : RuntimeActionButton { public ThumbsUpSelectedPlayer() : base("Do Thumbs Up Emote", "Emote", "Plays thumbs-up emote on selected player.", delegate { CharacterActionRuntime.PlaySelectedEmote("A_Scout_Emote_ThumbsUp"); }) { } } public class DestroyAllNetworkObjects : RuntimeActionButton { public DestroyAllNetworkObjects() : base("Clear Network Objects", "Clear", "Requests control of loaded non-player Photon views and clears them.", CharacterActionRuntime.DestroyAllNetworkObjects) { } } public class ForceAllGhostsToMe : RuntimeActionButton { public ForceAllGhostsToMe() : base("Set Ghosts Target To Me", "Set", "Sets loaded player ghosts to target your character.", CharacterActionRuntime.ForceGhostsToMe) { } } public class MakeAllScoutmastersThrow : RuntimeActionButton { public MakeAllScoutmastersThrow() : base("Make All Scoutmasters Throw", "Throw", "Runs the scoutmaster throw RPC on all scoutmasters.", CharacterActionRuntime.ThrowScoutmasters) { } } public class OpenAllLuggage : RuntimeActionButton { public OpenAllLuggage() : base("Open All Luggage", "Open", "Opens every loaded luggage container with items.", delegate { CharacterActionRuntime.OpenAllLuggage(spawnItems: true); }) { } } public class OpenAllLuggageWithoutItems : RuntimeActionButton { public OpenAllLuggageWithoutItems() : base("Open All Luggage Without Items", "Open", "Opens every loaded luggage container without item drops.", delegate { CharacterActionRuntime.OpenAllLuggage(spawnItems: false); }) { } } public class RefreshAllCharacterWeight : RuntimeActionButton { public RefreshAllCharacterWeight() : base("Refresh All Character Weight", "Refresh", "Refreshes carry weight on target players.", CharacterActionRuntime.RefreshAllCarryWeight) { } } public class SetRoomVersionRequirement : RuntimeActionButton { public SetRoomVersionRequirement() : base("Set Room Version Requirement", "Set", "Writes PeakVersion lobby data to the current Steam lobby.", CharacterActionRuntime.SetRoomVersionRequirement) { } } public class SpawnCharacterObject : RuntimeActionButton { public SpawnCharacterObject() : base("Spawn Character", "Spawn", "Spawns the Character prefab at your position.", CharacterActionRuntime.SpawnCharacter) { } } public class SpawnPlayerObject : RuntimeActionButton { public SpawnPlayerObject() : base("Spawn Player", "Spawn", "Spawns the Player prefab at your position.", CharacterActionRuntime.SpawnPlayer) { } } public class TeleportAllToMe : RuntimeActionButton { public TeleportAllToMe() : base("Teleport All To Me", "Warp", "Warps target players in front of your camera.", CharacterActionRuntime.TeleportAllToMe) { } } public class UnlockBingBongAchievement : RuntimeActionButton { public UnlockBingBongAchievement() : base("Unlock BingBong Achievement", "Unlock", "Broadcasts the BingBong achievement RPC.", CharacterActionRuntime.UnlockBingBongAchievement) { } } public class UnlockEmergencyAchievement : RuntimeActionButton { public UnlockEmergencyAchievement() : base("Unlock Emergency Achievement", "Unlock", "Broadcasts the emergency preparedness achievement RPC.", CharacterActionRuntime.UnlockEmergencyAchievement) { } } public class AddAfflictionSelectedPlayer : RuntimeActionButton { public AddAfflictionSelectedPlayer() : base("Apply Status Player", "Apply", "Applies 10% of the configured status to the selected player.", CharacterActionRuntime.SelectedAddAffliction) { } } public class BlowdartHitSelectedPlayer : RuntimeActionButton { public BlowdartHitSelectedPlayer() : base("Dart Impact Player", "Dart", "Uses a healing dart impact RPC on the selected player.", CharacterActionRuntime.SelectedBlowdartHit) { } } public class CarrySelectedPlayer : RuntimeActionButton { public CarrySelectedPlayer() : base("Carry Player", "Carry", "Starts local carry RPC for the selected player.", CharacterActionRuntime.SelectedCarry) { } } public class ClearAfflictionsSelectedPlayer : RuntimeActionButton { public ClearAfflictionsSelectedPlayer() : base("Clear Afflictions Player", "Clear", "Clears afflictions on the selected player.", CharacterActionRuntime.SelectedClearAfflictions) { } } public class CrouchSelectedPlayer : RuntimeActionButton { public CrouchSelectedPlayer() : base("Crouch Player", "Crouch", "Runs crouch RPC on the selected player.", CharacterActionRuntime.SelectedCrouch) { } } public class DestroySelectedPlayer : RuntimeActionButton { public DestroySelectedPlayer() : base("Clear Player Object", "Clear", "Clears the selected player PhotonView.", CharacterActionRuntime.SelectedDestroy) { } } public class DropAllSlotsSelectedPlayer : RuntimeActionButton { public DropAllSlotsSelectedPlayer() : base("Release All Slots Player", "Release", "Releases all selected player slots.", CharacterActionRuntime.SelectedDropAllSlots) { } } public class DropHeldItemSelectedPlayer : RuntimeActionButton { public DropHeldItemSelectedPlayer() : base("Release Held Item Player", "Release", "Releases the selected player's held item.", CharacterActionRuntime.SelectedDropHeldItem) { } } public class DropSlot1SelectedPlayer : RuntimeActionButton { public DropSlot1SelectedPlayer() : base("Release Slot 1 Player", "Release", "Releases selected player's slot 1 item.", CharacterActionRuntime.SelectedDropSlot1) { } } public class DropSlot2SelectedPlayer : RuntimeActionButton { public DropSlot2SelectedPlayer() : base("Release Slot 2 Player", "Release", "Releases selected player's slot 2 item.", CharacterActionRuntime.SelectedDropSlot2) { } } public class DropSlot3SelectedPlayer : RuntimeActionButton { public DropSlot3SelectedPlayer() : base("Release Slot 3 Player", "Release", "Releases selected player's slot 3 item.", CharacterActionRuntime.SelectedDropSlot3) { } } public class EmptyAllSlotsSelectedPlayer : RuntimeActionButton { public EmptyAllSlotsSelectedPlayer() : base("Clear All Slots Player", "Clear", "Clears all selected player slot items.", CharacterActionRuntime.SelectedEmptyAllSlots) { } } public class EmptySlot1SelectedPlayer : RuntimeActionButton { public EmptySlot1SelectedPlayer() : base("Clear Slot 1 Player", "Clear", "Clears selected player's slot 1 item.", CharacterActionRuntime.SelectedEmptySlot1) { } } public class EmptySlot2SelectedPlayer : RuntimeActionButton { public EmptySlot2SelectedPlayer() : base("Clear Slot 2 Player", "Clear", "Clears selected player's slot 2 item.", CharacterActionRuntime.SelectedEmptySlot2) { } } public class EmptySlot3SelectedPlayer : RuntimeActionButton { public EmptySlot3SelectedPlayer() : base("Clear Slot 3 Player", "Clear", "Clears selected player's slot 3 item.", CharacterActionRuntime.SelectedEmptySlot3) { } } public class ExplodeSelectedPlayer : RuntimeActionButton { public ExplodeSelectedPlayer() : base("Dynamite Event Player", "Event", "Spawns dynamite and triggers its event on the selected player.", CharacterActionRuntime.SelectedExplode) { } } public class FallSelectedPlayer : RuntimeActionButton { public FallSelectedPlayer() : base("Trip Player", "Trip", "Runs fall RPC on the selected player.", CharacterActionRuntime.SelectedFall) { } } public class FlingSelectedPlayer : RuntimeActionButton { public FlingSelectedPlayer() : base("Launch Player", "Launch", "Runs fall plus repeated jump RPCs.", CharacterActionRuntime.SelectedFling) { } } public class ForceEndScreenClosedSelectedPlayer : RuntimeActionButton { public ForceEndScreenClosedSelectedPlayer() : base("Register End Screen Closed", "Set", "Marks selected player as end-screen closed.", CharacterActionRuntime.SelectedForceEndScreenClosed) { } } public class ForceScoutmastersSelectedPlayer : RuntimeActionButton { public ForceScoutmastersSelectedPlayer() : base("Scoutmaster Target Player", "Target", "Sets scoutmasters to target the selected player.", CharacterActionRuntime.SelectedForceScoutmasters) { } } public class FullStaminaSelectedPlayer : RuntimeActionButton { public FullStaminaSelectedPlayer() : base("Full Stamina Player", "Stamina", "Runs full-stamina RPC on the selected player.", CharacterActionRuntime.SelectedFullStamina) { } } public class GrowVineSelectedPlayer : RuntimeActionButton { public GrowVineSelectedPlayer() : base("Grow Vine On Player", "Grow", "Grows a MagicBean vine on the selected player.", CharacterActionRuntime.SelectedGrowVine) { } } public class JumpSelectedPlayer : RuntimeActionButton { public JumpSelectedPlayer() : base("Jump Player", "Jump", "Runs jump RPC on the selected player.", CharacterActionRuntime.SelectedJump) { } } public class KickSelectedPlayer : RuntimeActionButton { public KickSelectedPlayer() : base("Disconnect From Lobby", "Disconnect", "Closes the selected player's Photon connection when you are master client.", CharacterActionRuntime.SelectedKickFromLobby) { } } public class PassOutSelectedPlayer : RuntimeActionButton { public PassOutSelectedPlayer() : base("Tired State Player", "State", "Runs pass-out RPC on the selected player.", CharacterActionRuntime.SelectedPassOut) { } } public class RefreshCharacterWeightSelectedPlayer : RuntimeActionButton { public RefreshCharacterWeightSelectedPlayer() : base("Refresh Character Weight", "Refresh", "Refreshes carry weight on the selected player.", CharacterActionRuntime.SelectedRefreshCarryWeight) { } } public class RemoveAfflictionSelectedPlayer : RuntimeActionButton { public RemoveAfflictionSelectedPlayer() : base("Remove Affliction Player", "Remove", "Removes 10% of the configured affliction from the selected player.", CharacterActionRuntime.SelectedRemoveAffliction) { } } public class RenderDeadSelectedPlayer : RuntimeActionButton { public RenderDeadSelectedPlayer() : base("Show Downed State Player", "Show", "Runs downed customization RPC on the selected player.", CharacterActionRuntime.SelectedRenderDead) { } } public class RenderPassedOutSelectedPlayer : RuntimeActionButton { public RenderPassedOutSelectedPlayer() : base("Render Passed Out Player", "Render", "Runs passed-out customization RPC on the selected player.", CharacterActionRuntime.SelectedRenderPassedOut) { } } public class RequestPickupSelectedPlayer : RuntimeActionButton { public RequestPickupSelectedPlayer() : base("Request Pickup On All Items", "Pickup", "Requests all loaded items for the selected player.", CharacterActionRuntime.SelectedRequestPickupOnAllItems) { } } public class ReviveSelectedPlayerWithStatuses : RuntimeActionButton { public ReviveSelectedPlayerWithStatuses() : base("Revive Player With Hunger & Curse", "Revive", "Revives the selected player with status restoration enabled.", CharacterActionRuntime.SelectedReviveWithStatuses) { } } public class ReviveTpSelectedPlayer : RuntimeActionButton { public ReviveTpSelectedPlayer() : base("Revive", "Revive", "Revives and warps selected player in front of your camera.", CharacterActionRuntime.SelectedReviveAndTeleportToMe) { } } public class ShakeScreenSelectedPlayer : RuntimeActionButton { public ShakeScreenSelectedPlayer() : base("Camera Shake Player", "Shake", "Runs screen-shake fall RPC on the selected player.", CharacterActionRuntime.SelectedShakeScreen) { } } public class SlipSelectedPlayer : RuntimeActionButton { public SlipSelectedPlayer() : base("Stumble Player", "Stumble", "Triggers banana stumble on the selected player.", CharacterActionRuntime.SelectedSlip) { } } public class StopClimbingSelectedPlayer : RuntimeActionButton { public StopClimbingSelectedPlayer() : base("Stop Climbing Player", "Stop", "Stops climbing, rope climbing, and vine climbing for the selected player.", CharacterActionRuntime.SelectedStopClimbing) { } } public class SwarmBeesSelectedPlayer : RuntimeActionButton { public SwarmBeesSelectedPlayer() : base("Bee Swarm Player", "Bees", "Spawns bee swarms on the selected player.", CharacterActionRuntime.SelectedSwarmBees) { } } public class TakeOwnershipSelectedPlayer : RuntimeActionButton { public TakeOwnershipSelectedPlayer() : base("Request Control Player", "Control", "Requests control of the selected player.", CharacterActionRuntime.SelectedTakeOwnership) { } } public class UnhangSelectedPlayer : RuntimeActionButton { public UnhangSelectedPlayer() : base("Unhang Player", "Unhang", "Unhangs the selected player from climb handles.", CharacterActionRuntime.SelectedUnhang) { } } public class UnpassOutSelectedPlayer : RuntimeActionButton { public UnpassOutSelectedPlayer() : base("Wake Up Player", "Wake", "Runs wake-up RPC on the selected player.", CharacterActionRuntime.SelectedUnpassOut) { } } public class ClearSelfAfflictions : RuntimeActionButton { public ClearSelfAfflictions() : base("Clear Self Afflictions", "Clear", "Sets your local afflictions to zero.", RuntimeActions.ClearLocalAfflictions) { } } public class FallSelf : RuntimeActionButton { public FallSelf() : base("Fall Self", "Fall", "Triggers a fall ragdoll on yourself.", RuntimeActions.FallLocal) { } } public class FullStaminaMorale : RuntimeActionButton { public FullStaminaMorale() : base("Full Stamina + Morale", "Boost", "Restores stamina and morale.", RuntimeActions.FullStaminaWithMorale) { } } public class RemoveItemRestrictions : RuntimeActionButton { public RemoveItemRestrictions() : base("Remove Item Restrictions", "Unlock", "Allows loaded items to be dropped and thrown.", RuntimeActions.RemoveItemRestrictions) { } } public class ReviveSelf : RuntimeActionButton { public ReviveSelf() : base("Revive Self", "Revive", "Revives your local character.", RuntimeActions.ReviveLocal) { } } public class SlipSelf : RuntimeActionButton { public SlipSelf() : base("Slip Self", "Slip", "Triggers the banana slip action on yourself.", RuntimeActions.SlipLocal) { } } public class UnpassOutSelf : RuntimeActionButton { public UnpassOutSelf() : base("Unpass Out Self", "Wake", "Clears local pass-out state.", RuntimeActions.UnpassOutLocal) { } } public class EndGameForceWinSelf : RuntimeActionButton { public EndGameForceWinSelf() : base("End Game With Force Win", "Win", "Sends the local force-win end-game RPC.", CharacterActionRuntime.EndGameForceWin) { } } public class EndGameSelf : RuntimeActionButton { public EndGameSelf() : base("End Game", "End", "Sends the local end-game RPC.", CharacterActionRuntime.EndGame) { } } public class FullStaminaSelf : RuntimeActionButton { public FullStaminaSelf() : base("Gain Full Stamina", "Gain", "Runs the local full-stamina action.", CharacterActionRuntime.FullStaminaLocal) { } } public class JoinFromSteamLink : RuntimeActionButton { public JoinFromSteamLink() : base("Join From Steam Link", "Join", "Attempts to join the configured Steam lobby link.", CharacterActionRuntime.JoinFromSteamLink) { } } public class KillSelf : RuntimeActionButton { public KillSelf() : base("Kill Self", "Kill", "Kills your local character.", CharacterActionRuntime.KillLocal) { } } public class PassOutSelf : RuntimeActionButton { public PassOutSelf() : base("Pass Out Self", "Pass", "Triggers pass-out on your local character.", CharacterActionRuntime.PassOutLocal) { } } public class ReviveSelfWithStatuses : RuntimeActionButton { public ReviveSelfWithStatuses() : base("Revive Self With Hunger & Curse", "Revive", "Revives your local character with status restoration enabled.", CharacterActionRuntime.ReviveLocalWithStatuses) { } } public class SetMasterClient : RuntimeActionButton { public SetMasterClient() : base("Set Master", "Set", "Makes you Photon master client when possible.", CharacterActionRuntime.SetMaster) { } } public class SetUsername : RuntimeActionButton { public SetUsername() : base("Set Username", "Set", "Sets Photon nickname with the selected color and resets your character when in a room.", CharacterActionRuntime.SetUsername) { } } public class SetUsernameColor : ColorFeature { public override int PresetCount => MenuConfig.Presets.Length; public SetUsernameColor() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) base.Name = "Set Username Color"; base.Description = "Pick the Photon nickname color to use when Set Username is pressed."; base.Value = CharacterActionRuntime.UsernameColor; } public override string GetPresetName(int index) { if (index < 0 || index >= MenuConfig.Presets.Length) { return string.Empty; } return MenuConfig.Presets[index].Name; } public override Color GetPresetColor(int index) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) if (index < 0 || index >= MenuConfig.Presets.Length) { return Color.white; } return MenuConfig.Presets[index].Color; } protected override void OnColorChanged(Color newColor) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) CharacterActionRuntime.SetUsernameColor(newColor); } } public class BreakPitons : RuntimeActionButton { public BreakPitons() : base("Break Pitons", "Break", "Breaks all pitons.", RuntimeActions.BreakPitons) { } } public class DetachRopes : RuntimeActionButton { public DetachRopes() : base("Detach Ropes", "Detach", "Detaches all rope objects.", RuntimeActions.DetachRopes) { } } public class DropBridges : RuntimeActionButton { public DropBridges() : base("Drop Bridges", "Drop", "Drops all breakable bridges.", RuntimeActions.DropBridges) { } } public class DropIcicles : RuntimeActionButton { public DropIcicles() : base("Drop Icicles", "Drop", "Drops all icicles.", RuntimeActions.DropIcicles) { } } public class ExtinguishCampfires : RuntimeActionButton { public ExtinguishCampfires() : base("Extinguish Nearby Campfire", "Off", "Extinguishes the nearest lit campfire within 10 meters without buffering the state.", RuntimeActions.ExtinguishCampfires) { } } public class ExtinguishLanterns : RuntimeActionButton { public ExtinguishLanterns() : base("Extinguish Lanterns", "Off", "Extinguishes all lanterns.", RuntimeActions.ExtinguishLanterns) { } } public class ForceEndScreenDone : RuntimeActionButton { public ForceEndScreenDone() : base("Complete End Screen", "Complete", "Runs the end-screen completion action.", RuntimeActions.ForceEndScreenDone) { } } public class GuidebookLeft : RuntimeActionButton { public GuidebookLeft() : base("Guidebook Page Left", "Left", "Flips all guidebooks left.", RuntimeActions.FlipGuidebooksLeft) { } } public class GuidebookRight : RuntimeActionButton { public GuidebookRight() : base("Guidebook Page Right", "Right", "Flips all guidebooks right.", RuntimeActions.FlipGuidebooksRight) { } } public class LightCampfires : RuntimeActionButton { public LightCampfires() : base("Light Nearby Campfire", "Light", "Lights the nearest unlit campfire within 10 meters using the game's campfire interaction flow.", RuntimeActions.LightCampfires) { } } public class LightFlares : RuntimeActionButton { public LightFlares() : base("Light Flares", "Light", "Lights all flares.", RuntimeActions.LightAllFlares) { } } public class LightLanterns : RuntimeActionButton { public LightLanterns() : base("Light Lanterns", "Light", "Lights all lanterns.", RuntimeActions.LightLanterns) { } } public class PauseBingBongTime : RuntimeActionButton { public PauseBingBongTime() : base("Pause Bing Bong Time", "Pause", "Sends time 0 to BingBongTimeControl.", RuntimeActions.PauseBingBongTime) { } } public class SetDayTime : RuntimeActionButton { public SetDayTime() : base("Set Day Time", "Set", "Sends configured day time to DayNightManager.", RuntimeActions.SetDayTime) { } } public class ShakeBridges : RuntimeActionButton { public ShakeBridges() : base("Shake Bridges", "Shake", "Shakes all breakable bridges.", RuntimeActions.ShakeBridges) { } } public class ShakeIcicles : RuntimeActionButton { public ShakeIcicles() : base("Shake Icicles", "Shake", "Shakes all icicles.", RuntimeActions.ShakeIcicles) { } } public class StartBreakingPitons : RuntimeActionButton { public StartBreakingPitons() : base("Start Breaking Pitons", "Start", "Starts the piton breaking RPC.", RuntimeActions.StartBreakingPitons) { } } public class StartFog : RuntimeActionButton { public StartFog() : base("Start Fog", "Start", "Starts all orb fog handlers.", RuntimeActions.StartFog) { } } public class StartLavaRise : RuntimeActionButton { public StartLavaRise() : base("Start Lava Rise", "Start", "Starts all MovingLava objects.", RuntimeActions.StartLavaRise) { } } public class ToggleWindOff : RuntimeActionButton { public ToggleWindOff() : base("Wind Off", "Off", "Toggles all wind chill zones off.", delegate { RuntimeActions.ToggleWind(enabled: false); }) { } } public class ToggleWindOn : RuntimeActionButton { public ToggleWindOn() : base("Wind On", "On", "Toggles all wind chill zones on.", delegate { RuntimeActions.ToggleWind(enabled: true); }) { } } public class BlowdartShotgun : Feature { public BlowdartShotgun() { base.Name = "Shoot Blowdart On Mouse Click"; base.Description = "Left-click to send a healing-dart impact at your aim point."; } protected override void OnEnable() { } protected override void OnDisable() { } public override void OnTick() { CharacterActionRuntime.BlowdartAtMouse(); } } public class UseEveryonesPingPointer : Feature { public UseEveryonesPingPointer() { base.Name = "Use Everyone's Ping Pointer"; base.Description = "Middle-click to broadcast your ping point through every loaded PointPinger."; } protected override void OnEnable() { } protected override void OnDisable() { } public override void OnTick() { CharacterActionRuntime.BroadcastPingAtMouse(); } } internal static class AfflictionRpcRuntime { private const int WeightStatusIndex = 7; private const int ThornsStatusIndex = 9; public static bool TryApply(Character character, int? statusIndex, bool clearAll, float delta, out string error) { error = null; if (!Object.op_Implicit((Object)(object)character)) { error = "Character is null."; return false; } CharacterAfflictions afflictions = GetAfflictions(character); if (!Object.op_Implicit((Object)(object)afflictions)) { error = "CharacterAfflictions component was not found."; return false; } if (afflictions.currentStatuses == null || afflictions.currentStatuses.Length == 0) { error = "Status list is empty."; return false; } if (!TryBuildDelta(afflictions, statusIndex, clearAll, delta, out var statusDelta, out error)) { return false; } if (!HasAnyDelta(statusDelta)) { return true; } PhotonView photonView = GetPhotonView(character, afflictions); if (PhotonNetwork.InRoom && PhotonNetwork.IsMasterClient && Object.op_Implicit((Object)(object)photonView)) { try { photonView.RPC("RPC_ApplyStatusesFromFloatArray", (RpcTarget)0, new object[1] { statusDelta }); return true; } catch (Exception ex) { error = "RPC_ApplyStatusesFromFloatArray failed: " + GetBaseMessage(ex); return false; } } if (CanApplyLocally(character, photonView)) { return TryApplyLocally(afflictions, statusDelta, clearAll, out error); } if (PhotonNetwork.InRoom && !PhotonNetwork.IsMasterClient) { RequestMasterClient(); error = "Status RPC requires master client; master-client request sent. Try again after the room switches."; return false; } error = "Cannot apply statuses without local ownership or master-client status RPC."; return false; } private static bool TryBuildDelta(CharacterAfflictions afflictions, int? statusIndex, bool clearAll, float delta, out float[] statusDelta, out string error) { error = null; statusDelta = new float[afflictions.currentStatuses.Length]; if (clearAll) { for (int i = 0; i < afflictions.currentStatuses.Length; i++) { statusDelta[i] = 0f - Mathf.Max(0f, afflictions.currentStatuses[i]); } return true; } if (!statusIndex.HasValue) { error = "Affliction index is missing."; return false; } int value = statusIndex.Value; if (value < 0 || value >= statusDelta.Length) { error = "Affliction index is out of range: " + value; return false; } if (value == 7 || value == 9) { error = "Weight and Thorns are derived statuses and are ignored by PEAK's status RPC."; return false; } statusDelta[value] = delta; return true; } private static bool TryApplyLocally(CharacterAfflictions afflictions, float[] statusDelta, bool clearAll, out string error) { error = null; try { afflictions.ApplyStatusesFromFloatArray(statusDelta); if (clearAll) { TrySetStatus(afflictions, 7, 0f); TrySetStatus(afflictions, 9, 0f); } afflictions.PushStatuses((Player)null); return true; } catch (Exception ex) { error = GetBaseMessage(ex); return false; } } private static void TrySetStatus(CharacterAfflictions afflictions, int index, float amount) { try { if (Object.op_Implicit((Object)(object)afflictions) && Object.op_Implicit((Object)(object)afflictions.character) && ((MonoBehaviourPun)afflictions.character).photonView.IsMine) { afflictions.SetStatus((STATUSTYPE)index, amount, false); } } catch { } } private static bool HasAnyDelta(float[] statusDelta) { if (statusDelta == null) { return false; } for (int i = 0; i < statusDelta.Length; i++) { if (Mathf.Abs(statusDelta[i]) > 0.001f) { return true; } } return false; } private static CharacterAfflictions GetAfflictions(Character character) { if (!Object.op_Implicit((Object)(object)character)) { return null; } CharacterAfflictions val = character.refs?.afflictions; if (!Object.op_Implicit((Object)(object)val)) { val = ((Component)character).GetComponent(); } if (!Object.op_Implicit((Object)(object)val)) { val = ((Component)character).GetComponentInChildren(); } return val; } private static PhotonView GetPhotonView(Character character, CharacterAfflictions afflictions) { if (Object.op_Implicit((Object)(object)character)) { PhotonView val = character.refs?.view; if (Object.op_Implicit((Object)(object)val)) { return val; } try { val = ((MonoBehaviourPun)character).photonView; if (Object.op_Implicit((Object)(object)val)) { return val; } } catch { } } if (Object.op_Implicit((Object)(object)afflictions)) { PhotonView val2 = ((Component)afflictions).GetComponent() ?? ((Component)afflictions).GetComponentInParent() ?? ((Component)afflictions).GetComponentInChildren(); if (Object.op_Implicit((Object)(object)val2)) { return val2; } } return null; } private static bool CanApplyLocally(Character character, PhotonView view) { try { if (Object.op_Implicit((Object)(object)character) && character.IsLocal) { return true; } } catch { } try { return Object.op_Implicit((Object)(object)view) && view.IsMine; } catch { return false; } } private static void RequestMasterClient() { try { if (PhotonNetwork.LocalPlayer != null) { PhotonNetwork.SetMasterClient(PhotonNetwork.LocalPlayer); } } catch { } } private static string GetBaseMessage(Exception ex) { while (ex is TargetInvocationException && ex.InnerException != null) { ex = ex.InnerException; } return ex.GetType().Name + ": " + ex.Message; } } internal static class CharacterActionRuntime { private const BindingFlags InstanceFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; private const BindingFlags StaticFlags = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; private const int BackpackSlot = 3; private const string PeakSteamAppId = "3527290"; public static string Username = string.Empty; public static Color UsernameColor = Color.white; public static string JoinLobbyLink = string.Empty; public static string RoomVersionRequirement = string.Empty; private static readonly Dictionary TypeCache = new Dictionary(StringComparer.Ordinal); private static readonly Dictionary StartCarryCache = new Dictionary(); private static readonly Dictionary MethodCache = new Dictionary(StringComparer.Ordinal); private static readonly Dictionary FieldCache = new Dictionary(StringComparer.Ordinal); public static void KillLocal() { RunLocalCharacterAction("Kill Local", Kill); } public static void PassOutLocal() { RunLocalCharacterAction("Pass Out Local", delegate(Character c) { RpcCharacter(c, "RPCA_PassOut"); }); } public static void ReviveLocalWithStatuses() { RunLocalCharacterAction("Revive Local", delegate(Character c) { RpcCharacter(c, "RPCA_Revive", true); }); } public static void EndGame() { RpcLocalCharacter("End Game", "RPCEndGame"); } public static void EndGameForceWin() { if (!RequireLocalCharacter("Force Win", out var local)) { return; } try { MethodInfo method = ((object)local).GetType().GetMethod("RPCEndGame_ForceWin", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (method != null) { method.Invoke(local, null); NotifyInfo("Force Win", "Called the game's force-win end-game function."); return; } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Force Win direct] " + GetBaseMessage(ex))); } } RpcCharacter(local, "RPCEndGame_ForceWin"); } public static void FullStaminaLocal() { if (!RequireLocalCharacter("Full Stamina", out var _)) { return; } try { Character.GainFullStamina(); NotifyInfo("Full Stamina", "Local stamina refilled."); } catch (Exception ex) { NotifyException("Full Stamina Failed", ex); } } public static void SetMaster() { if (RequireRoom("Set Master")) { if (PhotonNetwork.LocalPlayer == null) { NotifyWarning("Set Master Failed", "Photon local player is missing."); } else if (PhotonNetwork.IsMasterClient) { NotifyInfo("Set Master", "You are already the master client."); } else { NotifyByBool(PhotonNetwork.SetMasterClient(PhotonNetwork.LocalPlayer), "Set Master", "Master-client request sent.", "Set Master Failed", "Photon refused the master-client request."); } } } public static void SetUsernameColor() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) ApplyUsernameColor(UsernameColor); } public static void SetUsernameColor(Color color) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //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) UsernameColor = new Color(Mathf.Clamp01(color.r), Mathf.Clamp01(color.g), Mathf.Clamp01(color.b), 1f); } private static void ApplyUsernameColor(Color color) { //IL_003a: 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 (PhotonNetwork.LocalPlayer == null) { NotifyWarning("Set Username Color Failed", "Photon local player is missing."); return; } string usernameBaseValue = GetUsernameBaseValue(); if (string.IsNullOrWhiteSpace(usernameBaseValue)) { NotifyWarning("Set Username Color Failed", "Username value is empty."); return; } string text = "#" + ColorUtility.ToHtmlStringRGB(color); PhotonNetwork.LocalPlayer.NickName = FormatUsernameWithColor(usernameBaseValue, color); NotifyInfo("Set Username Color", "Username color set to: " + text); } public static void SetUsername() { //IL_0042: Unknown result type (might be due to invalid IL or missing references) if (PhotonNetwork.LocalPlayer == null) { NotifyWarning("Set Username Failed", "Photon local player is missing."); return; } string text = Username?.Trim(); if (string.IsNullOrWhiteSpace(text)) { NotifyWarning("Set Username Failed", "Username value is empty."); return; } string nickName = FormatUsernameWithColor(text, UsernameColor); PhotonNetwork.LocalPlayer.NickName = nickName; if (PhotonNetwork.InRoom) { ResetLocalCharacterAfterUsernameChange(); } else { NotifyInfo("Set Username", "Username set to: " + text); } } private static string GetUsernameBaseValue() { string text = Username?.Trim(); if (!string.IsNullOrWhiteSpace(text)) { return text; } Player localPlayer = PhotonNetwork.LocalPlayer; return StripOuterColorTags(((localPlayer != null) ? localPlayer.NickName : null) ?? string.Empty).Trim(); } private static string FormatUsernameWithColor(string name, Color color) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) string text = "#" + ColorUtility.ToHtmlStringRGB(color); return "" + StripOuterColorTags(name ?? string.Empty).Trim() + ""; } private static void ResetLocalCharacterAfterUsernameChange() { //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0071: 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) Character localCharacter = Character.localCharacter; if (!Object.op_Implicit((Object)(object)localCharacter)) { NotifyWarning("Set Username", "Username updated, but local character was not found for reset."); return; } PhotonView val = (Object.op_Implicit((Object)(object)localCharacter.refs?.view) ? localCharacter.refs.view : GetPhotonView((Component)(object)localCharacter)); if (!Object.op_Implicit((Object)(object)val)) { NotifyWarning("Set Username", "Username updated, but old character PhotonView was not found."); return; } Vector3 val2; Quaternion rotation; try { val2 = localCharacter.Head; rotation = ((Component)localCharacter).transform.rotation; localCharacter.BreakCharacterCarrying(true); } catch { val2 = ((Component)localCharacter).transform.position; rotation = ((Component)localCharacter).transform.rotation; } try { GameObject val3 = PhotonNetwork.Instantiate("Character", val2, rotation, (byte)0, (object[])null); Character val4 = (Object.op_Implicit((Object)(object)val3) ? val3.GetComponent() : null); if (Object.op_Implicit((Object)(object)val4)) { Character.localCharacter = val4; } TakeOwnership(val, notify: false); PhotonNetwork.Destroy(val); Character.AllCharacters?.Remove(localCharacter); Character.AllBotCharacters?.Remove(localCharacter); NotifyByObject((Object)(object)val3, "Set Username", "Username set and character reset.", "Set Username", "Username set, but Photon returned no replacement character."); } catch (Exception ex) { NotifyException("Set Username Reset Failed", ex); } } private static string StripOuterColorTags(string value) { string text = value ?? string.Empty; while (text.StartsWith("'); if (num < 0) { break; } int num2 = text.LastIndexOf("", StringComparison.OrdinalIgnoreCase); if (num2 <= num) { break; } text = text.Substring(num + 1, num2 - num - 1).Trim(); } return text; } public static void JoinFromSteamLink() { ulong num = ParseSteamLobbyId(JoinLobbyLink); if (num == 0L) { NotifyWarning("Join Steam Lobby Failed", "Steam lobby link or lobby ID is invalid."); } else if (SteamPlayerActions.JoinLobby(num)) { NotifyInfo("Join Steam Lobby", "Join request sent for lobby: " + num); SteamLobbyJoinStatusRuntime.StartMonitoring(num); } else { NotifyWarning("Join Steam Lobby Failed", "Steam lobby join API was not available."); } } public static void JumpAll() { ForEachTargetCharacter("Jump All", Jump); } public static void CrouchAll() { ForEachTargetCharacter("Crouch All", Crouch); } public static void FallAll() { ForEachTargetCharacter("Fall All", Fall); } public static void PassOutAll() { ForEachTargetCharacter("Pass Out All", delegate(Character character) { RpcCharacter(character, "RPCA_PassOut"); }); } public static void UnpassOutAll() { ForEachTargetCharacter("Unpass Out All", delegate(Character character) { RpcCharacter(character, "RPCA_UnPassOut"); }); } public static void ReviveAllWithStatuses() { ForEachTargetCharacter("Revive All", delegate(Character character) { RpcCharacter(character, "RPCA_Revive", true); }); } public static void FullStaminaAll() { ForEachTargetCharacter("Full Stamina All", FullStamina); } public static void KillAll() { ForEachTargetCharacter("Kill All", Kill); } public static void TakeOwnershipAll() { ForEachTargetCharacter("Take Ownership All", TakeOwnership); } public static void DestroyAllCharacters() { ForEachTargetCharacter("Destroy All Characters", DestroyCharacter); } public static void EmptyAllSlot1() { EmptySlotAll(0); } public static void EmptyAllSlot2() { EmptySlotAll(1); } public static void EmptyAllSlot3() { EmptySlotAll(2); } public static void EmptyAllSlots() { ForEachTargetCharacter("Empty All Slots", EmptySlots); } public static void DropAllSlot1() { RuntimeActions.DropSlotAll(0); } public static void DropAllSlot2() { RuntimeActions.DropSlotAll(1); } public static void DropAllSlot3() { RuntimeActions.DropSlotAll(2); } public static void ForceAllEndScreensClosed() { ForceEveryEndScreenClosed("Force End Screens Closed"); } public static void RefreshAllCarryWeight() { ForEachTargetCharacter("Refresh Carry Weight", delegate(Character character) { RpcComponent((Component)(object)character.refs?.items, "RefreshAllCharacterCarryWeightRPC"); }); } public static void TeleportAllToMe() { ForEachTargetCharacter("Teleport All To Me", WarpToCamera); } public static void SpawnScoutmastersForAll() { ForEachTargetCharacter("Spawn Scoutmasters All", GameActions.SpawnScoutmasterFor); } public static void SelectedJump() { WithSelected("Selected Jump", Jump); } public static void SelectedFling() { WithSelected("Selected Fling", Fling); } public static void SelectedCrouch() { WithSelected("Selected Crouch", Crouch); } public static void SelectedPassOut() { WithSelected("Selected Pass Out", delegate(Character character) { RpcCharacter(character, "RPCA_PassOut"); }); } public static void SelectedUnpassOut() { WithSelected("Selected Unpass Out", delegate(Character character) { RpcCharacter(character, "RPCA_UnPassOut"); }); } public static void SelectedFall() { WithSelected("Selected Fall", Fall); } public static void SelectedShakeScreen() { WithSelected("Selected Shake Screen", ShakeScreen); } public static void SelectedStopClimbing() { WithSelected("Selected Stop Climbing", StopClimbing); } public static void SelectedUnhang() { WithSelected("Selected Unhang", Unhang); } public static void SelectedSlip() { WithSelected("Selected Slip", Slip); } public static void SelectedBlowdartHit() { WithSelected("Selected Blowdart Hit", BlowdartHit); } public static void SelectedExplode() { WithSelected("Selected Explode", Explode); } public static void SelectedFullStamina() { WithSelected("Selected Full Stamina", FullStamina); } public static void SelectedTakeOwnership() { WithSelected("Selected Take Ownership", TakeOwnership); } public static void SelectedDestroy() { WithSelected("Selected Destroy", DestroyCharacter); } public static void SelectedRefreshCarryWeight() { WithSelected("Selected Refresh Carry Weight", delegate(Character character) { RpcComponent((Component)(object)character.refs?.items, "RefreshAllCharacterCarryWeightRPC"); }); } public static void SelectedReviveWithStatuses() { WithSelected("Selected Revive", delegate(Character character) { RpcCharacter(character, "RPCA_Revive", true); }); } public static void SelectedDropHeldItem() { WithSelected("Selected Drop Held Item", DropHeldItem); } public static void SelectedEmptySlot1() { WithSelected("Selected Empty Slot 1", delegate(Character character) { EmptySlot(character, 0); }); } public static void SelectedEmptySlot2() { WithSelected("Selected Empty Slot 2", delegate(Character character) { EmptySlot(character, 1); }); } public static void SelectedEmptySlot3() { WithSelected("Selected Empty Slot 3", delegate(Character character) { EmptySlot(character, 2); }); } public static void SelectedEmptyAllSlots() { WithSelected("Selected Empty All Slots", EmptySlots); } public static void SelectedDropSlot1() { WithSelected("Selected Drop Slot 1", delegate(Character character) { DropSlot(character, 0); }); } public static void SelectedDropSlot2() { WithSelected("Selected Drop Slot 2", delegate(Character character) { DropSlot(character, 1); }); } public static void SelectedDropSlot3() { WithSelected("Selected Drop Slot 3", delegate(Character character) { DropSlot(character, 2); }); } public static void SelectedDropAllSlots() { WithSelected("Selected Drop All Slots", DropSlots); } public static void SelectedRenderDead() { WithSelected("Selected Render Dead", delegate(Character character) { RpcComponent((Component)(object)character.refs?.customization, "CharacterDied"); }); } public static void SelectedRenderPassedOut() { WithSelected("Selected Render Passed Out", delegate(Character character) { RpcComponent((Component)(object)character.refs?.customization, "CharacterPassedOut"); }); } public static void SelectedForceEndScreenClosed() { WithSelected("Selected Force End Screen Closed", ForceEndScreenClosed); } public static void SelectedRequestPickupOnAllItems() { WithSelected("Selected Request Pickup", RequestPickupOnAllItems); } public static void SelectedSwarmBees() { WithSelected("Selected Swarm Bees", SwarmBees); } public static void SelectedGrowVine() { WithSelected("Selected Grow Vine", GrowVine); } public static void SelectedCarry() { WithSelected("Selected Carry", Carry); } public static void SelectedForceScoutmasters() { WithSelected("Selected Force Scoutmasters", ForceScoutmasters); } public static void SelectedClearAfflictions() { WithSelected("Selected Clear Afflictions", delegate(Character character) { SetAfflictions(character, null, clearAll: true); }); } public static void SelectedAddAffliction() { WithSelected("Selected Add Affliction", delegate(Character character) { SetAfflictions(character, RuntimeActions.AfflictionIndex, clearAll: false, 0.1f); }); } public static void SelectedRemoveAffliction() { WithSelected("Selected Remove Affliction", delegate(Character character) { SetAfflictions(character, RuntimeActions.AfflictionIndex, clearAll: false, -0.1f); }); } public static void SelectedReviveAndTeleportToMe() { WithSelected("Selected Revive", ReviveAndTeleportToMe); } public static void SelectedKickFromLobby() { WithSelected("Selected Kick From Lobby", KickFromLobby); } public static void PlaySelectedEmote(string emote) { string safeEmote = (string.IsNullOrWhiteSpace(emote) ? "Wave" : emote.Trim()); WithSelected("Play Selected Emote", delegate(Character character) { RpcCharacter(character, "RPCA_PlayRemove", safeEmote, false); }); } public static void PlayAllEmote(string emote) { string safeEmote = (string.IsNullOrWhiteSpace(emote) ? "Wave" : emote.Trim()); ForEachTargetCharacter("Play All Emote", delegate(Character character) { RpcCharacter(character, "RPCA_PlayRemove", safeEmote, false); }); } public static void SetRoomVersionRequirement() { if (string.IsNullOrWhiteSpace(RoomVersionRequirement)) { NotifyWarning("Set Room Version Failed", "Room version requirement value is empty."); } else { SetSteamLobbyData("PeakVersion", RoomVersionRequirement.Trim()); } } public static void SpawnCharacter() { SpawnNetworkObject("Character"); } public static void SpawnPlayer() { SpawnNetworkObject("Player"); } public static void SpawnPlayerGhost() { SpawnRoomObject("PlayerGhost"); } public static void SpawnScoutmaster() { SpawnRoomObject("Character_Scoutmaster"); } public static void SpawnMushroomZombie() { SpawnRoomObject("MushroomZombie"); } public static void SpawnTornado() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) if (!RequireRoom("Spawn Tornado")) { return; } try { GameObject val = PhotonNetwork.Instantiate("Tornado", GetCameraSpawnPosition(), Quaternion.identity, (byte)0, (object[])null); SpawnState.RegisterSpawnedEntity(val, "Tornado"); PhotonView val2 = (Object.op_Implicit((Object)(object)val) ? val.GetComponent() : null); if (!Object.op_Implicit((Object)(object)val2)) { NotifyWarning("Spawn Tornado Failed", "Tornado spawned without a PhotonView."); return; } val2.RPC("RPCA_InitTornado", (RpcTarget)0, new object[1] { val2.ViewID }); NotifyInfo("Spawn Tornado", "Tornado spawned and initialized."); } catch (Exception ex) { NotifyException("Spawn Tornado Failed", ex); } } public static void RemoveAllTornados() { Tornado[] array = Object.FindObjectsByType((FindObjectsSortMode)0); int num = 0; int num2 = 0; Tornado[] array2 = array; for (int i = 0; i < array2.Length; i++) { PhotonView photonView = GetPhotonView((Component)(object)array2[i]); if (!Object.op_Implicit((Object)(object)photonView)) { num2++; continue; } try { TakeOwnership(photonView, notify: false); PhotonNetwork.Destroy(photonView); num++; } catch { num2++; } } NotifyActionResult("Remove Tornados", num, num2, array.Length); } public static void ForceGhostsToMe() { if (!RequireLocalCharacter("Force Ghosts", out var local)) { return; } PhotonView photonView = GetPhotonView((Component)(object)local); if (!Object.op_Implicit((Object)(object)photonView)) { NotifyWarning("Force Ghosts Failed", "Local character PhotonView was not found."); return; } PlayerGhost[] array = Object.FindObjectsByType((FindObjectsSortMode)0); int num = 0; int num2 = 0; PlayerGhost[] array2 = array; foreach (PlayerGhost val in array2) { if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)val.m_view)) { num2++; continue; } try { val.m_view.RPC("RPCA_SetTarget", (RpcTarget)0, new object[1] { photonView }); num++; } catch { num2++; } } NotifyActionResult("Force Ghosts", num, num2, array.Length); } public static void OpenAllLuggage(bool spawnItems) { LuggageOpenRuntime.OpenMany(Object.FindObjectsByType((FindObjectsSortMode)0), spawnItems, "Open All Luggage"); } public static void ThrowScoutmasters() { Scoutmaster[] array = Object.FindObjectsByType((FindObjectsSortMode)0); int num = 0; int num2 = 0; Scoutmaster[] array2 = array; for (int i = 0; i < array2.Length; i++) { if (RpcComponent((Component)(object)array2[i], "RPCA_Throw")) { num++; } else { num2++; } } NotifyActionResult("Throw Scoutmasters", num, num2, array.Length); } public static void UnlockBingBongAchievement() { RpcComponent((Component)(object)GameUtils.instance, "ThrowBingBongAchievementRpc"); } public static void UnlockEmergencyAchievement() { RpcComponent((Component)(object)GameUtils.instance, "ThrowEmergencyPreparednessAchievementRpc"); } public static void DestroyAllNetworkObjects() { if (!RequireRoom("Destroy Network Objects")) { return; } SetMaster(); PhotonView[] array = Object.FindObjectsByType((FindObjectsSortMode)0); int num = 0; int num2 = 0; PhotonView[] array2 = array; foreach (PhotonView val in array2) { if (!Object.op_Implicit((Object)(object)val)) { num2++; } else if (!IsPlayerPhotonView(val)) { try { TakeOwnership(val, notify: false); PhotonNetwork.Destroy(val); num++; } catch { num2++; } } } NotifyActionResult("Destroy Network Objects", num, num2, array.Length); } private static bool IsPlayerPhotonView(PhotonView view) { if (!Object.op_Implicit((Object)(object)view)) { return false; } try { if (Object.op_Implicit((Object)(object)((Component)view).GetComponent()) || Object.op_Implicit((Object)(object)((Component)view).GetComponentInParent()) || Object.op_Implicit((Object)(object)((Component)view).GetComponentInChildren())) { return true; } string text = BuildTransformPath(((Component)view).transform); return text.IndexOf("Character", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("Player", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("Scout", StringComparison.OrdinalIgnoreCase) >= 0; } catch { return true; } } private static string BuildTransformPath(Transform transform) { if (!Object.op_Implicit((Object)(object)transform)) { return string.Empty; } string text = ((Object)transform).name; Transform parent = transform.parent; int num = 0; while (Object.op_Implicit((Object)(object)parent) && num++ < 8) { text = ((Object)parent).name + "/" + text; parent = parent.parent; } return text; } public static void BroadcastPingAtMouse() { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0078: 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) Camera main = Camera.main; if (!Object.op_Implicit((Object)(object)main)) { NotifyWarning("Broadcast Ping Failed", "Main camera was not found."); } else { if (!Input.GetMouseButtonDown(2)) { return; } RaycastHit val = default(RaycastHit); if (!Physics.Raycast(main.ScreenPointToRay(Input.mousePosition), ref val, 1000f)) { NotifyWarning("Broadcast Ping Failed", "Mouse raycast did not hit anything."); return; } PointPinger[] array = Object.FindObjectsByType((FindObjectsSortMode)0); int num = 0; int num2 = 0; PointPinger[] array2 = array; for (int i = 0; i < array2.Length; i++) { if (RpcComponent((Component)(object)array2[i], "ReceivePoint_Rpc", ((RaycastHit)(ref val)).point, ((RaycastHit)(ref val)).normal)) { num++; } else { num2++; } } NotifyActionResult("Broadcast Ping", num, num2, array.Length); } } public static void BlowdartAtMouse() { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) if (!Input.GetMouseButtonDown(0)) { return; } Camera main = Camera.main; if (!Object.op_Implicit((Object)(object)main)) { NotifyWarning("Blowdart Failed", "Main camera was not found."); return; } RaycastHit hit = default(RaycastHit); if (!Physics.Raycast(new Ray(((Component)main).transform.position, ((Component)main).transform.forward), ref hit, 100f)) { NotifyWarning("Blowdart Failed", "Camera raycast did not hit anything."); return; } Character obj = FindCharacterFromHit(hit); PhotonView photonView = GetPhotonView((Component)(object)obj); if (!Object.op_Implicit((Object)(object)obj) || !Object.op_Implicit((Object)(object)photonView)) { NotifyWarning("Blowdart Failed", "Aim at a player character."); return; } Action_RaycastDart val = Object.FindFirstObjectByType(); if (!Object.op_Implicit((Object)(object)val)) { GameObject val2 = PhotonNetwork.Instantiate("0_Items/HealingDart Variant", Vector3.zero, Quaternion.identity, (byte)0, (object[])null); val = (Object.op_Implicit((Object)(object)val2) ? val2.GetComponent() : null); } if (!Object.op_Implicit((Object)(object)val)) { NotifyWarning("Blowdart Failed", "Action_RaycastDart was not found or spawned."); return; } RpcComponent((Component)(object)val, "RPC_DartImpact", photonView.ViewID, ((Component)main).transform.position, ((RaycastHit)(ref hit)).point); } private static Character FindCharacterFromHit(RaycastHit hit) { Collider collider = ((RaycastHit)(ref hit)).collider; if (Object.op_Implicit((Object)(object)collider)) { Character componentInParent = ((Component)collider).GetComponentInParent(); if (Object.op_Implicit((Object)(object)componentInParent)) { return componentInParent; } Rigidbody attachedRigidbody = collider.attachedRigidbody; if (Object.op_Implicit((Object)(object)attachedRigidbody)) { componentInParent = ((Component)attachedRigidbody).GetComponentInParent(); if (Object.op_Implicit((Object)(object)componentInParent)) { return componentInParent; } } } Transform transform = ((RaycastHit)(ref hit)).transform; if (!Object.op_Implicit((Object)(object)transform)) { return null; } return ((Component)transform).GetComponentInParent(); } private static void SpawnNetworkObject(string prefab) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0047: 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_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrWhiteSpace(prefab)) { NotifyWarning("Spawn Failed", "Prefab name is empty."); } else if (RequireRoom("Spawn " + prefab)) { try { Character localCharacter = Character.localCharacter; Vector3 val = (Object.op_Implicit((Object)(object)localCharacter) ? localCharacter.Head : GetCameraSpawnPosition()); Quaternion val2 = (Object.op_Implicit((Object)(object)localCharacter) ? ((Component)localCharacter).transform.rotation : Quaternion.identity); GameObject obj = PhotonNetwork.Instantiate(prefab, val, val2, (byte)0, (object[])null); SpawnState.RegisterSpawnedEntity(obj, prefab); NotifyByObject((Object)(object)obj, "Spawn", "Spawned: " + prefab, "Spawn Failed", "Photon failed to spawn: " + prefab); } catch (Exception ex) { NotifyException("Spawn Failed", ex); } } } private static void SpawnRoomObject(string prefab) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_004b: 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_004e: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrWhiteSpace(prefab)) { NotifyWarning("Spawn Room Object Failed", "Prefab name is empty."); } else if (RequireRoom("Spawn " + prefab)) { SetMaster(); try { Character localCharacter = Character.localCharacter; Vector3 val = (Object.op_Implicit((Object)(object)localCharacter) ? localCharacter.Center : GetCameraSpawnPosition()); GameObject obj = PhotonNetwork.InstantiateRoomObject(prefab, val, Quaternion.identity, (byte)0, (object[])null); SpawnState.RegisterSpawnedEntity(obj, prefab); NotifyByObject((Object)(object)obj, "Spawn Room Object", "Spawned room object: " + prefab, "Spawn Room Object Failed", "Photon failed to spawn room object: " + prefab); } catch (Exception ex) { NotifyException("Spawn Room Object Failed", ex); } } } private static void RunLocalCharacterAction(string actionName, Action action) { if (!RequireLocalCharacter(actionName, out var local)) { return; } try { action?.Invoke(local); } catch (Exception ex) { NotifyException(actionName + " Failed", ex); } } private static void RpcLocalCharacter(string actionName, string rpcName, params object[] args) { if (RequireLocalCharacter(actionName, out var local)) { RpcCharacter(local, rpcName, args); } } private static void WithSelected(string actionName, Action action) { if (action == null) { NotifyWarning(actionName + " Failed", "Action callback is null."); return; } if (!PlayerDirectory.TryGetSelectedCharacter(out var character)) { NotifyWarning(actionName + " Failed", "No selected player character was found."); return; } try { action(character); NotifyInfo(actionName, "Action sent to selected player."); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[" + actionName + "] " + GetBaseMessage(ex))); } NotifyException(actionName + " Failed", ex); } } private static void ForEachTargetCharacter(string actionName, Action action) { if (action == null) { NotifyWarning(actionName + " Failed", "Action callback is null."); return; } Character localCharacter = Character.localCharacter; List list = new List(); foreach (Character character in GameActions.GetCharacters()) { if (Object.op_Implicit((Object)(object)character)) { list.Add(character); } } if (list.Count == 0) { NotifyWarning(actionName + " Failed", "No characters were found."); return; } int num = 0; int num2 = 0; int num3 = 0; foreach (Character item in list) { if (!Object.op_Implicit((Object)(object)item)) { num2++; continue; } if (!VisualPlayerText.IsRealPlayer(item)) { num3++; continue; } if (PlayerActionSettings.ExcludeSelfFromAllActions && Object.op_Implicit((Object)(object)localCharacter) && item == localCharacter) { num3++; continue; } try { action(item); num++; } catch (Exception ex) { num2++; ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[" + actionName + "] " + GetBaseMessage(ex))); } } } string text = num + " succeeded"; if (num3 > 0) { text = text + ", " + num3 + " skipped"; } if (num2 > 0) { text = text + ", " + num2 + " failed"; } if (num > 0 && num2 == 0) { NotifyInfo(actionName, text + "."); } else if (num > 0) { NotifyWarning(actionName, text + ". Check console for failures."); } else { NotifyWarning(actionName + " Failed", text + "."); } } private static void Jump(Character character) { if (CanUseMovementRpc(character, "Jump")) { RpcComponent((Component)(object)character.refs.movement, "JumpRpc", false); } } private static void Fall(Character character) { RpcCharacter(character, "RPCA_Fall", 7f); } private static void Crouch(Character character) { if (CanUseMovementRpc(character, "Crouch")) { RpcComponent((Component)(object)character.refs.movement, "RPCA_SetCrouch", true); } } private static void FullStamina(Character character) { RpcCharacter(character, "MoraleBoost", 1f, 1); } private static void Kill(Character character) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: 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) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)character)) { NotifyWarning("Kill Failed", "Character is null."); return; } RpcCharacter(character, "RPCA_Die", character.Center + Vector3.up * 0.2f + Vector3.forward * 0.1f); } private static void Fling(Character character) { Fall(character); for (int i = 0; i < 8; i++) { Jump(character); } } private static void ShakeScreen(Character character) { RpcCharacter(character, "RPCA_FallWithScreenShake", 0f, 5f); } private static void StopClimbing(Character character) { RpcCharacter(character, "StopClimbingRpc", 0f); RpcCharacter(character, "StopRopeClimbingRpc"); RpcCharacter(character, "StopVineClimbingRpc"); } private static void Unhang(Character character) { PhotonView photonView = GetPhotonView((Component)(object)character); if (!Object.op_Implicit((Object)(object)photonView)) { NotifyWarning("Unhang Failed", "Target character PhotonView was not found."); return; } ClimbHandle[] array = Object.FindObjectsByType((FindObjectsSortMode)0); int num = 0; int num2 = 0; ClimbHandle[] array2 = array; for (int i = 0; i < array2.Length; i++) { PhotonView photonView2 = GetPhotonView((Component)(object)array2[i]); if (!Object.op_Implicit((Object)(object)photonView2)) { num2++; continue; } try { photonView2.RPC("RPCA_UnHang", (RpcTarget)0, new object[1] { photonView }); num++; } catch { num2++; } } NotifyActionResult("Unhang", num, num2, array.Length); } private static void BlowdartHit(Character character) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: 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_00a9: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)character)) { NotifyWarning("Blowdart Failed", "Character is null."); return; } Action_RaycastDart val = Object.FindFirstObjectByType(); if (!Object.op_Implicit((Object)(object)val)) { GameObject val2 = PhotonNetwork.Instantiate("0_Items/HealingDart Variant", Vector3.zero, Quaternion.identity, (byte)0, (object[])null); val = (Object.op_Implicit((Object)(object)val2) ? val2.GetComponent() : null); } PhotonView photonView = GetPhotonView((Component)(object)character); PhotonView photonView2 = GetPhotonView((Component)(object)val); if (!Object.op_Implicit((Object)(object)photonView) || !Object.op_Implicit((Object)(object)photonView2)) { NotifyWarning("Blowdart Failed", "Dart or target PhotonView was not found."); return; } photonView2.RPC("RPC_DartImpact", (RpcTarget)0, new object[3] { photonView.ViewID, character.Center, character.Center }); } private static void Explode(Character character) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)character)) { NotifyWarning("Explode Failed", "Character is null."); return; } GameObject val = PhotonNetwork.Instantiate("0_Items/Dynamite", character.Head, Quaternion.identity, (byte)0, (object[])null); PhotonView photonView = GetPhotonView((Component)(object)(Object.op_Implicit((Object)(object)val) ? val.GetComponent() : null)); if (!Object.op_Implicit((Object)(object)photonView)) { NotifyWarning("Explode Failed", "Dynamite PhotonView was not found."); return; } photonView.RPC("RPC_Explode", (RpcTarget)0, Array.Empty()); PhotonNetwork.Destroy(photonView); } private static void WarpToCamera(Character character) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //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) Camera main = Camera.main; if (!Object.op_Implicit((Object)(object)main)) { NotifyWarning("Warp Failed", "Main camera was not found."); return; } RpcCharacter(character, "WarpPlayerRPC", ((Component)main).transform.position + ((Component)main).transform.forward * 2f, true); } private static void ReviveAndTeleportToMe(Character character) { RpcCharacter(character, "RPCA_Revive", false); WarpToCamera(character); } private static void Slip(Character character) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)character)) { NotifyWarning("Slip Failed", "Character is null."); return; } BananaPeel val = Object.FindFirstObjectByType(); if (!Object.op_Implicit((Object)(object)val)) { GameObject val2 = PhotonNetwork.Instantiate("0_Items/Berrynana Peel Pink Variant", character.Head, Quaternion.identity, (byte)0, (object[])null); val = (Object.op_Implicit((Object)(object)val2) ? val2.GetComponent() : null); } PhotonView photonView = GetPhotonView((Component)(object)val); PhotonView photonView2 = GetPhotonView((Component)(object)character); if (!Object.op_Implicit((Object)(object)photonView) || !Object.op_Implicit((Object)(object)photonView2)) { NotifyWarning("Slip Failed", "Banana peel or target PhotonView was not found."); return; } photonView.RPC("RPCA_TriggerBanana", (RpcTarget)0, new object[1] { photonView2.ViewID }); } private static void DropHeldItem(Character character) { if (!Object.op_Implicit((Object)(object)character)) { NotifyWarning("Drop Held Item Failed", "Character is null."); } else { RpcComponent((Component)(object)character.refs?.items, "DestroyHeldItemRpc"); } } private static void DropSlots(Character character) { for (int i = 0; i < 3; i++) { DropSlot(character, i); } DropSlot(character, 3); } private static void EmptySlots(Character character) { for (int i = 0; i < 3; i++) { EmptySlot(character, i); } EmptySlot(character, 3); } private static void DropSlot(Character character, int slot) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)character)) { NotifyWarning("Drop Slot Failed", "Character is null."); return; } RpcComponent((Component)(object)character.refs?.items, "DropItemFromSlotRPC", (byte)slot, character.Head); } private static void EmptySlotAll(int slot) { ForEachTargetCharacter("Empty Slot " + (slot + 1), delegate(Character character) { EmptySlot(character, slot); }); } private static void EmptySlot(Character character, int slot) { if (!Object.op_Implicit((Object)(object)character)) { NotifyWarning("Empty Slot Failed", "Character is null."); return; } Player val = null; try { val = character.player; } catch { } if (!Object.op_Implicit((Object)(object)val)) { NotifyWarning("Empty Slot Failed", "Player component was not found."); return; } RpcComponent((Component)(object)val, (RpcTarget)2, "RPCRemoveItemFromSlot", (byte)slot); } private static void TakeOwnership(Character character) { TakeOwnership(GetPhotonView((Component)(object)character)); } private static bool TakeOwnership(PhotonView view, bool notify = true) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)view)) { if (notify) { NotifyWarning("Take Ownership Failed", "PhotonView was not found."); } return false; } if (PhotonNetwork.LocalPlayer == null) { if (notify) { NotifyWarning("Take Ownership Failed", "Photon local player is missing."); } return false; } try { view.OwnershipTransfer = (OwnershipOption)1; view.OwnerActorNr = PhotonNetwork.LocalPlayer.ActorNumber; view.ControllerActorNr = PhotonNetwork.LocalPlayer.ActorNumber; view.RequestOwnership(); view.TransferOwnership(PhotonNetwork.LocalPlayer); return true; } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Take Ownership] " + GetBaseMessage(ex))); } if (notify) { NotifyException("Take Ownership Failed", ex); } return false; } } private static void KickFromLobby(Character character) { if (!RequireRoom("Kick From Lobby")) { return; } if (!PhotonNetwork.IsMasterClient && PhotonNetwork.LocalPlayer != null) { NotifyWarning("Kick From Lobby Failed", "Only the Master Client can kick players from the lobby."); return; } PhotonView photonView = GetPhotonView((Component)(object)character); if (!Object.op_Implicit((Object)(object)photonView)) { NotifyWarning("Kick From Lobby Failed", "Target PhotonView was not found."); return; } if (photonView.Controller == null || photonView.ControllerActorNr <= 0) { NotifyWarning("Kick From Lobby Failed", "Target Photon controller was not found."); return; } if (photonView.Controller.IsLocal) { NotifyWarning("Kick From Lobby Failed", "Cannot kick your own local player."); return; } PlayerHandler.Kick(photonView.ControllerActorNr); NotificationSystem.Push("Kick From Lobby", "Kick request sent for player: " + photonView.Controller.NickName); } private static void DestroyCharacter(Character character) { if (!Object.op_Implicit((Object)(object)character)) { NotifyWarning("Destroy Character Failed", "Character is null."); return; } PhotonView val = (Object.op_Implicit((Object)(object)character.refs?.view) ? character.refs.view : GetPhotonView((Component)(object)character)); if (!Object.op_Implicit((Object)(object)val)) { NotifyWarning("Destroy Character Failed", "Target PhotonView was not found."); return; } Player obj = val.Controller ?? val.Owner; int num = ((obj != null) ? obj.ActorNumber : (-1)); if (IsLocalCharacterTarget(character, val, num)) { NotifyWarning("Destroy Character Failed", "Refusing to clear your own local player objects."); return; } TakeOwnership(val, notify: false); try { PhotonNetwork.Destroy(val); if (num > 0) { PhotonNetwork.DestroyPlayerObjects(num); } try { PhotonNetwork.SendAllOutgoingCommands(); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Destroy Character] Photon command flush failed: " + ex.Message)); } } } catch (Exception ex2) { NotifyException("Destroy Character Failed", ex2); } } private static bool IsLocalCharacterTarget(Character character, PhotonView view, int targetActorNumber) { if (!Object.op_Implicit((Object)(object)character)) { return false; } Character localCharacter = Character.localCharacter; if (Object.op_Implicit((Object)(object)localCharacter) && character == localCharacter) { return true; } try { if (character.IsLocal) { return true; } } catch { } Player localPlayer = PhotonNetwork.LocalPlayer; if (localPlayer == null) { return false; } if (targetActorNumber == localPlayer.ActorNumber) { return true; } try { int? obj2; if (view == null) { obj2 = null; } else { Player controller = view.Controller; obj2 = ((controller != null) ? new int?(controller.ActorNumber) : null); } if (obj2 == localPlayer.ActorNumber) { return true; } int? obj3; if (view == null) { obj3 = null; } else { Player owner = view.Owner; obj3 = ((owner != null) ? new int?(owner.ActorNumber) : null); } if (obj3 == localPlayer.ActorNumber) { return true; } } catch { } return false; } private static void ForceEndScreenClosed(Character character) { PhotonView photonView = GetPhotonView((Component)(object)Object.FindFirstObjectByType()); PhotonView photonView2 = GetPhotonView((Component)(object)character); if (!Object.op_Implicit((Object)(object)photonView)) { NotifyWarning("Force End Screen Failed", "GameOverHandler PhotonView was not found."); return; } int? obj; if (photonView2 == null) { obj = null; } else { Player controller = photonView2.Controller; obj = ((controller != null) ? new int?(controller.ActorNumber) : null); } int? num = obj; int num2; if (!num.HasValue) { int? obj2; if (photonView2 == null) { obj2 = null; } else { Player owner = photonView2.Owner; obj2 = ((owner != null) ? new int?(owner.ActorNumber) : null); } num2 = obj2 ?? ((photonView2 != null) ? photonView2.ControllerActorNr : ((photonView2 != null) ? photonView2.OwnerActorNr : (-1))); } else { num2 = num.GetValueOrDefault(); } int targetActorNumber = num2; if (!IsLocalCharacterTarget(character, photonView2, targetActorNumber)) { NotifyWarning("Force End Screen Failed", "PEAK only accepts the sender for this RPC; selected remote players cannot be marked individually."); } else { photonView.RPC("PlayerHasClosedEndScreen", (RpcTarget)0, Array.Empty()); } } private static void ForceEveryEndScreenClosed(string actionName) { PhotonView photonView = GetPhotonView((Component)(object)Object.FindFirstObjectByType()); if (!Object.op_Implicit((Object)(object)photonView)) { NotifyWarning(actionName + " Failed", "GameOverHandler PhotonView was not found."); return; } photonView.RPC("ForceEveryPlayerDoneWithEndScreenRPC", (RpcTarget)0, Array.Empty()); NotifyInfo(actionName, "End screen completion sent for all players."); } private static void RequestPickupOnAllItems(Character character) { PhotonView photonView = GetPhotonView((Component)(object)character); if (!Object.op_Implicit((Object)(object)photonView)) { NotifyWarning("Request Pickup Failed", "Target character PhotonView was not found."); return; } Item[] array = Object.FindObjectsByType((FindObjectsSortMode)0); int num = 0; int num2 = 0; Item[] array2 = array; for (int i = 0; i < array2.Length; i++) { PhotonView photonView2 = GetPhotonView((Component)(object)array2[i]); if (!Object.op_Implicit((Object)(object)photonView2)) { num2++; continue; } try { photonView2.RPC("RequestPickup", (RpcTarget)0, new object[1] { photonView }); num++; } catch { num2++; } } NotifyActionResult("Request Pickup", num, num2, array.Length); } private static void SwarmBees(Character character) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)character)) { NotifyWarning("Swarm Bees Failed", "Character is null."); return; } GameObject val = PhotonNetwork.Instantiate("BeeSwarm", character.Head, Quaternion.identity, (byte)0, (object[])null); BeeSwarm val2 = (Object.op_Implicit((Object)(object)val) ? val.GetComponent() : null); if (!Object.op_Implicit((Object)(object)val2)) { NotifyWarning("Swarm Bees Failed", "BeeSwarm prefab was not found after spawning."); return; } RpcComponent((Component)(object)val2, "SetBeesAngryRPC", true); } private static void GrowVine(Character character) { if (!MagicBeanVineRuntime.TryGrowOn(character, out var error)) { NotifyWarning("Grow Vine Failed", error); } } private static void Carry(Character target) { Character localCharacter = Character.localCharacter; if (!Object.op_Implicit((Object)(object)localCharacter)) { NotifyWarning("Carry Failed", "Local character was not found."); return; } if (!Object.op_Implicit((Object)(object)target)) { NotifyWarning("Carry Failed", "Target character was not found."); return; } if (localCharacter == target) { NotifyWarning("Carry Failed", "Cannot carry yourself."); return; } CharacterCarrying val = localCharacter.refs?.carriying; if (!Object.op_Implicit((Object)(object)val)) { NotifyWarning("Carry Failed", "Local CharacterCarrying component was not found."); return; } PiggybackCarryRuntime.Register(localCharacter, target); MethodInfo startCarryMethod = GetStartCarryMethod(((object)val).GetType()); if (startCarryMethod != null) { startCarryMethod.Invoke(val, new object[1] { target }); return; } PhotonView val2 = (Object.op_Implicit((Object)(object)target.refs?.view) ? target.refs.view : GetPhotonView((Component)(object)target)); PhotonView val3 = (Object.op_Implicit((Object)(object)localCharacter.refs?.view) ? localCharacter.refs.view : GetPhotonView((Component)(object)val)); if (!Object.op_Implicit((Object)(object)val2) || !Object.op_Implicit((Object)(object)val3)) { NotifyWarning("Carry Failed", "Carrier or target PhotonView was not found."); return; } val3.RPC("RPCA_StartCarry", (RpcTarget)0, new object[1] { val2 }); } private static MethodInfo GetStartCarryMethod(Type type) { if (type == null) { return null; } if (StartCarryCache.TryGetValue(type, out var value)) { return value; } MethodInfo method = type.GetMethod("StartCarry", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); StartCarryCache[type] = method; return method; } private static void ForceScoutmasters(Character character) { PhotonView photonView = GetPhotonView((Component)(object)character); if (!Object.op_Implicit((Object)(object)photonView)) { NotifyWarning("Force Scoutmasters Failed", "Target PhotonView was not found."); return; } Scoutmaster[] array = Object.FindObjectsByType((FindObjectsSortMode)0); int num = 0; int num2 = 0; Scoutmaster[] array2 = array; for (int i = 0; i < array2.Length; i++) { if (RpcComponent((Component)(object)array2[i], "RPCA_SetCurrentTarget", photonView.ViewID, 7f)) { num++; } else { num2++; } } NotifyActionResult("Force Scoutmasters", num, num2, array.Length); } private static void SetAfflictions(Character character, int? statusIndex, bool clearAll, float delta = 0f) { if (!AfflictionRpcRuntime.TryApply(character, statusIndex, clearAll, delta, out var error)) { throw new InvalidOperationException(error); } } private static void SetSteamLobbyData(string key, string value) { if (string.IsNullOrWhiteSpace(key)) { NotifyWarning("Steam Lobby Data Failed", "Lobby data key is empty."); return; } if (value == null) { NotifyWarning("Steam Lobby Data Failed", "Lobby data value is null."); return; } try { SetMaster(); object steamLobbyHandler = GetSteamLobbyHandler(); if (steamLobbyHandler == null) { NotifyWarning("Steam Lobby Data Failed", "SteamLobbyHandler service was not found."); return; } object fieldValue = GetFieldValue(steamLobbyHandler, "m_currentLobby"); if (fieldValue == null) { NotifyWarning("Steam Lobby Data Failed", "Current Steam lobby ID was not found."); return; } Type type = FindType("Steamworks.SteamMatchmaking"); if (type == null) { NotifyWarning("Steam Lobby Data Failed", "SteamMatchmaking type was not found."); return; } MethodInfo method = type.GetMethod("SetLobbyData", BindingFlags.Static | BindingFlags.Public, null, new Type[3] { fieldValue.GetType(), typeof(string), typeof(string) }, null); if (method == null) { NotifyWarning("Steam Lobby Data Failed", "SetLobbyData method was not found."); return; } object obj = method.Invoke(null, new object[3] { fieldValue, key, value }); if (obj is bool && !(bool)obj) { NotifyWarning("Steam Lobby Data Failed", "Steam returned false for key: " + key); } else { NotifyInfo("Steam Lobby Data", key + " = " + value); } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Steam Lobby Data] " + GetBaseMessage(ex))); } NotifyException("Steam Lobby Data Failed", ex); } } private static object GetSteamLobbyHandler() { MethodInfo method = typeof(GameHandler).GetMethod("GetService", BindingFlags.Static | BindingFlags.Public); if (method == null) { return null; } Type type = FindType("SteamLobbyHandler") ?? FindType("pworld.Scripts.Extensions.SteamLobbyHandler"); if (type == null) { return null; } return method.MakeGenericMethod(type).Invoke(null, null); } private static object GetFieldValue(object target, string name) { if (target == null || string.IsNullOrWhiteSpace(name)) { return null; } return GetCachedField(target.GetType(), name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(target); } private static ulong ParseSteamLobbyId(string link) { if (string.IsNullOrWhiteSpace(link)) { return 0uL; } string[] array = link.Trim().Split(new char[2] { '/', '\\' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < array.Length; i++) { if (string.Equals(array[i], "joinlobby", StringComparison.OrdinalIgnoreCase)) { int num = i + 2; if (num < array.Length && ulong.TryParse(array[num], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result)) { return result; } } } for (int j = 0; j + 1 < array.Length; j++) { if (array[j] == "3527290" && ulong.TryParse(array[j + 1], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result2)) { return result2; } } if (array.Length == 1 && ulong.TryParse(array[0], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result3)) { return result3; } return 0uL; } private static Type FindType(string fullName) { if (string.IsNullOrWhiteSpace(fullName)) { return null; } if (TypeCache.TryGetValue(fullName, out var value)) { return value; } Type type = Type.GetType(fullName); if (type != null) { TypeCache[fullName] = type; return type; } Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { try { type = assembly.GetType(fullName); if (type != null) { TypeCache[fullName] = type; return type; } } catch { } } TypeCache[fullName] = null; return null; } private static MethodInfo GetCachedMethod(Type type, string name, BindingFlags flags) { if (type == null || string.IsNullOrWhiteSpace(name)) { return null; } string[] obj = new string[5] { type.FullName, "::", name, "::", null }; int num = (int)flags; obj[4] = num.ToString(); string key = string.Concat(obj); if (MethodCache.TryGetValue(key, out var value)) { return value; } MethodInfo method = type.GetMethod(name, flags); MethodCache[key] = method; return method; } private static FieldInfo GetCachedField(Type type, string name, BindingFlags flags) { if (type == null || string.IsNullOrWhiteSpace(name)) { return null; } string[] obj = new string[5] { type.FullName, "::", name, "::", null }; int num = (int)flags; obj[4] = num.ToString(); string key = string.Concat(obj); if (FieldCache.TryGetValue(key, out var value)) { return value; } FieldInfo field = type.GetField(name, flags); FieldCache[key] = field; return field; } private static bool RpcCharacter(Character character, string rpcName, params object[] args) { return TryRpc(GetPhotonView((Component)(object)character), rpcName, args); } private static bool RpcComponent(Component component, string rpcName, params object[] args) { return TryRpc(GetPhotonView(component), rpcName, args); } private static bool RpcComponent(Component component, RpcTarget target, string rpcName, params object[] args) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return TryRpc(GetPhotonView(component), target, rpcName, args); } private static bool TryRpc(PhotonView view, string rpcName, object[] args) { return TryRpc(view, (RpcTarget)0, rpcName, args); } private static bool TryRpc(PhotonView view, RpcTarget target, string rpcName, object[] args) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)view)) { NotifyWarning("RPC Failed", "PhotonView was not found for RPC: " + rpcName); return false; } if (string.IsNullOrEmpty(rpcName)) { NotifyWarning("RPC Failed", "RPC name is empty."); return false; } try { view.RPC(rpcName, target, args ?? Array.Empty()); return true; } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[RPC " + rpcName + "] " + GetBaseMessage(ex))); } NotifyWarning("RPC Failed", rpcName + ": " + GetBaseMessage(ex)); return false; } } private static bool CanUseMovementRpc(Character character, string actionName) { if (!Object.op_Implicit((Object)(object)character)) { NotifyWarning(actionName + " Failed", "Character is null."); return false; } if (!((Component)character).gameObject.activeInHierarchy) { NotifyWarning(actionName + " Failed", "Character GameObject is inactive."); return false; } if (!Object.op_Implicit((Object)(object)character.data)) { NotifyWarning(actionName + " Failed", "Character data is missing."); return false; } CharacterMovement val = character.refs?.movement; if (!Object.op_Implicit((Object)(object)val)) { NotifyWarning(actionName + " Failed", "CharacterMovement component is missing."); return false; } if (!((Component)val).gameObject.activeInHierarchy) { NotifyWarning(actionName + " Failed", "CharacterMovement GameObject is inactive."); return false; } return true; } private static bool RequireRoom(string actionName) { if (!PhotonNetwork.IsConnected) { NotifyWarning(actionName + " Failed", "Photon is not connected."); return false; } if (!PhotonNetwork.InRoom) { NotifyWarning(actionName + " Failed", "You are not currently in a Photon room."); return false; } return true; } private static bool RequireLocalCharacter(string actionName, out Character local) { local = Character.localCharacter; if (!Object.op_Implicit((Object)(object)local)) { NotifyWarning(actionName + " Failed", "Local character was not found."); return false; } return true; } private static string GetBaseMessage(Exception ex) { while (ex is TargetInvocationException && ex.InnerException != null) { ex = ex.InnerException; } return ex.GetType().Name + ": " + ex.Message; } private static PhotonView GetPhotonView(Component component) { if (!Object.op_Implicit((Object)(object)component)) { return null; } return component.GetComponent() ?? component.GetComponentInParent() ?? component.GetComponentInChildren(); } private static Vector3 GetCameraSpawnPosition() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) Camera main = Camera.main; if (!Object.op_Implicit((Object)(object)main)) { return Vector3.zero; } return ((Component)main).transform.position + ((Component)main).transform.forward * 2f; } private static void NotifyInfo(string title, string message) { NotificationSystem.Push(title, message); } private static void NotifyWarning(string title, string message) { NotificationSystem.Push(title, message, NotificationKind.Warning); } private static void NotifyError(string title, string message) { NotificationSystem.Push(title, message, NotificationKind.Error); } private static void NotifyException(string title, Exception ex) { string baseMessage = GetBaseMessage(ex); ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[" + title + "] " + baseMessage)); } NotifyError(title, baseMessage); } private static void NotifyByBool(bool ok, string okTitle, string okMessage, string failTitle, string failMessage) { if (ok) { NotifyInfo(okTitle, okMessage); } else { NotifyWarning(failTitle, failMessage); } } private static void NotifyByObject(Object obj, string okTitle, string okMessage, string failTitle, string failMessage) { if (Object.op_Implicit(obj)) { NotifyInfo(okTitle, okMessage); } else { NotifyWarning(failTitle, failMessage); } } private static void NotifyActionResult(string title, int success, int failed, int total) { if (total <= 0) { NotifyWarning(title + " Failed", "No matching objects were found."); } else if (failed <= 0 && success > 0) { NotifyInfo(title, success + "/" + total + " completed."); } else if (success > 0) { NotifyWarning(title, success + "/" + total + " completed, " + failed + " failed."); } else { NotifyWarning(title + " Failed", "0/" + total + " completed."); } } } internal static class MagicBeanVineRuntime { public const string GrowVineRpcName = "GrowVineRPC"; private const float DefaultMaxLength = 10f; public static bool TryGrowOn(Character character, out string error) { return TryGrowOn(character, 10f, out error); } public static bool TryGrowOn(Character character, float maxLength, out string error) { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) error = string.Empty; if (!Object.op_Implicit((Object)(object)character)) { error = "Character is null."; return false; } MagicBean val = Object.FindFirstObjectByType(); if (!Object.op_Implicit((Object)(object)val)) { error = "MagicBean was not found."; return false; } PhotonView photonView = GetPhotonView((Component)(object)val); if (!Object.op_Implicit((Object)(object)photonView)) { error = "MagicBean PhotonView was not found."; return false; } if (!RequireNetworkReady(out error)) { return false; } Vector3 val2 = Random.onUnitSphere; if (((Vector3)(ref val2)).sqrMagnitude < 0.0001f) { val2 = Vector3.up; } else { ((Vector3)(ref val2)).Normalize(); } try { photonView.RPC("GrowVineRPC", (RpcTarget)5, new object[3] { character.Head, val2, Mathf.Max(0.1f, maxLength) }); PhotonNetwork.SendAllOutgoingCommands(); return true; } catch (Exception ex) { error = GetBaseMessage(ex); ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Grow Vine] " + error)); } return false; } } private static bool RequireNetworkReady(out string error) { error = string.Empty; if (!PhotonNetwork.InRoom) { error = "You are not currently in a Photon room."; return false; } if (PhotonNetwork.LocalPlayer == null) { error = "Photon local player is missing."; return false; } return true; } private static PhotonView GetPhotonView(Component component) { if (!Object.op_Implicit((Object)(object)component)) { return null; } return component.GetComponent() ?? component.GetComponentInParent() ?? component.GetComponentInChildren(); } private static string GetBaseMessage(Exception ex) { while (ex is TargetInvocationException && ex.InnerException != null) { ex = ex.InnerException; } return ex.GetType().Name + ": " + ex.Message; } } internal static class RuntimeActions { private const BindingFlags InstanceFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; private const int BackpackSlot = 3; public static string EmoteName = "Wave"; public static int AfflictionIndex; public static float DayTime = 0.5f; public static float ThrowPower = 1f; public static bool CustomThrowPower; public static bool InstantThrow; public static void TickThrowPower() { Character localCharacter = Character.localCharacter; if (Object.op_Implicit((Object)(object)localCharacter) && Object.op_Implicit((Object)(object)localCharacter.refs?.items)) { if (InstantThrow) { localCharacter.refs.items.throwChargeLevel = 1f; } else if (CustomThrowPower) { localCharacter.refs.items.throwChargeLevel = ThrowPower; } } } public static void SlipLocal() { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) Character localCharacter = Character.localCharacter; if (Object.op_Implicit((Object)(object)localCharacter)) { BananaPeel val = Object.FindFirstObjectByType(); if (!Object.op_Implicit((Object)(object)val)) { GameObject val2 = PhotonNetwork.Instantiate("0_Items/Berrynana Peel Pink Variant", localCharacter.Head, Quaternion.identity, (byte)0, (object[])null); val = (Object.op_Implicit((Object)(object)val2) ? val2.GetComponent() : null); } PhotonView val3 = (Object.op_Implicit((Object)(object)val) ? ((Component)val).GetComponent() : null); if (Object.op_Implicit((Object)(object)val3) && Object.op_Implicit((Object)(object)localCharacter.refs?.view)) { val3.RPC("RPCA_TriggerBanana", (RpcTarget)0, new object[1] { localCharacter.refs.view.ViewID }); } } } public static void FallLocal() { RpcCharacter(Character.localCharacter, "RPCA_Fall", 7f); } public static void ReviveLocal() { RpcCharacter(Character.localCharacter, "RPCA_Revive", false); } public static void UnpassOutLocal() { RpcCharacter(Character.localCharacter, "RPCA_UnPassOut"); } public static void FullStaminaWithMorale() { RpcCharacter(Character.localCharacter, "MoraleBoost", 1f, 20); } public static void ClearLocalAfflictions() { Character localCharacter = Character.localCharacter; if (Object.op_Implicit((Object)(object)localCharacter)) { SetAfflictions(localCharacter, null, clearAll: true); } } public static void RemoveItemRestrictions() { Item[] array = Object.FindObjectsByType((FindObjectsSortMode)0); foreach (Item val in array) { if (Object.op_Implicit((Object)(object)val) && val.UIData != null) { val.UIData.canDrop = true; val.UIData.canThrow = true; } } } public static void ClearAfflictionsAll() { ForEachTargetCharacter(delegate(Character character) { SetAfflictions(character, null, clearAll: true); }); } public static void AddAfflictionAll() { ForEachTargetCharacter(delegate(Character character) { SetAfflictions(character, AfflictionIndex, clearAll: false, 0.1f); }); } public static void RemoveAfflictionAll() { ForEachTargetCharacter(delegate(Character character) { SetAfflictions(character, AfflictionIndex, clearAll: false, -0.1f); }); } public static void SlipAll() { ForEachTargetCharacter(delegate(Character character) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) BananaPeel val = Object.FindFirstObjectByType(); if (!Object.op_Implicit((Object)(object)val)) { GameObject val2 = PhotonNetwork.Instantiate("0_Items/Berrynana Peel Pink Variant", character.Head, Quaternion.identity, (byte)0, (object[])null); val = (Object.op_Implicit((Object)(object)val2) ? val2.GetComponent() : null); } PhotonView val3 = (Object.op_Implicit((Object)(object)val) ? ((Component)val).GetComponent() : null); if (Object.op_Implicit((Object)(object)val3) && Object.op_Implicit((Object)(object)character.refs?.view)) { val3.RPC("RPCA_TriggerBanana", (RpcTarget)0, new object[1] { character.refs.view.ViewID }); } }); } public static void FlingAll() { ForEachTargetCharacter(delegate(Character character) { RpcCharacter(character, "RPCA_Fall", 7f); for (int i = 0; i < 8; i++) { Jump(character); } }); } public static void ShakeAllScreens() { ForEachTargetCharacter(delegate(Character character) { RpcCharacter(character, "RPCA_FallWithScreenShake", 0f, 5f); }); } public static void BlowdartHitAll() { ForEachTargetCharacter(delegate(Character character) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) Action_RaycastDart val = Object.FindFirstObjectByType(); if (!Object.op_Implicit((Object)(object)val)) { GameObject val2 = PhotonNetwork.Instantiate("0_Items/HealingDart Variant", Vector3.zero, Quaternion.identity, (byte)0, (object[])null); val = (Object.op_Implicit((Object)(object)val2) ? val2.GetComponent() : null); } PhotonView photonView = GetPhotonView((Component)(object)character); PhotonView val3 = (Object.op_Implicit((Object)(object)val) ? ((Component)val).GetComponent() : null); if (Object.op_Implicit((Object)(object)photonView) && Object.op_Implicit((Object)(object)val3)) { val3.RPC("RPC_DartImpact", (RpcTarget)0, new object[3] { photonView.ViewID, character.Center, character.Center }); } }); } public static void ExplodeAll() { ForEachTargetCharacter(delegate(Character character) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) GameObject val = PhotonNetwork.Instantiate("0_Items/Dynamite", character.Head, Quaternion.identity, (byte)0, (object[])null); Dynamite val2 = (Object.op_Implicit((Object)(object)val) ? val.GetComponent() : null); PhotonView val3 = (Object.op_Implicit((Object)(object)val2) ? GetPhotonView((Component)(object)val2) : null); if (Object.op_Implicit((Object)(object)val3)) { val3.RPC("RPC_Explode", (RpcTarget)0, Array.Empty()); PhotonNetwork.Destroy(val3); } }); } public static void StopClimbingAll() { ForEachTargetCharacter(delegate(Character character) { RpcCharacter(character, "StopClimbingRpc", 0f); RpcCharacter(character, "StopRopeClimbingRpc"); RpcCharacter(character, "StopVineClimbingRpc"); }); } public static void UnhangAll() { ClimbHandle[] handles = Object.FindObjectsByType((FindObjectsSortMode)0); ForEachTargetCharacter(delegate(Character character) { PhotonView photonView = GetPhotonView((Component)(object)character); if (Object.op_Implicit((Object)(object)photonView)) { for (int i = 0; i < handles.Length; i++) { PhotonView val = (Object.op_Implicit((Object)(object)handles[i]) ? ((Component)handles[i]).GetComponent() : null); if (Object.op_Implicit((Object)(object)val)) { val.RPC("RPCA_UnHang", (RpcTarget)0, new object[1] { photonView }); } } } }); } public static void PlayEmoteAll() { string emote = (string.IsNullOrWhiteSpace(EmoteName) ? "Wave" : EmoteName); ForEachTargetCharacter(delegate(Character character) { RpcCharacter(character, "RPCA_PlayRemove", emote, false); }); } public static void GrowVinesOnAll() { int success = 0; int failed = 0; string lastError = string.Empty; ForEachTargetCharacter(delegate(Character character) { if (MagicBeanVineRuntime.TryGrowOn(character, out var error)) { success++; } else { failed++; lastError = error; } }); if (failed > 0) { NotificationSystem.Push("Grow Vines", success + " sent, " + failed + " failed. " + lastError, NotificationKind.Warning); } else if (success > 0) { NotificationSystem.Push("Grow Vines", success + " sent."); } } public static void AngryBeesAll() { ForEachTargetCharacter(delegate(Character character) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) GameObject val = PhotonNetwork.Instantiate("BeeSwarm", character.Head, Quaternion.identity, (byte)0, (object[])null); BeeSwarm val2 = (Object.op_Implicit((Object)(object)val) ? val.GetComponent() : null); PhotonView val3 = (Object.op_Implicit((Object)(object)val2) ? GetPhotonView((Component)(object)val2) : null); if (Object.op_Implicit((Object)(object)val3)) { val3.RPC("SetBeesAngryRPC", (RpcTarget)0, new object[1] { true }); } }); } public static void ReviveAllAndTeleportToMe() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) Camera main = Camera.main; if (!Object.op_Implicit((Object)(object)main)) { return; } Vector3 position = ((Component)main).transform.position + ((Component)main).transform.forward * 2f; foreach (Character character in GameActions.GetCharacters()) { RpcCharacter(character, "RPCA_Revive", false); GameActions.WarpCharacter(character, position); } } public static void RenderAllPassedOut() { ForEachTargetCharacter(delegate(Character character) { RpcComponent((Component)(object)character.refs?.customization, "CharacterPassedOut"); }); } public static void RenderAllDead() { ForEachTargetCharacter(delegate(Character character) { RpcComponent((Component)(object)character.refs?.customization, "CharacterDied"); }); } public static void RequestAllItems() { Item[] items = Object.FindObjectsByType((FindObjectsSortMode)0); ForEachTargetCharacter(delegate(Character character) { PhotonView photonView = GetPhotonView((Component)(object)character); if (Object.op_Implicit((Object)(object)photonView)) { Item[] array = items; foreach (Item val in array) { PhotonView val2 = (Object.op_Implicit((Object)(object)val) ? GetPhotonView((Component)(object)val) : null); if (Object.op_Implicit((Object)(object)val2)) { val2.RPC("RequestPickup", (RpcTarget)0, new object[1] { photonView }); } } } }); } public static void DropAllHeldItems() { ForEachTargetCharacter(delegate(Character character) { RpcComponent((Component)(object)character.refs?.items, "DestroyHeldItemRpc"); }); } public static void DropAllSlots() { DropSlotAll(0); DropSlotAll(1); DropSlotAll(2); DropSlotAll(3); } public static void DropSlotAll(int slot) { ForEachTargetCharacter(delegate(Character character) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) RpcComponent((Component)(object)character.refs?.items, "DropItemFromSlotRPC", (byte)slot, character.Head); }); } public static void ToggleWind(bool enabled) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) WindChillZone[] array = Object.FindObjectsByType((FindObjectsSortMode)0); for (int i = 0; i < array.Length; i++) { PhotonView photonView = GetPhotonView((Component)(object)array[i]); if (Object.op_Implicit((Object)(object)photonView)) { photonView.RPC("RPCA_ToggleWind", (RpcTarget)0, new object[3] { enabled, Vector3.forward, 999999f }); } } } public static void StartLavaRise() { RpcAllByType("RPCA_StartLavaRise", Array.Empty()); } public static void ShakeIcicles() { RpcAllByType("ShakeRock_Rpc", Array.Empty()); } public static void DropIcicles() { RpcAllByType("Fall_Rpc", Array.Empty()); } public static void ShakeBridges() { RpcAllByType("ShakeBridge_Rpc", Array.Empty()); } public static void DropBridges() { RpcAllByType("Fall_Rpc", Array.Empty()); } public static void LightAllFlares() { RpcAllByType("SetFlareLitRPC", Array.Empty()); } public static void BreakPitons() { RpcAllByType("RPCA_Break", Array.Empty()); } public static void StartBreakingPitons() { RpcAllByType("RPCA_StartBreaking", Array.Empty()); } public static void StartFog() { RpcAllByType("StartMovingRPC", Array.Empty()); } public static void DetachRopes() { Rope[] array = Object.FindObjectsByType((FindObjectsSortMode)0); foreach (Rope val in array) { if (Object.op_Implicit((Object)(object)val)) { RpcComponent((Component)(object)val, "Detach_Rpc", val.Segments); } } } public static void FlipGuidebooksLeft() { RpcAllByType("FlipPageLeft_RPC", new object[1] { Random.Range(0, 5) }); } public static void FlipGuidebooksRight() { RpcAllByType("FlipPageRight_RPC", new object[1] { Random.Range(0, 5) }); } public static void PauseBingBongTime() { RpcAllByType("RPCA_SyncTimeScale", new object[1] { 0f }); } public static void SetDayTime() { RpcAllByType("RPCA_SyncTime", new object[1] { DayTime }); } public static void LightLanterns() { RpcAllByType("LightLanternRPC", new object[1] { true }); } public static void ExtinguishLanterns() { RpcAllByType("LightLanternRPC", new object[1] { false }); } public static void LightCampfires() { Character localCharacter = Character.localCharacter; if (!Object.op_Implicit((Object)(object)localCharacter)) { NotificationSystem.Push("Light Campfire", "Local character was not found.", NotificationKind.Warning); return; } Campfire val = FindNearestCampfire(localCharacter, lit: false, 10f); if (!Object.op_Implicit((Object)(object)val)) { NotificationSystem.Push("Light Campfire", "No unlit campfire is within 10 meters.", NotificationKind.Warning); return; } try { val.Interact_CastFinished(localCharacter); NotificationSystem.Push("Light Campfire", "Nearby campfire lit."); return; } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Light Campfire] Game interaction failed: " + GetBaseMessage(ex))); } } PhotonView photonView = GetPhotonView((Component)(object)val); if (!Object.op_Implicit((Object)(object)photonView)) { NotificationSystem.Push("Light Campfire", "Campfire PhotonView was not found.", NotificationKind.Warning); return; } photonView.RPC("Light_Rpc", (RpcTarget)0, new object[2] { true, 0f }); NotificationSystem.Push("Light Campfire", "Nearby campfire lit."); } public static void ExtinguishCampfires() { Character localCharacter = Character.localCharacter; if (!Object.op_Implicit((Object)(object)localCharacter)) { NotificationSystem.Push("Extinguish Campfire", "Local character was not found.", NotificationKind.Warning); return; } Campfire val = FindNearestCampfire(localCharacter, lit: true, 10f); if (!Object.op_Implicit((Object)(object)val)) { NotificationSystem.Push("Extinguish Campfire", "No lit campfire is within 10 meters.", NotificationKind.Warning); return; } PhotonView photonView = GetPhotonView((Component)(object)val); if (!Object.op_Implicit((Object)(object)photonView)) { NotificationSystem.Push("Extinguish Campfire", "Campfire PhotonView was not found.", NotificationKind.Warning); return; } photonView.RPC("Extinguish_Rpc", (RpcTarget)0, Array.Empty()); NotificationSystem.Push("Extinguish Campfire", "Nearby campfire extinguished."); } public static void ForceEndScreenDone() { RpcAllByType("ForceEveryPlayerDoneWithEndScreenRPC", Array.Empty()); } private static Campfire FindNearestCampfire(Character local, bool lit, float maxDistance) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)local)) { return null; } Campfire result = null; float num = Mathf.Max(0f, maxDistance); Campfire[] array = Object.FindObjectsByType((FindObjectsSortMode)0); foreach (Campfire val in array) { if (Object.op_Implicit((Object)(object)val) && val.Lit == lit) { float num2 = Vector3.Distance(local.Center, val.Center()); if (!(num2 > num)) { result = val; num = num2; } } } return result; } private static void SetAfflictions(Character character, int? statusIndex, bool clearAll, float delta = 0f) { if (!AfflictionRpcRuntime.TryApply(character, statusIndex, clearAll, delta, out var error)) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Afflictions] " + error)); } } } private static void RpcAllByType(string rpcName, params object[] args) where T : Component { T[] array = Object.FindObjectsByType((FindObjectsSortMode)0); for (int i = 0; i < array.Length; i++) { RpcComponent((Component)(object)array[i], rpcName, args); } } private static void RpcAllByType(RpcTarget target, string rpcName, params object[] args) where T : Component { //IL_0017: Unknown result type (might be due to invalid IL or missing references) T[] array = Object.FindObjectsByType((FindObjectsSortMode)0); for (int i = 0; i < array.Length; i++) { RpcComponent((Component)(object)array[i], target, rpcName, args); } } private static void ForEachTargetCharacter(Action action) { if (action == null) { return; } Character localCharacter = Character.localCharacter; foreach (Character character in GameActions.GetCharacters()) { if (!Object.op_Implicit((Object)(object)character) || !VisualPlayerText.IsRealPlayer(character) || (PlayerActionSettings.ExcludeSelfFromAllActions && Object.op_Implicit((Object)(object)localCharacter) && character == localCharacter)) { continue; } try { action(character); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[All Action] " + GetBaseMessage(ex))); } } } } private static void Jump(Character character) { if (CanUseMovementRpc(character)) { RpcComponent((Component)(object)character.refs.movement, "JumpRpc", false); } } private static void RpcCharacter(Character character, string rpcName, params object[] args) { if (Object.op_Implicit((Object)(object)character)) { TryRpc(GetPhotonView((Component)(object)character), rpcName, args); } } private static void RpcComponent(Component component, string rpcName, params object[] args) { if (Object.op_Implicit((Object)(object)component)) { TryRpc(GetPhotonView(component), rpcName, args); } } private static void RpcComponent(Component component, RpcTarget target, string rpcName, params object[] args) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)component)) { TryRpc(GetPhotonView(component), target, rpcName, args); } } private static void TryRpc(PhotonView view, string rpcName, object[] args) { TryRpc(view, (RpcTarget)0, rpcName, args); } private static void TryRpc(PhotonView view, RpcTarget target, string rpcName, object[] args) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)view) || string.IsNullOrEmpty(rpcName)) { return; } try { view.RPC(rpcName, target, args ?? Array.Empty()); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[RPC " + rpcName + "] " + GetBaseMessage(ex))); } } } private static bool CanUseMovementRpc(Character character) { if (!Object.op_Implicit((Object)(object)character) || !((Component)character).gameObject.activeInHierarchy || !Object.op_Implicit((Object)(object)character.data)) { return false; } CharacterMovement val = character.refs?.movement; if (Object.op_Implicit((Object)(object)val)) { return ((Component)val).gameObject.activeInHierarchy; } return false; } private static string GetBaseMessage(Exception ex) { while (ex is TargetInvocationException && ex.InnerException != null) { ex = ex.InnerException; } return ex.GetType().Name + ": " + ex.Message; } private static PhotonView GetPhotonView(Component component) { if (!Object.op_Implicit((Object)(object)component)) { return null; } return component.GetComponent() ?? component.GetComponentInParent() ?? component.GetComponentInChildren(); } } internal sealed class SteamLobbyJoinStatusRuntime : MonoBehaviourPunCallbacks { private const float JoinTimeoutSeconds = 25f; private static SteamLobbyJoinStatusRuntime _instance; private bool _waiting; private ulong _lobbyId; private float _startedAt; private string _startingRoomName; private static SteamLobbyJoinStatusRuntime Instance { get { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown if (Object.op_Implicit((Object)(object)_instance)) { return _instance; } GameObject val = new GameObject("CubeX_SteamLobbyJoinStatusRuntime"); Object.DontDestroyOnLoad((Object)val); _instance = val.AddComponent(); return _instance; } } public static void StartMonitoring(ulong lobbyId) { Instance.Begin(lobbyId); } private void Begin(ulong lobbyId) { _waiting = true; _lobbyId = lobbyId; _startedAt = Time.realtimeSinceStartup; _startingRoomName = ((PhotonNetwork.CurrentRoom != null) ? PhotonNetwork.CurrentRoom.Name : null); NotificationSystem.Push("Steam Lobby Join", "Join request sent. Waiting for lobby result..."); } private void Update() { if (!_waiting) { return; } if (PhotonNetwork.InRoom && PhotonNetwork.CurrentRoom != null) { string name = PhotonNetwork.CurrentRoom.Name; if (!string.IsNullOrWhiteSpace(name) && name != _startingRoomName) { NotifySuccess(name); return; } } if (!(Time.realtimeSinceStartup - _startedAt < 25f)) { CubeXDiagnostics.Warning("Steam Lobby Join Failed", "Timed out waiting for a result from Steam/Photon for lobby " + _lobbyId + ". The lobby may be private, closed, full, or the invite may be stale."); ResetState(); } } public override void OnJoinedRoom() { if (_waiting) { string roomName = ((PhotonNetwork.CurrentRoom != null) ? PhotonNetwork.CurrentRoom.Name : "unknown room"); NotifySuccess(roomName); } } public override void OnJoinRoomFailed(short returnCode, string message) { if (_waiting) { string message2 = PhotonJoinFailureMessages.Describe(returnCode, message); CubeXDiagnostics.Warning("Steam Lobby Join Failed", message2); ResetState(); } } public override void OnJoinRandomFailed(short returnCode, string message) { if (_waiting) { string message2 = PhotonJoinFailureMessages.Describe(returnCode, message); CubeXDiagnostics.Warning("Steam Lobby Join Failed", message2); ResetState(); } } public override void OnDisconnected(DisconnectCause cause) { if (_waiting) { CubeXDiagnostics.Warning("Steam Lobby Join Failed", "Disconnected while joining Steam lobby: " + ((object)(DisconnectCause)(ref cause)).ToString()); ResetState(); } } private void NotifySuccess(string roomName) { NotificationSystem.Push("Steam Lobby Join", "Successfully joined lobby/room: " + roomName, NotificationKind.Success); ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)("[Steam Lobby Join] Successfully joined lobby " + _lobbyId + " / room " + roomName)); } ResetState(); } private void ResetState() { _waiting = false; _lobbyId = 0uL; _startedAt = 0f; _startingRoomName = null; } } } namespace CubeX.Core { internal static class AppDataPaths { public const string GameFolderName = "Peak"; public static string RootDirectory => Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "CubeX"); public static string GameDirectory => Path.Combine(RootDirectory, "Peak"); public static string FilePath(string fileName) { return Path.Combine(GameDirectory, fileName); } public static string DirectoryPath(string directoryName) { return Path.Combine(GameDirectory, directoryName); } public static string FilePath(string directoryName, string fileName) { return Path.Combine(DirectoryPath(directoryName), fileName); } public static string LegacyFilePath(string fileName) { return Path.Combine(RootDirectory, fileName); } public static string LegacyDirectoryPath(string directoryName) { return Path.Combine(RootDirectory, directoryName); } public static void MigrateLegacyFile(string fileName) { string text = FilePath(fileName); if (File.Exists(text)) { return; } string text2 = LegacyFilePath(fileName); if (!File.Exists(text2)) { return; } try { Directory.CreateDirectory(GameDirectory); File.Copy(text2, text, overwrite: false); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[AppData] Failed to migrate " + fileName + " to Peak: " + ex.Message)); } } } public static void MigrateFileToDirectory(string fileName, string directoryName) { string text = DirectoryPath(directoryName); string text2 = Path.Combine(text, fileName); if (File.Exists(text2)) { return; } string text3 = FilePath(fileName); string text4 = LegacyFilePath(fileName); try { Directory.CreateDirectory(text); if (File.Exists(text3)) { File.Copy(text3, text2, overwrite: false); } else if (File.Exists(text4)) { File.Copy(text4, text2, overwrite: false); } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[AppData] Failed to migrate " + fileName + " to Peak/" + directoryName + ": " + ex.Message)); } } } public static void MigrateLegacyDirectory(string directoryName) { string text = DirectoryPath(directoryName); if (Directory.Exists(text)) { return; } string text2 = LegacyDirectoryPath(directoryName); if (!Directory.Exists(text2)) { return; } try { CopyDirectory(text2, text); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[AppData] Failed to migrate " + directoryName + " to Peak: " + ex.Message)); } } } private static void CopyDirectory(string source, string destination) { Directory.CreateDirectory(destination); string[] files = Directory.GetFiles(source); foreach (string text in files) { string text2 = Path.Combine(destination, Path.GetFileName(text)); if (!File.Exists(text2)) { File.Copy(text, text2); } } files = Directory.GetDirectories(source); foreach (string text3 in files) { CopyDirectory(text3, Path.Combine(destination, Path.GetFileName(text3))); } } } public abstract class ButtonFeature : Feature { public string ButtonLabel { get; protected set; } = "Run"; public abstract void Execute(); } public abstract class ColorFeature : Feature { public Color Value { get; protected set; } = Color.white; public virtual int PresetCount => 0; public virtual string GetDisplayValue() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return "#" + ColorUtility.ToHtmlStringRGB(Value); } public virtual string GetPresetName(int index) { return string.Empty; } public virtual Color GetPresetColor(int index) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return Color.white; } public virtual void ApplyPreset(int index) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) if (index >= 0 && index < PresetCount) { SetColor(GetPresetColor(index)); } } public void SetColor(Color color) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) Color val = default(Color); ((Color)(ref val))..ctor(Mathf.Clamp01(color.r), Mathf.Clamp01(color.g), Mathf.Clamp01(color.b), 1f); if (!Approximately(val, Value)) { Value = val; OnColorChanged(Value); ConfigService.MarkDirty(); } } protected virtual void OnColorChanged(Color newColor) { } private static bool Approximately(Color a, Color b) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) if (Mathf.Approximately(a.r, b.r) && Mathf.Approximately(a.g, b.g) && Mathf.Approximately(a.b, b.b)) { return Mathf.Approximately(a.a, b.a); } return false; } } [Serializable] public class ConfigMetadataState { public string displayName; public string note; public string createdAtUtc; public string updatedAtUtc; } public static class ConfigService { private const int ConfigVersion = 3; private const float AutoSaveDelay = 1f; private const int MaxConfigNameLength = 64; private const int MaxConfigNoteLength = 220; private const string LegacyDistantMobUpdateCullId = "CubeX.Features.Visuals.DistantMobUpdateCull"; private const string MobCullDistanceId = "CubeX.Features.Visuals.MobCullDistance"; private static FeatureManager _features; private static bool _initialized; private static bool _applying; private static bool _shuttingDown; private static bool _dirty; private static float _nextAutoSaveAt; private const string ConfigFolderName = "Configs"; public static bool IsApplying => _applying; public static bool IsShuttingDown => _shuttingDown; public static string ConfigDirectory => AppDataPaths.DirectoryPath("Configs"); public static string ConfigPath => Path.Combine(ConfigDirectory, "config.json"); public static string GetNamedConfigPath(string configName) { return Path.Combine(ConfigDirectory, BuildNamedConfigFileName(configName)); } public static string NormalizeConfigName(string value) { return SanitizeConfigName(value); } public static IReadOnlyList GetConfigFiles() { try { MigrateConfigFiles(); Directory.CreateDirectory(ConfigDirectory); return (from entry in Directory.GetFiles(ConfigDirectory, "*.json", SearchOption.TopDirectoryOnly).Select(CreateConfigFileEntry) orderby entry.IsMain descending select entry).ThenBy((ConfigFileEntry entry) => entry.DisplayName, StringComparer.OrdinalIgnoreCase).ThenBy((ConfigFileEntry entry) => entry.FileName, StringComparer.OrdinalIgnoreCase).ToList(); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("Failed to list config files: " + ex.Message)); } return Array.Empty(); } } public static void Initialize(FeatureManager features) { _features = features; _initialized = true; _applying = false; _shuttingDown = false; _dirty = false; if (!TryRead(out var config)) { return; } _applying = true; try { ApplyStoredConfigFlags(config); if (MenuConfig.AutoLoadOnStart) { Apply(config); } else { SyncSettingsFeatures(); } } finally { _applying = false; _dirty = false; } } public static void Tick() { if (_initialized && !_applying && !_shuttingDown && _dirty && MenuConfig.AutoSave && !(Time.unscaledTime < _nextAutoSaveAt)) { SaveCurrent(logSuccess: false); } } public static void MarkDirty() { if (_initialized && !_applying && !_shuttingDown && MenuConfig.AutoSave) { _dirty = true; _nextAutoSaveAt = Time.unscaledTime + 1f; } } public static bool SaveCurrent(bool logSuccess = true) { MigrateConfigFiles(); return SaveCurrentToPath(ConfigPath, logSuccess, "Main", null, noteProvided: false); } public static bool SaveCurrentAs(string configName, bool logSuccess = true) { return SaveCurrentAs(configName, string.Empty, logSuccess); } public static bool SaveCurrentAs(string configName, string note, bool logSuccess = true) { string text = SanitizeConfigName(configName); return SaveCurrentToPath(GetNamedConfigPath(text), logSuccess, text, note, noteProvided: true); } public static bool SaveToFile(string fileName, bool logSuccess = true) { string text = ResolveConfigFilePath(fileName); if (!string.IsNullOrEmpty(text)) { return SaveCurrentToPath(text, logSuccess, null, null, noteProvided: false); } return false; } public static bool SaveToFile(string fileName, string note, bool logSuccess = true) { string text = ResolveConfigFilePath(fileName); if (!string.IsNullOrEmpty(text)) { return SaveCurrentToPath(text, logSuccess, null, note, noteProvided: true); } return false; } private static bool SaveCurrentToPath(string path, bool logSuccess, string displayName, string note, bool noteProvided) { if (_features == null) { return false; } try { Directory.CreateDirectory(Path.GetDirectoryName(path) ?? ConfigDirectory); string contents = JsonConvert.SerializeObject((object)Capture(BuildMetadata(path, displayName, note, noteProvided)), (Formatting)1); File.WriteAllText(path, contents); if (PathsEqual(path, ConfigPath)) { _dirty = false; } if (logSuccess) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)("Saved config to " + path)); } } return true; } catch (Exception ex) { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogError((object)("Failed to save config: " + ex)); } return false; } } public static bool LoadCurrent() { MigrateConfigFiles(); return LoadFromPath(ConfigPath, migrateLegacy: true); } public static bool LoadNamed(string configName) { return LoadFromPath(GetNamedConfigPath(configName), migrateLegacy: false); } public static bool LoadFile(string fileName) { string text = ResolveConfigFilePath(fileName); if (!string.IsNullOrEmpty(text)) { return LoadFromPath(text, migrateLegacy: false); } return false; } public static bool DeleteFile(string fileName) { string text = ResolveConfigFilePath(fileName); if (string.IsNullOrEmpty(text) || !File.Exists(text) || PathsEqual(text, ConfigPath)) { return false; } try { File.Delete(text); return true; } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("Failed to delete config " + fileName + ": " + ex.Message)); } return false; } } public static bool RenameFile(string fileName, string newConfigName) { string text = ResolveConfigFilePath(fileName); if (string.IsNullOrEmpty(text) || !File.Exists(text) || PathsEqual(text, ConfigPath)) { return false; } string text2 = SanitizeConfigName(newConfigName); string namedConfigPath = GetNamedConfigPath(text2); if (PathsEqual(text, namedConfigPath)) { return UpdateMetadata(text, text2, null, noteProvided: false); } if (File.Exists(namedConfigPath)) { return false; } try { if (!TryRead(text, migrateLegacy: false, out var config)) { return false; } config.metadata = BuildMetadata(text, text2, null, noteProvided: false); config.metadata.displayName = text2; config.metadata.updatedAtUtc = DateTime.UtcNow.ToString("O", CultureInfo.InvariantCulture); Directory.CreateDirectory(ConfigDirectory); File.WriteAllText(namedConfigPath, JsonConvert.SerializeObject((object)config, (Formatting)1)); File.Delete(text); ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)("Renamed config " + text + " to " + namedConfigPath)); } return true; } catch (Exception ex) { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogWarning((object)("Failed to rename config " + fileName + ": " + ex.Message)); } return false; } } public static bool UpdateFileNote(string fileName, string note) { string text = ResolveConfigFilePath(fileName); if (!string.IsNullOrEmpty(text) && File.Exists(text)) { return UpdateMetadata(text, null, note, noteProvided: true); } return false; } private static bool LoadFromPath(string path, bool migrateLegacy) { if (!TryRead(path, migrateLegacy, out var config)) { return false; } _applying = true; try { Apply(config); _dirty = false; ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)("Loaded config from " + path)); } return true; } finally { _applying = false; } } public static void Shutdown() { if (_initialized && !_applying && MenuConfig.AutoSave && _dirty) { SaveCurrent(); } _shuttingDown = true; } private static CubeXConfig Capture(ConfigMetadataState metadata) { //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) CubeXConfig cubeXConfig = new CubeXConfig { version = 3, metadata = metadata, menu = CaptureMenuConfig(), features = new List() }; foreach (Feature item in _features.All) { if (ShouldPersist(item)) { FeatureState featureState = new FeatureState { id = GetFeatureId(item), name = item.Name, enabled = item.Enabled }; if (item is NumberFeature numberFeature) { featureState.hasNumber = true; featureState.numberValue = numberFeature.Value; } if (item is ColorFeature colorFeature) { featureState.hasColor = true; featureState.colorR = colorFeature.Value.r; featureState.colorG = colorFeature.Value.g; featureState.colorB = colorFeature.Value.b; } if (item is TextFeature textFeature) { featureState.hasText = true; featureState.textValue = textFeature.Value; } cubeXConfig.features.Add(featureState); } } return cubeXConfig; } private static MenuConfigState CaptureMenuConfig() { //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_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) Color accentColor = MenuConfig.AccentColor; return new MenuConfigState { presetIndex = MenuConfig.PresetIndex, accentR = accentColor.r, accentG = accentColor.g, accentB = accentColor.b, menuWidth = MenuConfig.MenuWidth, uiScale = MenuConfig.UIScale, highlightLerpSpeed = MenuConfig.HighlightLerpSpeed, maxVisibleRows = MenuConfig.MaxVisibleRows, showBreadcrumb = MenuConfig.ShowBreadcrumb, showDescription = MenuConfig.ShowDescription, showFooter = MenuConfig.ShowFooter, showScrollbar = MenuConfig.ShowScrollbar, autoSave = MenuConfig.AutoSave, autoLoadOnStart = MenuConfig.AutoLoadOnStart }; } private static ConfigFileEntry CreateConfigFileEntry(string path) { string fileName = Path.GetFileName(path); ConfigMetadataState configMetadataState = TryReadMetadata(path); return new ConfigFileEntry(fileName, path, GetDisplayName(fileName, configMetadataState), configMetadataState?.note ?? string.Empty, configMetadataState?.createdAtUtc ?? string.Empty, configMetadataState?.updatedAtUtc ?? string.Empty); } private static ConfigMetadataState TryReadMetadata(string path) { if (string.IsNullOrEmpty(path) || !File.Exists(path)) { return null; } try { return JsonConvert.DeserializeObject(File.ReadAllText(path))?.metadata; } catch { return null; } } private static ConfigMetadataState BuildMetadata(string path, string displayName, string note, bool noteProvided) { ConfigMetadataState configMetadataState = TryReadMetadata(path); string text = DateTime.UtcNow.ToString("O", CultureInfo.InvariantCulture); string fileName = Path.GetFileName(path); return new ConfigMetadataState { displayName = CleanDisplayName(displayName ?? configMetadataState?.displayName ?? BuildDisplayName(fileName)), note = CleanNote(noteProvided ? note : configMetadataState?.note), createdAtUtc = (string.IsNullOrWhiteSpace(configMetadataState?.createdAtUtc) ? text : configMetadataState.createdAtUtc), updatedAtUtc = text }; } private static bool UpdateMetadata(string path, string displayName, string note, bool noteProvided) { try { if (!TryRead(path, migrateLegacy: false, out var config)) { return false; } config.metadata = BuildMetadata(path, displayName, note, noteProvided); File.WriteAllText(path, JsonConvert.SerializeObject((object)config, (Formatting)1)); return true; } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("Failed to update config metadata: " + ex.Message)); } return false; } } private static bool TryRead(out CubeXConfig config) { return TryRead(ConfigPath, migrateLegacy: true, out config); } private static bool TryRead(string path, bool migrateLegacy, out CubeXConfig config) { config = null; try { if (migrateLegacy) { MigrateConfigFiles(); } if (!File.Exists(path)) { return false; } string text = File.ReadAllText(path); config = JsonConvert.DeserializeObject(text); return config != null; } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogError((object)("Failed to read config: " + ex)); } return false; } } private static void Apply(CubeXConfig config) { if (config != null) { ApplyMenuConfig(config.menu); SyncSettingsFeatures(); ApplyFeatureStates(config.features, config.version); } } private static void ApplyStoredConfigFlags(CubeXConfig config) { if (config?.menu != null) { MenuConfig.AutoSave = config.menu.autoSave; MenuConfig.AutoLoadOnStart = config.menu.autoLoadOnStart; } } private static void ApplyMenuConfig(MenuConfigState menu) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) if (menu != null) { MenuConfig.PresetIndex = Mathf.Clamp(menu.presetIndex, 0, MenuConfig.Presets.Length - 1); MenuConfig.SetAccentColor(new Color(menu.accentR, menu.accentG, menu.accentB, 1f)); MenuConfig.MenuWidth = Mathf.Clamp(menu.menuWidth, 380f, 720f); MenuConfig.SetUIScale(menu.uiScale); MenuConfig.HighlightLerpSpeed = Mathf.Clamp(menu.highlightLerpSpeed, 4f, 40f); MenuConfig.MaxVisibleRows = Mathf.Clamp(menu.maxVisibleRows, 1, 32); MenuConfig.ShowBreadcrumb = menu.showBreadcrumb; MenuConfig.ShowDescription = menu.showDescription; MenuConfig.ShowFooter = menu.showFooter; MenuConfig.ShowScrollbar = menu.showScrollbar; MenuConfig.AutoSave = menu.autoSave; MenuConfig.AutoLoadOnStart = menu.autoLoadOnStart; } } private static void ApplyFeatureStates(List states, int configVersion) { //IL_015c: Unknown result type (might be due to invalid IL or missing references) if (states == null || _features == null) { return; } Dictionary dictionary = new Dictionary(); Dictionary dictionary2 = new Dictionary(StringComparer.Ordinal); foreach (Feature item in _features.All.Where(ShouldPersist)) { dictionary[GetFeatureId(item)] = item; if (!string.IsNullOrEmpty(item.Name)) { dictionary2.TryAdd(item.Name, item); } } foreach (FeatureState state in states) { if (state == null) { continue; } Feature value = null; if (!string.IsNullOrEmpty(state.id)) { dictionary.TryGetValue(state.id, out value); } if (value == null && !string.IsNullOrEmpty(state.name)) { dictionary2.TryGetValue(state.name, out value); } if (value == null) { value = ResolveLegacyFeature(state, dictionary); } if (value != null) { if (state.hasNumber && value is NumberFeature numberFeature) { numberFeature.SetValue(state.numberValue); } if (state.hasColor && value is ColorFeature colorFeature) { colorFeature.SetColor(new Color(state.colorR, state.colorG, state.colorB, 1f)); } if (state.hasText && value is TextFeature textFeature) { textFeature.SetText(state.textValue ?? string.Empty); } if (CanToggleFromConfig(value) && ShouldApplyEnabled(state, value, configVersion)) { value.Enabled = state.enabled; } } } } private static Feature ResolveLegacyFeature(FeatureState state, Dictionary byId) { if (state == null || byId == null) { return null; } if ((!string.Equals(state.id, "CubeX.Features.Visuals.DistantMobUpdateCull", StringComparison.Ordinal) && !string.Equals(state.name, "Distant Mob Update Cull", StringComparison.Ordinal)) || !byId.TryGetValue("CubeX.Features.Visuals.MobCullDistance", out var value)) { return null; } return value; } private static void SyncSettingsFeatures() { if (_features == null) { return; } foreach (Feature item in _features.All) { if (item is ISettingsFeature settingsFeature) { settingsFeature.SyncFromConfig(); } } } private static bool ShouldPersist(Feature feature) { if (feature == null) { return false; } if (feature is ButtonFeature) { return false; } if (feature is SubmenuFeature) { return false; } if (feature is SeparatorFeature) { return false; } if (feature is InfoFeature) { return false; } if (feature is IMenuRowProvider) { return false; } if (feature is IMenuSidePanelProvider) { return false; } if (feature is ISettingsFeature) { return false; } return true; } private static bool CanToggleFromConfig(Feature feature) { if (feature is NumberFeature && !(feature is NumberBoolFeature)) { return false; } if (feature is ColorFeature) { return false; } if (feature is TextFeature) { return false; } return true; } private static bool ShouldApplyEnabled(FeatureState state, Feature feature, int configVersion) { if (configVersion < 2 && feature is MobCullDistance && string.Equals(state.id, "CubeX.Features.Visuals.MobCullDistance", StringComparison.Ordinal)) { return false; } return true; } private static string GetFeatureId(Feature feature) { return feature.GetType().FullName; } private static string BuildNamedConfigFileName(string configName) { return "config_" + SanitizeConfigName(configName) + ".json"; } private static string GetDisplayName(string fileName, ConfigMetadataState metadata) { return CleanDisplayName(metadata?.displayName ?? BuildDisplayName(fileName)); } private static string BuildDisplayName(string fileName) { if (string.Equals(fileName, "config.json", StringComparison.OrdinalIgnoreCase)) { return "Main"; } string text = Path.GetFileNameWithoutExtension(fileName ?? string.Empty); if (text.StartsWith("config_", StringComparison.OrdinalIgnoreCase)) { text = text.Substring("config_".Length); } text = text.Replace('_', ' ').Trim(); if (!string.IsNullOrWhiteSpace(text)) { return text; } return "Custom"; } private static string CleanDisplayName(string value) { string text = (string.IsNullOrWhiteSpace(value) ? "1" : value.Trim()); if (text.Length > 64) { text = text.Substring(0, 64).Trim(); } if (!string.IsNullOrWhiteSpace(text)) { return text; } return "1"; } private static string CleanNote(string value) { string text = value ?? string.Empty; text = text.Replace("\r", " ").Replace("\n", " ").Trim(); if (text.Length <= 220) { return text; } return text.Substring(0, 220).Trim(); } private static string SanitizeConfigName(string value) { string path = CleanDisplayName(value); path = Path.GetFileNameWithoutExtension(path); if (path.StartsWith("config_", StringComparison.OrdinalIgnoreCase)) { path = path.Substring("config_".Length); } char[] invalidFileNameChars = Path.GetInvalidFileNameChars(); foreach (char oldChar in invalidFileNameChars) { path = path.Replace(oldChar, '_'); } path = path.Replace(' ', '_').Trim('_'); if (!string.IsNullOrWhiteSpace(path)) { return path; } return "1"; } private static bool PathsEqual(string left, string right) { try { return string.Equals(Path.GetFullPath(left), Path.GetFullPath(right), StringComparison.OrdinalIgnoreCase); } catch { return string.Equals(left, right, StringComparison.OrdinalIgnoreCase); } } private static void MigrateConfigFiles() { AppDataPaths.MigrateFileToDirectory("config.json", "Configs"); try { Directory.CreateDirectory(ConfigDirectory); if (!Directory.Exists(AppDataPaths.GameDirectory)) { return; } string[] files = Directory.GetFiles(AppDataPaths.GameDirectory, "config_*.json", SearchOption.TopDirectoryOnly); foreach (string text in files) { string text2 = Path.Combine(ConfigDirectory, Path.GetFileName(text)); if (!File.Exists(text2)) { File.Copy(text, text2, overwrite: false); } } string rootDirectory = AppDataPaths.RootDirectory; if (!Directory.Exists(rootDirectory)) { return; } files = Directory.GetFiles(rootDirectory, "config_*.json", SearchOption.TopDirectoryOnly); foreach (string text3 in files) { string text4 = Path.Combine(ConfigDirectory, Path.GetFileName(text3)); if (!File.Exists(text4)) { File.Copy(text3, text4, overwrite: false); } } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("Failed to migrate config files: " + ex.Message)); } } } private static string ResolveConfigFilePath(string fileName) { if (string.IsNullOrWhiteSpace(fileName)) { return null; } string text = Path.GetFileName(fileName.Trim()); if (string.IsNullOrWhiteSpace(text)) { return null; } if (!text.EndsWith(".json", StringComparison.OrdinalIgnoreCase)) { string text2 = Path.Combine(ConfigDirectory, text + ".json"); if (File.Exists(text2)) { return text2; } text = BuildNamedConfigFileName(text); } return Path.Combine(ConfigDirectory, text); } } public sealed class ConfigFileEntry { public string FileName { get; } public string Path { get; } public string DisplayName { get; } public string Note { get; } public string CreatedAtUtc { get; } public string UpdatedAtUtc { get; } public bool IsMain => string.Equals(FileName, "config.json", StringComparison.OrdinalIgnoreCase); public ConfigFileEntry(string fileName, string path, string displayName, string note, string createdAtUtc, string updatedAtUtc) { FileName = fileName ?? string.Empty; Path = path ?? string.Empty; DisplayName = (string.IsNullOrWhiteSpace(displayName) ? BuildFallbackDisplayName(FileName) : displayName.Trim()); Note = note ?? string.Empty; CreatedAtUtc = createdAtUtc ?? string.Empty; UpdatedAtUtc = updatedAtUtc ?? string.Empty; } private static string BuildFallbackDisplayName(string fileName) { if (string.Equals(fileName, "config.json", StringComparison.OrdinalIgnoreCase)) { return "Main"; } string text = System.IO.Path.GetFileNameWithoutExtension(fileName ?? string.Empty); if (text.StartsWith("config_", StringComparison.OrdinalIgnoreCase)) { text = text.Substring("config_".Length); } text = text.Replace('_', ' ').Trim(); if (!string.IsNullOrWhiteSpace(text)) { return text; } return "Custom"; } } [Serializable] public class CubeXConfig { public int version; public ConfigMetadataState metadata; public MenuConfigState menu; public List features; } [Serializable] public class FeatureState { public string id; public string name; public bool enabled; public bool hasNumber; public float numberValue; public bool hasColor; public float colorR; public float colorG; public float colorB; public bool hasText; public string textValue; } [Serializable] public class MenuConfigState { public int presetIndex; public float accentR; public float accentG; public float accentB; public float menuWidth; public float uiScale; public float highlightLerpSpeed; public int maxVisibleRows; public bool showBreadcrumb; public bool showDescription; public bool showFooter; public bool showScrollbar = true; public bool autoSave; public bool autoLoadOnStart; } public abstract class Feature { [CompilerGenerated] private bool k__BackingField; public string Name { get; protected set; } = "Unnamed"; public string Description { get; protected set; } = string.Empty; public string Category { get; private set; } = "Misc"; public int Order { get; private set; } public bool Enabled { [CompilerGenerated] get { return k__BackingField; } set { if (k__BackingField == value) { return; } bool flag = k__BackingField; k__BackingField = value; try { if (value) { OnEnable(); } else { OnDisable(); } } catch (Exception ex) { Plugin.Log.LogError((object)("[" + Name + "] toggle error: " + ex)); k__BackingField = flag; return; } ConfigService.MarkDirty(); } } public virtual bool TickWhenDisabled => false; internal void Place(string category, int order) { Category = category; Order = order; } protected virtual void OnEnable() { } protected virtual void OnDisable() { } public virtual void OnTick() { } public virtual void OnRender() { } } public class FeatureManager { private readonly struct GuiRenderState { private Color Color { get; } private Color BackgroundColor { get; } private Color ContentColor { get; } private Matrix4x4 Matrix { get; } private bool Enabled { get; } private int Depth { get; } private GUISkin Skin { get; } public GuiRenderState(Color color, Color backgroundColor, Color contentColor, Matrix4x4 matrix, bool enabled, int depth, GUISkin skin) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) Color = color; BackgroundColor = backgroundColor; ContentColor = contentColor; Matrix = matrix; Enabled = enabled; Depth = depth; Skin = skin; } public static GuiRenderState Capture() { //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_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) return new GuiRenderState(GUI.color, GUI.backgroundColor, GUI.contentColor, GUI.matrix, GUI.enabled, GUI.depth, GUI.skin); } public void Restore() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) GUI.color = Color; GUI.backgroundColor = BackgroundColor; GUI.contentColor = ContentColor; GUI.matrix = Matrix; GUI.enabled = Enabled; GUI.depth = Depth; GUI.skin = Skin; } } private readonly List _features = new List(); private readonly List _categories = new List(); private readonly Dictionary> _featuresByCategory = new Dictionary>(); private readonly List _rowProviders = new List(); private readonly List _sidePanelProviders = new List(); public static FeatureManager Current { get; private set; } public List All => _features; public List Categories => _categories; public IEnumerable RowProviders => _rowProviders; public IEnumerable SidePanelProviders => _sidePanelProviders; public FeatureManager() { Current = this; } public IEnumerable InCategory(string category) { if (category == null || !_featuresByCategory.TryGetValue(category, out var value)) { return Array.Empty(); } return value; } public void RegisterAllFromAssembly() { _features.Clear(); _categories.Clear(); _featuresByCategory.Clear(); _rowProviders.Clear(); _sidePanelProviders.Clear(); Assembly executingAssembly = Assembly.GetExecutingAssembly(); List list = DiscoverPages(executingAssembly); if (list.Count > 0) { RegisterPages(list); } else { RegisterLooseFeatures(executingAssembly); } RebuildIndexes(); } private static List DiscoverPages(Assembly asm) { List list = new List(); Type[] types = asm.GetTypes(); foreach (Type type in types) { if (!type.IsAbstract && typeof(FeaturePage).IsAssignableFrom(type) && !(type.GetConstructor(Type.EmptyTypes) == null)) { try { list.Add((FeaturePage)Activator.CreateInstance(type)); } catch (Exception ex) { Plugin.Log.LogError((object)("Failed to create page " + type.Name + ": " + ex.Message)); } } } return (from p in list orderby p.SortOrder, p.Name select p).ToList(); } private void RegisterPages(IEnumerable pages) { foreach (FeaturePage page in pages) { if (page == null || string.IsNullOrEmpty(page.Name)) { continue; } if (!_categories.Contains(page.Name)) { _categories.Add(page.Name); } List list; try { list = page.CreateFeatures(); } catch (Exception ex) { Plugin.Log.LogError((object)("Failed to build page " + page.Name + ": " + ex.Message)); continue; } foreach (Feature item in list) { Register(item); } } } private void RegisterLooseFeatures(Assembly asm) { Type[] types = asm.GetTypes(); foreach (Type type in types) { if (!type.IsAbstract && typeof(Feature).IsAssignableFrom(type) && !(type.GetConstructor(Type.EmptyTypes) == null)) { try { Register((Feature)Activator.CreateInstance(type)); } catch (Exception ex) { Plugin.Log.LogError((object)("Failed to register " + type.Name + ": " + ex.Message)); } } } foreach (string item in _features.Select((Feature f) => f.Category).Distinct()) { _categories.Add(item); } _categories.Sort(delegate(string a, string b) { int num = ((a == "Settings") ? 2 : ((a == "Misc") ? 1 : 0)); int value = ((b == "Settings") ? 2 : ((b == "Misc") ? 1 : 0)); int num2 = num.CompareTo(value); return (num2 == 0) ? string.CompareOrdinal(a, b) : num2; }); } private void Register(Feature feature) { if (feature != null && (feature is SubmenuFeature || feature is SeparatorFeature || !_features.Any((Feature f) => f.GetType() == feature.GetType()))) { _features.Add(feature); } } private void RebuildIndexes() { _featuresByCategory.Clear(); _rowProviders.Clear(); _sidePanelProviders.Clear(); foreach (Feature feature in _features) { if (feature == null) { continue; } if (feature is IMenuRowProvider item) { _rowProviders.Add(item); } if (feature is IMenuSidePanelProvider item2) { _sidePanelProviders.Add(item2); } if (!(feature is IMenuRowProvider)) { string category = feature.Category; if (!_featuresByCategory.TryGetValue(category, out var value)) { value = new List(); _featuresByCategory[category] = value; } value.Add(feature); } } foreach (List value2 in _featuresByCategory.Values) { value2.Sort(CompareFeaturesForMenu); } } private static int CompareFeaturesForMenu(Feature a, Feature b) { if (a == b) { return 0; } if (a == null) { return 1; } if (b == null) { return -1; } int num = a.Order.CompareTo(b.Order); if (num == 0) { return string.CompareOrdinal(a.Name, b.Name); } return num; } public void Tick() { foreach (Feature feature in _features) { if (feature.Enabled || feature.TickWhenDisabled) { try { feature.OnTick(); } catch (Exception ex) { Plugin.Log.LogError((object)("[" + feature.Name + "] OnTick: " + ex.Message)); } } } } public void Render() { foreach (Feature feature in _features) { if (!feature.Enabled) { continue; } GuiRenderState guiRenderState = GuiRenderState.Capture(); try { feature.OnRender(); } catch (Exception ex) { Plugin.Log.LogError((object)("[" + feature.Name + "] OnRender: " + ex.Message)); } finally { guiRenderState.Restore(); } } } public void DisableAll() { foreach (Feature feature in _features) { feature.Enabled = false; if (feature is IDisposable disposable) { disposable.Dispose(); } } } } public abstract class FeaturePage { public abstract string Name { get; } public virtual int SortOrder => 0; internal List CreateFeatures() { FeaturePageBuilder featurePageBuilder = new FeaturePageBuilder(Name); Build(featurePageBuilder); return featurePageBuilder.Features; } protected abstract void Build(FeaturePageBuilder page); } public sealed class FeaturePageBuilder { private readonly string _pageName; private int _nextOrder; internal readonly List Features = new List(); internal FeaturePageBuilder(string pageName) { _pageName = pageName; } public T Add() where T : Feature, new() { return (T)Add(new T()); } public SubmenuFeature AddSubmenu(string name, Action build) { string text = _pageName + "/" + name; SubmenuFeature result = (SubmenuFeature)Add(new SubmenuFeature(name, text)); if (build == null) { return result; } FeaturePageBuilder featurePageBuilder = new FeaturePageBuilder(text); build(featurePageBuilder); Features.AddRange(featurePageBuilder.Features); return result; } public SeparatorFeature AddBreak() { return (SeparatorFeature)Add(new SeparatorFeature()); } public Feature Add(Feature feature) { if (feature == null) { return null; } feature.Place(_pageName, _nextOrder++); Features.Add(feature); return feature; } } public interface IMenuNavigationTarget { string TargetCategory { get; } string TargetChildCategory { get; } Type TargetFeatureType { get; } string TargetRowName { get; } } public interface IMenuRowProvider { IEnumerable GetRows(string category); } public interface IMenuSidePanelProvider { bool TryGetSidePanel(string category, object selectedRow, out MenuSidePanel panel); } public interface IMenuTagProvider { List Tags { get; } } public class InfoFeature : Feature { public string ValueText { get; } public InfoFeature(string name, string valueText, string description = "") { base.Name = name; ValueText = valueText; base.Description = description; } } public sealed class MenuSidePanel { public string Title { get; } public string Subtitle { get; } public List Rows { get; } public Texture PreviewTexture { get; } public List Tags { get; } public MenuSidePanel(string title, string subtitle, List rows, Texture previewTexture = null, List tags = null) { Title = title; Subtitle = subtitle; Rows = rows ?? new List(); PreviewTexture = previewTexture; Tags = tags ?? new List(); base..ctor(); } } public sealed class MenuTag { public string Text { get; } = text ?? string.Empty; public Color Color { get; } public MenuTag(string text, Color color) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) Color = color; base..ctor(); } } public class SeparatorFeature : Feature { public SeparatorFeature() { base.Name = string.Empty; base.Description = string.Empty; } } public class SubmenuFeature : Feature, IMenuTagProvider { public string ChildCategory { get; } public List Tags { get; } public SubmenuFeature(string name, string childCategory, string description = "", List tags = null) { base.Name = name; ChildCategory = childCategory; base.Description = (string.IsNullOrEmpty(description) ? ("Open the " + name + " menu.") : description); Tags = tags ?? new List(); } } public abstract class NumberBoolFeature : NumberFeature { public virtual string GetStateText() { if (!base.Enabled) { return "X"; } return "✓"; } } public abstract class NumberFeature : Feature { public float Min { get; protected set; } public float Max { get; protected set; } public float Value { get; protected set; } public string Unit { get; protected set; } public int Decimals { get; protected set; } public float Step { get; protected set; } public virtual bool AllowTextInput => true; protected NumberFeature() { Min = 0f; Max = 10f; Value = 1f; Unit = string.Empty; Decimals = 1; Step = 0.1f; } public virtual string GetDisplayValue() { return Value.ToString("F" + Mathf.Max(0, Decimals)) + Unit; } public void Adjust(int direction) { float num = (Mathf.Approximately(Step, 0f) ? 0.1f : Mathf.Abs(Step)); SetValue(Value + num * (float)direction); } public void SetValue(float value) { float num = Mathf.Clamp(value, Min, Max); if (Decimals >= 0) { float num2 = Mathf.Pow(10f, (float)Decimals); num = Mathf.Round(num * num2) / num2; } if (!Mathf.Approximately(num, Value)) { Value = num; OnValueChanged(Value); ConfigService.MarkDirty(); } } protected virtual void OnValueChanged(float newValue) { } } public abstract class TextFeature : Feature { public string Value { get; private set; } = string.Empty; public int MaxLength { get; protected set; } = 64; public string EmptyDisplayText { get; protected set; } = "None"; public virtual bool RefreshRowsWhileEditing => false; public virtual string GetDisplayValue() { if (!string.IsNullOrEmpty(Value)) { return Value; } return EmptyDisplayText; } public void SetText(string text) { if (text == null) { text = string.Empty; } if (MaxLength > 0 && text.Length > MaxLength) { text = text.Substring(0, MaxLength); } if (!(Value == text)) { Value = text; OnTextChanged(Value); } } protected virtual void OnTextChanged(string newValue) { } } }