using System; using System.CodeDom.Compiler; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.IO.Compression; using System.Linq; using System.Net.WebSockets; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Cryptography; using System.Security.Permissions; using System.Text; using System.Threading; using System.Threading.Tasks; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using FFSPeak; using FFSPeak.CameraSystem; using FFSPeak.Items; using FFSPeak.Network; using FFSPeak.Patches; using FFSPeak.PlayerState; using FFSPeak.PlayerState.Mobs; using FFSPeak.Protocol.Protobuf; using FFSPeak.RemotePlayers; using FFSPeak.RemotePlayers.Mobs; using FFSPeak.UI; using FFSPeak.UI.AdminCommand; using FFSPeak.UI.AdminCommand.Buttons; using FFSPeak.UI.AdminConsole; using FFSPeak.UI.AdminMessage; using FFSPeak.UI.EventFeed; using FFSPeak.UI.Toolbox; using FFSPeak.Utils; using Google.Protobuf; using Google.Protobuf.Collections; using Google.Protobuf.Reflection; using HarmonyLib; using ItemSpawnSync; using ItemSpawnSync.Data; using ItemSpawnSync.Patches; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Newtonsoft.Json.Serialization; using PEAKLib.UI; using PEAKLib.UI.Elements; using Peak.Afflictions; using Photon.Pun; using Photon.Realtime; using Photon.Voice.PUN; using Photon.Voice.Unity; using TMPro; using Unity.Mathematics; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.InputSystem; using UnityEngine.SceneManagement; using UnityEngine.UI; using UnityEngine.UIElements; using Zorro.Core; using Zorro.Settings; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("com.github.flonou.FFSPeak")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.9.1.0")] [assembly: AssemblyInformationalVersion("0.9.1+6438b3476f6a99e558599112683b6378c6297ecf")] [assembly: AssemblyProduct("com.github.flonou.FFSPeak")] [assembly: AssemblyTitle("FFSPeak")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.9.1.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] internal sealed class RequiresLocationAttribute : Attribute { } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } public class DisableItems { public static void Disable(List itemsToDisable) { if (itemsToDisable.Count == 0) { Plugin.Logger.LogMessage((object)"No GameObjects configured to be disabled."); return; } int num = 0; foreach (string item in itemsToDisable) { Item[] array = FindItemsByName(item); Item[] array2 = array; foreach (Item val in array2) { ((Component)val).gameObject.SetActive(false); num++; Plugin.Logger.LogInfo((object)("Disabled GameObject: " + ((Object)val).name)); } } Plugin.Logger.LogMessage((object)$"Successfully disabled {num} GameObject(s)."); } public static void DisableBackpacksPhysics() { Item[] array = (Item[])(object)Object.FindObjectsByType((FindObjectsInactive)1, (FindObjectsSortMode)0); Item[] array2 = array; if (Plugin.IsObserver) { for (int i = 1; i < array2.Length; i++) { array2[0].rig.detectCollisions = false; array2[0].rig.isKinematic = true; } } } public static Item[] FindItemsByName(string name) { return (from obj in Resources.FindObjectsOfTypeAll() where ((Object)obj).name == name select obj).ToArray(); } public static void RunDisableLogic() { Plugin.Logger.LogMessage((object)"Running DisableItems logic"); Disable(new List { "Guidebook(Clone)", "Frisbee(Clone)", "BingBong(Clone)", "Shell Big(Clone)", "Flare(Clone)", "Bugle(Clone)", "Compass(Clone)", "GuidebookPageScroll(Clone)", "GuidebookPageScroll Variant(Clone)", "Binoculars(Clone)" }); DisableBackpacksPhysics(); Object.FindObjectsByType((FindObjectsInactive)1, (FindObjectsSortMode)0).ToList().ForEach(delegate(TornadoSpawner val) { ((Component)val).gameObject.SetActive(false); }); List source = new List { "Dynamite" }; PropSpawner[] array = Object.FindObjectsByType((FindObjectsInactive)1, (FindObjectsSortMode)0); foreach (PropSpawner spawner in array) { if (source.Any((string name) => ((Object)spawner).name.StartsWith(name))) { ((Component)spawner).gameObject.SetActive(false); Plugin.Logger.LogInfo((object)("Disabled GameObject: " + ((Object)spawner).name)); } } _ = Plugin.IsObserver; } public static void DisableLavaRiversOutsideCaldera() { //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Expected O, but got Unknown //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Expected O, but got Unknown //IL_00a5: 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) Biome[] array = Object.FindObjectsByType((FindObjectsInactive)0, (FindObjectsSortMode)0); foreach (Biome val in array) { if (!((Object)val).name.StartsWith("Volcano")) { continue; } for (int j = 0; j < ((Component)val).transform.childCount; j++) { Transform child = ((Component)val).transform.GetChild(j); if (!((Object)child).name.StartsWith("Caldera")) { continue; } foreach (Transform item in child) { Transform val2 = item; if (!((Object)val2).name.StartsWith("LavaRivers")) { continue; } foreach (Transform item2 in val2) { Transform val3 = item2; if (((Component)val3).transform.position.z > 1850f || ((Component)val3).transform.position.y > 1150f) { ((Component)val3).gameObject.SetActive(false); Plugin.Logger.LogMessage((object)("Disabled GameObject: " + ((Object)val3).name + " in biome " + ((Object)val).name)); } } Plugin.Logger.LogMessage((object)("Disabled GameObject: " + ((Object)val2).name + " in biome " + ((Object)val).name)); } } } } } [Serializable] public class ResumeDTO : BaseDTO { public new string LobbyCode; public FFSPeak.Network.PlayerStateDTO PlayerState; public PlayerCustomizationDTO Customization; public JToken Items; public ResumeDTO(string playerName, string lobbyCode, FFSPeak.Network.PlayerStateDTO playerState, PlayerCustomizationDTO customization, JToken items) { PlayerName = playerName; LobbyCode = lobbyCode; PlayerState = playerState; Customization = customization; Items = items; } } [DefaultExecutionOrder(99999)] public class RemotePlayerRope : MonoBehaviour { private RopeBoneVisualizer ropeBoneVisualizer; private RopeSyncDTO ropeSyncLast; public Rope Rope { get; set; } public void HandleRopeSync(RopeSyncDTO ropeSync) { ropeSyncLast = ropeSync; UpdateRopeFromSync(); } public void Initialize(Rope ropeComponent, RopeAnchor ropeAnchor, int segmentCount) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) Rope = ropeComponent; Rope.creatorLeft = false; Rope.Segments = segmentCount; Rope.attachmenState = (ATTACHMENT)2; ropeBoneVisualizer = ((Component)this).GetComponentInChildren(); ropeBoneVisualizer.StartTransform = ((Component)ropeAnchor.anchorPoint).transform; RemotePlayer.ViewIsMineProperty.SetValue(((MonoBehaviourPun)Rope).photonView, false); } public void UpdateRopeFromSync() { //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) if (ropeSyncLast == null) { Plugin.Logger.LogWarning((object)"UpdateRopeFromSync: ropeSyncLast is null"); return; } RopeSyncData syncData = ropeSyncLast.ToRopeSyncData(); Rope.SetSyncData(syncData); } } namespace BepInEx { [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] [Conditional("CodeGeneration")] internal sealed class BepInAutoPluginAttribute : Attribute { public BepInAutoPluginAttribute(string? id = null, string? name = null, string? version = null) { } } } namespace BepInEx.Preloader.Core.Patching { [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] [Conditional("CodeGeneration")] internal sealed class PatcherAutoPluginAttribute : Attribute { public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null) { } } } namespace FFSPeak { public class CampfireManager : Singleton { private List campfireComponents = new List(); private List campfires = new List(); private string lastSentCheckpointHash; private GameObject newCampfire; public int GetCampfireIndex(Campfire campfire) { //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_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_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_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_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) int num = campfireComponents.IndexOf(campfire); if (num >= 0) { return num; } Vector3 position = ((Component)campfire).transform.position; float num2 = float.MaxValue; int result = -1; for (int i = 0; i < campfires.Count; i++) { if (!((Object)(object)campfires[i] == (Object)null)) { Vector3 val = campfires[i].position - position; float num3 = val.y * val.y + val.z * val.z; if (num3 < num2) { num2 = num3; result = i; } } } if (num2 < 5f) { return result; } Plugin.Logger.LogWarning((object)("GetCampfireIndex: '" + ((Object)campfire).name + "' not found and no nearby campfire within threshold. Returning -1.")); return -1; } public IEnumerable GetCampfires() { if (campfires.Count == 0 && (Object)(object)Singleton.Instance != (Object)null) { UpdateCampfires(); } return campfires; } public void UpdateCampfires() { //IL_0132: 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) campfires.Clear(); campfireComponents.Clear(); MapHandler val = Singleton.Instance; foreach (MapSegment item in val.segments.Where((MapSegment s) => (Object)(object)s.segmentCampfire != (Object)null)) { Campfire componentInChildren = item.segmentCampfire.GetComponentInChildren(); campfires.Add(((Component)componentInChildren).transform); campfireComponents.Add(componentInChildren); } Campfire val2 = campfireComponents[0]; campfires.Insert(0, ((Component)SpawnPoint.allSpawnPoints[0]).transform); campfireComponents.Insert(0, null); GameObject val3 = GameObject.Find("Flag_planted_seagull"); if ((Object)(object)val3 != (Object)null) { if ((Object)(object)newCampfire == (Object)null) { newCampfire = PhotonCloneUtils.CloneWithPhoton(((Component)val2).gameObject, val3.transform); if ((Object)(object)newCampfire == (Object)null) { Plugin.Logger.LogWarning((object)"Failed to clone campfire with Photon"); return; } newCampfire.transform.localPosition = Vector3.zero; newCampfire.transform.localRotation = Quaternion.identity; } Campfire componentInChildren2 = newCampfire.GetComponentInChildren(); campfires.Add(((Component)componentInChildren2).transform); campfireComponents.Add(componentInChildren2); } else { campfires.Add(Singleton.Instance.progressPoints.Last().transform); campfireComponents.Add(null); } Plugin.Logger.LogInfo((object)string.Format("Updated campfires: {0}. Total campfires: {1}", string.Join(", ", campfires.Select((Transform c) => ((Object)c).name)), campfires.Count)); SendCheckpointPositionsIfChanged(); } private void SendCheckpointPositionsIfChanged() { try { CheckpointPositionsDTO.CheckpointEntry[] array = campfires.Select((Transform t, int i) => new CheckpointPositionsDTO.CheckpointEntry { Index = i, Position = (((Object)(object)t != (Object)null) ? t.position : Vector3.zero) }).ToArray(); string text = string.Join("|", array.Select((CheckpointPositionsDTO.CheckpointEntry e) => $"{Mathf.RoundToInt(e.Position.x)},{Mathf.RoundToInt(e.Position.y)},{Mathf.RoundToInt(e.Position.z)}")).GetHashCode().ToString("X8"); if (!(text == lastSentCheckpointHash)) { lastSentCheckpointHash = text; CheckpointPositionsDTO dto = new CheckpointPositionsDTO { Checkpoints = array, Hash = text }; if (Plugin.IsPlayer) { PlayerNetworkManager.SendCheckpointPositions(dto); } if (Plugin.IsObserver) { NetworkManager.ObserverNetworkManager?.SendCheckpointPositions(dto); } Plugin.Logger.LogMessage((object)$"Sent {array.Length} checkpoint positions to server (hash: {text})"); } } catch (Exception ex) { Plugin.Logger.LogWarning((object)("Failed to send checkpoint positions: " + ex.Message)); } } } public class InputManager : Singleton { public static bool IsFrozen = false; public static bool InputsEnabled = true; public static bool PlayersInputsEnabled = true; public static bool ShouldBeInvincible; protected bool willFreeze; protected Dictionary originalBodypartPositions = new Dictionary(); public void Freeze() { IsFrozen = true; originalBodypartPositions.Clear(); willFreeze = true; DisableInputs(); } public void Unfreeze() { IsFrozen = false; willFreeze = false; originalBodypartPositions.Clear(); if ((Object)(object)Character.localCharacter != (Object)null && (Object)(object)Character.localCharacter.refs.ragdoll != (Object)null && Character.localCharacter.refs.ragdoll.rigidbodies != null) { Character.localCharacter.refs.ragdoll.ToggleKinematic(false); } EnableInputs(); } public void DisableInputs() { InputsEnabled = false; PlayersInputsEnabled = false; if (Plugin.IsPlayer) { ShouldBeInvincible = true; ((MonoBehaviour)this).StartCoroutine(EnableInvincibility()); } Singleton.Instance.Show(); Plugin.Logger.LogMessage((object)"Inputs Disabled"); } public void DisableInputsTemporarily(float duration) { DisableInputs(); ((MonoBehaviour)this).Invoke("EnableInputs", duration); } public void ToggleInvincibility(bool enabled) { if (Plugin.IsPlayer) { if (enabled) { ShouldBeInvincible = true; ((MonoBehaviour)this).StartCoroutine(EnableInvincibility()); } else { ShouldBeInvincible = false; ((MonoBehaviour)this).StopCoroutine(EnableInvincibility()); } } } public void EnableInputs() { InputsEnabled = true; PlayersInputsEnabled = true; ShouldBeInvincible = false; ((MonoBehaviour)this).StopCoroutine(EnableInvincibility()); Singleton.Instance.Hide(); Plugin.Logger.LogMessage((object)"Inputs Enabled"); } public static void FreezePlayers() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) Singleton.Instance?.ShowMessage(new SimpleEventMessage("Freezing players!", Color.red, 2f)); NetworkManager.ObserverNetworkManager?.SendAdminCommand("broadcast_message", new BroadcastMessageDTO { Message = "Freezing players!", Color = "#FF0000", Lifetime = 2f }); Plugin.Logger.LogMessage((object)"Sending freeze command"); int value = Singleton.Instance.LoadedLevelIndex.Value; NetworkManager.ObserverNetworkManager?.SendAdminCommand("load_level", new LoadLevelDTO { LevelIndex = value, Freeze = true }); Singleton.Instance.PlayersFrozen = true; } public void SetAfflictions() { //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_004e: Expected O, but got Unknown //IL_0077: 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_008d: Expected O, but got Unknown if (ShouldBeInvincible && FFSPeak.PlayerState.PlayerState.IsInitialized) { Affliction val = default(Affliction); if (!Character.localCharacter.refs.afflictions.HasAfflictionType((AfflictionType)16, ref val)) { Character.localCharacter.refs.afflictions.AddAffliction((Affliction)new Affliction_Invincibility { totalTime = 0.5f }, false); } if (!Character.localCharacter.refs.afflictions.HasAfflictionType((AfflictionType)21, ref val)) { Character.localCharacter.refs.afflictions.AddAffliction((Affliction)new Affliction_NoHunger { totalTime = 0.5f }, false); } } } public static IEnumerator UnfreezeCountdown() { for (int i = 5; i >= 1; i--) { string message = $"Unfreezing in {i}..."; Singleton.Instance?.ShowMessage(new SimpleEventMessage(message, Color.yellow, 1f)); NetworkManager.ObserverNetworkManager?.SendAdminCommand("broadcast_message", new BroadcastMessageDTO { Message = message, Color = "#FFFF00", Lifetime = 1f }); Plugin.Logger.LogMessage((object)$"Countdown: {i}"); yield return (object)new WaitForSeconds(1f); } Singleton.Instance?.ShowMessage(new SimpleEventMessage("Unfreezing players!", Color.green, 2f)); NetworkManager.ObserverNetworkManager?.SendAdminCommand("broadcast_message", new BroadcastMessageDTO { Message = "Unfreezing players!", Color = "#00FF00", Lifetime = 2f }); Plugin.Logger.LogMessage((object)"Sending unfreeze command"); int value = Singleton.Instance.LoadedLevelIndex.Value; NetworkManager.ObserverNetworkManager?.SendAdminCommand("load_level", new LoadLevelDTO { LevelIndex = value, Freeze = false }); Singleton.Instance.PlayersFrozen = false; } public void Update() { if (Plugin.IsPlayer && ShouldBeInvincible) { SetAfflictions(); } } public void FixedUpdate() { //IL_0158: 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_0168: 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_00ca: 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_00ed: Unknown result type (might be due to invalid IL or missing references) if (!Plugin.IsPlayer || !Plugin.IsOnMapScene || !IsFrozen || !(Time.timeSinceLevelLoad > 15f)) { return; } if (willFreeze) { Plugin.Logger.LogMessage((object)"Freezing player character"); if (!((Object)(object)Character.localCharacter != (Object)null) || !((Object)(object)Character.localCharacter.refs.ragdoll != (Object)null) || Character.localCharacter.refs.ragdoll.rigidbodies == null) { return; } Character.localCharacter.refs.ragdoll.ToggleKinematic(true); foreach (Bodypart part in Character.localCharacter.refs.ragdoll.partList) { if (!originalBodypartPositions.ContainsKey(part.partType)) { originalBodypartPositions[part.partType] = ((Component)part.rig).transform.position; } } willFreeze = false; return; } Character.localCharacter.refs.ragdoll.ToggleKinematic(true); foreach (Bodypart part2 in Character.localCharacter.refs.ragdoll.partList) { if (originalBodypartPositions.TryGetValue(part2.partType, out var value) && value != Vector3.zero) { ((Component)part2.rig).transform.position = value; } } } protected override void Initialize() { Plugin.Logger.LogMessage((object)"InputManager initialized"); } private IEnumerator EnableInvincibility() { ShouldBeInvincible = true; yield return (object)new WaitUntil((Func)(() => FFSPeak.PlayerState.PlayerState.IsInitialized)); SetAfflictions(); Plugin.Logger.LogMessage((object)"Invincibility Enabled"); } } [BepInProcess("PEAK.exe")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInPlugin("com.github.flonou.FFSPeak", "FFSPeak", "0.9.1")] public class Plugin : BaseUnityPlugin { private ConfigEntry autoLoadItems; private ConfigEntry autoOpenLuggages; private readonly Harmony harmony = new Harmony("com.zerator.ffspeak"); private ConfigEntry isObserver; private ConfigEntry isPlayer; private ConfigEntry loadFromFile; private ConfigEntry saveSpawnDataToLocalFile; private ConfigEntry lobbyCode; private string observerKey; private ConfigEntry observerKeyFile; private ConfigEntry serverUrl; private ConfigEntry autoOpenAdminConsole; private ConfigEntry adminConsoleShortcut; private ConfigEntry scoreLoggingEnabled; private ConfigEntry scoreLoggingFolderPath; private ConfigEntry scoreLoggingInterval; public const string Id = "com.github.flonou.FFSPeak"; public static bool AutoOpenLuggages => Instance.autoOpenLuggages.Value; public static AssetBundle FfsPeakAssets { get; private set; } public static Plugin Instance { get; private set; } public static bool IsInLobby { get; private set; } = false; public static bool IsObserver => Instance.isObserver.Value; public static bool IsOnMapScene { get; private set; } = false; public static bool IsPlayer => Instance.isPlayer.Value; public static int? LevelToLoad { get; set; } = null; public static bool LoadingLevel { get; set; } = false; public static string LobbyCode { get; set; } = "000000"; public static int? LobbyPlayerLimit { get; set; } = null; public static bool ShouldLoadItems { get { if (Instance.autoLoadItems.Value) { return LoadItemsOnNextMapLoad; } return false; } } public static bool LoadItemsOnNextMapLoad { get; set; } = true; public static bool ScoreLoggingEnabled => Instance.scoreLoggingEnabled.Value; public static string ScoreLoggingFolderPath => Instance.scoreLoggingFolderPath.Value; public static float ScoreLoggingInterval => Instance.scoreLoggingInterval.Value; public static string LocalPlayerName { get; private set; } = "UnknownPlayer" + Guid.NewGuid().ToString().Substring(0, 10); public static ManualLogSource Logger { get; set; } public static bool MapSceneReady { get; set; } = false; public static string SceneName { get; private set; } = null; public static bool AutoOpenAdminConsole => Instance.autoOpenAdminConsole.Value; public string ServerUrl => serverUrl.Value; public static string Name => "FFSPeak"; public static string Version => "0.9.1"; public static event Action LevelLoaded; private static string TryGetArgValue(string[] args, params string[] names) { if (args == null || args.Length == 0 || names == null || names.Length == 0) { return null; } for (int i = 0; i < args.Length; i++) { string text = args[i]; if (string.IsNullOrEmpty(text)) { continue; } foreach (string text2 in names) { if (!string.IsNullOrEmpty(text2)) { if (string.Equals(text, text2, StringComparison.OrdinalIgnoreCase) && i + 1 < args.Length) { return args[i + 1]; } string text3 = text2 + "="; if (text.StartsWith(text3, StringComparison.OrdinalIgnoreCase)) { return text.Substring(text3.Length); } } } } return null; } public static string GetMapName() { //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 (SceneName != null) { return SceneName; } for (int i = 0; i < SceneManager.sceneCount; i++) { Scene sceneAt = SceneManager.GetSceneAt(i); if (((Scene)(ref sceneAt)).name.Contains("Level_")) { SceneName = ((Scene)(ref sceneAt)).name; return ((Scene)(ref sceneAt)).name; } } return null; } public static void HandleLoadLevel(int levelIndex = -1, int? playerLimit = 50) { Logger.LogMessage((object)$"Received load level command from server: levelIndex={levelIndex}, playerLimit={playerLimit}"); LevelToLoad = levelIndex; LobbyPlayerLimit = playerLimit; if (levelIndex < 0) { Logger.LogMessage((object)"Level load cleared by server"); LevelToLoad = null; } else if (IsInLobby && !LoadingLevel) { LoadingLevel = true; ((MonoBehaviour)Instance).StartCoroutine(AutoStartGameInAirport(levelIndex)); if (IsObserver) { Singleton.Instance.LoadedLevelIndex = levelIndex; } } } public static IEnumerator TryCapturePlayerName() { while (PhotonNetwork.LocalPlayer == null || string.IsNullOrEmpty(PhotonNetwork.LocalPlayer.NickName)) { yield return null; } try { LocalPlayerName = PhotonNetwork.LocalPlayer.NickName; if (IsObserver && !IsPlayer) { LocalPlayerName += "_Obs"; } Logger.LogMessage((object)("Captured player name from Photon: " + LocalPlayerName)); } catch (Exception ex) { Logger.LogWarning((object)("Error capturing player name: " + ex.Message)); } } public void Update() { //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_009c: 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_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) if (Input.GetKeyDown((KeyCode)289)) { Singleton.Instance.ToggleShow(); } if (!IsObserver) { return; } if (Input.GetKeyDown((KeyCode)284)) { Singleton.Instance.Toggle(); } if (Input.GetKeyDown((KeyCode)285)) { Singleton.Instance.Toggle(); } if (Input.GetKeyDown((KeyCode)290)) { Singleton.Instance.Toggle(); } if (Input.GetKeyDown((KeyCode)291)) { Singleton.Instance.ToggleDisplay(); } if (Input.GetKeyDown((KeyCode)292)) { Singleton.Instance.ToggleDisplay(); } KeyboardShortcut value = adminConsoleShortcut.Value; if (Input.GetKeyDown(((KeyboardShortcut)(ref value)).MainKey)) { value = adminConsoleShortcut.Value; if (((KeyboardShortcut)(ref value)).Modifiers != null) { value = adminConsoleShortcut.Value; if (!((KeyboardShortcut)(ref value)).Modifiers.All((KeyCode m) => Input.GetKey(m))) { goto IL_0100; } } Singleton.Instance.Toggle(); } goto IL_0100; IL_0100: if (Input.GetKeyDown((KeyCode)115) && Input.GetKey((KeyCode)306)) { scoreLoggingEnabled.Value = !scoreLoggingEnabled.Value; if (scoreLoggingEnabled.Value) { Singleton.Instance.LogScores(); } } } protected void Awake() { //IL_0166: Unknown result type (might be due to invalid IL or missing references) Instance = this; Logger = ((BaseUnityPlugin)this).Logger; isObserver = ((BaseUnityPlugin)this).Config.Bind("General", "IsObserver", false, "Should this instance act as an observer?"); isPlayer = ((BaseUnityPlugin)this).Config.Bind("General", "IsPlayer", true, "Should this instance act as a player?"); serverUrl = ((BaseUnityPlugin)this).Config.Bind("General", "ServerUrl", "ws://localhost:4000", "The WebSocket server URL to connect to."); lobbyCode = ((BaseUnityPlugin)this).Config.Bind("General", "LobbyCode", "000000", "Lobby code (6 chars A-Z0-9) used to isolate instances. Same code = same lobby."); autoLoadItems = ((BaseUnityPlugin)this).Config.Bind("Items", "AutoLoadItems", true, "Should automatically load items when joining a map?"); loadFromFile = ((BaseUnityPlugin)this).Config.Bind("Items", "LoadFromFile", true, "Load item data from files"); saveSpawnDataToLocalFile = ((BaseUnityPlugin)this).Config.Bind("Items", "SaveSpawnDataToLocalFile", true, "Save spawn data to local file when saving through the shortcut"); autoOpenLuggages = ((BaseUnityPlugin)this).Config.Bind("AdminCommands", "AutoOpenLuggages", false, "Automatically open all luggages for observers when a level is loaded (for easier spectating)"); autoOpenAdminConsole = ((BaseUnityPlugin)this).Config.Bind("AdminCommands", "AutoOpenAdminConsole", false, "Automatically open the admin console when the game starts"); adminConsoleShortcut = ((BaseUnityPlugin)this).Config.Bind("AdminCommands", "AdminConsoleShortcut", new KeyboardShortcut((KeyCode)282, (KeyCode[])(object)new KeyCode[1] { (KeyCode)306 }), "Keyboard shortcut to open the admin console"); scoreLoggingEnabled = ((BaseUnityPlugin)this).Config.Bind("ScoreLogging", "ScoreLoggingEnabled", false, "Enable score logging to a file"); scoreLoggingFolderPath = ((BaseUnityPlugin)this).Config.Bind("ScoreLogging", "ScoreLoggingFolderPath", "Scores", "File path for score logging (relative to the peak application)"); scoreLoggingInterval = ((BaseUnityPlugin)this).Config.Bind("ScoreLogging", "ScoreLoggingInterval", 5f, "Interval in seconds for logging scores to the file"); string[] commandLineArgs = Environment.GetCommandLineArgs(); if (commandLineArgs.Contains("-observer")) { isObserver.Value = true; isPlayer.Value = false; } if (commandLineArgs.Contains("-player")) { isPlayer.Value = true; isObserver.Value = false; } string text = TryGetArgValue(commandLineArgs, "-serverurl", "--server-url", "--serverurl", "-url", "--url"); if (!string.IsNullOrWhiteSpace(text)) { serverUrl.Value = text.Trim(); Logger.LogMessage((object)("Overriding server URL from command line: " + serverUrl.Value)); } string text2 = TryGetArgValue(commandLineArgs, "-port", "--port", "-wsport", "--ws-port", "--wsport"); if (!string.IsNullOrWhiteSpace(text2)) { if (int.TryParse(text2, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result) && result > 0 && result <= 65535) { try { Uri uri = new Uri(serverUrl.Value); UriBuilder uriBuilder = new UriBuilder(uri) { Port = result }; serverUrl.Value = uriBuilder.Uri.ToString().TrimEnd('/'); Logger.LogMessage((object)$"Overriding server port from command line: {result} -> {serverUrl.Value}"); } catch (Exception ex) { Logger.LogWarning((object)("Could not apply command line port override '" + text2 + "' to server URL '" + serverUrl.Value + "': " + ex.Message)); } } else { Logger.LogWarning((object)("Ignoring invalid port value from command line: '" + text2 + "'")); } } Logger.LogMessage((object)("Plugin " + Name + " is loaded!")); Logger.LogMessage((object)$"Network Mode - Player: {IsPlayer}, Observer: {IsObserver}"); harmony.PatchAll(Assembly.GetExecutingAssembly()); ItemActionBase_RunAction_Patch.ApplyPatches(harmony); ModChecker.Check(); ((MonoBehaviour)this).StartCoroutine(AutoLoadItems.LoadItemsFromFiles()); SceneManager.sceneLoaded += OnSceneLoaded; SceneManager.sceneUnloaded += OnSceneUnloaded; LobbyCode = lobbyCode.Value; observerKeyFile = ((BaseUnityPlugin)this).Config.Bind("General", "ObserverKeyFile", "observer_key.txt", "Filename for the observer key (relative to config/FFSPeak/)"); if (IsObserver) { string path = Path.Combine(Paths.ConfigPath, "FFSPeak"); string text3 = observerKeyFile.Value; if (!Path.IsPathRooted(text3)) { text3 = Path.Combine(path, text3); } if (File.Exists(text3)) { observerKey = File.ReadAllText(text3).Trim(); Logger.LogMessage((object)("Loaded observer key from " + text3)); } else { Logger.LogWarning((object)("Observer key file not found: " + text3)); } if (scoreLoggingEnabled.Value) { Singleton.Instance.LogScores(); } } if (IsPlayer) { ModChecker.StartCheckAsync(); } if (IsObserver) { SpawnerSpawnItemsPatch.OnItemsSpawned += delegate(List photonViews) { foreach (PhotonView photonView in photonViews) { Item component = ((Component)photonView).GetComponent(); if ((Object)(object)component.rig != (Object)null) { component.rig.isKinematic = true; ((Behaviour)component).enabled = false; Logger.LogInfo((object)("Set item " + ((Object)component).name + " to kinematic for observer and disabled item script.")); } } }; } string text4 = Path.Combine(Paths.PluginPath, "FFSPeak", "ffspeak_assets.bundle"); FfsPeakAssets = AssetBundle.LoadFromFile(text4); Logger.LogMessage((object)$"Loaded asset bundle with name [ffspeak_assets.bundle]: success={(Object)(object)FfsPeakAssets != (Object)null}"); string[] allAssetNames = FfsPeakAssets.GetAllAssetNames(); Logger.LogMessage((object)("Assets in bundle: " + string.Join(", ", allAssetNames))); if (saveSpawnDataToLocalFile.Value) { Plugin.Instance.OnSpawnDataSaved += delegate(string text6) { string text5 = Path.GetFileName(text6); if (text5.StartsWith("Level_")) { int num = text5.IndexOf('_', 6); if (num > 0) { text5 = text5.Substring(0, num) + ".json"; } } else { text5 = Path.GetFileNameWithoutExtension(text5) + ".json"; } string text7 = Path.Combine(Paths.ConfigPath, "FFSPeak", text5); File.Copy(text6, text7, overwrite: true); Logger.LogMessage((object)("Copied spawn data file to " + text7)); ((MonoBehaviour)this).StartCoroutine(AutoLoadItems.LoadItemsFromFiles()); }; } if ((Object)(object)RemoteMessageHandler.Instance == (Object)null) { ((Component)this).gameObject.AddComponent(); } } private static IEnumerator AutoStartGameInAirport(int levelIndex) { yield return null; try { Logger.LogMessage((object)$"Auto-starting game with level index: {levelIndex} with {LobbyPlayerLimit} player limit"); while (LoadingScreenHandler.loading) { yield return null; } AirportCheckInKiosk kiosk = null; while ((Object)(object)kiosk == (Object)null) { kiosk = Object.FindFirstObjectByType(); if ((Object)(object)kiosk == (Object)null) { yield return null; } } yield return null; string level = SingletonAsset.Instance.GetLevel((levelIndex >= 0) ? levelIndex : Ascents.currentAscent); RunSettings.Init(); byte[] serializedRunSettings = RunSettings.GetSerializedRunSettings(); Logger.LogMessage((object)("Starting game with level parameter: " + level)); ((MonoBehaviourPun)kiosk).photonView.RPC("BeginIslandLoadRPC", (RpcTarget)0, new object[3] { level, 0, serializedRunSettings }); } finally { LoadingLevel = false; } } public static void ReturnToAirport() { Logger.LogMessage((object)"Returning to airport..."); Player.LeaveCurrentGame(); } private IEnumerator InitializeNetworkManager() { NetworkConnector connector = null; while ((Object)(object)connector == (Object)null) { connector = Object.FindFirstObjectByType(); if ((Object)(object)connector == (Object)null || !((Behaviour)connector).enabled) { connector = null; yield return null; } } yield return null; _ = Singleton.Instance; NetworkManager.Initialize(new NetworkConfig { ServerUrl = ServerUrl, LobbyCode = LobbyCode, EnableNetworking = true, IsPlayer = IsPlayer, IsObserver = IsObserver, TimeoutMs = 5000, ObserverKey = observerKey }); if (IsObserver) { ObserverNetworkManager.WsClient.WsClient.RegisterServerMessageHandler("lobby_join_result", OnLobbyJoined); ObserverNetworkManager.WsClient.WsClient.RegisterServerMessageHandler("message", OnServerMessage); } if (IsPlayer) { PlayerNetworkManager.WsClient.WsClient.RegisterServerMessageHandler("lobby_join_result", OnLobbyJoined); PlayerNetworkManager.WsClient.WsClient.RegisterServerMessageHandler("message", OnServerMessage); } } private void OnServerMessage(ServerMessageDTO dTO) { //IL_003f: Unknown result type (might be due to invalid IL or missing references) Logger.LogMessage((object)("Received server message: subtype=" + dTO.Subtype + ", data=" + dTO.Data)); Singleton.Instance?.ShowMessage(new SimpleEventMessage("Server: " + dTO.Data, Color.cyan, 5f)); } private bool IsSceneLoaded(string nameContains) { //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) for (int i = 0; i < SceneManager.sceneCount; i++) { Scene sceneAt = SceneManager.GetSceneAt(i); if (((Scene)(ref sceneAt)).name.Contains(nameContains)) { return true; } } return false; } private IEnumerator MapSceneLoaded() { while ((Object)(object)RunManager.Instance == (Object)null || RunManager.Instance.timeSinceRunStarted <= 0f) { yield return null; } Singleton.Instance.UpdateCampfires(); Singleton.Instance.Clear(); HeightBarsUIManager.Instance.Reinitialize(); if (IsObserver) { Singleton.Instance.Clear(); Singleton.Instance.SetDisplay(show: true); ((Behaviour)Singleton.Instance).enabled = true; Singleton.Instance.Hide(); Singleton.Instance.Hide(); } if (IsPlayer) { ModChecker.StartCheckAsync(); Singleton.Instance.Hide(); yield return FFSPeak.PlayerState.PlayerState.AddPlayerStateToCharacter(); ((Component)Character.localCharacter).gameObject.AddComponent(); } if (IsPlayer && CheckpointTeleportUI.Enabled) { _ = Singleton.Instance; Singleton.Instance.Refresh(); } FFSPeak.PlayerState.PlayerState.EnableCapturePlayerState = true; Logger.LogMessage((object)"Player state capture enabled on scene load."); if (ShouldLoadItems) { Logger.LogMessage((object)("Auto-loading items for map " + GetMapName())); AutoLoadItems.LoadItems(GetMapName()); } DisableItems.RunDisableLogic(); MapSceneReady = true; if (IsPlayer) { PlayerLeftOrJoinedDTO joined = new PlayerLeftOrJoinedDTO { PlayerName = LocalPlayerName, LevelName = GetMapName(), Joined = true }; PlayerNetworkManager.SendPlayerLeftJoined(joined); } if (IsObserver) { Singleton.Instance.HandleSceneLoaded(); Singleton.Instance.HandleMapLoaded(); Singleton.Instance.SetCurrentLevel(GetMapName()); Singleton.Instance.UpdateDisplay(); _ = Singleton.Instance; if (!NetworkManager.ObserverNetworkManager.IsConnected()) { NetworkManager.ObserverNetworkManager.Connect(); } Lava[] array = Object.FindObjectsByType((FindObjectsInactive)1, (FindObjectsSortMode)0); Lava[] array2 = array; foreach (Lava val in array2) { FieldInfo field = typeof(Lava).GetField("bounds", BindingFlags.Instance | BindingFlags.NonPublic); if (field != null) { Bounds val2 = (Bounds)field.GetValue(val); Logger.LogInfo((object)$"Lava bounds for {((Object)val).name}: center={((Bounds)(ref val2)).center}, size={((Bounds)(ref val2)).size}, extents={((Bounds)(ref val2)).extents}"); } } } Plugin.LevelLoaded?.Invoke(GetMapName()); } private void OnLobbyJoined(ServerMessageDTO dTO) { LobbyCode = dTO.Data; Logger.LogMessage((object)("Joined lobby: " + LobbyCode)); } private void OnSceneLoaded(Scene arg0, LoadSceneMode arg1) { Logger.LogInfo((object)("Loaded scene : [" + ((Scene)(ref arg0)).name + "]")); if (IsSceneLoaded("Title")) { Singleton.Instance.EnableInputs(); ModChecker.Check(); if (ModChecker.UnauthorizedMods.Count > 0) { Singleton.Instance.Show(ModChecker.UnauthorizedMods); } if (IsOnMapScene) { if (IsPlayer) { PlayerLeftOrJoinedDTO joined = new PlayerLeftOrJoinedDTO { PlayerName = LocalPlayerName, LevelName = string.Empty, Joined = false }; PlayerNetworkManager.SendPlayerLeftJoined(joined); ModChecker.StopCheckAsync(); Logger.LogMessage((object)"Sent player left notification to server on returning to main menu."); } PlayerNetworkManager.SendJoinLobby(new JoinLobbyDTO("000000")); } if (IsObserver) { Singleton.Instance.Clear(); Singleton.Instance.SetDisplay(show: false); ((Behaviour)Singleton.Instance).enabled = false; Singleton.Instance.Hide(); Singleton.Instance.Hide(); } } if (IsSceneLoaded("Airport")) { Singleton.Instance.EnableInputs(); SceneName = null; ModChecker.Check(); if (ModChecker.UnauthorizedMods.Count > 0) { return; } IsInLobby = true; _ = Singleton.Instance; _ = Singleton.Instance; ((MonoBehaviour)this).StartCoroutine(TryCapturePlayerName()); ((MonoBehaviour)this).StartCoroutine(InitializeNetworkManager()); HeightBarsUIManager.Instance.Initialize(); VersionString val = Object.FindFirstObjectByType(); if ((Object)(object)val != (Object)null) { ((Behaviour)val).enabled = false; } Singleton.Instance.HandleSceneLoaded(); if (IsObserver) { _ = Singleton.Instance; _ = Singleton.Instance; Singleton.Instance.Show(); Singleton.Instance.ToggleFreeCam(forceEnable: true); LoadItemsOnNextMapLoad = true; } else { Singleton.Instance.Show(); } if (IsOnMapScene && IsObserver && NetworkManager.ObserverNetworkManager.IsConnected()) { NetworkManager.ObserverNetworkManager.Disconnect(); Logger.LogInfo((object)"Remote observer disabled on returning to lobby."); } } else { IsInLobby = false; } if (IsSceneLoaded("Level_")) { if (!IsOnMapScene) { IsOnMapScene = true; ((MonoBehaviour)this).StartCoroutine(MapSceneLoaded()); } } else { IsOnMapScene = false; LoadingLevel = false; } } private void OnSceneUnloaded(Scene arg0) { Logger.LogInfo((object)("Unloaded scene : [" + ((Scene)(ref arg0)).name + "]")); if (!IsSceneLoaded("Level_")) { MapSceneReady = false; IsOnMapScene = false; Singleton.Instance.Hide(); FFSPeak.PlayerState.PlayerState.EnableCapturePlayerState = false; Logger.LogInfo((object)"Player state capture disabled on scene unload."); } if (!IsSceneLoaded("Airport")) { IsInLobby = false; } } } public abstract class Singleton : MonoBehaviour where T : Singleton { private static bool applicationIsQuitting = false; private static T instance; private bool isInitialized; private static readonly object @lock = new object(); public static T Instance { get { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Expected O, but got Unknown if (applicationIsQuitting) { return null; } lock (@lock) { if ((Object)(object)instance == (Object)null) { instance = Object.FindFirstObjectByType(); if ((Object)(object)instance == (Object)null) { GameObject val = new GameObject(typeof(T).Name); instance = val.AddComponent(); Object.DontDestroyOnLoad((Object)(object)val); if (!instance.isInitialized) { instance.Initialize(); instance.isInitialized = true; } } } return instance; } } } protected virtual void Awake() { if ((Object)(object)instance != (Object)null && (Object)(object)instance != (Object)(object)this) { Object.Destroy((Object)(object)((Component)this).gameObject); return; } instance = (T)this; Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject); if ((Object)(object)instance == (Object)(object)this && !isInitialized) { Initialize(); isInitialized = true; } } protected virtual void Initialize() { } protected virtual void OnApplicationQuit() { applicationIsQuitting = true; } protected virtual void OnDestroy() { if ((Object)(object)instance == (Object)(object)this) { instance = null; } } } } namespace FFSPeak.Utils { public static class ModChecker { public static readonly HashSet AuthorizedGuids = new HashSet { "com.github.flonou.FFSPeak", "com.github.flonou.Peak-ItemSpawnSync", "com.github.PEAKModding.PEAKLib.UI", "com.github.PEAKModding.PEAKLib.Core", "com.github.PEAKModding.SoftDependencyFix", "com.snosz.photoncustompropsutils", "com.turtledsr.peakversionbypass", "toastoverflow.EpilepsySafePEAK", "Linkoid.Peak.StableCamera" }; public static readonly HashSet ForbiddenExternalMods = new HashSet { "WeMod", "Wand", "Cheat Engine" }; public static List UnauthorizedExternalModsDetected = new List(); private static bool checkThreadRunning = false; private static Thread checkThread; private static AutoResetEvent checkThreadStopEvent = new AutoResetEvent(initialState: false); public static IReadOnlyList UnauthorizedMods { get; private set; } = Array.Empty(); public static void Check() { Plugin.Logger.LogMessage((object)"Running mod check against allowlist..."); Plugin.Logger.LogMessage((object)("Plugins currently loaded: " + string.Join(", ", Chainloader.PluginInfos.Values.Select((PluginInfo p) => $"{p.Metadata.GUID} v{p.Metadata.Version}")))); UnauthorizedMods = Chainloader.PluginInfos.Values.Where((PluginInfo p) => !AuthorizedGuids.Contains(p.Metadata.GUID)).ToList(); if (UnauthorizedMods.Count > 0) { Plugin.Logger.LogWarning((object)("[ModChecker] Unauthorized mod(s) detected: " + string.Join(", ", UnauthorizedMods.Select((PluginInfo p) => $"{p.Metadata.GUID} v{p.Metadata.Version}")))); } else { Plugin.Logger.LogMessage((object)"[ModChecker] All loaded mods are authorized."); } } public static void StartCheckAsync() { if (!checkThreadRunning) { checkThreadRunning = true; checkThread = new Thread(CheckLoop) { IsBackground = true }; checkThread.Start(); } } public static void StopCheckAsync() { if (checkThreadRunning) { checkThreadRunning = false; checkThreadStopEvent.Set(); try { checkThread.Join(500); } catch { } checkThread = null; } } public static void CheckLoop() { while (checkThreadRunning) { foreach (string forbiddenExternalMod in ForbiddenExternalMods) { if (Process.GetProcessesByName(forbiddenExternalMod).Length != 0) { UnauthorizedModDTO unauthorizedMod = CreateUnauthorizedModDTO(forbiddenExternalMod); PlayerNetworkManager.SendUnauthorizedModDetected(unauthorizedMod); } } checkThreadStopEvent.WaitOne(30000); } } public static UnauthorizedModDTO CreateUnauthorizedModDTO(string modName) { return new UnauthorizedModDTO { PlayerName = Plugin.LocalPlayerName, ModName = modName, LevelName = Plugin.GetMapName() }; } } public class PhotonCloneUtils : MonoBehaviourPun { private static PhotonCloneUtils instance; public static PhotonCloneUtils Instance { get { if ((Object)(object)instance == (Object)null) { if ((Object)(object)GameUtils.instance == (Object)null) { Plugin.Logger.LogWarning((object)"PhotonCloneUtils requires GameUtils.instance to exist"); return null; } GameObject gameObject = ((Component)GameUtils.instance).gameObject; instance = gameObject.GetComponent(); if ((Object)(object)instance == (Object)null) { instance = gameObject.AddComponent(); } } return instance; } } public static GameObject CloneWithPhoton(GameObject source, Transform parent) { if ((Object)(object)source == (Object)null) { Plugin.Logger.LogWarning((object)"CloneWithPhoton called with null source"); return null; } if ((Object)(object)Instance == (Object)null) { return null; } if (!Instance.EnsurePhotonViewValid()) { Plugin.Logger.LogWarning((object)"CloneWithPhoton requires a valid PhotonView on GameUtils (join a room first)"); return null; } return Instance.CloneLocalAndRpc(source, parent); } private GameObject CloneLocalAndRpc(GameObject source, Transform parent) { //IL_00cf: 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) PhotonView component = source.GetComponent(); if ((Object)(object)component == (Object)null) { Plugin.Logger.LogWarning((object)"CloneWithPhoton requires a PhotonView on the source object"); return null; } int viewID = component.ViewID; int num = 0; if ((Object)(object)parent != (Object)null) { PhotonView component2 = ((Component)parent).GetComponent(); if ((Object)(object)component2 != (Object)null) { num = component2.ViewID; } } List photonViewPaths = GetPhotonViewPaths(source.transform); if (photonViewPaths.Count == 0) { Plugin.Logger.LogWarning((object)"CloneWithPhoton found no PhotonViews in source hierarchy"); } int[] array = AllocateViewIds(photonViewPaths.Count); int[] array2 = AllocateViewIds(photonViewPaths.Count); if (!EnsurePhotonViewValid()) { Plugin.Logger.LogWarning((object)"CloneWithPhoton requires a valid PhotonView on GameUtils (join a room first)"); return null; } ((MonoBehaviourPun)this).photonView.RPC("RpcCloneWithPhoton", (RpcTarget)1, new object[7] { viewID, num, source.transform.position, source.transform.rotation, photonViewPaths.ToArray(), array, array2 }); return CloneLocal(source, parent, photonViewPaths, array, array2); } [PunRPC] private void RpcCloneWithPhoton(int sourceViewId, int parentViewId, Vector3 position, Quaternion rotation, string[] viewPaths, int[] originalIds, int[] cloneIds) { //IL_0059: 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) PhotonView val = PhotonView.Find(sourceViewId); if ((Object)(object)val == (Object)null) { Plugin.Logger.LogWarning((object)$"RpcCloneWithPhoton: source PhotonView {sourceViewId} not found"); return; } Transform parent = null; if (parentViewId != 0) { PhotonView val2 = PhotonView.Find(parentViewId); if ((Object)(object)val2 != (Object)null) { parent = ((Component)val2).transform; } } CloneLocal(((Component)val).gameObject, parent, new List(viewPaths), originalIds, cloneIds, position, rotation); } private static GameObject CloneLocal(GameObject source, Transform parent, List viewPaths, int[] originalIds, int[] cloneIds, Vector3? positionOverride = null, Quaternion? rotationOverride = null) { //IL_0031: 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_0036: 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_004a: 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_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) if ((Object)(object)source == (Object)null) { return null; } DisablePhotonViews(source.transform); Vector3 val = (Vector3)(((??)positionOverride) ?? source.transform.position); Quaternion val2 = (Quaternion)(((??)rotationOverride) ?? source.transform.rotation); GameObject val3 = Object.Instantiate(source, val, val2); if ((Object)(object)parent != (Object)null) { val3.transform.SetParent(parent, true); } RecreatePhotonViewsWithIds(source.transform, viewPaths, originalIds); RecreatePhotonViewsWithIds(val3.transform, viewPaths, cloneIds); return val3; } private static void DisablePhotonViews(Transform root) { PhotonView component = ((Component)root).GetComponent(); if ((Object)(object)component != (Object)null) { Plugin.Logger.LogInfo((object)$"Disabling existing PhotonView on root '{((Object)((Component)root).gameObject).name}' with ViewID {component.ViewID}"); component.ViewID = 0; } PhotonView[] componentsInChildren = ((Component)root).GetComponentsInChildren(true); foreach (PhotonView val in componentsInChildren) { Plugin.Logger.LogInfo((object)$"Disabling existing PhotonView on '{((Object)((Component)val).gameObject).name}' with ViewID {val.ViewID}"); val.ViewID = 0; } } private static List GetPhotonViewPaths(Transform root) { PhotonView[] componentsInChildren = ((Component)root).GetComponentsInChildren(true); List list = new List(componentsInChildren.Length); PhotonView[] array = componentsInChildren; foreach (PhotonView val in array) { list.Add(GetRelativePath(root, ((Component)val).transform)); } return list; } private static string GetRelativePath(Transform root, Transform target) { if ((Object)(object)root == (Object)(object)target) { return string.Empty; } List list = new List(); Transform val = target; while ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)root) { list.Add(((Object)val).name); val = val.parent; } if ((Object)(object)val != (Object)(object)root) { return string.Empty; } list.Reverse(); return string.Join("/", list); } private static Transform FindByRelativePath(Transform root, string path) { if (string.IsNullOrEmpty(path)) { return root; } return root.Find(path); } private static void RecreatePhotonViewsWithIds(Transform root, List viewPaths, int[] viewIds) { DisablePhotonViews(root); if (viewIds == null || viewPaths.Count != viewIds.Length) { Plugin.Logger.LogWarning((object)"RecreatePhotonViewsWithIds: invalid mapping payload"); return; } for (int i = 0; i < viewPaths.Count; i++) { Transform val = FindByRelativePath(root, viewPaths[i]); if ((Object)(object)val == (Object)null) { Plugin.Logger.LogWarning((object)("RecreatePhotonViewsWithIds: missing target transform for path '" + viewPaths[i] + "'")); continue; } if (viewIds[i] == 0) { Plugin.Logger.LogWarning((object)("RecreatePhotonViewsWithIds: invalid ViewID for path '" + viewPaths[i] + "'")); continue; } PhotonView component = ((Component)val).gameObject.GetComponent(); component.ViewID = viewIds[i]; Plugin.Logger.LogInfo((object)$"Recreated PhotonView on '{((Object)val).name}' with ViewID {viewIds[i]} at path '{viewPaths[i]}'"); } } private static int[] AllocateViewIds(int count) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected O, but got Unknown int[] array = new int[count]; if (!PhotonNetwork.InRoom) { Plugin.Logger.LogWarning((object)"AllocateViewIds requires PhotonNetwork.InRoom"); return array; } for (int i = 0; i < count; i++) { GameObject val = new GameObject("PhotonViewIdAllocator"); PhotonView val2 = val.AddComponent(); bool flag = PhotonNetwork.AllocateViewID(val2); array[i] = (flag ? val2.ViewID : 0); Object.DestroyImmediate((Object)(object)val); } return array; } private bool EnsurePhotonViewValid() { if ((Object)(object)((MonoBehaviourPun)this).photonView == (Object)null) { return false; } if (PhotonNetwork.InRoom) { return ((MonoBehaviourPun)this).photonView.ViewID != 0; } return false; } } public class ScoreLogger : Singleton { private float lastLogTime; public void LogScores() { if (!Plugin.ScoreLoggingEnabled || !Plugin.IsOnMapScene || (Object)(object)Singleton.Instance == (Object)null || Singleton.Instance.GetAllPlayers().Count() == 0) { return; } string text = Path.Combine(Plugin.ScoreLoggingFolderPath, "FFSPeak"); Directory.CreateDirectory(text); string text2 = Path.Combine(text, $"Scores_{Plugin.GetMapName()}_{DateTime.Now:yyyy-MM-dd_HH-mm-ss}.csv"); using (StreamWriter streamWriter = new StreamWriter(text2)) { streamWriter.WriteLine("Time; Player Name; State; Last Checkpoint; Max Score; Current Score; Finish Time"); foreach (RemotePlayerData allPlayer in Singleton.Instance.GetAllPlayers()) { string text3 = (allPlayer.IsFinished ? "Finished" : (allPlayer.IsDead ? "Dead" : "In Progress")); streamWriter.WriteLine($" {DateTime.Now}; {allPlayer.PlayerName}; {text3}; {allPlayer.LastCheckpoint}; {allPlayer.MaxHeight.ToString(CultureInfo.InvariantCulture)}; {allPlayer.CurrentHeight.ToString(CultureInfo.InvariantCulture)} ; {allPlayer.FinishTime.ToString(CultureInfo.InvariantCulture)}"); } } Plugin.Logger.LogMessage((object)("Scores logged to " + text2)); } public void Update() { if (Plugin.ScoreLoggingEnabled && Plugin.IsOnMapScene && Time.time - lastLogTime >= Plugin.ScoreLoggingInterval) { LogScores(); lastLogTime = Time.time; } } } } namespace FFSPeak.UI { public class CheckpointTeleportUI : Singleton { public static bool Enabled = false; private const KeyCode TOGGLE_KEY = (KeyCode)290; private const float SPAWN_HEIGHT_OFFSET = 1.5f; private static readonly KeyCode[] NumpadKeys; private static readonly FieldInfo IsInvincibleField; private ManualLogSource logger; private GameObject uiRoot; private Transform rowContainer; private readonly List rows = new List(); private TextMeshProUGUI invincibilityStatusText; private bool _isInvincible; private readonly List _checkpoints = new List(); public bool IsVisible { get { if ((Object)(object)uiRoot != (Object)null) { return uiRoot.activeSelf; } return false; } } protected override void Initialize() { logger = Plugin.Logger; BuildUI(); logger.LogMessage((object)string.Format("{0} initialized (toggle: {1})", "CheckpointTeleportUI", (object)(KeyCode)290)); } public void Refresh() { if (Enabled) { RebuildRows(); } } private void Update() { if (!Enabled) { return; } if (Input.GetKeyDown((KeyCode)290)) { Toggle(); } if (!Input.GetKey((KeyCode)306) && !Input.GetKey((KeyCode)305)) { return; } if (Input.GetKeyDown((KeyCode)271)) { ToggleInvincible(); } else { if (_checkpoints.Count == 0) { return; } for (int i = 0; i < NumpadKeys.Length && i < _checkpoints.Count; i++) { if (Input.GetKeyDown(NumpadKeys[i])) { TeleportTo(_checkpoints[i]); break; } } } } public void Show() { if ((Object)(object)uiRoot != (Object)null) { uiRoot.SetActive(true); } } public void Hide() { if ((Object)(object)uiRoot != (Object)null) { uiRoot.SetActive(false); } } public void Toggle() { if (!((Object)(object)uiRoot == (Object)null)) { bool flag = !uiRoot.activeSelf; uiRoot.SetActive(flag); if (flag) { RebuildRows(); } } } private void TeleportTo(Transform 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_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_003c: 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) Character localCharacter = Character.localCharacter; if ((Object)(object)localCharacter == (Object)null) { logger.LogWarning((object)"[CheckpointTeleportUI] Cannot teleport: localCharacter is null."); return; } Vector3 val = target.position + Vector3.up * 1.5f; localCharacter.WarpPlayerRPC(val, true); logger.LogMessage((object)string.Format("[{0}] Teleported to {1} → {2}", "CheckpointTeleportUI", ((Object)target).name, val)); } private void ToggleInvincible() { Character localCharacter = Character.localCharacter; if ((Object)(object)localCharacter == (Object)null || IsInvincibleField == null) { logger.LogWarning((object)"[CheckpointTeleportUI] Cannot toggle invincibility: localCharacter or field is null."); return; } _isInvincible = !_isInvincible; IsInvincibleField.SetValue(localCharacter.data, _isInvincible); UpdateInvincibilityLabel(); logger.LogMessage((object)string.Format("[{0}] Invincibility: {1}", "CheckpointTeleportUI", _isInvincible)); } private void UpdateInvincibilityLabel() { if (!((Object)(object)invincibilityStatusText == (Object)null)) { ((TMP_Text)invincibilityStatusText).text = (_isInvincible ? "[Ctrl+NumEnter] God mode ON" : "[Ctrl+NumEnter] God mode OFF"); } } private void BuildUI() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown //IL_0063: 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_0083: Expected O, but got Unknown //IL_00ac: 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_00d6: 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_0100: 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_0140: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Expected O, but got Unknown //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Expected O, but got Unknown //IL_01fc: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Expected O, but got Unknown //IL_027a: Unknown result type (might be due to invalid IL or missing references) //IL_0291: Unknown result type (might be due to invalid IL or missing references) //IL_0298: Expected O, but got Unknown //IL_0303: Unknown result type (might be due to invalid IL or missing references) //IL_030a: Expected O, but got Unknown //IL_0351: Unknown result type (might be due to invalid IL or missing references) //IL_0360: Unknown result type (might be due to invalid IL or missing references) //IL_0367: Expected O, but got Unknown //IL_03b2: Unknown result type (might be due to invalid IL or missing references) uiRoot = new GameObject("CheckpointTeleportUI"); uiRoot.transform.SetParent(((Component)this).transform, false); Canvas val = uiRoot.AddComponent(); val.renderMode = (RenderMode)0; val.sortingOrder = 200; CanvasScaler val2 = uiRoot.AddComponent(); val2.uiScaleMode = (ScaleMode)1; val2.referenceResolution = new Vector2(1920f, 1080f); val2.matchWidthOrHeight = 0.5f; GameObject val3 = new GameObject("Panel"); val3.transform.SetParent(uiRoot.transform, false); RectTransform val4 = val3.AddComponent(); val4.anchorMin = new Vector2(1f, 1f); val4.anchorMax = new Vector2(1f, 1f); val4.pivot = new Vector2(1f, 1f); val4.anchoredPosition = new Vector2(-20f, -20f); val4.sizeDelta = new Vector2(300f, 0f); Image val5 = val3.AddComponent(); ((Graphic)val5).color = new Color(0f, 0f, 0f, 0.82f); VerticalLayoutGroup val6 = val3.AddComponent(); ((LayoutGroup)val6).padding = new RectOffset(8, 8, 6, 8); ((HorizontalOrVerticalLayoutGroup)val6).spacing = 4f; ((HorizontalOrVerticalLayoutGroup)val6).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)val6).childControlHeight = true; ((HorizontalOrVerticalLayoutGroup)val6).childForceExpandWidth = true; ((HorizontalOrVerticalLayoutGroup)val6).childForceExpandHeight = false; ContentSizeFitter val7 = val3.AddComponent(); val7.verticalFit = (FitMode)2; GameObject val8 = new GameObject("Header"); val8.transform.SetParent(val3.transform, false); HorizontalLayoutGroup val9 = val8.AddComponent(); ((HorizontalOrVerticalLayoutGroup)val9).spacing = 6f; ((LayoutGroup)val9).childAlignment = (TextAnchor)3; ((HorizontalOrVerticalLayoutGroup)val9).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)val9).childControlHeight = true; ((HorizontalOrVerticalLayoutGroup)val9).childForceExpandWidth = false; ((HorizontalOrVerticalLayoutGroup)val9).childForceExpandHeight = false; LayoutElement val10 = val8.AddComponent(); val10.preferredHeight = 22f; GameObject val11 = new GameObject("Title"); val11.transform.SetParent(val8.transform, false); LayoutElement val12 = val11.AddComponent(); val12.flexibleWidth = 1f; TextMeshProUGUI val13 = val11.AddComponent(); ((TMP_Text)val13).text = $"=> Checkpoints [{(object)(KeyCode)290}]"; ((TMP_Text)val13).fontSize = 13f; ((TMP_Text)val13).fontStyle = (FontStyles)1; ((Graphic)val13).color = new Color(0.95f, 0.85f, 0.3f, 1f); ((Graphic)val13).raycastTarget = false; GameObject val14 = new GameObject("Rows"); val14.transform.SetParent(val3.transform, false); VerticalLayoutGroup val15 = val14.AddComponent(); ((HorizontalOrVerticalLayoutGroup)val15).spacing = 3f; ((HorizontalOrVerticalLayoutGroup)val15).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)val15).childControlHeight = true; ((HorizontalOrVerticalLayoutGroup)val15).childForceExpandWidth = true; ((HorizontalOrVerticalLayoutGroup)val15).childForceExpandHeight = false; ContentSizeFitter val16 = val14.AddComponent(); val16.verticalFit = (FitMode)2; rowContainer = val14.transform; GameObject val17 = new GameObject("Divider"); val17.transform.SetParent(val3.transform, false); LayoutElement val18 = val17.AddComponent(); val18.preferredHeight = 1f; Image val19 = val17.AddComponent(); ((Graphic)val19).color = new Color(0.5f, 0.5f, 0.5f, 0.4f); GameObject val20 = new GameObject("InvincibilityRow"); val20.transform.SetParent(val3.transform, false); LayoutElement val21 = val20.AddComponent(); val21.preferredHeight = 20f; invincibilityStatusText = val20.AddComponent(); ((TMP_Text)invincibilityStatusText).fontSize = 11f; ((Graphic)invincibilityStatusText).color = Color.white; ((Graphic)invincibilityStatusText).raycastTarget = false; UpdateInvincibilityLabel(); uiRoot.SetActive(false); Plugin.Logger.LogMessage((object)"[CheckpointTeleportUI] UI built"); } private void RebuildRows() { foreach (GameObject row in rows) { Object.Destroy((Object)(object)row); } rows.Clear(); _checkpoints.Clear(); if ((Object)(object)Singleton.Instance == (Object)null) { return; } Singleton.Instance.UpdateCampfires(); int num = 0; foreach (Transform campfire in Singleton.Instance.GetCampfires()) { if ((Object)(object)campfire == (Object)null) { num++; continue; } _checkpoints.Add(campfire); string labelText = BuildLabel(num, campfire); GameObject val = MakeRow(labelText); val.transform.SetParent(rowContainer, false); rows.Add(val); num++; } } private static string BuildLabel(int index, Transform cp) { string text = ((index == 0) ? "Spawn" : $"Camp {index}"); string text2 = ((index < NumpadKeys.Length) ? $"[Ctrl+Num{index}]" : ""); return text2 + " " + text + " " + ((Object)cp).name + ""; } private GameObject MakeRow(string labelText) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_003e: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Row"); LayoutElement val2 = val.AddComponent(); val2.preferredHeight = 20f; RectTransform val3 = val.AddComponent(); TextMeshProUGUI val4 = val.AddComponent(); ((TMP_Text)val4).text = labelText; ((TMP_Text)val4).fontSize = 11f; ((Graphic)val4).color = Color.white; ((Graphic)val4).raycastTarget = false; ((TMP_Text)val4).overflowMode = (TextOverflowModes)1; return val; } static CheckpointTeleportUI() { KeyCode[] array = new KeyCode[10]; RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); NumpadKeys = (KeyCode[])(object)array; IsInvincibleField = typeof(CharacterData).GetField("isInvincible", BindingFlags.Instance | BindingFlags.NonPublic); } } public class ForbiddenModUI : Singleton { private GameObject uiContainer; private TextMeshProUGUI modListText; public void Show(IReadOnlyList unauthorizedMods) { if ((Object)(object)modListText != (Object)null) { ((TMP_Text)modListText).text = string.Join("\n", unauthorizedMods.Select((PluginInfo p) => $"{p.Metadata.GUID} v{p.Metadata.Version}")); } GameObject obj = uiContainer; if (obj != null) { obj.SetActive(true); } } public void Show(IReadOnlyList forbiddenMods) { if ((Object)(object)modListText != (Object)null) { ((TMP_Text)modListText).text = string.Join("\n", forbiddenMods); } GameObject obj = uiContainer; if (obj != null) { obj.SetActive(true); } } public void Hide() { GameObject obj = uiContainer; if (obj != null) { obj.SetActive(false); } } protected override void Initialize() { try { BuildUI(); Hide(); Plugin.Logger.LogMessage((object)"ForbiddenModUI initialized."); } catch (Exception ex) { Plugin.Logger.LogError((object)("[ForbiddenModUI] Init error: " + ex.Message + "\n" + ex.StackTrace)); } } private void BuildUI() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown //IL_0063: 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_0078: Expected O, but got Unknown //IL_00a1: 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_00cb: 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_00eb: 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_014b: 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_018e: 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_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_01df: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Expected O, but got Unknown //IL_020e: Unknown result type (might be due to invalid IL or missing references) //IL_0224: Unknown result type (might be due to invalid IL or missing references) //IL_0230: 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_0278: Unknown result type (might be due to invalid IL or missing references) uiContainer = new GameObject("ForbiddenModUI"); uiContainer.transform.SetParent(((Component)this).transform, false); Canvas val = uiContainer.AddComponent(); val.renderMode = (RenderMode)0; val.sortingOrder = 600; CanvasScaler val2 = uiContainer.AddComponent(); val2.uiScaleMode = (ScaleMode)1; val2.referenceResolution = new Vector2(1920f, 1080f); GameObject val3 = new GameObject("Panel"); val3.transform.SetParent(uiContainer.transform, false); RectTransform val4 = val3.AddComponent(); val4.anchorMin = new Vector2(0.5f, 0.5f); val4.anchorMax = new Vector2(0.5f, 0.5f); val4.pivot = new Vector2(0.5f, 0.5f); val4.anchoredPosition = Vector2.zero; val4.sizeDelta = new Vector2(900f, 240f); Image val5 = val3.AddComponent(); ((Graphic)val5).color = new Color(0.1f, 0f, 0f, 0.88f); PeakText val6 = MenuAPI.CreateText("⚠ FORBIDDEN MOD(S) DETECTED ⚠"); ((TMP_Text)val6.TextMesh).emojiFallbackSupport = true; ((Component)val6).transform.SetParent(val3.transform, false); val6.SetColor(Color.red); val6.SetFontSize(28f); RectTransform component = ((Component)val6).GetComponent(); component.anchorMin = new Vector2(0f, 1f); component.anchorMax = new Vector2(1f, 1f); component.pivot = new Vector2(0.5f, 1f); component.anchoredPosition = new Vector2(0f, -12f); component.sizeDelta = new Vector2(0f, 40f); GameObject val7 = new GameObject("ModList"); val7.transform.SetParent(val3.transform, false); RectTransform val8 = val7.AddComponent(); val8.anchorMin = new Vector2(0.05f, 0.05f); val8.anchorMax = new Vector2(0.95f, 0.65f); val8.offsetMin = Vector2.zero; val8.offsetMax = Vector2.zero; modListText = val7.AddComponent(); ((TMP_Text)modListText).fontSize = 18f; ((Graphic)modListText).color = new Color(1f, 0.6f, 0.6f); ((TMP_Text)modListText).alignment = (TextAlignmentOptions)514; } } public class FPSUI : Singleton { private float deltaTime; private TextMeshProUGUI fpsText; private float timeSinceLastUpdate; private GameObject uiContainer; private float updateInterval = 0.5f; public void Hide() { GameObject obj = uiContainer; if (obj != null) { obj.SetActive(false); } ((Behaviour)this).enabled = false; } public void Show() { GameObject obj = uiContainer; if (obj != null) { obj.SetActive(true); } ((Behaviour)this).enabled = true; } public void Show(bool state) { GameObject obj = uiContainer; if (obj != null) { obj.SetActive(state); } ((Behaviour)this).enabled = state; } public void ToggleShow() { Show(!((Behaviour)this).enabled); } protected override void Initialize() { CreateUI(); Plugin.Logger.LogMessage((object)"FPSUI initialized"); Hide(); } protected void Update() { deltaTime += (Time.unscaledDeltaTime - deltaTime) * 0.1f; timeSinceLastUpdate += Time.unscaledDeltaTime; if (timeSinceLastUpdate >= updateInterval) { float fps = 1f / deltaTime; UpdateFPSDisplay(fps); timeSinceLastUpdate = 0f; } } private void CreateUI() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Expected O, but got Unknown //IL_0079: 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_00a3: 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_00cd: 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_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) uiContainer = new GameObject("FPSUI"); uiContainer.transform.SetParent(((Component)this).transform, false); Canvas val = uiContainer.AddComponent(); val.renderMode = (RenderMode)0; val.sortingOrder = 1000; GameObject val2 = new GameObject("FPSText"); val2.transform.SetParent(uiContainer.transform, false); RectTransform val3 = val2.AddComponent(); val3.anchorMin = new Vector2(0f, 1f); val3.anchorMax = new Vector2(0f, 1f); val3.pivot = new Vector2(0f, 1f); val3.anchoredPosition = new Vector2(10f, -10f); val3.sizeDelta = new Vector2(150f, 40f); fpsText = val2.AddComponent(); ((TMP_Text)fpsText).fontSize = 24f; ((TMP_Text)fpsText).fontStyle = (FontStyles)1; ((TMP_Text)fpsText).alignment = (TextAlignmentOptions)257; ((TMP_Text)fpsText).text = "FPS: --"; ((Graphic)fpsText).color = Color.white; ((TMP_Text)fpsText).outlineWidth = 0.2f; ((TMP_Text)fpsText).outlineColor = Color32.op_Implicit(Color.black); } private void UpdateFPSDisplay(float fps) { //IL_0081: 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_0055: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)fpsText != (Object)null) { float num = Mathf.Ceil(fps); ((TMP_Text)fpsText).text = $"FPS: {num}"; ((Graphic)fpsText).color = ((num >= 60f) ? new Color(0.3f, 1f, 0.3f) : ((num >= 30f) ? new Color(1f, 1f, 0.3f) : new Color(1f, 0.3f, 0.3f))); } } } public class HeightBarsUI : MonoBehaviour { public enum MarkerShape { Circle, Triangle } public Color barBorderColor = new Color(0.3f, 0.6f, 1f, 0.9f); public Color barBottomColor = new Color(0.1f, 0.2f, 0.4f, 0.8f); public Color barTopColor = new Color(0.2f, 0.4f, 0.8f, 0.8f); public Color markerColor = new Color(0.2f, 0.8f, 1f, 0.9f); public Color markerOutlineColor = new Color(1f, 1f, 1f, 1f); public MarkerShape markerShape; private ManualLogSource _logger; private RectTransform barBackground; private Transform labelsContainer; private GameObject markerPrefab; private Transform markersContainer; private float maxHeightScale = 400f; private Dictionary playerMarkers = new Dictionary(); private Transform scaleLabelsContainer; private float maxDisplayHeight; private float minDisplayHeight; private float heightRange; private GameObject timerObj; private TextMeshProUGUI timerLabel; private float currentTimeLimit = -1f; private bool isExpanded; private Image barBgImage; private Sprite bar1DSprite; private Sprite bar2DSprite; private float minDisplayX; private float maxDisplayX; private float xRange; private Transform xAxisLabelsContainer; private Transform scaleLabels2DContainer; private TextMeshProUGUI modeHintLabel; private PlayerHeightBar currentSelectedPlayerMarker; private List heights; private List _sortedMarkers = new List(); private static readonly Comparison _heightAscending = (PlayerHeightBar a, PlayerHeightBar b) => a.GetCurrentHeight().CompareTo(b.GetCurrentHeight()); private int cachedMinZone = -1; private int cachedMaxZone = -1; public bool IsExpanded => isExpanded; public void ClearAllBars() { foreach (PlayerHeightBar value in playerMarkers.Values) { if ((Object)(object)value != (Object)null) { Object.Destroy((Object)(object)((Component)value).gameObject); } } playerMarkers.Clear(); } public void Initialize(ManualLogSource logger) { _logger = logger; CreateUI(); } public void RegenerateScaleLabels(IEnumerable heightObjects) { if ((Object)(object)labelsContainer == (Object)null) { _logger.LogWarning((object)"Cannot regenerate scale labels - bar not initialized"); return; } CreateScaleLabels(heightObjects); _logger.LogMessage((object)$"Regenerated scale labels from {heightObjects.Count()} objects"); } public void RemovePlayer(string playerName) { if (playerMarkers.ContainsKey(playerName)) { Object.Destroy((Object)(object)((Component)playerMarkers[playerName]).gameObject); playerMarkers.Remove(playerName); } } public void UpdateTimer(float remainingTime) { //IL_0093: Unknown result type (might be due to invalid IL or missing references) currentTimeLimit = Mathf.Max(0f, remainingTime); if (!((Object)(object)timerLabel != (Object)null)) { return; } if (currentTimeLimit < 0f || !Plugin.IsOnMapScene) { timerObj.SetActive(false); return; } TimeSpan timeSpan = TimeSpan.FromSeconds(currentTimeLimit); if (Plugin.IsPlayer) { float num = (((Object)(object)FFSPeak.PlayerState.PlayerState.PlayerCharacter != (Object)null && FFSPeak.PlayerState.PlayerState.CurrentPlayerState != null) ? RemotePlayerData.GetCurrentHeight(FFSPeak.PlayerState.PlayerState.PlayerCharacter.data.dead, FFSPeak.PlayerState.PlayerState.CurrentPlayerState.IsFinished, FFSPeak.PlayerState.PlayerState.CurrentPlayerState.Position, FFSPeak.PlayerState.PlayerState.CurrentPlayerState.LastCheckpoint) : 0f); ((TMP_Text)timerLabel).text = $"Time: {timeSpan.Hours:D2}:{timeSpan.Minutes:D2}:{timeSpan.Seconds:D2} - Score: {num:F1}"; } else { ((TMP_Text)timerLabel).text = $"Time: {timeSpan.Hours:D2}:{timeSpan.Minutes:D2}:{timeSpan.Seconds:D2}"; } if (!timerObj.activeSelf) { timerObj.SetActive(true); } } public void UpdatePlayer(RemotePlayerData playerData) { if (!playerMarkers.TryGetValue(playerData.PlayerName, out var value)) { if ((Object)(object)markerPrefab == (Object)null) { markerPrefab = CreateMarkerPrefab(); } GameObject val = Object.Instantiate(markerPrefab, markersContainer); value = val.GetComponent(); value.Initialize(playerData); playerMarkers[playerData.PlayerName] = value; _logger.LogMessage((object)("Created marker for " + playerData.PlayerName)); } value.UpdateData(); } private void LateUpdate() { UpdateVisibleZoneRange(); UpdateMarkerPositions(); UpdateTimer(currentTimeLimit - Time.deltaTime); } private GameObject CreateMarkerPrefab() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_001d: 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: Expected O, but got Unknown //IL_0056: 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_0095: 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_00e8: 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_0118: Expected O, but got Unknown //IL_0140: 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_016c: 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_0198: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: 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_01db: Expected O, but got Unknown //IL_0203: Unknown result type (might be due to invalid IL or missing references) //IL_0219: 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_0245: Unknown result type (might be due to invalid IL or missing references) //IL_025b: Unknown result type (might be due to invalid IL or missing references) //IL_0288: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("PlayerMarker"); RectTransform val2 = val.AddComponent(); val2.sizeDelta = new Vector2(200f, 30f); GameObject val3 = new GameObject("Background"); val3.transform.SetParent(val.transform, false); RectTransform val4 = val3.AddComponent(); val4.anchorMin = new Vector2(0f, 0.5f); val4.anchorMax = new Vector2(0f, 0.5f); val4.pivot = new Vector2(0f, 0.5f); val4.anchoredPosition = new Vector2(-12f, 0f); val4.sizeDelta = new Vector2(32f, 32f); Image val5 = val3.AddComponent(); Texture2D val6 = GenerateMarkerTexture(32, markerShape); Sprite sprite = Sprite.Create(val6, new Rect(0f, 0f, (float)((Texture)val6).width, (float)((Texture)val6).height), new Vector2(0.5f, 0.5f)); val5.sprite = sprite; GameObject val7 = new GameObject("Checkpoint"); val7.transform.SetParent(val.transform, false); RectTransform val8 = val7.AddComponent(); val8.anchorMin = new Vector2(0f, 0.5f); val8.anchorMax = new Vector2(0f, 0.5f); val8.pivot = new Vector2(0f, 0.5f); val8.anchoredPosition = new Vector2(0f, 0f); val8.sizeDelta = new Vector2(40f, 10f); TextMeshProUGUI val9 = val7.AddComponent(); ((TMP_Text)val9).alignment = (TextAlignmentOptions)513; ((TMP_Text)val9).fontSize = 14f; ((Graphic)val9).color = Color.white; GameObject val10 = new GameObject("PlayerName"); val10.transform.SetParent(val.transform, false); RectTransform val11 = val10.AddComponent(); val11.anchorMin = new Vector2(0f, 0.5f); val11.anchorMax = new Vector2(0f, 0.5f); val11.pivot = new Vector2(0f, 0.5f); val11.anchoredPosition = new Vector2(22f, 0f); val11.sizeDelta = new Vector2(200f, 0f); TextMeshProUGUI val12 = val10.AddComponent(); ((TMP_Text)val12).alignment = (TextAlignmentOptions)513; ((TMP_Text)val12).fontSize = 14f; ((Graphic)val12).color = Color.white; ((TMP_Text)val12).fontStyle = (FontStyles)1; PlayerHeightBar playerHeightBar = val.AddComponent(); playerHeightBar.playerNameText = val12; playerHeightBar.checkpointText = val9; playerHeightBar.markerImage = val5; return val; } private void CreateScaleLabels(IEnumerable heightObjects) { //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_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_006c: 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_007c: 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) heights = new List(); List list = heightObjects.ToList(); float num = 0f; heights.Add(0f); for (int i = 1; i < list.Count; i++) { if ((Object)(object)list[i] != (Object)null && (Object)(object)list[i - 1] != (Object)null) { Vector3 position = list[i - 1].position; Vector3 position2 = list[i].position; float num2 = position2.y - position.y; float num3 = position2.z - position.z; num += Mathf.Sqrt(num2 * num2 + num3 * num3) * CharacterStats.unitsToMeters; } heights.Add(num); } if (heights.Count == 0) { heights.Add(0f); } minDisplayHeight = 0f; maxDisplayHeight = ((heights.Count > 0) ? heights.Max() : maxHeightScale); if (maxDisplayHeight < 1f) { maxDisplayHeight = maxHeightScale; } heightRange = maxDisplayHeight - minDisplayHeight; minDisplayX = -250f; maxDisplayX = 250f; xRange = maxDisplayX - minDisplayX; cachedMinZone = 0; cachedMaxZone = Mathf.Max(0, heights.Count - 2); RebuildScaleLabelDisplay(cachedMinZone, cachedMaxZone); Create2DYAxisLabels(); } private int GetZoneIndex(float height) { if (heights == null || heights.Count < 2) { return 0; } for (int num = heights.Count - 2; num >= 0; num--) { if (height >= heights[num]) { return num; } } return 0; } private (int minZone, int maxZone) ComputeVisibleZoneRange() { int item = Mathf.Max(0, (heights?.Count ?? 1) - 2); if (heights == null || heights.Count < 2 || playerMarkers.Count == 0) { return (minZone: 0, maxZone: item); } int num = int.MaxValue; int num2 = int.MinValue; foreach (PlayerHeightBar value in playerMarkers.Values) { int zoneIndex = GetZoneIndex(value.GetCurrentHeight()); if (zoneIndex < num) { num = zoneIndex; } if (zoneIndex > num2) { num2 = zoneIndex; } } if (num == int.MaxValue) { return (minZone: 0, maxZone: item); } return (minZone: num, maxZone: num2); } private void UpdateVisibleZoneRange() { if (heights != null && heights.Count >= 2) { var (num, num2) = ComputeVisibleZoneRange(); if (num != cachedMinZone || num2 != cachedMaxZone) { cachedMinZone = num; cachedMaxZone = num2; minDisplayHeight = heights[num]; maxDisplayHeight = heights[Mathf.Min(num2 + 1, heights.Count - 1)]; heightRange = Mathf.Max(0.01f, maxDisplayHeight - minDisplayHeight); RebuildScaleLabelDisplay(num, num2); Create2DYAxisLabels(); } } } private void RebuildScaleLabelDisplay(int visibleMinZone, int visibleMaxZone) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Expected O, but got Unknown //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) //IL_0076: 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_0128: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Expected O, but got Unknown //IL_0154: 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_017d: 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_01a9: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)labelsContainer == (Object)null) { return; } if ((Object)(object)scaleLabelsContainer != (Object)null) { Object.Destroy((Object)(object)((Component)scaleLabelsContainer).gameObject); } bool expanded = isExpanded; SetExpanded(expanded: false); GameObject val = new GameObject("ScaleLabels"); val.transform.SetParent(labelsContainer, false); RectTransform val2 = val.AddComponent(); val2.anchorMin = Vector2.zero; val2.anchorMax = Vector2.one; val2.offsetMin = Vector2.zero; val2.offsetMax = Vector2.zero; scaleLabelsContainer = val.transform; if (heights != null && heights.Count != 0) { int num = Mathf.Clamp(visibleMinZone, 0, heights.Count - 1); int num2 = Mathf.Clamp(visibleMaxZone + 1, 0, heights.Count - 1); for (int i = num; i <= num2; i++) { float num3 = heights[i]; float num4 = ((heightRange > 0f) ? ((num3 - minDisplayHeight) / heightRange) : 0f); GameObject val3 = new GameObject($"Scale_{num3:F1}m"); val3.transform.SetParent(scaleLabelsContainer, false); RectTransform val4 = val3.AddComponent(); val4.anchorMin = new Vector2(0f, num4); val4.anchorMax = new Vector2(1f, num4); val4.pivot = new Vector2(0.5f, 0.5f); val4.anchoredPosition = new Vector2(-40f, 0f); val4.sizeDelta = new Vector2(60f, 20f); TextMeshProUGUI val5 = val3.AddComponent(); ((TMP_Text)val5).text = $"{num3:F0}m - {i}"; ((TMP_Text)val5).fontSize = 12f; ((Graphic)val5).color = Color.gray; ((TMP_Text)val5).alignment = (TextAlignmentOptions)514; } SetExpanded(expanded); } } private void CreateUI() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_004b: 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: Expected O, but got Unknown //IL_008d: 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_00b9: 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_00e5: 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_0131: 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) //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Expected O, but got Unknown //IL_01ed: 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_0219: 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_0245: 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_026c: Expected O, but got Unknown //IL_028a: 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_02a2: 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_02ca: Unknown result type (might be due to invalid IL or missing references) //IL_02d1: Expected O, but got Unknown //IL_02ef: Unknown result type (might be due to invalid IL or missing references) //IL_02fb: 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_0313: Unknown result type (might be due to invalid IL or missing references) //IL_032f: Unknown result type (might be due to invalid IL or missing references) //IL_0336: Expected O, but got Unknown //IL_035e: Unknown result type (might be due to invalid IL or missing references) //IL_0374: Unknown result type (might be due to invalid IL or missing references) //IL_038a: Unknown result type (might be due to invalid IL or missing references) //IL_0396: Unknown result type (might be due to invalid IL or missing references) //IL_03ac: Unknown result type (might be due to invalid IL or missing references) //IL_03e1: Unknown result type (might be due to invalid IL or missing references) //IL_03e8: Expected O, but got Unknown //IL_0410: Unknown result type (might be due to invalid IL or missing references) //IL_0426: Unknown result type (might be due to invalid IL or missing references) //IL_0432: Unknown result type (might be due to invalid IL or missing references) //IL_043e: Unknown result type (might be due to invalid IL or missing references) //IL_048f: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("HeightBarCanvas"); val.transform.SetParent(((Component)this).transform); Canvas val2 = val.AddComponent(); val2.renderMode = (RenderMode)0; val2.sortingOrder = 100; CanvasScaler val3 = val.AddComponent(); val3.uiScaleMode = (ScaleMode)1; val3.referenceResolution = new Vector2(1920f, 1080f); val.AddComponent(); GameObject val4 = new GameObject("HeightBar"); val4.transform.SetParent(val.transform, false); RectTransform val5 = val4.AddComponent(); val5.anchorMin = new Vector2(0.05f, 0.17f); val5.anchorMax = new Vector2(0.05f, 0.9f); val5.pivot = new Vector2(1f, 0.5f); val5.anchoredPosition = new Vector2(0f, 0f); val5.sizeDelta = new Vector2(10f, 0f); Image val6 = val4.AddComponent(); Texture2D val7 = GenerateBarTexture(80, 2048); Sprite val8 = (val6.sprite = Sprite.Create(val7, new Rect(0f, 0f, (float)((Texture)val7).width, (float)((Texture)val7).height), new Vector2(0.5f, 0.5f))); val6.type = (Type)1; barBgImage = val6; bar1DSprite = val8; Texture2D val10 = GeneratePanel2DTexture(512, 512); bar2DSprite = Sprite.Create(val10, new Rect(0f, 0f, 512f, 512f), new Vector2(0.5f, 0.5f)); barBackground = val5; timerObj = new GameObject("TimerLabel"); timerObj.transform.SetParent(val.transform, false); RectTransform val11 = timerObj.AddComponent(); val11.anchorMin = new Vector2(0.1f, 0.1f); val11.anchorMax = new Vector2(0.35f, 0.04f); val11.pivot = new Vector2(1f, 0.5f); val11.anchoredPosition = new Vector2(0f, 0f); val11.sizeDelta = new Vector2(100f, 30f); timerLabel = timerObj.AddComponent(); GameObject val12 = new GameObject("Labels"); val12.transform.SetParent(val4.transform, false); RectTransform val13 = val12.AddComponent(); val13.anchorMin = Vector2.zero; val13.anchorMax = Vector2.one; val13.offsetMin = Vector2.zero; val13.offsetMax = Vector2.zero; labelsContainer = val12.transform; GameObject val14 = new GameObject("Markers"); val14.transform.SetParent(val4.transform, false); RectTransform val15 = val14.AddComponent(); val15.anchorMin = Vector2.zero; val15.anchorMax = Vector2.one; val15.offsetMin = Vector2.zero; val15.offsetMax = Vector2.zero; markersContainer = val14.transform; GameObject val16 = new GameObject("XAxisLabels"); val16.transform.SetParent(val4.transform, false); RectTransform val17 = val16.AddComponent(); val17.anchorMin = new Vector2(0f, 0f); val17.anchorMax = new Vector2(1f, 0f); val17.pivot = new Vector2(0f, 1f); val17.anchoredPosition = Vector2.zero; val17.sizeDelta = new Vector2(0f, 22f); xAxisLabelsContainer = val16.transform; val16.SetActive(false); CreateScaleLabels(new List()); CreateXAxisLabels(); GameObject val18 = new GameObject("ModeHint"); val18.transform.SetParent(val.transform, false); RectTransform val19 = val18.AddComponent(); val19.anchorMin = new Vector2(0.01f, 0.15f); val19.anchorMax = new Vector2(0.22f, 0.15f); val19.offsetMin = Vector2.zero; val19.offsetMax = Vector2.zero; modeHintLabel = val18.AddComponent(); ((TMP_Text)modeHintLabel).text = "[TAB] 2D VIEW"; ((TMP_Text)modeHintLabel).fontSize = 11f; ((Graphic)modeHintLabel).color = new Color(0.6f, 0.7f, 0.9f, 0.8f); ((TMP_Text)modeHintLabel).alignment = (TextAlignmentOptions)513; _logger.LogMessage((object)"Single height bar UI created"); } private Texture2D GenerateBarTexture(int width, int height) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //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_006d: 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_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_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_005a: 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) Texture2D val = new Texture2D(width, height); for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { Color val2; if (j < 3 || j >= width - 3) { val2 = barBorderColor; } else { float num = (float)i / (float)height; val2 = Color.Lerp(barBottomColor, barTopColor, num); if (j % 20 < 2) { val2 = Color.Lerp(val2, new Color(1f, 1f, 1f, 0.1f), 0.3f); } } val.SetPixel(j, i, val2); } } val.Apply(); return val; } private Texture2D GenerateMarkerTexture(int size, MarkerShape shape) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //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_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_01ad: 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_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_009c: 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_0189: Unknown result type (might be due to invalid IL or missing references) //IL_0190: 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_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) Texture2D val = new Texture2D(size, size); Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor((float)size / 2f, (float)size / 2f); float num = (float)size / 2f - 2f; Vector2 val3 = default(Vector2); for (int i = 0; i < size; i++) { for (int j = 0; j < size; j++) { ((Vector2)(ref val3))..ctor((float)j, (float)i); Color val4 = Color.clear; switch (shape) { case MarkerShape.Circle: { float num7 = Vector2.Distance(val3, val2); if (num7 <= num) { if (num7 > num - 2f) { val4 = markerOutlineColor; } else { float num8 = 1f - num7 / num * 0.3f; val4 = markerColor * num8; val4.a = markerColor.a; } if (num7 > num - 1f) { float num9 = num - num7; val4.a *= num9; } } break; } case MarkerShape.Triangle: { float num2 = (float)size * 0.2f; float num3 = (float)size * 0.8f; float num4 = (float)i - val2.y; float num5 = ((float)j - num2) / (num3 - num2) * num; if ((float)j >= num2 && (float)j <= num3 && Mathf.Abs(num4) <= num5) { if ((float)j <= num2 + 2f || (float)j >= num3 - 2f || Mathf.Abs(Mathf.Abs(num4) - num5) < 2f) { val4 = markerOutlineColor; break; } float num6 = 1f - ((float)j - num2) / (num3 - num2) * 0.3f; val4 = markerColor * num6; val4.a = markerColor.a; } break; } } val.SetPixel(j, i, val4); } } val.Apply(); return val; } private void UpdateMarkerPositions() { //IL_0152: 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_00b1: 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_00d3: 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_01ae: 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_01d0: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)barBackground == (Object)null) { return; } if (!isExpanded) { _sortedMarkers.Clear(); _sortedMarkers.AddRange(playerMarkers.Values); _sortedMarkers.Sort(_heightAscending); { foreach (PlayerHeightBar sortedMarker in _sortedMarkers) { float currentHeight = sortedMarker.GetCurrentHeight(); float num = ((heightRange > 0f) ? ((currentHeight - minDisplayHeight) / heightRange) : 0f); RectTransform component = ((Component)sortedMarker).GetComponent(); component.anchorMin = new Vector2(0f, num); component.anchorMax = new Vector2(1f, num); component.pivot = new Vector2(0f, 0.5f); component.anchoredPosition = Vector2.zero; } return; } } foreach (PlayerHeightBar value in playerMarkers.Values) { float currentHeight2 = value.GetCurrentHeight(); float num2 = ((heightRange > 0f) ? Mathf.Clamp01((currentHeight2 - minDisplayHeight) / heightRange) : 0.5f); float num3 = value.GetPosition().x * CharacterStats.unitsToMeters; float num4 = ((xRange > 0f) ? Mathf.Clamp01((num3 - minDisplayX) / xRange) : 0.5f); RectTransform component2 = ((Component)value).GetComponent(); component2.anchorMin = new Vector2(num4, num2); component2.anchorMax = new Vector2(num4, num2); component2.pivot = new Vector2(0f, 0.5f); component2.anchoredPosition = Vector2.zero; } } public void SetPriorityPlayer(string playerName) { //IL_0071: Unknown result type (might be due to invalid IL or missing references) if (!string.IsNullOrEmpty(playerName) && playerMarkers.ContainsKey(playerName)) { if ((Object)(object)currentSelectedPlayerMarker != (Object)null && (Object)(object)currentSelectedPlayerMarker != (Object)(object)playerMarkers[playerName]) { currentSelectedPlayerMarker.ResetColor(); } currentSelectedPlayerMarker = playerMarkers[playerName]; ((Component)currentSelectedPlayerMarker).transform.SetAsLastSibling(); currentSelectedPlayerMarker.SetColor(Color.cyan); } } public void SetExpanded(bool expanded) { //IL_010d: 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_0141: 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_0175: 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_004b: 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) //IL_007b: Unknown result type (might be due to invalid IL or missing references) isExpanded = expanded; if ((Object)(object)barBackground == (Object)null) { return; } if (isExpanded) { barBackground.anchorMin = new Vector2(0.05f, 0.17f); barBackground.anchorMax = new Vector2(0.45f, 0.9f); barBackground.pivot = Vector2.zero; barBackground.anchoredPosition = Vector2.zero; barBackground.sizeDelta = Vector2.zero; if ((Object)(object)barBgImage != (Object)null) { barBgImage.sprite = bar2DSprite; barBgImage.type = (Type)0; } Transform obj = scaleLabelsContainer; if (obj != null) { ((Component)obj).gameObject.SetActive(false); } Transform obj2 = xAxisLabelsContainer; if (obj2 != null) { ((Component)obj2).gameObject.SetActive(true); } Transform obj3 = scaleLabels2DContainer; if (obj3 != null) { ((Component)obj3).gameObject.SetActive(true); } } else { barBackground.anchorMin = new Vector2(0.05f, 0.17f); barBackground.anchorMax = new Vector2(0.05f, 0.9f); barBackground.pivot = new Vector2(1f, 0.5f); barBackground.anchoredPosition = new Vector2(-10f, 0f); barBackground.sizeDelta = new Vector2(10f, 0f); if ((Object)(object)barBgImage != (Object)null) { barBgImage.sprite = bar1DSprite; barBgImage.type = (Type)1; } Transform obj4 = scaleLabelsContainer; if (obj4 != null) { ((Component)obj4).gameObject.SetActive(true); } Transform obj5 = xAxisLabelsContainer; if (obj5 != null) { ((Component)obj5).gameObject.SetActive(false); } Transform obj6 = scaleLabels2DContainer; if (obj6 != null) { ((Component)obj6).gameObject.SetActive(false); } } UpdateMarkerPositions(); if ((Object)(object)modeHintLabel != (Object)null) { ((TMP_Text)modeHintLabel).text = (isExpanded ? "[TAB] 1D VIEW" : "[TAB] 2D VIEW"); } } private void Create2DYAxisLabels() { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown //IL_0043: 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_0059: 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_0079: 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_0160: Expected O, but got Unknown //IL_0185: 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_01ae: 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_01da: 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) if ((Object)(object)scaleLabels2DContainer != (Object)null) { Object.Destroy((Object)(object)((Component)scaleLabels2DContainer).gameObject); } GameObject val = new GameObject("YAxisLabels2D"); val.transform.SetParent((Transform)(object)barBackground, false); RectTransform val2 = val.AddComponent(); val2.anchorMin = Vector2.zero; val2.anchorMax = Vector2.one; val2.offsetMin = Vector2.zero; val2.offsetMax = Vector2.zero; val2.anchoredPosition = new Vector2(-60f, 0f); scaleLabels2DContainer = val.transform; if (heights == null || heights.Count == 0) { val.SetActive(isExpanded); return; } int num = Mathf.Clamp((cachedMinZone >= 0) ? cachedMinZone : 0, 0, heights.Count - 1); int num2 = Mathf.Clamp(((cachedMaxZone < 0) ? (heights.Count - 2) : cachedMaxZone) + 1, 0, heights.Count - 1); for (int i = num; i <= num2; i++) { float num3 = heights[i]; float num4 = ((heightRange > 0f) ? ((num3 - minDisplayHeight) / heightRange) : 0f); GameObject val3 = new GameObject($"YLabel_{num3:F0}m"); val3.transform.SetParent(scaleLabels2DContainer, false); RectTransform val4 = val3.AddComponent(); val4.anchorMin = new Vector2(0f, num4); val4.anchorMax = new Vector2(0f, num4); val4.pivot = new Vector2(0f, 0.5f); val4.anchoredPosition = new Vector2(4f, 0f); val4.sizeDelta = new Vector2(60f, 18f); TextMeshProUGUI val5 = val3.AddComponent(); ((TMP_Text)val5).text = $"{num3:F0}m - {i}"; ((TMP_Text)val5).fontSize = 11f; ((Graphic)val5).color = new Color(0.7f, 0.7f, 0.85f, 0.9f); ((TMP_Text)val5).alignment = (TextAlignmentOptions)513; } val.SetActive(isExpanded); } private void CreateXAxisLabels() { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Expected O, but got Unknown //IL_00ae: 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_00d7: 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_00f9: 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) if ((Object)(object)xAxisLabelsContainer == (Object)null) { return; } foreach (Transform item in xAxisLabelsContainer) { Transform val = item; Object.Destroy((Object)(object)((Component)val).gameObject); } for (int i = 0; i <= 4; i++) { float num = (float)i / 4f; float num2 = minDisplayX + num * xRange; GameObject val2 = new GameObject($"XLabel_{i}"); val2.transform.SetParent(xAxisLabelsContainer, false); RectTransform val3 = val2.AddComponent(); val3.anchorMin = new Vector2(num, 0f); val3.anchorMax = new Vector2(num, 1f); val3.pivot = new Vector2(0.5f, 0f); val3.anchoredPosition = Vector2.zero; val3.sizeDelta = new Vector2(60f, 0f); TextMeshProUGUI val4 = val2.AddComponent(); ((TMP_Text)val4).text = $"{num2:F0}m"; ((TMP_Text)val4).fontSize = 11f; ((Graphic)val4).color = new Color(0.7f, 0.7f, 0.85f, 0.9f); ((TMP_Text)val4).alignment = (TextAlignmentOptions)514; } } private Texture2D GeneratePanel2DTexture(int width, int height) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //IL_00db: 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_00d5: Unknown result type (might be due to invalid IL or missing references) Texture2D val = new Texture2D(width, height); ((Texture)val).filterMode = (FilterMode)1; Color val2 = default(Color); ((Color)(ref val2))..ctor(0.04f, 0.07f, 0.14f, 0.9f); Color val3 = default(Color); ((Color)(ref val3))..ctor(0.25f, 0.45f, 0.75f, 0.95f); Color val4 = default(Color); ((Color)(ref val4))..ctor(0.15f, 0.25f, 0.45f, 0.45f); int num = Mathf.Max(2, width / 128); int num2 = Mathf.Max(1, width / 256); int num3 = width / 4; for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { bool flag = j < num || j >= width - num || i < num || i >= height - num; bool flag2 = j % num3 < num2 || i % num3 < num2; val.SetPixel(j, i, flag ? val3 : (flag2 ? val4 : val2)); } } val.Apply(); return val; } } public class HeightBarsUIManager : MonoBehaviour { private HeightBarsUI _heightBarsUI; private static HeightBarsUIManager _instance; private ManualLogSource logger = Plugin.Logger; private string priorityPlayerName; private List _back = new List(); private HashSet _backNames = new HashSet(); private HashSet _appliedNames = new HashSet(); private List _removedNames = new List(); private List _source = new List(); private int _cursor; private float _stableTimer = 5f; private const float STABLE_INTERVAL = 5f; private GameObject uiObject; public static HeightBarsUIManager Instance { get { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown if ((Object)(object)_instance == (Object)null) { GameObject val = new GameObject("HeightBarsUIManager"); Object.DontDestroyOnLoad((Object)(object)val); _instance = val.AddComponent(); } return _instance; } } public static HeightBarsUI GetHeightBarsUI() { return Instance._heightBarsUI; } public void Initialize() { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Expected O, but got Unknown if ((Object)(object)_heightBarsUI != (Object)null) { logger.LogWarning((object)"HeightBarsUI already initialized"); return; } uiObject = new GameObject("HeightBarsUI"); uiObject.transform.SetParent(((Component)this).transform, false); _heightBarsUI = uiObject.AddComponent(); _heightBarsUI.Initialize(logger); logger.LogMessage((object)"HeightBarsUIManager initialized with UI at scene root"); } public void Reinitialize() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown if ((Object)(object)uiObject == (Object)null) { uiObject = new GameObject("HeightBarsUI"); uiObject.transform.SetParent(((Component)this).transform, false); } if ((Object)(object)_heightBarsUI == (Object)null && !uiObject.TryGetComponent(ref _heightBarsUI)) { _heightBarsUI = uiObject.AddComponent(); _heightBarsUI.Initialize(logger); } Singleton.Instance.UpdateCampfires(); _heightBarsUI.RegenerateScaleLabels(Singleton.Instance.GetCampfires()); _heightBarsUI.ClearAllBars(); UpdatePriorityPlayer(Plugin.LocalPlayerName); _back.Clear(); _backNames.Clear(); _appliedNames.Clear(); _removedNames.Clear(); _source.Clear(); _cursor = 0; logger.LogMessage((object)"HeightBarsUIManager reinitialized HeightBarsUI"); } private void Awake() { if ((Object)(object)_instance != (Object)null && (Object)(object)_instance != (Object)(object)this) { Object.Destroy((Object)(object)((Component)this).gameObject); return; } _instance = this; Singleton.Instance.OnSelectedPlayerChanged += UpdatePriorityPlayer; } private void OnDestroy() { if ((Object)(object)_instance == (Object)(object)this) { _instance = null; } } public void UpdateTimer(float timeRemaining) { _heightBarsUI?.UpdateTimer(timeRemaining); } public void UpdatePriorityPlayer(string newPlayerName = null) { priorityPlayerName = newPlayerName; _heightBarsUI?.SetPriorityPlayer(priorityPlayerName); } private void Update() { if (Input.GetKeyDown((KeyCode)9) && (Object)(object)_heightBarsUI != (Object)null) { _heightBarsUI.SetExpanded(!_heightBarsUI.IsExpanded); } if ((Object)(object)_heightBarsUI == (Object)null) { return; } _stableTimer += Time.deltaTime; if (_stableTimer >= 5f) { _stableTimer = 0f; _removedNames.Clear(); foreach (string appliedName in _appliedNames) { if (!_backNames.Contains(appliedName)) { _removedNames.Add(appliedName); } } foreach (string removedName in _removedNames) { _heightBarsUI.RemovePlayer(removedName); } foreach (RemotePlayerData item in _back) { _heightBarsUI.UpdatePlayer(item); } _heightBarsUI.SetPriorityPlayer(priorityPlayerName); _appliedNames.Clear(); foreach (string backName in _backNames) { _appliedNames.Add(backName); } _back.Clear(); _backNames.Clear(); _source.Clear(); _source.AddRange(Singleton.Instance.GetAllPlayers()); _cursor = 0; return; } if (_source.Count == 0) { _source.AddRange(Singleton.Instance.GetAllPlayers()); } if (_cursor < _source.Count) { RemotePlayerData remotePlayerData = _source[_cursor++]; if (remotePlayerData != null && _backNames.Add(remotePlayerData.PlayerName)) { _back.Add(remotePlayerData); } } } } public class InputDisabledUI : Singleton { private GameObject uiContainer; public void Show() { GameObject obj = uiContainer; if (obj != null) { obj.SetActive(true); } } public void Hide() { GameObject obj = uiContainer; if (obj != null) { obj.SetActive(false); } } protected override void Initialize() { try { CreateUI(); Hide(); Plugin.Logger.LogMessage((object)"InputDisabledUI initialized"); } catch (Exception ex) { Plugin.Logger.LogError((object)("Error initializing InputDisabledUI: " + ex.Message + " \n " + ex.StackTrace)); } } private void CreateUI() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown //IL_0072: 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_0087: Expected O, but got Unknown //IL_00b0: 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_00da: 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_00fa: 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_014d: Unknown result type (might be due to invalid IL or missing references) try { Plugin.Logger.LogMessage((object)"Creating InputDisabledUI"); uiContainer = new GameObject("InputDisabledUI"); uiContainer.transform.SetParent(((Component)this).transform, false); Canvas val = uiContainer.AddComponent(); val.renderMode = (RenderMode)0; val.sortingOrder = 500; CanvasScaler val2 = uiContainer.AddComponent(); val2.uiScaleMode = (ScaleMode)1; val2.referenceResolution = new Vector2(1920f, 1080f); GameObject val3 = new GameObject("Panel"); val3.transform.SetParent(uiContainer.transform, false); RectTransform val4 = val3.AddComponent(); val4.anchorMin = new Vector2(0.5f, 0.5f); val4.anchorMax = new Vector2(0.5f, 0.5f); val4.pivot = new Vector2(0.5f, 0.5f); val4.anchoredPosition = Vector2.zero; val4.sizeDelta = new Vector2(840f, 160f); Image val5 = val3.AddComponent(); ((Graphic)val5).color = new Color(0f, 0f, 0f, 0.7f); PeakText val6 = MenuAPI.CreateText("FFS Peak : INPUTS DISABLED"); ((Component)val6).transform.SetParent(val3.transform, false); val6.SetColor(Color.red); val6.SetFontSize(32f); ElementExtensions.AlignToParent(val6, (UIAlignment)4); } catch (Exception ex) { Plugin.Logger.LogError((object)("Error initializing InputDisabledUI: " + ex.Message + " \n " + ex.StackTrace)); } } } public class LevelPlayerCountUI : MonoBehaviour { private PeakText countText; private GameObject uiContainer; private string currentLevel = ""; private int _serverPlayerCount; private ManualLogSource logger => Plugin.Logger; public void Initialize() { CreateUI(); logger.LogMessage((object)"LevelPlayerCountUI initialized"); } public void SetCurrentLevel(string levelName) { currentLevel = levelName; UpdateDisplay(); } public void UpdateLevelStats(Dictionary levelCounts) { _serverPlayerCount = ((!string.IsNullOrEmpty(currentLevel) && levelCounts.TryGetValue(currentLevel, out var value)) ? value : 0); UpdateDisplay(); } public void Show() { if ((Object)(object)uiContainer != (Object)null) { uiContainer.SetActive(true); } } public void Hide() { if ((Object)(object)uiContainer != (Object)null) { uiContainer.SetActive(false); } } private void CreateUI() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown //IL_0060: 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_0075: Expected O, but got Unknown //IL_009e: 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_00c8: 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_00f2: 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_0129: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Expected O, but got Unknown //IL_014e: 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_0170: 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_01f3: Unknown result type (might be due to invalid IL or missing references) uiContainer = new GameObject("LevelPlayerCountUI"); uiContainer.transform.SetParent(((Component)this).transform, false); Canvas val = uiContainer.AddComponent(); val.renderMode = (RenderMode)0; val.sortingOrder = 100; CanvasScaler val2 = uiContainer.AddComponent(); val2.uiScaleMode = (ScaleMode)1; val2.referenceResolution = new Vector2(1920f, 1080f); GameObject val3 = new GameObject("Panel"); val3.transform.SetParent(uiContainer.transform, false); RectTransform val4 = val3.AddComponent(); val4.anchorMin = new Vector2(0f, 1f); val4.anchorMax = new Vector2(0f, 1f); val4.pivot = new Vector2(0f, 1f); val4.anchoredPosition = new Vector2(20f, -40f); val4.sizeDelta = new Vector2(220f, 60f); Image val5 = val3.AddComponent(); ((Graphic)val5).color = new Color(0f, 0f, 0f, 0.7f); GameObject val6 = new GameObject("CountText"); val6.transform.SetParent(val3.transform, false); RectTransform val7 = val6.AddComponent(); val7.anchorMin = Vector2.zero; val7.anchorMax = Vector2.one; val7.offsetMin = new Vector2(10f, 10f); val7.offsetMax = new Vector2(-10f, -10f); countText = val6.AddComponent(); ((TMP_Text)countText.TextMesh).enableAutoSizing = true; ((TMP_Text)countText.TextMesh).fontSizeMin = 18f; ((TMP_Text)countText.TextMesh).fontSizeMax = 22f; ((TMP_Text)countText.TextMesh).fontSize = 22f; countText.SetColor(Color.white); ((TMP_Text)countText.TextMesh).alignment = (TextAlignmentOptions)514; ((TMP_Text)countText.TextMesh).fontStyle = (FontStyles)16; ((TMP_Text)countText.TextMesh).outlineWidth = 0.1f; UpdateDisplay(); } public void UpdateDisplay() { if (!((Object)(object)countText == (Object)null)) { if (string.IsNullOrEmpty(currentLevel)) { countText.SetText("Not in level"); return; } int serverPlayerCount = _serverPlayerCount; string text = (Plugin.LobbyPlayerLimit.HasValue ? $"{serverPlayerCount}/{Plugin.LobbyPlayerLimit.Value}" : $"{serverPlayerCount}"); countText.SetText("Players in " + currentLevel + ":\n" + text + ""); } } } public class LevelPlayerCountUIManager : Singleton { private LevelPlayerCountUI ui; private static readonly object instanceLock = new object(); private ManualLogSource logger => Plugin.Logger; public static LevelPlayerCountUI GetUI() { if ((Object)(object)Singleton.Instance.ui == (Object)null) { Singleton.Instance.Initialize(); } return Singleton.Instance.ui; } protected override void Initialize() { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown if ((Object)(object)ui != (Object)null) { logger.LogWarning((object)"LevelPlayerCountUI already initialized"); return; } GameObject val = new GameObject("LevelPlayerCountUI"); val.transform.SetParent(((Component)this).transform, false); ui = val.AddComponent(); ui.Initialize(); UpdateDisplay(); logger.LogMessage((object)"LevelPlayerCountUIManager initialized"); } public void UpdateLevelStats(Dictionary levelCounts) { if ((Object)(object)ui != (Object)null) { ui.UpdateLevelStats(levelCounts); } } public void SetCurrentLevel(string levelName) { if ((Object)(object)ui != (Object)null) { ui.SetCurrentLevel(levelName); } } public void Show() { if ((Object)(object)ui != (Object)null) { ui.Show(); } } public void Hide() { if ((Object)(object)ui != (Object)null) { ui.Hide(); } } public void UpdateDisplay() { if ((Object)(object)ui != (Object)null) { ui.UpdateDisplay(); } } } public class CreateLobbyUI : MonoBehaviour { private UIDocument uiDocument; private VisualElement root; private TextField nameField; private TextField passwordField; private TextField stateField; private Button createButton; private Button closeButton; private HashSet existingLobbies = new HashSet(); private Action onLobbyCreated; private bool isVisible; protected LobbyManagerUI lobbyManagerUI; public void Initialize(LobbyManagerUI lobbyManagerUI, PanelSettings panelSettings, HashSet lobbies, Action onCreated) { this.lobbyManagerUI = lobbyManagerUI; existingLobbies = lobbies ?? new HashSet(); onLobbyCreated = onCreated; LoadUIFromAssetBundle(panelSettings); Hide(); } private void LoadUIFromAssetBundle(PanelSettings panelSettings) { //IL_0087: 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_00b7: 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_00d7: 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_0112: 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_0127: Unknown result type (might be due to invalid IL or missing references) try { VisualTreeAsset val = Plugin.FfsPeakAssets.LoadAsset("Assets/FFSPeak/CreateLobby.uxml"); if ((Object)(object)val == (Object)null) { Plugin.Logger.LogError((object)"CreateLobby.uxml not found in asset bundle!"); return; } uiDocument = ((Component)this).gameObject.AddComponent(); uiDocument.panelSettings = panelSettings; uiDocument.visualTreeAsset = val; uiDocument.sortingOrder = 200f; root = uiDocument.rootVisualElement; root.style.flexGrow = StyleFloat.op_Implicit(0f); root.style.flexShrink = StyleFloat.op_Implicit(0f); root.style.position = StyleEnum.op_Implicit((Position)1); root.style.left = new StyleLength(new Length(50f, (LengthUnit)1)); root.style.top = new StyleLength(new Length(50f, (LengthUnit)1)); root.style.translate = new StyleTranslate(new Translate(new Length(-50f, (LengthUnit)1), new Length(-50f, (LengthUnit)1))); BindUIElements(); Plugin.Logger.LogInfo((object)"CreateLobby UI created successfully from UXML"); } catch (Exception ex) { Plugin.Logger.LogError((object)("Error loading CreateLobby UI from asset bundle: " + ex.Message + "\n" + ex.StackTrace)); } } private void BindUIElements() { nameField = UQueryExtensions.Q(root, "Name", (string)null); passwordField = UQueryExtensions.Q(root, "Password", (string)null); stateField = UQueryExtensions.Q(root, "State", (string)null); createButton = UQueryExtensions.Q