The BepInEx console will not appear when launching like it does for other games on Thunderstore (you can turn it back on in your BepInEx.cfg file). If your PEAK crashes on startup, add -dx12 to your launch parameters.
Decompiled source of PingItems v1.6.2
PingItems.dll
Decompiled a month 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