Decompiled source of PingItems v1.6.2
PingItems.dll
Decompiled 3 months ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using Photon.Pun; using PingItems.Adapters.Animals; using PingItems.Adapters.Celestial; using PingItems.Adapters.Items; using PingItems.Adapters.SpecialObjects; using PingItems.Common; using PingItems.Common.Interfaces; using PingItems.Configuration; using PingItems.Core; using PingItems.Core.Highlighting; using PingItems.Core.Management; using PingItems.Factories; using PingItems.Pooling; using PingItems.Services; using PingItems.Spatial; using TMPro; using UnityEngine; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("PingItems")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.6.2.0")] [assembly: AssemblyInformationalVersion("1.6.2")] [assembly: AssemblyProduct("Ping Items")] [assembly: AssemblyTitle("PingItems")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.6.2.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace PingItems { [BepInPlugin("com.memiczny.peak.pingitems", "Ping Items", "1.6.2")] [BepInProcess("PEAK.exe")] public class Plugin : BaseUnityPlugin { public static class PluginInfo { public const string PLUGIN_GUID = "com.memiczny.peak.pingitems"; public const string PLUGIN_NAME = "Ping Items"; public const string PLUGIN_VERSION = "1.6.2"; } public static ManualLogSource Logger { get; private set; } public static Plugin Instance { get; private set; } private void Awake() { Instance = this; Logger = ((BaseUnityPlugin)this).Logger; try { PingItemsConfig.Initialize(((BaseUnityPlugin)this).Config); Logger.LogInfo((object)"⚙\ufe0f Configuration initialized"); ApplyHarmonyPatches(); InitializeUISystem(); PingService.Initialize(); Logger.LogInfo((object)"\ud83d\udce1 Ping service initialized"); SmartObjectManager.Initialize(); Logger.LogInfo((object)"\ud83c\udfaf Smart object manager initialized"); OptimizedPingableFactory.Initialize(); Logger.LogInfo((object)"⚡ Performance optimizations initialized"); InitializeCustomLocalization(); InitializePoolingSystems(); Logger.LogInfo((object)"\ud83d\ude80 Ping Items v1.6.2 loaded successfully!"); } catch (Exception arg) { Logger.LogError((object)$"❌ Failed to initialize plugin: {arg}"); } } private static void ApplyHarmonyPatches() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) try { new Harmony("com.memiczny.peak.pingitems").PatchAll(); Logger.LogInfo((object)"\ud83d\udd27 Harmony patches applied successfully"); } catch (Exception arg) { Logger.LogError((object)$"❌ Failed to apply Harmony patches: {arg}"); throw; } } private static void InitializePoolingSystems() { ObjectPool.Initialize(); Logger.LogInfo((object)"\ud83c\udfca Pooling systems initialized (will populate when prefab available)"); } private static void InitializeCustomLocalization() { try { CustomLocalization.IntegrateWithGameLocalization(); Logger.LogInfo((object)"\ud83c\udf0d Custom localization system integrated"); } catch (Exception ex) { Logger.LogWarning((object)("⚠\ufe0f Failed to initialize custom localization: " + ex.Message)); } } public static void PopulateAllPools() { try { UIManager instance = UIManager.Instance; if ((Object)(object)instance != (Object)null) { instance.PopulatePools(); } else { Logger.LogWarning((object)"⚠\ufe0f UIManager not available for pool population"); } } catch (Exception ex) { Logger.LogWarning((object)("⚠\ufe0f Failed to populate pools: " + ex.Message)); } } private static void WriteLocalizedTextToFile() { try { string text = Path.Combine(Paths.ConfigPath, "LocalizedText.txt"); File.WriteAllLines(text, LocalizedText.mainTable.Select((KeyValuePair<string, List<string>> entry) => entry.Key + "=" + entry.Value.Aggregate((string a, string b) => a + "," + b))); Logger.LogInfo((object)("\ud83d\udcdd Localized text written to " + text)); } catch (Exception arg) { Logger.LogError((object)$"❌ Failed to write localized text to file: {arg}"); } } private static void InitializeUISystem() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown try { if ((Object)(object)UIManager.Instance == (Object)null) { GameObject val = new GameObject("PingItems_UIManager"); val.AddComponent<UIManager>(); Object.DontDestroyOnLoad((Object)val); } Logger.LogInfo((object)"\ud83c\udfa8 UI system initialized"); } catch (Exception arg) { Logger.LogError((object)$"❌ Failed to initialize UI system: {arg}"); throw; } } private void OnDestroy() { try { ObjectPool.Cleanup(); Logger.LogInfo((object)"\ud83e\uddf9 Plugin cleanup completed"); } catch (Exception ex) { Logger.LogWarning((object)("⚠\ufe0f Error during plugin cleanup: " + ex.Message)); } } } } namespace PingItems.Spatial { public class SpatialGrid { private readonly float _cellSize; private readonly Dictionary<Vector2Int, List<IPingable>> _grid; public SpatialGrid(float cellSize = 50f) { _cellSize = cellSize; _grid = new Dictionary<Vector2Int, List<IPingable>>(); } private Vector2Int GetCellCoords(Vector3 worldPos) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) return new Vector2Int(Mathf.FloorToInt(worldPos.x / _cellSize), Mathf.FloorToInt(worldPos.z / _cellSize)); } public void AddObject(IPingable pingable) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002b: 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_0039: Unknown result type (might be due to invalid IL or missing references) try { if (!((Object)(object)pingable?.GetGameObject() == (Object)null)) { Vector3 center = pingable.GetCenter(); Vector2Int cellCoords = GetCellCoords(center); if (!_grid.ContainsKey(cellCoords)) { _grid[cellCoords] = new List<IPingable>(); } _grid[cellCoords].Add(pingable); } } catch (Exception ex) { if (PingItemsConfig.EnableDebugLogging.Value) { Plugin.Logger.LogDebug((object)("Failed to add object to spatial grid: " + ex.Message)); } } } public List<IPingable> FindNearbyObjects(Vector3 position, float radius) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: 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_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) List<IPingable> list = new List<IPingable>(); float num = radius * radius; Vector2Int cellCoords = GetCellCoords(position); int num2 = Mathf.CeilToInt(radius / _cellSize); Vector2Int key = default(Vector2Int); for (int i = -num2; i <= num2; i++) { for (int j = -num2; j <= num2; j++) { ((Vector2Int)(ref key))..ctor(((Vector2Int)(ref cellCoords)).x + i, ((Vector2Int)(ref cellCoords)).y + j); if (!_grid.TryGetValue(key, out var value)) { continue; } foreach (IPingable item in value) { if (!((Object)(object)item?.GetGameObject() == (Object)null)) { Vector3 val = item.GetCenter() - position; if (((Vector3)(ref val)).sqrMagnitude <= num) { list.Add(item); } } } } } return list; } public void Clear() { _grid.Clear(); } public (int totalCells, int totalObjects, float avgObjectsPerCell) GetStats() { int num = 0; foreach (List<IPingable> value in _grid.Values) { num += value.Count; } float item = ((_grid.Count > 0) ? ((float)num / (float)_grid.Count) : 0f); return (_grid.Count, num, item); } } } namespace PingItems.Services { public static class PingService { private static readonly List<PingHighlighter> _activeHighlights = new List<PingHighlighter>(); private static readonly Dictionary<GameObject, PingHighlighter> _itemToGroupMapping = new Dictionary<GameObject, PingHighlighter>(); private static float _lastPingTime = 0f; public static void Initialize() { _activeHighlights.Clear(); Application.quitting += Cleanup; } public static void Cleanup() { foreach (PingHighlighter item in from h in _activeHighlights.AsEnumerable() where (Object)(object)h != (Object)null select h) { item.Cleanup(); } _activeHighlights.Clear(); _itemToGroupMapping.Clear(); Application.quitting -= Cleanup; } public static void ProcessPing(Vector3 pingPosition, Color playerColor, string playerName, Character pingingCharacter = null) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) try { if (!ShouldProcessPing()) { return; } if (PingItemsConfig.EnableDebugLogging.Value) { Plugin.Logger.LogDebug((object)$"Processing ping at position: {pingPosition}, player: {playerName}"); } List<IPingable> list = OptimizedPingableFactory.FindPingablesForPing(pingPosition, pingingCharacter, PingItemsConfig.DetectionRadius.Value, PingItemsConfig.LuggageDetectionRadius.Value); if (list.Count == 0) { if (PingItemsConfig.EnableDebugLogging.Value) { Plugin.Logger.LogDebug((object)"No pingables found near ping position"); } return; } EnforcePingLimit(); if (TryRefreshExistingHighlights(list, pingPosition)) { if (PingItemsConfig.EnableDebugLogging.Value) { Plugin.Logger.LogDebug((object)"Refreshed existing highlights"); } return; } if (PingItemsConfig.EnableItemGrouping.Value) { CreateGroupedHighlights(list, pingPosition, playerColor, playerName); } else { CreateIndividualHighlights(list, pingPosition, playerColor, playerName); } if (PingItemsConfig.EnableDebugLogging.Value) { Plugin.Logger.LogDebug((object)$"Created {list.Count} new ping highlights"); } _lastPingTime = Time.time; } catch (Exception ex) { Plugin.Logger.LogError((object)("Error processing ping: " + ex.Message)); } } public static void ProcessCelestialPing(Vector3 pingPosition, Color playerColor, string playerName, Character pingingCharacter, List<IPingable> celestialBodies) { //IL_0080: 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_0075: 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) try { if (celestialBodies == null || celestialBodies.Count == 0) { DebugLogger.Log("No celestial bodies provided for celestial ping"); return; } DebugLogger.Log($"Processing celestial ping for {celestialBodies.Count} celestial bodies"); foreach (IPingable celestialBody in celestialBodies) { try { string displayName = celestialBody.GetDisplayName(); PingHighlighter pingHighlighter = FindExistingCelestialHighlight(displayName); if ((Object)(object)pingHighlighter != (Object)null) { DebugLogger.Log("Refreshing existing celestial highlight for " + displayName); RefreshCelestialHighlight(pingHighlighter, celestialBody, pingPosition, playerColor, playerName); continue; } PingHighlighter pingHighlighter2 = CreateCelestialHighlight(celestialBody, pingPosition, playerColor, playerName); if ((Object)(object)pingHighlighter2 != (Object)null) { _activeHighlights.Add(pingHighlighter2); DebugLogger.Log("Created new celestial ping highlight for " + displayName); } } catch (Exception ex) { Plugin.Logger.LogWarning((object)("Failed to process celestial body " + celestialBody.GetDisplayName() + ": " + ex.Message)); } } _lastPingTime = Time.time; DebugLogger.Log("Celestial ping processing completed"); } catch (Exception ex2) { Plugin.Logger.LogError((object)("Error processing celestial ping: " + ex2.Message)); } } private static bool ShouldProcessPing() { if (PingItemsConfig.DetectionRadius.Value <= 0.01f && PingItemsConfig.LuggageDetectionRadius.Value <= 0.01f) { return false; } float num = Time.time - _lastPingTime; if (num < PingItemsConfig.PingCooldownDelay.Value) { if (PingItemsConfig.EnableDebugLogging.Value) { Plugin.Logger.LogDebug((object)$"Ping cooldown active: {num:F2}s < {PingItemsConfig.PingCooldownDelay.Value:F2}s"); } return false; } return true; } private static void EnforcePingLimit() { int value = PingItemsConfig.MaxActivePings.Value; if (value <= 0) { return; } while (_activeHighlights.Count >= value) { PingHighlighter pingHighlighter = _activeHighlights.FirstOrDefault(); if ((Object)(object)pingHighlighter != (Object)null) { if (PingItemsConfig.EnableDebugLogging.Value) { Plugin.Logger.LogDebug((object)$"Removing oldest ping to enforce limit of {value}"); } RemoveHighlight(pingHighlighter); continue; } break; } } public static void RemoveHighlight(PingHighlighter highlighter) { if ((Object)(object)highlighter == (Object)null) { return; } try { if (_activeHighlights.Remove(highlighter)) { CleanupGroupMapping(highlighter); UIManager instance = UIManager.Instance; if ((Object)(object)instance != (Object)null) { highlighter.Cleanup(); instance.ReleaseHighlighter(highlighter); } else { highlighter.Cleanup(); ObjectPool.ReturnObject(((Component)highlighter).gameObject, ObjectPool.ObjectType.Highlighter); } } } catch (Exception ex) { Plugin.Logger.LogWarning((object)("Failed to remove highlighter: " + ex.Message)); } } private static PingHighlighter FindExistingCelestialHighlight(string celestialBodyName) { foreach (PingHighlighter activeHighlight in _activeHighlights) { if ((Object)(object)activeHighlight == (Object)null) { continue; } try { FieldInfo field = typeof(PingHighlighter).GetField("_targetPingable", BindingFlags.Instance | BindingFlags.NonPublic); if (field != null && field.GetValue(activeHighlight) as IPingable is CelestialBodyPingableAdapter celestialBodyPingableAdapter && celestialBodyPingableAdapter.GetDisplayName().Equals(celestialBodyName, StringComparison.OrdinalIgnoreCase)) { return activeHighlight; } } catch (Exception ex) { Plugin.Logger.LogWarning((object)("Error checking celestial highlight: " + ex.Message)); } } return null; } private static void RefreshCelestialHighlight(PingHighlighter existingHighlight, IPingable celestialBody, Vector3 pingPosition, Color playerColor, string playerName) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) try { string displayName = celestialBody.GetDisplayName(); DebugLogger.Log("Refreshing celestial highlight for " + displayName + " - removing old and creating new"); RemoveHighlight(existingHighlight); PingHighlighter pingHighlighter = CreateCelestialHighlight(celestialBody, pingPosition, playerColor, playerName); if ((Object)(object)pingHighlighter != (Object)null) { _activeHighlights.Add(pingHighlighter); DebugLogger.Log("Successfully refreshed celestial highlight for " + displayName); } } catch (Exception ex) { Plugin.Logger.LogWarning((object)("Failed to refresh celestial highlight: " + ex.Message)); } } private static bool TryRefreshExistingHighlights(List<IPingable> pingables, Vector3 pingPosition) { //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) bool result = false; HashSet<PingHighlighter> hashSet = new HashSet<PingHighlighter>(); foreach (IPingable pingable in pingables) { GameObject gameObject = pingable.GetGameObject(); if ((Object)(object)gameObject == (Object)null) { continue; } PingHighlighter pingHighlighter = _activeHighlights.FirstOrDefault((PingHighlighter h) => (Object)(object)h?.TargetGameObject == (Object)(object)gameObject); PingHighlighter value; if ((Object)(object)pingHighlighter != (Object)null && !hashSet.Contains(pingHighlighter)) { if (pingHighlighter.IsGroupedPing) { RefreshGroupHighlight(pingHighlighter, pingables, pingPosition); } else { pingHighlighter.Init(pingable, pingPosition); } hashSet.Add(pingHighlighter); result = true; } else if (_itemToGroupMapping.TryGetValue(gameObject, out value) && (Object)(object)value != (Object)null && !hashSet.Contains(value)) { RefreshGroupHighlight(value, pingables, pingPosition); hashSet.Add(value); result = true; } } return result; } private static void CreateIndividualHighlights(List<IPingable> pingables, Vector3 pingPosition, Color playerColor, string playerName) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) foreach (IPingable pingable in pingables) { CreateIndividualHighlight(pingable, pingPosition, playerColor, playerName); } } private static void CreateGroupedHighlights(List<IPingable> pingables, Vector3 pingPosition, Color playerColor, string playerName) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) foreach (List<IPingable> item in GroupPingablesByType(ExpandItemClusters(pingables))) { CreateGroupHighlight(item, pingPosition, playerColor, playerName); } } private static void CreateIndividualHighlight(IPingable pingable, Vector3 pingPosition, Color playerColor, string playerName) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) try { PingHighlighter pingHighlighter = CreateNewHighlight(pingable, pingPosition, playerColor, playerName); if ((Object)(object)pingHighlighter != (Object)null) { _activeHighlights.Add(pingHighlighter); } } catch (Exception ex) { Plugin.Logger.LogWarning((object)("Failed to create individual highlight for " + pingable?.GetDisplayName() + ": " + ex.Message)); } } private static void CreateGroupHighlight(List<IPingable> group, Vector3 pingPosition, Color playerColor, string playerName) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) try { PingHighlighter pingHighlighter = CreateNewGroupedHighlight(group, pingPosition, playerColor, playerName); if ((Object)(object)pingHighlighter != (Object)null) { _activeHighlights.Add(pingHighlighter); UpdateGroupMapping(pingHighlighter, group); } } catch (Exception ex) { Plugin.Logger.LogWarning((object)("Failed to create group highlight: " + ex.Message)); } } private static void RefreshGroupHighlight(PingHighlighter groupHighlight, List<IPingable> newPingables, Vector3 pingPosition) { //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) if (groupHighlight == null || !groupHighlight.IsGroupedPing) { return; } try { List<IPingable> currentGroupItems = GetGroupItems(groupHighlight); if (PingItemsConfig.EnableItemGrouping.Value) { List<IPingable> source = ExpandItemClusters(newPingables); string groupItemType = currentGroupItems.FirstOrDefault()?.GetDisplayName(); if (!string.IsNullOrEmpty(groupItemType)) { List<IPingable> source2 = source.Where((IPingable item) => item.GetDisplayName() == groupItemType).ToList(); List<IPingable> list = currentGroupItems.Concat(source2.Where((IPingable newItem) => !ContainsItem(currentGroupItems, newItem))).ToList(); groupHighlight.Init(list, pingPosition); UpdateGroupMapping(groupHighlight, list); } } else { groupHighlight.Init(currentGroupItems, pingPosition); } } catch (Exception ex) { Plugin.Logger.LogWarning((object)("Failed to refresh group highlight: " + ex.Message)); } } private static List<IPingable> ExpandItemClusters(List<IPingable> initialItems) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) if (initialItems.Count == 0) { return initialItems; } try { List<IPingable> allItems = PingableFactory.FindPingablesNearPosition(Vector3.zero, float.MaxValue, float.MaxValue); List<IPingable> list = new List<IPingable>(); HashSet<string> hashSet = new HashSet<string>(); foreach (IPingable initialItem in initialItems) { string displayName = initialItem.GetDisplayName(); if (hashSet.Add(displayName)) { List<IPingable> collection = FindCompleteClusterForType(initialItem, allItems); list.AddRange(collection); } } return (from item in list group item by item.GetGameObject() into @group select @group.First()).ToList(); } catch (Exception ex) { Plugin.Logger.LogWarning((object)("Cluster expansion failed, using original items: " + ex.Message)); return initialItems; } } private static List<IPingable> FindCompleteClusterForType(IPingable seedItem, List<IPingable> allItems) { HashSet<IPingable> processed = new HashSet<IPingable>(); return BuildItemCluster(seedItem, allItems, processed); } private static List<IPingable> GetGroupItems(PingHighlighter groupHighlight) { List<IPingable> list = new List<IPingable>(); foreach (KeyValuePair<GameObject, PingHighlighter> item in _itemToGroupMapping) { if ((Object)(object)item.Value == (Object)(object)groupHighlight) { IPingable pingable = CreatePingableFromGameObject(item.Key); if (pingable != null) { list.Add(pingable); } } } return list; } private static void UpdateGroupMapping(PingHighlighter groupHighlight, List<IPingable> items) { foreach (KeyValuePair<GameObject, PingHighlighter> item in _itemToGroupMapping.Where((KeyValuePair<GameObject, PingHighlighter> kvp) => (Object)(object)kvp.Value == (Object)(object)groupHighlight).ToList()) { _itemToGroupMapping.Remove(item.Key); } foreach (IPingable item2 in items) { GameObject gameObject = item2.GetGameObject(); if ((Object)(object)gameObject != (Object)null) { _itemToGroupMapping[gameObject] = groupHighlight; } } } private static IPingable CreatePingableFromGameObject(GameObject gameObject) { if ((Object)(object)gameObject == (Object)null) { return null; } Item component = gameObject.GetComponent<Item>(); if ((Object)(object)component != (Object)null) { return new ItemPingableAdapter(component); } Luggage component2 = gameObject.GetComponent<Luggage>(); if ((Object)(object)component2 != (Object)null) { return new LuggagePingableAdapter(component2); } MirageLuggage component3 = gameObject.GetComponent<MirageLuggage>(); if ((Object)(object)component3 != (Object)null) { return new MirageLuggagePingableAdapter(component3); } return null; } private static bool ContainsItem(List<IPingable> items, IPingable targetItem) { GameObject targetGameObject = targetItem?.GetGameObject(); if ((Object)(object)targetGameObject == (Object)null) { return false; } return items.Any((IPingable item) => (Object)(object)item?.GetGameObject() == (Object)(object)targetGameObject); } private static void CleanupGroupMapping(PingHighlighter highlighter) { foreach (KeyValuePair<GameObject, PingHighlighter> item in _itemToGroupMapping.Where((KeyValuePair<GameObject, PingHighlighter> kvp) => (Object)(object)kvp.Value == (Object)(object)highlighter).ToList()) { _itemToGroupMapping.Remove(item.Key); } } private static PingHighlighter CreateNewHighlight(IPingable pingable, Vector3 pingPoint, Color playerColor, string playerName) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) try { UIManager instance = UIManager.Instance; if ((Object)(object)instance == (Object)null) { return null; } PingHighlighter pingHighlighter = instance.RentHighlighter(); if ((Object)(object)pingHighlighter == (Object)null) { return null; } pingHighlighter.PlayerColor = playerColor; pingHighlighter.PlayerName = playerName; pingHighlighter.Init(pingable, pingPoint); return pingHighlighter; } catch (Exception ex) { Plugin.Logger.LogWarning((object)("Failed to create highlight: " + ex.Message)); return null; } } private static PingHighlighter CreateCelestialHighlight(IPingable pingable, Vector3 pingPoint, Color playerColor, string playerName) { //IL_002b: 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) try { UIManager instance = UIManager.Instance; if ((Object)(object)instance == (Object)null) { return null; } PingHighlighter pingHighlighter = instance.RentHighlighter(); if ((Object)(object)pingHighlighter == (Object)null) { return null; } pingHighlighter.PlayerColor = playerColor; pingHighlighter.PlayerName = playerName; pingHighlighter.Init(pingable, pingPoint); FieldInfo field = typeof(PingHighlighter).GetField("_distanceFadeProvider", BindingFlags.Instance | BindingFlags.NonPublic); if (field != null) { field.SetValue(pingHighlighter, new CelestialDistanceFadeProvider()); DebugLogger.Log("Applied celestial distance fade provider for infinite visibility"); } return pingHighlighter; } catch (Exception ex) { Plugin.Logger.LogWarning((object)("Failed to create celestial highlight: " + ex.Message)); return null; } } private static List<List<IPingable>> GroupPingablesByType(List<IPingable> pingables) { List<List<IPingable>> list = new List<List<IPingable>>(); HashSet<IPingable> hashSet = new HashSet<IPingable>(); foreach (IPingable pingable in pingables) { if (!hashSet.Contains(pingable)) { List<IPingable> list2 = BuildItemCluster(pingable, pingables, hashSet); if (list2.Count > 0) { list.Add(list2); } } } return list; } private static List<IPingable> BuildItemCluster(IPingable startItem, List<IPingable> allItems, HashSet<IPingable> processed) { List<IPingable> list = new List<IPingable>(); Queue<IPingable> queue = new Queue<IPingable>(); string displayName = startItem.GetDisplayName(); float value = PingItemsConfig.GroupingRadius.Value; int value2 = PingItemsConfig.MaxGroupSize.Value; queue.Enqueue(startItem); while (queue.Count > 0 && list.Count < value2) { IPingable pingable = queue.Dequeue(); if (processed.Contains(pingable)) { continue; } if (list.Count >= value2) { if (PingItemsConfig.EnableDebugLogging.Value) { Plugin.Logger.LogDebug((object)$"Stopping cluster expansion: reached max group size of {value2}"); } break; } processed.Add(pingable); list.Add(pingable); foreach (IPingable item in from n in FindItemNeighbors(pingable, allItems, displayName, value, processed) where !processed.Contains(n) select n) { if (list.Count + queue.Count < value2) { queue.Enqueue(item); } } } if (PingItemsConfig.EnableDebugLogging.Value && list.Count > 1) { Plugin.Logger.LogDebug((object)$"Built cluster of {list.Count} {displayName} items (max: {value2})"); } return list; } private static List<IPingable> FindItemNeighbors(IPingable centerItem, List<IPingable> allItems, string itemType, float radius, HashSet<IPingable> processed) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_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) List<IPingable> list = new List<IPingable>(); Vector3 center = centerItem.GetCenter(); foreach (IPingable allItem in allItems) { if (!processed.Contains(allItem) && allItem != centerItem && !(allItem.GetDisplayName() != itemType) && Vector3.Distance(center, allItem.GetCenter()) <= radius) { list.Add(allItem); } } return list; } private static PingHighlighter CreateNewGroupedHighlight(List<IPingable> group, Vector3 pingPoint, Color playerColor, string playerName) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) try { UIManager instance = UIManager.Instance; if ((Object)(object)instance == (Object)null) { return null; } PingHighlighter pingHighlighter = instance.RentHighlighter(); if ((Object)(object)pingHighlighter == (Object)null) { return null; } pingHighlighter.PlayerColor = playerColor; pingHighlighter.PlayerName = playerName; pingHighlighter.Init(group, pingPoint); return pingHighlighter; } catch (Exception ex) { Plugin.Logger.LogWarning((object)("Failed to create grouped highlight: " + ex.Message)); return null; } } } } namespace PingItems.Pooling { public static class ObjectPool { public enum ObjectType { Generic, Reticle, Highlighter, Label, EdgeText } private static readonly Dictionary<ObjectType, Queue<GameObject>> _availableObjects = new Dictionary<ObjectType, Queue<GameObject>>(); private static readonly Dictionary<ObjectType, HashSet<GameObject>> _activeObjects = new Dictionary<ObjectType, HashSet<GameObject>>(); private const int MAX_POOL_SIZE_PER_TYPE = 30; private const int INITIAL_POOL_SIZE_PER_TYPE = 5; private static bool _initialized = false; public static void Initialize() { if (_initialized) { return; } foreach (ObjectType value in Enum.GetValues(typeof(ObjectType))) { _availableObjects[value] = new Queue<GameObject>(); _activeObjects[value] = new HashSet<GameObject>(); for (int i = 0; i < 5; i++) { GameObject val = CreatePooledObject(value); val.SetActive(false); _availableObjects[value].Enqueue(val); } } _initialized = true; Plugin.Logger.LogInfo((object)$"ObjectPool initialized with {5} objects per type"); } public static GameObject GetObject(ObjectType objectType = ObjectType.Generic) { EnsureInitialized(); GameObject val; if (_availableObjects[objectType].Count > 0) { val = _availableObjects[objectType].Dequeue(); ResetObjectState(val, objectType); } else { val = CreatePooledObject(objectType); } if ((Object)(object)val != (Object)null) { _activeObjects[objectType].Add(val); val.SetActive(true); } return val; } public static void ReturnObject(GameObject obj, ObjectType objectType = ObjectType.Generic) { if (!((Object)(object)obj == (Object)null)) { EnsureInitialized(); _activeObjects[objectType].Remove(obj); obj.SetActive(false); if (_availableObjects[objectType].Count < 30) { _availableObjects[objectType].Enqueue(obj); } else { Object.Destroy((Object)(object)obj); } } } public static void Cleanup() { foreach (ObjectType item in _availableObjects.Keys.ToList()) { while (_availableObjects[item].Count > 0) { GameObject val = _availableObjects[item].Dequeue(); if ((Object)(object)val != (Object)null) { Object.Destroy((Object)(object)val); } } _activeObjects[item].Where((GameObject obj) => (Object)(object)obj != (Object)null).ToList().ForEach((Action<GameObject>)Object.Destroy); _activeObjects[item].Clear(); } _availableObjects.Clear(); _activeObjects.Clear(); _initialized = false; Plugin.Logger.LogInfo((object)"ObjectPool cleaned up"); } public static string GetPoolStats() { StringBuilder stringBuilder = new StringBuilder(); foreach (ObjectType key in _availableObjects.Keys) { int count = _availableObjects[key].Count; int count2 = _activeObjects[key].Count; stringBuilder.AppendLine($"{key}: Available={count}, Active={count2}"); } return stringBuilder.ToString(); } private static void EnsureInitialized() { if (!_initialized) { Initialize(); } } private static GameObject CreatePooledObject(ObjectType objectType) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Expected O, but got Unknown //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Expected O, but got Unknown //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Expected O, but got Unknown //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Expected O, but got Unknown GameObject val; switch (objectType) { case ObjectType.Reticle: val = new GameObject("PooledReticle"); val.AddComponent<RectTransform>(); val.AddComponent<Image>(); break; case ObjectType.Highlighter: val = new GameObject("PooledHighlighter"); val.AddComponent<PingHighlighter>(); break; case ObjectType.Label: val = new GameObject("PooledLabel"); val.AddComponent<TextMeshProUGUI>(); break; case ObjectType.EdgeText: val = new GameObject("PooledEdgeText"); val.AddComponent<EdgeDistanceText>(); break; default: val = new GameObject("PooledObject"); val.AddComponent<RectTransform>(); break; } Object.DontDestroyOnLoad((Object)(object)val); return val; } private static void ResetObjectState(GameObject obj, ObjectType objectType) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0030: 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_0056: 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_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)obj == (Object)null) { return; } obj.transform.localScale = Vector3.one; obj.transform.localPosition = Vector3.zero; obj.transform.localRotation = Quaternion.identity; RectTransform component = obj.GetComponent<RectTransform>(); if ((Object)(object)component != (Object)null) { component.anchoredPosition = Vector2.zero; component.sizeDelta = Vector2.zero; component.offsetMin = Vector2.zero; component.offsetMax = Vector2.zero; } switch (objectType) { case ObjectType.Reticle: { Image component3 = obj.GetComponent<Image>(); if ((Object)(object)component3 != (Object)null) { ((Graphic)component3).color = Color.white; component3.sprite = null; } break; } case ObjectType.Label: case ObjectType.EdgeText: { TextMeshProUGUI component2 = obj.GetComponent<TextMeshProUGUI>(); if ((Object)(object)component2 != (Object)null) { ((TMP_Text)component2).text = ""; ((Graphic)component2).color = Color.white; ((TMP_Text)component2).fontSize = 12f; } break; } } } } } namespace PingItems.Patches { [HarmonyPatch(typeof(GUIManager), "InitReticleList")] public static class GUIManagerPatch { private static readonly ReticleResolver _reticleResolver = new ReticleResolver(); [HarmonyPostfix] public static void Postfix(GUIManager __instance) { try { CaptureReticle(__instance); CaptureFont(__instance); ConfigureCanvasFromHUD(); } catch (Exception ex) { Plugin.Logger.LogError((object)("❌ GUIManager patch failed: " + ex.Message)); } } private static void CaptureReticle(GUIManager guiManager) { try { GameObject configuredReticle = _reticleResolver.GetConfiguredReticle(guiManager); if ((Object)(object)configuredReticle != (Object)null) { Plugin.Logger.LogInfo((object)$"\ud83c\udfaf Captured reticle: {((Object)configuredReticle).name} ({PingItemsConfig.ReticleType.Value})"); UIManager.Instance?.SetReticlePrefab(configuredReticle); Plugin.PopulateAllPools(); } else { Plugin.Logger.LogWarning((object)"⚠\ufe0f No reticle captured from GUIManager"); } } catch (Exception ex) { Plugin.Logger.LogWarning((object)("⚠\ufe0f Failed to capture reticle: " + ex.Message)); } } private static void CaptureFont(GUIManager guiManager) { try { TMP_FontAsset val = (from textComponent in ((Component)guiManager).GetComponentsInChildren<TMP_Text>(true) select textComponent.font).FirstOrDefault((Func<TMP_FontAsset, bool>)((TMP_FontAsset f) => (Object)(object)f != (Object)null)); if ((Object)(object)val != (Object)null) { Plugin.Logger.LogInfo((object)("\ud83d\udd24 Captured font: " + ((Object)val).name)); UIManager.Instance?.SetGameFont(val); } } catch (Exception ex) { Plugin.Logger.LogError((object)("❌ Failed to capture font: " + ex.Message)); } } private static void ConfigureCanvasFromHUD() { try { UIManager instance = UIManager.Instance; if ((Object)(object)instance == (Object)null) { Plugin.Logger.LogWarning((object)"⚠\ufe0f UIManager not available for Canvas_HUD configuration"); return; } Canvas val = FindCanvasHUD(); if ((Object)(object)val != (Object)null) { instance.ConfigureCanvasFromHUD(val); } else { Plugin.Logger.LogInfo((object)"ℹ\ufe0f Canvas_HUD not found - using fallback configuration"); } } catch (Exception ex) { Plugin.Logger.LogError((object)("❌ Failed to configure canvas from Canvas_HUD: " + ex.Message)); } } private static Canvas FindCanvasHUD() { GameObject val = GameObject.Find("Canvas_HUD"); if ((Object)(object)val != (Object)null) { Canvas component = val.GetComponent<Canvas>(); if ((Object)(object)component != (Object)null) { Plugin.Logger.LogInfo((object)$"\ud83c\udfaf Found Canvas_HUD: {((Object)val).name} (sorting: {component.sortingOrder})"); return component; } } return null; } } [HarmonyPatch(typeof(PointPinger))] public static class PointPingerPatch { [HarmonyPatch("Update")] [HarmonyPrefix] private static bool Prefix_Update(PointPinger __instance) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_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_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) try { PhotonView val = (PhotonView)typeof(PointPinger).GetField("photonView", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(__instance); if (!val.IsMine) { return true; } if (!PingItemsConfig.EnableEnhancedPingSystem.Value) { return true; } FieldInfo field = typeof(PointPinger).GetField("coolDownLeft", BindingFlags.Instance | BindingFlags.NonPublic); float num = (float)field.GetValue(__instance); num -= Time.deltaTime; field.SetValue(__instance, num); if (num > 0f) { return false; } if (!__instance.character.input.pingWasPressed) { return false; } if (__instance.character.data.dead) { return false; } Vector3 position = ((Component)Camera.main).transform.position; Vector3 forward = ((Component)Camera.main).transform.forward; if (CelestialBodyDetectionService.DetectCelestialBodies(forward, position).Count > 0) { DebugLogger.Log("Detected celestial body ping - handling without raycast"); field.SetValue(__instance, __instance.coolDown); Vector3 val2 = position + forward * 1000f; Vector3 val3 = -forward; val.RPC("ReceivePoint_Rpc", (RpcTarget)0, new object[2] { val2, val3 }); return false; } return true; } catch (Exception arg) { Plugin.Logger.LogError((object)$"Error in PointPinger Update prefix: {arg}"); return true; } } [HarmonyPatch("Update")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> UpdateTranspiler(IEnumerable<CodeInstruction> instructions) { //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Expected O, but got Unknown List<CodeInstruction> list = new List<CodeInstruction>(instructions); if (!PingItemsConfig.EnableEnhancedPingSystem.Value) { Plugin.Logger.LogInfo((object)"\ud83d\udd04 Enhanced ping system disabled - skipping raycast patch"); return list; } for (int i = 0; i < list.Count - 1; i++) { if (list[i].opcode == OpCodes.Ldc_I4_1 && IsMethodCallWithName(list[i + 1], "ToLayerMask")) { list[i] = new CodeInstruction(OpCodes.Ldc_I4, (object)5); Plugin.Logger.LogInfo((object)"✅ Enhanced ping system enabled - patched raycast to use AllPhysicalExceptCharacter layers"); break; } } return list; } private static bool IsMethodCallWithName(CodeInstruction instruction, string methodName) { if (instruction.opcode == OpCodes.Call && instruction.operand is MethodInfo methodInfo) { return methodInfo.Name == methodName; } return false; } [HarmonyPatch("ReceivePoint_Rpc")] [HarmonyPostfix] private static void Postfix_ReceivePoint_Rpc(PointPinger __instance, Vector3 point, Vector3 hitNormal) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_005f: 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_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: 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) try { if (!PingItemsConfig.EnableEnhancedPingSystem.Value) { Plugin.Logger.LogDebug((object)"Enhanced ping system disabled - skipping item detection"); return; } Plugin.Logger.LogDebug((object)$"ReceivePoint_Rpc postfix called with point: {point}"); Color pingingPlayerColor = GetPingingPlayerColor(__instance); string pingingPlayerName = GetPingingPlayerName(__instance); Character val = __instance?.character; DebugLogger.Log("Checking for celestial body ping..."); Vector3 val2 = point - val.Center; List<IPingable> list = CelestialBodyDetectionService.DetectCelestialBodies(((Vector3)(ref val2)).normalized, val.Center); if (list.Count > 0) { DebugLogger.Log("Celestial bodies detected: " + string.Join(", ", list.Select((IPingable cb) => cb.GetDisplayName()))); PingService.ProcessCelestialPing(point, pingingPlayerColor, pingingPlayerName, val, list); } else { PingService.ProcessPing(point, pingingPlayerColor, pingingPlayerName, val); } } catch (Exception arg) { Plugin.Logger.LogError((object)$"Error in PointPinger ReceivePoint_Rpc postfix: {arg}"); } } private static Color GetPingingPlayerColor(PointPinger pointPinger) { //IL_0063: 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_0041: 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) try { if ((Object)(object)pointPinger?.character?.refs?.customization != (Object)null) { return pointPinger.character.refs.customization.PlayerColor; } } catch (Exception ex) { Plugin.Logger.LogWarning((object)("Failed to get pinging player color: " + ex.Message)); } return Color.cyan; } private static string GetPingingPlayerName(PointPinger pointPinger) { try { if (pointPinger != null) { Character character = pointPinger.character; if (((character != null) ? character.characterName : null) != null) { return pointPinger.character.characterName; } } } catch (Exception ex) { Plugin.Logger.LogWarning((object)("Failed to get pinging player name: " + ex.Message)); } return "Unknown"; } } } namespace PingItems.Factories { public static class OptimizedPingableFactory { private static SpatialGrid _spatialGrid; private static float _lastGridRebuildTime = 0f; private static readonly float GRID_REBUILD_INTERVAL = 5f; private static string _lastSceneName = ""; private static int _lastGameSegment = -1; public static void Initialize() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) _spatialGrid = new SpatialGrid(PingItemsConfig.SpatialGridCellSize.Value); Scene activeScene = SceneManager.GetActiveScene(); _lastSceneName = ((Scene)(ref activeScene)).name; _lastGameSegment = GetCurrentGameSegment(); RebuildSpatialGrid(); } public static List<IPingable> FindPingablesForPing(Vector3 pingPosition, Character pingingCharacter, float itemRadius, float luggageRadius) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) if (!PingItemsConfig.EnableSpatialOptimization.Value) { return PingableFactory.FindPingablesForPing(pingPosition, pingingCharacter, itemRadius, luggageRadius); } try { return FindPingablesOptimized(pingPosition, pingingCharacter, itemRadius, luggageRadius); } catch (Exception ex) { Plugin.Logger.LogWarning((object)("Spatial optimization failed, using standard method: " + ex.Message)); return PingableFactory.FindPingablesForPing(pingPosition, pingingCharacter, itemRadius, luggageRadius); } } private static List<IPingable> FindPingablesOptimized(Vector3 pingPosition, Character pingingCharacter, float itemRadius, float luggageRadius) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) if (ShouldRebuildGrid()) { RebuildSpatialGrid(); } if (_spatialGrid == null) { DebugLogger.Log("Spatial grid is null, falling back to standard method"); return PingableFactory.FindPingablesForPing(pingPosition, pingingCharacter, itemRadius, luggageRadius); } return ProcessCandidates(pingPosition, itemRadius, luggageRadius); } private static bool ShouldRebuildGrid() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) Scene activeScene = SceneManager.GetActiveScene(); string name = ((Scene)(ref activeScene)).name; if (name != _lastSceneName) { DebugLogger.Log("Scene changed from '" + _lastSceneName + "' to '" + name + "', forcing grid rebuild"); _lastSceneName = name; return true; } int currentGameSegment = GetCurrentGameSegment(); if (currentGameSegment != -1 && currentGameSegment != _lastGameSegment) { DebugLogger.Log($"Game segment changed from {_lastGameSegment} to {currentGameSegment}, forcing grid rebuild"); _lastGameSegment = currentGameSegment; return true; } return Time.time - _lastGridRebuildTime > GRID_REBUILD_INTERVAL; } private static List<IPingable> ProcessCandidates(Vector3 pingPosition, float itemRadius, float luggageRadius) { //IL_000d: 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) float radius = Mathf.Max(itemRadius, luggageRadius); List<IPingable> list = _spatialGrid.FindNearbyObjects(pingPosition, radius); List<IPingable> list2 = new List<IPingable>(); int num = 0; int value = PingItemsConfig.MaxDistanceChecksPerFrame.Value; foreach (IPingable item in list) { if (num >= value) { DebugLogger.Log($"Hit distance check limit of {value}, stopping early"); break; } if (IsValidCandidate(item)) { float num2 = Vector3.Distance(item.GetCenter(), pingPosition); num++; float applicableRadius = GetApplicableRadius(item, itemRadius, luggageRadius); if (num2 <= applicableRadius) { list2.Add(item); } } } LogPerformanceStats(list.Count, num, list2.Count); return list2; } private static bool IsValidCandidate(IPingable candidate) { try { return candidate != null && candidate.CanBePinged() && (Object)(object)candidate.GetGameObject() != (Object)null; } catch { return false; } } private static float GetApplicableRadius(IPingable pingable, float itemRadius, float luggageRadius) { GameObject gameObject = pingable.GetGameObject(); if ((Object)(object)gameObject == (Object)null) { return itemRadius; } if (!((Object)(object)gameObject.GetComponent<Luggage>() != (Object)null) && !((Object)(object)gameObject.GetComponent<MirageLuggage>() != (Object)null)) { return itemRadius; } return luggageRadius; } private static void RebuildSpatialGrid() { DebugLogger.Log("Rebuilding spatial grid..."); float realtimeSinceStartup = Time.realtimeSinceStartup; try { _spatialGrid?.Clear(); if (_spatialGrid == null) { _spatialGrid = new SpatialGrid(PingItemsConfig.SpatialGridCellSize.Value); } AddObjectsToGrid(SmartObjectManager.GetItems(), (Item item) => new ItemPingableAdapter(item), "items"); AddObjectsToGrid(Luggage.ALL_LUGGAGE, (Luggage luggage) => new LuggagePingableAdapter(luggage), "luggage"); AddObjectsToGrid(SmartObjectManager.GetMirageLuggages(), (MirageLuggage mirage) => new MirageLuggagePingableAdapter(mirage), "mirage luggage"); AddObjectsToGrid(SmartObjectManager.GetSlipperyJellyfish(), (SlipperyJellyfish jellyfish) => new SlipperyJellyfishPingableAdapter((Component)(object)jellyfish), "jellyfish"); AddObjectsToGrid(SmartObjectManager.GetSporeShrooms(), (GameObject shroom) => new SporeShroomPingableAdapter(shroom), "shrooms"); AddObjectsToGrid(SmartObjectManager.GetCapybaras(), (Capybara capybara) => new CapybaraPingableAdapter(capybara), "capybaras"); _lastGridRebuildTime = Time.time; float num = (Time.realtimeSinceStartup - realtimeSinceStartup) * 1000f; var (num2, num3, num4) = _spatialGrid.GetStats(); DebugLogger.Log($"Spatial grid rebuilt in {num:F1}ms: {num3} objects in {num2} cells ({num4:F1} avg per cell)"); } catch (Exception ex) { Plugin.Logger.LogWarning((object)("Failed to rebuild spatial grid: " + ex.Message)); _spatialGrid = new SpatialGrid(PingItemsConfig.SpatialGridCellSize.Value); _lastGridRebuildTime = Time.time; } } private static void AddObjectsToGrid<T>(IEnumerable<T> objects, Func<T, IPingable> createPingable, string typeName) where T : class { if (objects == null) { return; } int num = 0; foreach (T @object in objects) { try { if (@object == null) { continue; } object obj = ((@object is GameObject) ? @object : null); if (obj == null) { T obj2 = ((@object is Component) ? @object : null); obj = ((obj2 != null) ? ((Component)obj2).gameObject : null); } if (!((Object)obj == (Object)null)) { IPingable pingable = createPingable(@object); if (pingable != null && pingable.CanBePinged() && (Object)(object)pingable.GetGameObject() != (Object)null) { _spatialGrid.AddObject(pingable); num++; } } } catch (Exception ex) { DebugLogger.Log("Skipped invalid " + typeName + " during grid rebuild: " + ex.Message); } } DebugLogger.Log($"Added {num} {typeName} to spatial grid"); } private static int GetCurrentGameSegment() { try { Type? type = Type.GetType("MapHandler"); object obj = (type?.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public))?.GetValue(null); object obj2 = (type?.GetMethod("GetCurrentSegment"))?.Invoke(obj, null); return (obj2 != null) ? ((int)obj2) : (-1); } catch (Exception ex) { DebugLogger.Log("Could not get current game segment: " + ex.Message); return -1; } } private static void LogPerformanceStats(int candidatesCount, int distanceChecks, int resultCount) { if (DebugLogger.IsDebugEnabled) { var (num, num2, num3) = _spatialGrid.GetStats(); DebugLogger.Log($"Spatial optimization: {candidatesCount} candidates from {num} cells, {distanceChecks} distance checks, {resultCount} valid"); DebugLogger.Log($"Grid stats: {num2} objects, {num3:F1} avg per cell"); } } public static void ForceRebuild() { _lastGridRebuildTime = 0f; } public static (int totalCells, int totalObjects, float avgObjectsPerCell) GetPerformanceStats() { return _spatialGrid?.GetStats() ?? (0, 0, 0f); } } public static class PingableFactory { public static List<IPingable> FindPingablesForPing(Vector3 pingPosition, Character pingingCharacter, float itemRadius, float luggageRadius) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return FindPingablesNearPosition(pingPosition, itemRadius, luggageRadius); } public static List<IPingable> FindPingablesNearPosition(Vector3 position, float itemRadius, float luggageRadius) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001e: 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_002e: Unknown result type (might be due to invalid IL or missing references) List<IPingable> list = new List<IPingable>(); float radiusSquared = itemRadius * itemRadius; float radiusSquared2 = luggageRadius * luggageRadius; AddPingableItems(list, position, radiusSquared); AddPingableLuggage(list, position, radiusSquared2); AddPingableMirageLuggage(list, position, radiusSquared2); AddPingableSlipperyJellyfish(list, position, radiusSquared); AddPingableSporeShrooms(list, position, radiusSquared); return list; } private static void AddPingableItems(List<IPingable> pingables, Vector3 position, float radiusSquared) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) List<Item> items = SmartObjectManager.GetItems(); for (int i = 0; i < items.Count; i++) { Item val = items[i]; if ((Object)(object)val != (Object)null && IsObjectNearPositionSquared(((Component)val).gameObject, position, radiusSquared)) { ItemPingableAdapter itemPingableAdapter = new ItemPingableAdapter(val); if (itemPingableAdapter.CanBePinged()) { pingables.Add(itemPingableAdapter); } } } } private static void AddPingableLuggage(List<IPingable> pingables, Vector3 position, float radiusSquared) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) foreach (Luggage item in Luggage.ALL_LUGGAGE.Where((Luggage luggage) => (Object)(object)luggage != (Object)null && IsObjectNearPositionSquared(((Component)luggage).gameObject, position, radiusSquared))) { LuggagePingableAdapter luggagePingableAdapter = new LuggagePingableAdapter(item); if (luggagePingableAdapter.CanBePinged()) { pingables.Add(luggagePingableAdapter); } } } private static void AddPingableMirageLuggage(List<IPingable> pingables, Vector3 position, float radiusSquared) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) List<MirageLuggage> mirageLuggages = SmartObjectManager.GetMirageLuggages(); for (int i = 0; i < mirageLuggages.Count; i++) { MirageLuggage val = mirageLuggages[i]; if ((Object)(object)val != (Object)null && IsObjectNearPositionSquared(((Component)val).gameObject, position, radiusSquared)) { MirageLuggagePingableAdapter mirageLuggagePingableAdapter = new MirageLuggagePingableAdapter(val); if (mirageLuggagePingableAdapter.CanBePinged()) { pingables.Add(mirageLuggagePingableAdapter); } } } } private static void AddPingableSlipperyJellyfish(List<IPingable> pingables, Vector3 position, float radiusSquared) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) List<SlipperyJellyfish> slipperyJellyfish = SmartObjectManager.GetSlipperyJellyfish(); for (int i = 0; i < slipperyJellyfish.Count; i++) { SlipperyJellyfish val = slipperyJellyfish[i]; if ((Object)(object)val != (Object)null && IsObjectNearPositionSquared(((Component)val).gameObject, position, radiusSquared)) { SlipperyJellyfishPingableAdapter slipperyJellyfishPingableAdapter = new SlipperyJellyfishPingableAdapter((Component)(object)val); if (slipperyJellyfishPingableAdapter.CanBePinged()) { pingables.Add(slipperyJellyfishPingableAdapter); } } } } private static void AddPingableSporeShrooms(List<IPingable> pingables, Vector3 position, float radiusSquared) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) List<GameObject> sporeShrooms = SmartObjectManager.GetSporeShrooms(); for (int i = 0; i < sporeShrooms.Count; i++) { GameObject val = sporeShrooms[i]; if ((Object)(object)val != (Object)null && IsObjectNearPositionSquared(val.gameObject, position, radiusSquared)) { SporeShroomPingableAdapter sporeShroomPingableAdapter = new SporeShroomPingableAdapter(val); if (sporeShroomPingableAdapter.CanBePinged()) { pingables.Add(sporeShroomPingableAdapter); } } } } private static bool IsObjectNearPositionSquared(GameObject gameObject, Vector3 position, float radiusSquared) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)gameObject == (Object)null || !gameObject.activeInHierarchy) { return false; } Vector3 val = gameObject.transform.position - position; return ((Vector3)(ref val)).sqrMagnitude <= radiusSquared; } } public static class SimplifiedPingableFactory { public delegate IEnumerable<object> ObjectSourceDelegate(); private static readonly List<ObjectSourceDelegate> _objectSources = new List<ObjectSourceDelegate>(); public static void Initialize() { PingTypeRegistry.Initialize(); RegisterObjectSource(() => SmartObjectManager.GetItems().Cast<object>()); RegisterObjectSource(() => Luggage.ALL_LUGGAGE.Cast<object>()); RegisterObjectSource(() => SmartObjectManager.GetMirageLuggages().Cast<object>()); RegisterObjectSource(() => SmartObjectManager.GetSlipperyJellyfish().Cast<object>()); RegisterObjectSource(() => SmartObjectManager.GetSporeShrooms().Cast<object>()); RegisterObjectSource(() => SmartObjectManager.GetCapybaras().Cast<object>()); } public static void RegisterObjectSource(ObjectSourceDelegate sourceDelegate) { _objectSources.Add(sourceDelegate); } public static List<IPingable> FindPingablesForPing(Vector3 pingPosition, Character pingingCharacter, float itemRadius, float luggageRadius) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) List<IPingable> list = new List<IPingable>(); try { foreach (ObjectSourceDelegate objectSource in _objectSources) { ProcessObjectSource(objectSource, pingPosition, itemRadius, luggageRadius, list); } DebugLogger.Log($"SimplifiedPingableFactory found {list.Count} pingable objects"); return list; } catch (Exception ex) { Plugin.Logger.LogError((object)("Error in SimplifiedPingableFactory: " + ex.Message)); return new List<IPingable>(); } } private static void ProcessObjectSource(ObjectSourceDelegate sourceDelegate, Vector3 pingPosition, float itemRadius, float luggageRadius, List<IPingable> result) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) try { IEnumerable<object> enumerable = sourceDelegate(); if (enumerable == null) { return; } foreach (object item in enumerable) { IPingable pingable = CreatePingableFromObject(item); if (pingable != null && pingable.CanBePinged()) { float num = Vector3.Distance(pingable.GetCenter(), pingPosition); float applicableRadius = GetApplicableRadius(pingable, itemRadius, luggageRadius); if (num <= applicableRadius) { result.Add(pingable); } } } } catch (Exception ex) { DebugLogger.Log("Error processing object source: " + ex.Message); } } private static IPingable CreatePingableFromObject(object obj) { if (obj == null) { return null; } Component val = (Component)((obj is Component) ? obj : null); if (val != null) { IPingable pingable = PingTypeRegistry.TryCreateAdapter(val); if (pingable != null) { return pingable; } } return PingTypeRegistry.TryCreateAdapter(obj); } private static float GetApplicableRadius(IPingable pingable, float itemRadius, float luggageRadius) { GameObject gameObject = pingable.GetGameObject(); if ((Object)(object)gameObject == (Object)null) { return itemRadius; } if (!((Object)(object)gameObject.GetComponent<Luggage>() != (Object)null) && !((Object)(object)gameObject.GetComponent<MirageLuggage>() != (Object)null)) { return itemRadius; } return luggageRadius; } } } namespace PingItems.Core { public abstract class BasePingableAdapter<T> : IPingable where T : Component { protected readonly T _component; protected readonly GameObject _gameObject; protected BasePingableAdapter(T component) { _component = component ?? throw new ArgumentNullException("component"); _gameObject = ((Component)component).gameObject; } public virtual string GetDisplayName() { try { return CustomLocalization.GetLocalizedName(GetLocalizationKey()); } catch (Exception ex) { Plugin.Logger.LogWarning((object)("Failed to get localized name for " + GetLocalizationKey() + ": " + ex.Message)); return GetFallbackName(); } } public GameObject GetGameObject() { return _gameObject; } public virtual Vector3 GetCenter() { //IL_000b: Unknown result type (might be due to invalid IL or missing references) return _gameObject.transform.position; } public virtual bool CanBePinged() { return ValidationUtility.IsActiveAndValid((Component)(object)_component); } protected abstract string GetLocalizationKey(); protected abstract string GetFallbackName(); } public class EdgeDistanceText : MonoBehaviour { private TextMeshProUGUI _distanceText; private RectTransform _textRectTransform; private CanvasGroup _canvasGroup; private Transform _parentTransform; private Canvas _targetCanvas; private IPingDataProvider _pingDataProvider; private IDistanceFadeProvider _fadeFadeProvider; private bool _isVisible; private float _targetAlpha; private Vector2 _targetPosition = Vector2.zero; private float _lastDisplayedDistance = -1f; public void Initialize(Transform parentTransform, Canvas targetCanvas, IPingDataProvider pingDataProvider, float maxVisibilityDistance) { if ((Object)(object)parentTransform == (Object)null) { Plugin.Logger.LogError((object)"EdgeDistanceText: parentTransform is null"); return; } if ((Object)(object)targetCanvas == (Object)null) { Plugin.Logger.LogError((object)"EdgeDistanceText: targetCanvas is null"); return; } if (pingDataProvider == null) { Plugin.Logger.LogError((object)"EdgeDistanceText: pingDataProvider is null"); return; } _parentTransform = parentTransform; _targetCanvas = targetCanvas; _pingDataProvider = pingDataProvider; _fadeFadeProvider = new DistanceFadeProvider(maxVisibilityDistance); try { CreateTextElements(); } catch (Exception ex) { Plugin.Logger.LogError((object)("EdgeDistanceText: Failed to create text elements: " + ex.Message)); } } public void UpdateDisplay(bool isVisible, ReticlePositionData positionData) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) if (!PingItemsConfig.ShowEdgeDistance.Value || (Object)(object)_distanceText == (Object)null) { SetVisible(visible: false); return; } try { if (isVisible && positionData.IsOnEdge) { float num = CalculateDistanceBasedAlpha(); if (num > 0f) { Vector2 targetPosition = CalculateSmartTextPosition(positionData); UpdateTextPosition(targetPosition); UpdateDistanceContent(); UpdateTextColor(); SetVisibleWithAlpha(visible: true, num); } else { SetVisible(visible: false); } } else { SetVisible(visible: false); } } catch (Exception ex) { Plugin.Logger.LogError((object)("EdgeDistanceText: UpdateDisplay failed: " + ex.Message)); SetVisible(visible: false); } } public void DestroyText() { if ((Object)(object)_distanceText != (Object)null && (Object)(object)((Component)_distanceText).gameObject != (Object)null) { ValidationUtility.SafeDestroy((Object)(object)((Component)_distanceText).gameObject); } _distanceText = null; _textRectTransform = null; _canvasGroup = null; } public void Cleanup() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) _isVisible = false; _targetAlpha = 0f; _targetPosition = Vector2.zero; _lastDisplayedDistance = -1f; if ((Object)(object)_canvasGroup != (Object)null) { _canvasGroup.alpha = 0f; } if ((Object)(object)_distanceText != (Object)null) { ((TMP_Text)_distanceText).text = string.Empty; } _parentTransform = null; _targetCanvas = null; _pingDataProvider = null; _fadeFadeProvider = null; } private void CreateTextElements() { //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Expected O, but got Unknown if ((Object)(object)_targetCanvas == (Object)null || (Object)(object)_parentTransform == (Object)null) { return; } if ((Object)(object)_distanceText != (Object)null && (Object)(object)((Component)_distanceText).gameObject != (Object)null) { ((Component)_distanceText).gameObject.transform.SetParent(_parentTransform, false); ConfigureTextAppearance(); ConfigureRectTransform(); if ((Object)(object)_canvasGroup != (Object)null) { _canvasGroup.alpha = 0f; } _isVisible = false; } else { GameObject val = new GameObject("EdgeDistanceText"); val.transform.SetParent(_parentTransform, false); _distanceText = val.AddComponent<TextMeshProUGUI>(); _textRectTransform = val.GetComponent<RectTransform>(); _canvasGroup = val.AddComponent<CanvasGroup>(); ConfigureTextAppearance(); ConfigureRectTransform(); _canvasGroup.alpha = 0f; _isVisible = false; } } private void ConfigureTextAppearance() { //IL_003b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_distanceText == (Object)null) { return; } try { ((TMP_Text)_distanceText).text = ""; ((TMP_Text)_distanceText).fontSize = PingItemsConfig.EdgeDistanceFontSize.Value; ((Graphic)_distanceText).color = Color.white; ((TMP_Text)_distanceText).alignment = (TextAlignmentOptions)514; ((TMP_Text)_distanceText).fontStyle = (FontStyles)0; TrySetGameFont(); if (TextOutlineUtility.ShouldApplyOutline()) { TextOutlineUtility.ApplyTextOutline(_distanceText); } ((TMP_Text)_distanceText).enableAutoSizing = true; ((TMP_Text)_distanceText).fontSizeMin = 10f; ((TMP_Text)_distanceText).fontSizeMax = PingItemsConfig.EdgeDistanceFontSize.Value; } catch (Exception ex) { Plugin.Logger.LogError((object)("EdgeDistanceText: Failed to configure text appearance: " + ex.Message)); } } private void TrySetGameFont() { try { UIManager instance = UIManager.Instance; if ((Object)(object)instance != (Object)null) { TextMeshProUGUI val = instance.RentLabel(); if ((Object)(object)val != (Object)null && (Object)(object)((TMP_Text)val).font != (Object)null) { ((TMP_Text)_distanceText).font = ((TMP_Text)val).font; instance.ReleaseLabel(val); } } } catch (Exception ex) { Plugin.Logger.LogWarning((object)("EdgeDistanceText: Could not set game font, using default: " + ex.Message)); } } private void ConfigureRectTransform() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0049: 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_006d: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_textRectTransform == (Object)null)) { _textRectTransform.anchorMin = Vector2.one * 0.5f; _textRectTransform.anchorMax = Vector2.one * 0.5f; _textRectTransform.pivot = Vector2.one * 0.5f; _textRectTransform.sizeDelta = new Vector2(100f, 30f); } } private Vector2 CalculateSmartTextPosition(ReticlePositionData positionData) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0067: 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_0073: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: 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_00d9: 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_00f1: 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_0103: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) Vector2 screenPosition = positionData.ScreenPosition; return (Vector2)(positionData.EdgeLocation switch { EdgeLocation.Left => new Vector2(screenPosition.x + 35f, screenPosition.y), EdgeLocation.Right => new Vector2(screenPosition.x - 35f, screenPosition.y), EdgeLocation.Top => new Vector2(screenPosition.x, screenPosition.y - 35f), EdgeLocation.Bottom => new Vector2(screenPosition.x, screenPosition.y + 35f), EdgeLocation.TopLeft => new Vector2(screenPosition.x + 25f, screenPosition.y - 25f), EdgeLocation.TopRight => new Vector2(screenPosition.x - 25f, screenPosition.y - 25f), EdgeLocation.BottomLeft => new Vector2(screenPosition.x + 25f, screenPosition.y + 25f), EdgeLocation.BottomRight => new Vector2(screenPosition.x - 25f, screenPosition.y + 25f), _ => new Vector2(screenPosition.x + 35f, screenPosition.y), }); } private void UpdateTextPosition(Vector2 targetPosition) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_textRectTransform == (Object)null)) { _targetPosition = targetPosition; _textRectTransform.anchoredPosition = _targetPosition; } } private void UpdateDistanceContent() { if (!((Object)(object)_distanceText == (Object)null) && _pingDataProvider != null) { float distance = _pingDataProvider.GetDistance(); float value = PingItemsConfig.DistanceUpdateThreshold.Value; if (Mathf.Abs(distance - _lastDisplayedDistance) > value) { _lastDisplayedDistance = distance; string text = FormatDistanceText(distance); ((TMP_Text)_distanceText).text = text; } } } private void UpdateTextColor() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_distanceText == (Object)null) && _pingDataProvider != null) { Color playerColor = _pingDataProvider.GetPlayerColor(); ((Graphic)_distanceText).color = playerColor; } } private static string FormatDistanceText(float distance) { if (distance < 1000f) { return $"{distance:F0}m"; } return $"{distance / 1000f:F1}km"; } private float CalculateDistanceBasedAlpha() { if (_pingDataProvider == null || _fadeFadeProvider == null) { return 1f; } try { float distance = _pingDataProvider.GetDistance(); return _fadeFadeProvider.CalculateDistanceAlpha(distance); } catch (Exception ex) { Plugin.Logger.LogError((object)("EdgeDistanceText: Failed to calculate distance alpha: " + ex.Message)); return 1f; } } private void SetVisible(bool visible) { _isVisible = visible; _targetAlpha = (visible ? 1f : 0f); } private void SetVisibleWithAlpha(bool visible, float alpha) { _isVisible = visible; _targetAlpha = (visible ? Mathf.Clamp01(alpha) : 0f); } private void Update() { if (!((Object)(object)_canvasGroup == (Object)null) && !((Object)(object)_textRectTransform == (Object)null) && Mathf.Abs(_canvasGroup.alpha - _targetAlpha) > 0.01f) { _canvasGroup.alpha = Mathf.Lerp(_canvasGroup.alpha, _targetAlpha, Time.deltaTime / 0.3f); } } } public enum EdgeLocation { None, Left, Right, Top, Bottom, TopLeft, TopRight, BottomLeft, BottomRight } public struct ReticlePositionData { public Vector2 ScreenPosition { get; set; } public float TargetScale { get; set; } public bool IsOnEdge { get; set; } public bool IsVisible { get; set; } public EdgeLocation EdgeLocation { get; set; } public Vector2 CanvasSize { get; set; } } public class EdgeTracker { private readonly Camera _camera; private readonly RectTransform _canvasRect; public EdgeTracker(Camera camera, RectTransform canvasRect) { _camera = camera ?? throw new ArgumentNullException("camera"); _canvasRect = canvasRect ?? throw new ArgumentNullException("canvasRect"); } public ReticlePositionData CalculateReticlePosition(Vector3 worldPosition, float baseScale) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) Vector2 sizeDelta = _canvasRect.sizeDelta; ReticlePositionData result; if ((Object)(object)_camera == (Object)null) { result = default(ReticlePositionData); result.ScreenPosition = Vector2.zero; result.TargetScale = baseScale; result.IsOnEdge = false; result.IsVisible = false; result.EdgeLocation = EdgeLocation.None; result.CanvasSize = sizeDelta; return result; } Vector3 val = _camera.WorldToViewportPoint(worldPosition); bool flag = val.z < 0f; bool flag2 = !IsWithinScreenBounds(Vector2.op_Implicit(val)); if (flag || flag2) { Vector2 val2 = ((!flag) ? CalculateSmoothEdgeIntersection(val, isBehindCamera: false) : CalculateSmoothEdgeIntersection(val, isBehindCamera: true)); float targetScale = CalculateAngularBasedScale(worldPosition, baseScale); EdgeLocation edgeLocation = DetermineEdgeLocation(val2); result = default(ReticlePositionData); result.ScreenPosition = ViewportToCanvasPosition(val2); result.TargetScale = targetScale; result.IsOnEdge = true; result.IsVisible = true; result.EdgeLocation = edgeLocation; result.CanvasSize = sizeDelta; return result; } result = default(ReticlePositionData); result.ScreenPosition = ViewportToCanvasPosition(Vector2.op_Implicit(val)); result.TargetScale = baseScale; result.IsOnEdge = false; result.IsVisible = true; result.EdgeLocation = EdgeLocation.None; result.CanvasSize = sizeDelta; return result; } private static EdgeLocation DetermineEdgeLocation(Vector2 viewportPosition) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) bool flag = viewportPosition.x <= 0.15f; bool flag2 = viewportPosition.x >= 0.85f; bool flag3 = viewportPosition.y >= 0.85f; bool flag4 = viewportPosition.y <= 0.15f; if (flag && flag3) { return EdgeLocation.TopLeft; } if (flag2 && flag3) { return EdgeLocation.TopRight; } if (flag && flag4) { return EdgeLocation.BottomLeft; } if (flag2 && flag4) { return EdgeLocation.BottomRight; } if (flag) { return EdgeLocation.Left; } if (flag2) { return EdgeLocation.Right; } if (flag3) { return EdgeLocation.Top; } if (flag4) { return EdgeLocation.Bottom; } return EdgeLocation.None; } private static bool IsWithinScreenBounds(Vector2 viewportPos) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) if (viewportPos.x >= 0f && viewportPos.x <= 1f && viewportPos.y >= 0f) { return viewportPos.y <= 1f; } return false; } private Vector2 CalculateSmoothEdgeIntersection(Vector3 viewportPos, bool isBehindCamera) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) Vector2 val; Vector2 normalized; Vector2 origin = default(Vector2); if (isBehindCamera) { val = new Vector2(0f - viewportPos.x, 0f - viewportPos.y); normalized = ((Vector2)(ref val)).normalized; ((Vector2)(ref origin))..ctor(0.5f, 0.5f); } else { val = new Vector2(viewportPos.x, viewportPos.y) - new Vector2(0.5f, 0.5f); normalized = ((Vector2)(ref val)).normalized; ((Vector2)(ref origin))..ctor(0.5f, 0.5f); } return CalculateRayEdgeIntersection(origin, normalized); } private Vector2 CalculateRayEdgeIntersection(Vector2 origin, Vector2 direction) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0078: 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_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) float num = 50f / Mathf.Min(_canvasRect.sizeDelta.x, _canvasRect.sizeDelta.y); float edgeValue = num; float edgeValue2 = 1f - num; float edgeValue3 = num; float edgeValue4 = 1f - num; Vector2? val = null; float num2 = float.MaxValue; Vector2?[] array = new Vector2?[4] { CalculateEdgeIntersection(origin, direction, edgeValue, isVertical: true), CalculateEdgeIntersection(origin, direction, edgeValue2, isVertical: true), CalculateEdgeIntersection(origin, direction, edgeValue3, isVertical: false), CalculateEdgeIntersection(origin, direction, edgeValue4, isVertical: false) }; for (int i = 0; i < array.Length; i++) { Vector2? val2 = array[i]; if (val2.HasValue) { float num3 = Vector2.Distance(origin, val2.Value); if (num3 < num2) { num2 = num3; val = val2; } } } return (Vector2)(((??)val) ?? new Vector2(0.5f, 0.5f)); } private static Vector2? CalculateEdgeIntersection(Vector2 origin, Vector2 direction, float edgeValue, bool isVertical) { //IL_0000: 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_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0067: 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_0074: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) if (Mathf.Approximately(direction.x, 0f) && isVertical) { return null; } if (Mathf.Approximately(direction.y, 0f) && !isVertical) { return null; } Vector2 val = default(Vector2); if (isVertical) { float num = (edgeValue - origin.x) / direction.x; ((Vector2)(ref val))..ctor(edgeValue, origin.y + num * direction.y); if (val.y < 0f || val.y > 1f || num < 0f) { return null; } } else { float num2 = (edgeValue - origin.y) / direction.y; ((Vector2)(ref val))..ctor(origin.x + num2 * direction.x, edgeValue); if (val.x < 0f || val.x > 1f || num2 < 0f) { return null; } } return val; } private float CalculateAngularBasedScale(Vector3 worldPosition, float baseScale) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_camera == (Object)null) { return baseScale; } baseScale = Mathf.Clamp(baseScale, 0.1f, 5f); float num = Mathf.Clamp01(CalculateViewingAngleInWorldSpace(worldPosition) / 90f); float num2 = Mathf.Lerp(1f, 0.6f, num * num); return Mathf.Clamp(baseScale * num2, 0.1f, 5f); } private float CalculateViewingAngleInWorldSpace(Vector3 worldPosition) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_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_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_camera == (Object)null) { return 0f; } Vector3 forward = ((Component)_camera).transform.forward; Vector3 val = worldPosition - ((Component)_camera).transform.position; Vector3 normalized = ((Vector3)(ref val)).normalized; return Vector3.Angle(forward, normalized); } private Vector2 ViewportToCanvasPosition(Vector2 viewportPos) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) Vector2 sizeDelta = _canvasRect.sizeDelta; return new Vector2((viewportPos.x - 0.5f) * sizeDelta.x, (viewportPos.y - 0.5f) * sizeDelta.y); } } public class ReticleResolver { private readonly Dictionary<ReticleType, Func<GUIManager, GameObject>> _reticleGetters; public ReticleResolver() { _reticleGetters = new Dictionary<ReticleType, Func<GUIManager, GameObject>> { { ReticleType.Default, (GUIManager gui) => gui.reticleDefault }, { ReticleType.X, (GUIManager gui) => gui.reticleX }, { ReticleType.Climb, (GUIManager gui) => gui.reticleClimb }, { ReticleType.ClimbJump, (GUIManager gui) => gui.reticleClimbJump }, { ReticleType.Throw, (GUIManager gui) => gui.reticleThrow }, { ReticleType.Reach, (GUIManager gui) => gui.reticleReach }, { ReticleType.Spike, (GUIManager gui) => gui.reticleSpike }, { ReticleType.Rope, (GUIManager gui) => gui.reticleRope }, { ReticleType.ClimbTry, (GUIManager gui) => gui.reticleClimbTry }, { ReticleType.Vine, (GUIManager gui) => gui.reticleVine }, { ReticleType.Boost, (GUIManager gui) => gui.reticleBoost }, { ReticleType.Shoot, (GUIManager gui) => gui.reticleShoot } }; } public GameObject GetReticle(GUIManager guiManager, ReticleType reticleType) { if ((Object)(object)guiManager == (Object)null) { Plugin.Logger.LogWarning((object)"GUIManager is null, cannot resolve reticle"); return null; } if (!_reticleGetters.TryGetValue(reticleType, out var value)) { Plugin.Logger.LogWarning((object)$"Unknown reticle type: {reticleType}, falling back to Default"); value = _reticleGetters[ReticleType.Default]; } try { GameObject val = value(guiManager); if ((Object)(object)val == (Object)null) { Plugin.Logger.LogWarning((object)$"Reticle {reticleType} is null, falling back to Default"); return _reticleGetters[ReticleType.Default](guiManager); } return val; } catch (Exception ex) { Plugin.Logger.LogWarning((object)$"Failed to get reticle {reticleType}: {ex.Message}, falling back to Default"); return _reticleGetters[ReticleType.Default](guiManager); } } public GameObject GetConfiguredReticle(GUIManager guiManager) { return GetReticle(guiManager, PingItemsConfig.ReticleType.Value); } } public class ReticleScaleProvider { private readonly Dictionary<ReticleType, float> _baseScaleFactors; public ReticleScaleProvider() { _baseScaleFactors = new Dictionary<ReticleType, float> { { ReticleType.Default, 0.75f }, { ReticleType.X, 1f }, { ReticleType.Climb, 0.25f }, { ReticleType.ClimbJump, 0.25f }, { ReticleType.Throw, 0.25f }, { ReticleType.Reach, 0.25f }, { ReticleType.Spike, 0.25f }, { ReticleType.Rope, 0.25f }, { ReticleType.ClimbTry, 0.25f }, { ReticleType.Vine, 0.25f }, { ReticleType.Boost, 0.25f }, { ReticleType.Shoot, 0.25f } }; } public float GetNormalizedScaleFactor(ReticleType reticleType) { if (_baseScaleFactors.TryGetValue(reticleType, out var value)) { return value; } Plugin.Logger.LogWarning((object)$"⚠\ufe0f Unknown reticle type for scaling: {reticleType}, using default scale"); return _baseScaleFactors[ReticleType.Default]; } public float GetFinalScale(ReticleType reticleType, float userScale) { float normalizedScaleFactor = GetNormalizedScaleFactor(reticleType); return userScale * normalizedScaleFactor; } public float GetConfiguredReticleSca