Decompiled source of EquipmentTimers v1.0.8
BepInEx/plugins/EquipmentTimers/EquipmentTimers.dll
Decompiled 16 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using AK; using BepInEx; using BepInEx.Configuration; using BepInEx.Core.Logging.Interpolation; using BepInEx.Logging; using BepInEx.Unity.IL2CPP; using GameData; using Gear; using HarmonyLib; using HawChow.EquipmentTimers.Diagnostics; using HawChow.EquipmentTimers.Game; using HawChow.EquipmentTimers.Timers; using HawChow.EquipmentTimers.Ui; using Il2CppInterop.Runtime.Injection; using Il2CppInterop.Runtime.InteropTypes; using Il2CppSystem.Collections.Generic; using Microsoft.CodeAnalysis; using Player; using SNetwork; using TMPro; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("EquipmentTimers")] [assembly: AssemblyProduct("EquipmentTimers")] [assembly: AssemblyCompany("HawChow")] [assembly: AssemblyFileVersion("1.0.8.0")] [assembly: AssemblyInformationalVersion("1.0.8")] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = "")] [assembly: AssemblyVersion("1.0.8.0")] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } } namespace HawChow.EquipmentTimers { [BepInPlugin("HawChow.EquipmentTimers", "EquipmentTimers", "1.0.8")] public sealed class Plugin : BasePlugin { internal static Plugin Instance; internal static bool Ready; internal static ConfigEntry<bool> Enabled; internal static ConfigEntry<bool> ShowMeleeCharge; internal static ConfigEntry<bool> ShowReload; internal static ConfigEntry<bool> ShowScanner; internal static ConfigEntry<bool> PlayReadySound; internal static ConfigEntry<bool> ShowGlueGun; internal static ConfigEntry<string> ReadySoundEvent; internal static ConfigEntry<float> ReadyHoldSeconds; internal static ConfigEntry<float> OverrunGraceSeconds; internal static ConfigEntry<float> GapRatio; internal static ConfigEntry<float> MinGap; internal static ConfigEntry<float> MaxGap; internal static ConfigEntry<float> LabelWidthRatio; internal static ConfigEntry<float> MinLabelWidth; internal static ConfigEntry<string> ReadyColor; internal static ConfigEntry<float> NeutralAlpha; internal static ConfigEntry<bool> VerboseLog; private static TimerPolicy _policy = TimerPolicy.Default(); private static TimerStyle _style = TimerStyle.Default; internal static int LogLineBudget { get { if (VerboseLog == null || !VerboseLog.Value) { return 40; } return 400; } } internal static TimerPolicy Policy => _policy; internal static TimerStyle Style => _style; internal static uint ReadySoundId => ResolveEvent((ReadySoundEvent == null) ? "IMPLANTREADY" : ReadySoundEvent.Value); public override void Load() { //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Expected O, but got Unknown //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Expected O, but got Unknown //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Expected O, but got Unknown //IL_01d7: Unknown result type (might be due to invalid IL or missing references) //IL_01e1: Expected O, but got Unknown //IL_0214: Unknown result type (might be due to invalid IL or missing references) //IL_021e: Expected O, but got Unknown //IL_0251: Unknown result type (might be due to invalid IL or missing references) //IL_025b: Expected O, but got Unknown //IL_028e: Unknown result type (might be due to invalid IL or missing references) //IL_0298: Expected O, but got Unknown //IL_02cb: Unknown result type (might be due to invalid IL or missing references) //IL_02d5: Expected O, but got Unknown //IL_032c: Unknown result type (might be due to invalid IL or missing references) //IL_0336: Expected O, but got Unknown //IL_03f8: Unknown result type (might be due to invalid IL or missing references) //IL_03fe: Expected O, but got Unknown //IL_03a3: Unknown result type (might be due to invalid IL or missing references) //IL_03a8: Unknown result type (might be due to invalid IL or missing references) Instance = this; Enabled = ((BasePlugin)this).Config.Bind<bool>("General", "Enabled", true, "Draw the equipment timers. Turning this off hides every label immediately; nothing else changes."); ShowMeleeCharge = ((BasePlugin)this).Config.Bind<bool>("General", "ShowMeleeCharge", true, "Show the remaining time until the melee charge-up reaches full damage."); ShowReload = ((BasePlugin)this).Config.Bind<bool>("General", "ShowReload", true, "Show the remaining reload time for primary and secondary weapons."); ShowScanner = ((BasePlugin)this).Config.Bind<bool>("General", "ShowScanner", true, "Show the BioTracker (enemy scanner) recharge countdown."); ShowGlueGun = ((BasePlugin)this).Config.Bind<bool>("General", "ShowGlueGun", true, "Show the GlueGun charge read-out: the native burst shot count and the charge time already accumulated, on one line, only while the charge is being held."); PlayReadySound = ((BasePlugin)this).Config.Bind<bool>("General", "PlayReadySound", true, "Play one vanilla Wwise UI event when a timer really completes. Cancels, the first observation and weapon switches never play it."); ReadySoundEvent = ((BasePlugin)this).Config.Bind<string>("General", "ReadySoundEvent", "IMPLANTREADY", new ConfigDescription("Vanilla Wwise event used for the one-shot ready cue. 'None' disables the sound without touching the green READY label.", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[6] { "IMPLANTREADY", "IMPLANTREADYSMALL", "HUD_SCAN_COMPLETE_INDICATION", "BUTTONGENERICBLIPACTIVATED", "BUTTONGENERICBLIPONE", "None" }), Array.Empty<object>())); ReadyHoldSeconds = ((BasePlugin)this).Config.Bind<float>("General", "ReadyHoldSeconds", 0.6f, new ConfigDescription("How long the green READY label stays after a real completion. Clamped to 0.2-3 seconds.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.2f, 3f), Array.Empty<object>())); OverrunGraceSeconds = ((BasePlugin)this).Config.Bind<float>("General", "OverrunGraceSeconds", 2.5f, new ConfigDescription("If the native action is still running this long after the countdown hit zero, the label is dropped silently instead of claiming success. Clamped to 0.5-10 seconds.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 10f), Array.Empty<object>())); GapRatio = ((BasePlugin)this).Config.Bind<float>("Layout", "GapRatio", 0.22f, new ConfigDescription("Gap between the timer and the native equipment name, as a fraction of the native font size. Clamped to 0.02-1.5.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.02f, 1.5f), Array.Empty<object>())); MinGap = ((BasePlugin)this).Config.Bind<float>("Layout", "MinGap", 2f, new ConfigDescription("Lower clamp for that gap, in canvas units.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 40f), Array.Empty<object>())); MaxGap = ((BasePlugin)this).Config.Bind<float>("Layout", "MaxGap", 40f, new ConfigDescription("Upper clamp for that gap, in canvas units.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 200f), Array.Empty<object>())); LabelWidthRatio = ((BasePlugin)this).Config.Bind<float>("Layout", "LabelWidthRatio", 4f, new ConfigDescription("Width of the timer box, as a multiple of the native font size. The text is left-aligned on the shared column, and the whole column (widest label + this gap) stays left of every native name. Clamped to 1.5-12.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1.5f, 12f), Array.Empty<object>())); MinLabelWidth = ((BasePlugin)this).Config.Bind<float>("Layout", "MinLabelWidth", 24f, new ConfigDescription("Lower clamp for that width, in canvas units.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(8f, 200f), Array.Empty<object>())); ReadyColor = ((BasePlugin)this).Config.Bind<string>("Layout", "ReadyColor", "#6BF25A", "Colour of the READY label. Accepts #RRGGBB or 'r,g,b' (0-1 or 0-255)."); NeutralAlpha = ((BasePlugin)this).Config.Bind<float>("Layout", "NeutralAlpha", 0.92f, new ConfigDescription("Opacity of the neutral countdown; it always inherits the native name colour.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.2f, 1f), Array.Empty<object>())); VerboseLog = ((BasePlugin)this).Config.Bind<bool>("Debug", "VerboseLog", false, "Raise the bounded log budget from 40 to 400 lines. The plugin still never logs per frame."); ((BasePlugin)this).Config.SettingChanged += delegate { Refresh(); }; Refresh(); ClassInjector.RegisterTypeInIl2Cpp<EquipmentTimerOverlay>(); ((BasePlugin)this).AddComponent<EquipmentTimerOverlay>(); Ready = true; int num = 0; try { Harmony val = new Harmony("HawChow.EquipmentTimers"); val.PatchAll(typeof(Plugin).Assembly); num = ((val.GetPatchedMethods() != null) ? 1 : 0); } catch (Exception ex) { ((BasePlugin)this).Log.LogWarning((object)("Harmony patching failed; timers stay disabled this session: " + ex.Message)); } ManualLogSource log = ((BasePlugin)this).Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(134, 9, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>("EquipmentTimers"); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>("1.0.8"); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" loaded; read-only HUD labels left of the native equipment names; "); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("enabled="); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<bool>(Enabled.Value); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("; melee="); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<bool>(ShowMeleeCharge.Value); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("; reload="); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<bool>(ShowReload.Value); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("; scanner="); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<bool>(ShowScanner.Value); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("; "); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("readySound="); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(ReadySoundEvent.Value); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("; hold="); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<float>(ReadyHoldSeconds.Value, "0.00"); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("s; patches="); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>((num > 0) ? "applied" : "FAILED"); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("."); } log.LogInfo(val2); } internal static void Refresh() { //IL_00f3: Unknown result type (might be due to invalid IL or missing references) _policy = TimerPolicy.Sanitized((ReadyHoldSeconds == null) ? 0.6f : ReadyHoldSeconds.Value, (OverrunGraceSeconds == null) ? 2.5f : OverrunGraceSeconds.Value, unitSuffix: true, "READY", 1); if (ReadyColor == null || !TimerColor.TryParse(ReadyColor.Value, out var color)) { color = TimerColor.DefaultReady; } _style = new TimerStyle((GapRatio == null) ? 0.22f : GapRatio.Value, (MinGap == null) ? 2f : MinGap.Value, (MaxGap == null) ? 40f : MaxGap.Value, (LabelWidthRatio == null) ? 4f : LabelWidthRatio.Value, (MinLabelWidth == null) ? 24f : MinLabelWidth.Value, new Color(color.R, color.G, color.B, 1f), (NeutralAlpha == null) ? 0.92f : NeutralAlpha.Value); } internal static bool KindEnabled(TimerKind kind) { switch (kind) { case TimerKind.MeleeCharge: if (ShowMeleeCharge != null) { return ShowMeleeCharge.Value; } return true; case TimerKind.Reload: if (ShowReload != null) { return ShowReload.Value; } return true; case TimerKind.ScannerRecharge: if (ShowScanner != null) { return ShowScanner.Value; } return true; case TimerKind.GlueGunCharge: if (ShowGlueGun != null) { return ShowGlueGun.Value; } return true; default: return false; } } internal static uint ResolveEvent(string name) { return name switch { "IMPLANTREADYSMALL" => EVENTS.IMPLANTREADYSMALL, "HUD_SCAN_COMPLETE_INDICATION" => EVENTS.HUD_SCAN_COMPLETE_INDICATION, "BUTTONGENERICBLIPACTIVATED" => EVENTS.BUTTONGENERICBLIPACTIVATED, "BUTTONGENERICBLIPONE" => EVENTS.BUTTONGENERICBLIPONE, "None" => 0u, _ => EVENTS.IMPLANTREADY, }; } } internal static class PluginInfo { public const string Guid = "HawChow.EquipmentTimers"; public const string Name = "EquipmentTimers"; public const string Version = "1.0.8"; } } namespace HawChow.EquipmentTimers.Ui { public sealed class EquipmentTimerOverlay : MonoBehaviour { public EquipmentTimerOverlay(IntPtr pointer) : base(pointer) { } private void Awake() { try { TimerController.Initialize(); } catch (Exception ex) { Plugin instance = Plugin.Instance; if (instance != null) { ((BasePlugin)instance).Log.LogWarning((object)("[hud] controller init failed: " + ex.GetType().Name)); } } } private void Update() { try { TimerController.Tick(Time.time); } catch (Exception ex) { Plugin instance = Plugin.Instance; if (instance != null) { ((BasePlugin)instance).Log.LogWarning((object)("[hud] pump failed: " + ex.GetType().Name)); } } } private void OnDestroy() { try { TimerController.Shutdown(); } catch (Exception ex) { Plugin instance = Plugin.Instance; if (instance != null) { ((BasePlugin)instance).Log.LogWarning((object)("[hud] shutdown failed: " + ex.GetType().Name)); } } } } public readonly struct TimerColor { public float R { get; } public float G { get; } public float B { get; } public static TimerColor DefaultReady => new TimerColor(0.42f, 0.95f, 0.35f); private TimerColor(float r, float g, float b) { R = r; G = g; B = b; } public static bool TryParse(string text, out TimerColor color) { color = DefaultReady; if (string.IsNullOrWhiteSpace(text)) { return false; } string text2 = text.Trim(); if (text2.StartsWith("#", StringComparison.Ordinal)) { text2 = text2.Substring(1); if (text2.Length != 6) { return false; } if (!TryHex(text2, 0, out var channel) || !TryHex(text2, 2, out var channel2) || !TryHex(text2, 4, out var channel3)) { return false; } color = new TimerColor(channel, channel2, channel3); return true; } string[] array = text2.Split(','); if (array.Length != 3) { return false; } if (!float.TryParse(array[0], NumberStyles.Float, CultureInfo.InvariantCulture, out var result) || !float.TryParse(array[1], NumberStyles.Float, CultureInfo.InvariantCulture, out var result2) || !float.TryParse(array[2], NumberStyles.Float, CultureInfo.InvariantCulture, out var result3)) { return false; } float num = ((result > 1f || result2 > 1f || result3 > 1f) ? 0.003921569f : 1f); color = new TimerColor(Clamp01(result * num), Clamp01(result2 * num), Clamp01(result3 * num)); return true; } private static bool TryHex(string value, int offset, out float channel) { channel = 0f; if (!byte.TryParse(value.Substring(offset, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var result)) { return false; } channel = (float)(int)result / 255f; return true; } private static float Clamp01(float value) { if (value < 0f) { return 0f; } if (value > 1f) { return 1f; } return value; } } internal static class TimerController { private struct SlotProbe { public bool TryGetSucceeded; public bool BackpackLoaded; public bool InstanceAlive; public bool InstanceIsGear; public bool SlotMatches; public ItemEquippable Item; } private const float ProbeSeconds = 0.5f; private static readonly InventorySlot[] Slots; private static readonly List<TimerSlotRow> Rows; private static readonly Dictionary<InventorySlot, ItemEquippable> Items; private static BoundedLog _log; private static PlayerAgent _localPlayer; private static PlayerAgent _player; private static PlayerInventoryBase _inventory; private static PUI_Inventory _hud; private static float _nextHudProbe; private static float _nextInventoryProbe; private static float _nextSlotScan; private static bool _slotsDirty; private static bool _initialised; private static int _budget; private static readonly RepeatGate ResetLogGate; private static readonly SlotReadDiagnostics SlotDiagnostics; private static bool _slotReadFellBack; private static readonly bool[] ItemProbeWarned; private static readonly float[] ColumnEdges; private static readonly float[] ColumnWidths; private static readonly float[] ColumnGaps; private static readonly bool[] RowReady; internal static int LiveLabelCount { get { int num = 0; for (int i = 0; i < Rows.Count; i++) { if (Rows[i].HasLabel) { num++; } } return num; } } internal static void Initialize() { if (_initialised) { return; } _initialised = true; _budget = Plugin.LogLineBudget; _log = new BoundedLog(delegate(string message) { Plugin instance = Plugin.Instance; if (instance != null) { ((BasePlugin)instance).Log.LogInfo((object)message); } }, delegate(string message) { Plugin instance = Plugin.Instance; if (instance != null) { ((BasePlugin)instance).Log.LogWarning((object)message); } }, _budget); _slotsDirty = true; _nextHudProbe = 0f; _nextInventoryProbe = 0f; _nextSlotScan = 0f; SlotDiagnostics.Reset(); _slotReadFellBack = false; Array.Clear(ItemProbeWarned, 0, ItemProbeWarned.Length); _log.Info("[hud] controller initialised; budget=" + _budget + " lines."); } internal static void Shutdown() { DestroyRows(); Items.Clear(); _hud = null; _inventory = null; _player = null; _localPlayer = null; _slotsDirty = true; _initialised = false; ResetLogGate.Reset(); Array.Clear(ItemProbeWarned, 0, ItemProbeWarned.Length); _log = null; } internal static void AttachLocalPlayer(PlayerAgent player) { _localPlayer = player; _player = null; _inventory = null; _nextInventoryProbe = 0f; if (_initialised) { BindPlayer(); } } internal static void NotifyHudRebuilt(PUI_Inventory hud) { if (!((Object)(object)hud == (Object)null)) { _slotsDirty = true; } } internal static void NotifyLevelCleanup() { if (_initialised) { ResetRows("level-cleanup"); _hud = null; _inventory = null; _player = null; _nextHudProbe = 0f; _nextInventoryProbe = 0f; _slotsDirty = true; if (!TimerSlotRow.IsAlive((Object)(object)_localPlayer)) { _localPlayer = null; } } } internal static void Tick(float now) { try { if (!_initialised) { Initialize(); } if (Plugin.Ready) { int logLineBudget = Plugin.LogLineBudget; if (logLineBudget != _budget) { _budget = logLineBudget; _log.SetBudget(logLineBudget); } if (!Plugin.Enabled.Value) { HideRows(); return; } if (!EnsureHud(now) || !EnsureInventory(now)) { HideRows(); return; } ScanSlots(now); SyncSlotItems(); UpdateRows(now); } } catch (Exception ex) { if (_log != null && _log.HasWarnBudget) { _log.Warn("[hud] update failed: " + ex.GetType().Name + ": " + ex.Message); } HideRows(); } } private static void BindPlayer() { PlayerAgent localPlayer = _localPlayer; if (!TimerSlotRow.IsAlive((Object)(object)localPlayer)) { _localPlayer = null; } else if (!((Object)(object)_player != (Object)null) || !(((Il2CppObjectBase)_player).Pointer == ((Il2CppObjectBase)localPlayer).Pointer) || !((Object)(object)_inventory != (Object)null)) { _player = localPlayer; _inventory = SafeInventory(localPlayer); _slotsDirty = true; if (_log.HasInfoBudget) { _log.Info("[hud] local player bound; inventory=" + (((Object)(object)_inventory != (Object)null) ? "ready" : "pending") + "."); } } } private static bool EnsureHud(float now) { if ((Object)(object)_hud != (Object)null) { return true; } HideRows(); if (now < _nextHudProbe) { return false; } _nextHudProbe = now + 0.5f; PUI_Inventory inventory; try { PlayerGuiLayer playerLayer = GuiManager.PlayerLayer; if (playerLayer == null) { return false; } inventory = playerLayer.Inventory; } catch (Exception ex) { _hud = null; if (_log.HasWarnBudget) { _log.Warn("[hud] player layer unavailable: " + ex.GetType().Name); } return false; } if ((Object)(object)inventory == (Object)null) { return false; } _hud = inventory; _slotsDirty = true; if (_log.HasInfoBudget) { _log.Info("[hud] player inventory HUD acquired."); } return true; } private static bool EnsureInventory(float now) { if ((Object)(object)_inventory != (Object)null) { return true; } _player = null; if (now < _nextInventoryProbe) { return false; } _nextInventoryProbe = now + 0.5f; PlayerInventoryBase val; try { PlayerAgent localPlayer = _localPlayer; if (!TimerSlotRow.IsAlive((Object)(object)localPlayer)) { _localPlayer = null; return false; } _player = localPlayer; val = SafeInventory(localPlayer); } catch (Exception ex) { _player = null; _inventory = null; if (_log.HasWarnBudget) { _log.Warn("[hud] local inventory unavailable: " + ex.GetType().Name); } return false; } if ((Object)(object)val == (Object)null) { _player = null; return false; } _inventory = val; _slotsDirty = true; return true; } private static PlayerInventoryBase SafeInventory(PlayerAgent player) { try { return ((Object)(object)player == (Object)null) ? null : player.Inventory; } catch { return null; } } private unsafe static void ScanSlots(float now) { //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: 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_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) if (!_slotsDirty && now < _nextSlotScan && RowsBound()) { return; } _nextSlotScan = now + 0.5f; _slotsDirty = false; Dictionary<InventorySlot, PUI_InventoryItem> inventorySlots; try { inventorySlots = _hud.m_inventorySlots; } catch (Exception ex) { _hud = null; DestroyRows(); if (_log.HasWarnBudget) { _log.Warn("[hud] slot table unavailable: " + ex.GetType().Name); } return; } if (inventorySlots == null) { DestroyRows(); return; } for (int i = 0; i < Slots.Length; i++) { InventorySlot val = Slots[i]; try { if (!TryResolveSlot(inventorySlots, val, i, out var item)) { RemoveRow(val); continue; } if ((Object)(object)item == (Object)null || (int)item.CurrentState == 0) { RemoveRow(val); continue; } TimerSlotRow timerSlotRow = FindRow(val); if (timerSlotRow == null) { timerSlotRow = new TimerSlotRow(val); Rows.Add(timerSlotRow); if (_log.HasInfoBudget) { _log.Info("[hud] row added for slot " + ((object)(*(InventorySlot*)(&val))/*cast due to .constrained prefix*/).ToString() + "."); } } else if ((Object)(object)timerSlotRow.UiItem != (Object)null && ((Il2CppObjectBase)timerSlotRow.UiItem).Pointer != ((Il2CppObjectBase)item).Pointer) { timerSlotRow.Invalidate(); Items.Remove(val); } timerSlotRow.UiItem = item; } catch (Exception ex2) { RemoveRow(val); if (_log.HasWarnBudget) { _log.Warn("[hud] slot " + ((object)(*(InventorySlot*)(&val))/*cast due to .constrained prefix*/).ToString() + " unavailable: " + ex2.GetType().Name + ": " + ex2.Message); } } } } private static bool TryResolveSlot(Dictionary<InventorySlot, PUI_InventoryItem> slots, InventorySlot slot, int slotIndex, out PUI_InventoryItem item) { //IL_002c: 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_000b: 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_0019: Unknown result type (might be due to invalid IL or missing references) item = null; if (!_slotReadFellBack) { try { if (!slots.ContainsKey(slot)) { return true; } item = slots[slot]; return true; } catch (Exception error) { _slotReadFellBack = true; ReportSlotFailure(slotIndex, slot, "ContainsKey/indexer", error); } } try { PUI_InventoryItem val = default(PUI_InventoryItem); bool flag = slots.TryGetValue(slot, ref val); item = (flag ? val : null); return true; } catch (Exception error2) { ReportSlotFailure(slotIndex, slot, "TryGetValue", error2); return false; } } private unsafe static void ReportSlotFailure(int slotIndex, InventorySlot slot, string member, Exception error) { if (_log != null && _log.HasWarnBudget && SlotDiagnostics.ShouldReport(slotIndex)) { _log.Warn(SlotReadDiagnostics.Describe(((object)(*(InventorySlot*)(&slot))/*cast due to .constrained prefix*/).ToString(), member, error)); } } private static bool RowsBound() { for (int i = 0; i < Rows.Count; i++) { if ((Object)(object)Rows[i].UiItem == (Object)null) { return false; } } return true; } private static void SyncSlotItems() { //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Invalid comparison between Unknown and I4 SNet_Player val = null; try { PlayerAgent player = _player; if (TimerSlotRow.IsAlive((Object)(object)player)) { val = player.Owner; } } catch (Exception error) { val = null; WarnItemProbe(0, "owner", error); } ItemEquippable val2 = null; try { PlayerAgent player2 = _player; if (TimerSlotRow.IsAlive((Object)(object)player2) && (Object)(object)player2.FPItemHolder != (Object)null) { val2 = player2.FPItemHolder.m_meleeWeapon; } } catch (Exception error2) { val2 = null; WarnItemProbe(3, "holder", error2); } if (!TimerSlotRow.IsAlive((Object)(object)val2)) { val2 = null; } for (int i = 0; i < Rows.Count; i++) { TimerSlotRow timerSlotRow = Rows[i]; try { SlotProbe slotProbe = ProbeSlot(timerSlotRow.Slot, val, i); ItemEquippable val3 = (ItemEquippable)(SlotItemRules.Decide((int)timerSlotRow.Slot == 10, (Object)(object)val != (Object)null, slotProbe.TryGetSucceeded, slotProbe.BackpackLoaded, slotProbe.InstanceAlive, slotProbe.InstanceIsGear, slotProbe.SlotMatches, (Object)(object)val2 != (Object)null) switch { SlotItemVerdict.BindHolderMelee => val2, SlotItemVerdict.BindBackpack => slotProbe.Item, _ => null, }); if (!TimerSlotRow.IsAlive((Object)(object)val3)) { DetachItem(timerSlotRow); } else { BindItem(timerSlotRow, val3); } } catch (Exception error3) { DetachItem(timerSlotRow); WarnItemProbe(i, "slot " + ((object)timerSlotRow.Slot/*cast due to .constrained prefix*/).ToString(), error3); } } } private unsafe static SlotProbe ProbeSlot(InventorySlot slot, SNet_Player owner, int rowIndex) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) SlotProbe result = default(SlotProbe); if ((Object)(object)owner == (Object)null) { return result; } try { BackpackItem val = default(BackpackItem); if (!PlayerBackpackManager.TryGetItem(owner, slot, ref val) || val == null) { return result; } result.TryGetSucceeded = true; if (!val.IsLoaded) { return result; } result.BackpackLoaded = true; Item instance = val.Instance; if ((Object)(object)instance == (Object)null || ((Il2CppObjectBase)instance).Pointer == IntPtr.Zero || !TimerSlotRow.IsAlive((Object)(object)instance)) { return result; } result.InstanceAlive = true; ItemEquippable val2 = ((Il2CppObjectBase)instance).TryCast<ItemEquippable>(); if ((Object)(object)val2 == (Object)null) { return result; } result.InstanceIsGear = true; ItemDataBlock itemDataBlock = ((Item)val2).ItemDataBlock; if (itemDataBlock == null || itemDataBlock.inventorySlot != slot) { return result; } result.SlotMatches = true; result.Item = val2; } catch (Exception error) { result.Item = null; WarnItemProbe(rowIndex, "backpack " + ((object)(*(InventorySlot*)(&slot))/*cast due to .constrained prefix*/).ToString(), error); } return result; } private static void WarnItemProbe(int rowIndex, string what, Exception error) { if (_log == null || !_log.HasWarnBudget) { return; } if (rowIndex >= 0 && rowIndex < ItemProbeWarned.Length) { if (ItemProbeWarned[rowIndex]) { return; } ItemProbeWarned[rowIndex] = true; } _log.Warn("[hud] item probe failed (" + what + "): " + error.GetType().Name); } private static void DetachItem(TimerSlotRow row) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)row.Item == (Object)null) || row.Kind != TimerKind.None || row.Tracker != null) { row.DetachItem(); Items.Remove(row.Slot); } } private static void BindItem(TimerSlotRow row, ItemEquippable item) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: 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_0126: Unknown result type (might be due to invalid IL or missing references) TimerKind timerKind; try { timerKind = GearSampler.KindOf(item); } catch (Exception ex) { timerKind = TimerKind.None; if (_log.HasWarnBudget) { _log.Warn("[hud] slot " + ((object)row.Slot/*cast due to .constrained prefix*/).ToString() + " type probe failed: " + ex.GetType().Name); } } bool flag = timerKind != TimerKind.None && timerKind != TimerKind.GlueGunCharge; if (!((Object)(object)row.Item != (Object)null) || !(((Il2CppObjectBase)row.Item).Pointer == ((Il2CppObjectBase)item).Pointer) || row.Kind != timerKind || (flag && row.Tracker == null)) { row.Item = item; Items[row.Slot] = item; if (row.Kind != timerKind || (flag && row.Tracker == null)) { row.Kind = timerKind; row.Tracker = (flag ? new TimerTracker(timerKind, Plugin.Policy) : null); row.Clock = ((timerKind == TimerKind.Reload) ? new ReloadClock() : null); } else { row.ResetTimer(); } if (_log.HasInfoBudget) { _log.Info("[hud] slot " + ((object)row.Slot/*cast due to .constrained prefix*/).ToString() + " bound; kind=" + timerKind.ToString() + "."); } } } private static void UpdateRows(float now) { TimerStyle style = Plugin.Style; TimerPolicy policy = Plugin.Policy; for (int i = 0; i < Rows.Count; i++) { TimerSlotRow timerSlotRow = Rows[i]; RowReady[i] = false; try { if (!PrepareRow(timerSlotRow, now, style)) { timerSlotRow.Hide(); continue; } RowReady[i] = true; timerSlotRow.SyncLayout(style); } catch (Exception error) { DropRow(timerSlotRow, error); } } for (int j = 0; j < Rows.Count; j++) { if (!RowReady[j]) { continue; } TimerSlotRow timerSlotRow2 = Rows[j]; try { if (!PaintRow(timerSlotRow2, now, style, policy)) { timerSlotRow2.Hide(); } } catch (Exception error2) { DropRow(timerSlotRow2, error2); } } int num = 0; for (int k = 0; k < Rows.Count; k++) { if (!RowReady[k] || num >= ColumnEdges.Length) { continue; } TimerSlotRow timerSlotRow3 = Rows[k]; try { if (timerSlotRow3.TryMeasureColumnVote(style, out var nameLeftEdge, out var labelWidth, out var gap)) { ColumnEdges[num] = nameLeftEdge; ColumnWidths[num] = labelWidth; ColumnGaps[num] = gap; num++; } } catch (Exception error3) { DropRow(timerSlotRow3, error3); } } float leftEdge; float columnWorldX = (TimerLayout.TryColumnLeftEdge(ColumnEdges, ColumnWidths, ColumnGaps, num, out leftEdge) ? leftEdge : float.NaN); for (int l = 0; l < Rows.Count; l++) { if (RowReady[l]) { TimerSlotRow timerSlotRow4 = Rows[l]; try { timerSlotRow4.PlaceOnColumn(style, columnWorldX); } catch (Exception error4) { DropRow(timerSlotRow4, error4); } } } } private static void DropRow(TimerSlotRow row, Exception error) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) row.Invalidate(); Items.Remove(row.Slot); _slotsDirty = true; if (_log.HasWarnBudget) { _log.Warn("[hud] slot " + ((object)row.Slot/*cast due to .constrained prefix*/).ToString() + " read failed: " + error.GetType().Name); } } private static bool PrepareRow(TimerSlotRow row, float now, TimerStyle style) { PUI_InventoryItem uiItem = row.UiItem; if ((Object)(object)uiItem == (Object)null || !TimerSlotRow.IsAlive((Object)(object)((Component)uiItem).gameObject)) { return false; } TextMeshPro val = ResolveName(uiItem); if ((Object)(object)val == (Object)null) { return false; } return row.EnsureLabel(val, style, now); } private static bool PaintRow(TimerSlotRow row, float now, TimerStyle style, TimerPolicy policy) { if (row.Kind == TimerKind.None || !Plugin.KindEnabled(row.Kind)) { return false; } if (row.Kind == TimerKind.GlueGunCharge) { if ((Object)(object)row.Item == (Object)null) { return false; } TimerSample timerSample = GearSampler.Sample(row.Kind, row.Item, row.Clock, now); TimerRowView view = TimerDisplayPolicy.ForGlueGun(policy, timerSample.Active, timerSample.ShotsKnown, timerSample.Shots, timerSample.ChargeElapsedKnown, timerSample.ChargeElapsed); row.Apply(view, style, now); ReportRowDiagnostics(row, now); return true; } if ((Object)(object)row.Item == (Object)null || row.Tracker == null) { return false; } if (policy != null) { row.Tracker.Policy = policy; } TimerSample sample = GearSampler.Sample(row.Kind, row.Item, row.Clock, now); if (row.Kind == TimerKind.MeleeCharge && !sample.InChargeState) { sample.Cancelled = true; } int completions = row.Tracker.Completions; int suppressedCompletions = row.Tracker.SuppressedCompletions; TimerRowView view2 = row.Tracker.Observe(in sample); bool sessionSuppressed = row.Tracker.SuppressedCompletions > suppressedCompletions; if (row.Tracker.Completions > completions) { PlayReadySound(row, now); } TimerRowView view3 = ForKind(row, view2, sample, sessionSuppressed, policy); row.Apply(view3, style, now); ReportRowDiagnostics(row, now); return true; } private static TimerRowView ForKind(TimerSlotRow row, TimerRowView view, TimerSample sample, bool sessionSuppressed, TimerPolicy policy) { string readyText = policy?.ReadyText; bool overrunHidden = row.Tracker != null && row.Tracker.OverrunHidden; return row.Kind switch { TimerKind.Reload => TimerDisplayPolicy.ForWeapon(view, sample.Active, sample.ClipKnown, sample.Clip, sample.MaxClip, sample.Cancelled, overrunHidden, sessionSuppressed, readyText), TimerKind.ScannerRecharge => TimerDisplayPolicy.ForScanner(view, sample.Active, sample.Cancelled, overrunHidden, sessionSuppressed, readyText), TimerKind.MeleeCharge => TimerDisplayPolicy.ForMelee(view, sample.InChargeState, sample.Done, sample.MeleeReleaseWarning, sample.Cancelled, readyText), _ => view, }; } private static void ReportRowDiagnostics(TimerSlotRow row, float now) { string text = row.TakeInvalidMeshNote(); if (text != null && _log.HasInfoBudget) { _log.Info(text + "."); } string text2 = row.TakeVisibleSample(now); if (text2 != null && _log.HasInfoBudget) { _log.Info(text2 + "; " + SafeGeometry(row) + "."); } } private static void PlayReadySound(TimerSlotRow row, float now) { //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_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) uint readySoundId = Plugin.ReadySoundId; if (!NativeRules.ShouldPostReadyCue(Plugin.PlayReadySound != null && Plugin.PlayReadySound.Value, readySoundId)) { if (_log.HasInfoBudget) { _log.Info("[hud] slot " + ((object)row.Slot/*cast due to .constrained prefix*/).ToString() + " completed; ready cue disabled."); } return; } bool flag = false; try { CellSoundPlayer val = (((Object)(object)_player == (Object)null) ? null : _player.Sound); if (val != null) { val.Post(readySoundId, true); flag = true; } } catch (Exception ex) { if (_log.HasWarnBudget) { _log.Warn("[sound] player 2D post failed: " + ex.GetType().Name); } } if (!flag) { try { if ((Object)(object)CellSound.Current != (Object)null) { CellSound.Post(readySoundId); flag = true; } } catch (Exception ex2) { if (_log.HasWarnBudget) { _log.Warn("[sound] global post failed: " + ex2.GetType().Name); } } } if (_log.HasInfoBudget) { _log.Info("[hud] slot " + ((object)row.Slot/*cast due to .constrained prefix*/).ToString() + " completed; ready cue " + (flag ? "posted" : "unavailable") + " at " + now.ToString("0.00") + "."); } } private static string SafeName(Object native) { try { return (native == (Object)null) ? "-" : native.name; } catch { return "?"; } } private static string SafeGeometry(TimerSlotRow row) { try { return row.DescribeGeometry(); } catch (Exception ex) { return "geometry=?(" + ex.GetType().Name + ")"; } } private static TextMeshPro ResolveName(PUI_InventoryItem item) { //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_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected I4, but got Unknown try { TextMeshPro selected_archetypeName = item.m_selected_archetypeName; TextMeshPro slim_archetypeName = item.m_slim_archetypeName; bool flag = TimerSlotRow.IsAlive((Object)(object)selected_archetypeName) && ((Component)selected_archetypeName).gameObject.activeInHierarchy; bool flag2 = TimerSlotRow.IsAlive((Object)(object)slim_archetypeName) && ((Component)slim_archetypeName).gameObject.activeInHierarchy; ePUI_InventortyItemState currentState = item.CurrentState; switch ((int)currentState) { case 2: if (flag) { return selected_archetypeName; } return flag2 ? slim_archetypeName : null; case 1: if (flag2) { return slim_archetypeName; } return flag ? selected_archetypeName : null; case 0: return null; default: if (flag) { return selected_archetypeName; } return flag2 ? slim_archetypeName : null; } } catch { return null; } } private static TimerSlotRow FindRow(InventorySlot slot) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < Rows.Count; i++) { if (Rows[i].Slot == slot) { return Rows[i]; } } return null; } private static void RemoveRow(InventorySlot slot) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) for (int num = Rows.Count - 1; num >= 0; num--) { if (Rows[num].Slot == slot) { Rows[num].DestroyLabel(); Rows.RemoveAt(num); } } Items.Remove(slot); } private static void HideRows() { for (int i = 0; i < Rows.Count; i++) { try { Rows[i].Hide(); } catch (Exception ex) { if (_log != null && _log.HasWarnBudget) { _log.Warn("[hud] hide failed: " + ex.GetType().Name); } } } } private static void ResetRows(string reason) { _slotsDirty = true; if (Rows.Count == 0 && Items.Count == 0) { return; } int count = Rows.Count; for (int i = 0; i < count; i++) { try { Rows[i].Invalidate(); } catch (Exception ex) { if (_log != null && _log.HasWarnBudget) { _log.Warn("[hud] reset failed: " + ex.GetType().Name); } } } Items.Clear(); if (ResetLogGate.ShouldLog(count, reason) && _log != null && _log.HasInfoBudget) { _log.Info("[hud] rows reset (" + reason + "), rows=" + count + "."); } } private static void DestroyRows() { for (int i = 0; i < Rows.Count; i++) { try { Rows[i].DestroyLabel(); } catch (Exception ex) { if (_log != null && _log.HasWarnBudget) { _log.Warn("[hud] destroy failed: " + ex.GetType().Name); } } } Rows.Clear(); Items.Clear(); _slotsDirty = true; ResetLogGate.Reset(); } static TimerController() { InventorySlot[] array = new InventorySlot[4]; RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); Slots = (InventorySlot[])(object)array; Rows = new List<TimerSlotRow>(Slots.Length); Items = new Dictionary<InventorySlot, ItemEquippable>(); _slotsDirty = true; ResetLogGate = new RepeatGate(); SlotDiagnostics = new SlotReadDiagnostics(Slots.Length); ItemProbeWarned = new bool[4]; ColumnEdges = new float[4]; ColumnWidths = new float[4]; ColumnGaps = new float[4]; RowReady = new bool[4]; } } public static class TimerLayout { public const float DefaultGapRatio = 0.22f; public const float DefaultMinGap = 2f; public const float DefaultMaxGap = 40f; public const float DefaultWidthRatio = 4f; public const float DefaultMinWidth = 24f; public const int MaxColumnSlots = 4; public static float Gap(float fontSize, float gapRatio, float minGap, float maxGap) { float num = Sanitize(gapRatio, 0.22f, 0.02f, 1.5f); float min = Sanitize(minGap, 2f, 0f, 40f); float max = Sanitize(maxGap, 40f, min, 200f); return Clamp(((fontSize > 0f) ? fontSize : 12f) * num, min, max); } public static float LabelAnchoredX(float nativeAnchoredX, float nativeWidth, float nativePivotX, float gap) { float num = ((nativeWidth > 0f) ? nativeWidth : 0f); return nativeAnchoredX - num * nativePivotX - gap; } public static float LabelWidth(float fontSize, float widthRatio, float minWidth) { float num = Sanitize(widthRatio, 4f, 1.5f, 12f); float val = Sanitize(minWidth, 24f, 8f, 200f); float num2 = ((fontSize > 0f) ? fontSize : 12f); return Math.Max(val, num2 * num); } public static float LabelAnchoredY(float nativeAnchoredY, float nativeHeight, float nativePivotY) { float num = ((nativeHeight > 0f) ? nativeHeight : 0f); return nativeAnchoredY + num * (0.5f - nativePivotY); } public static float LabelAnchoredXFromGlyph(float nativeAnchoredX, float glyphLeftDelta, float gap) { return nativeAnchoredX + glyphLeftDelta - gap; } public static float PointAnchorX(float anchorMinX, float anchorMaxX, float pivotX) { float num = Clean(anchorMinX); float num2 = Clean(anchorMaxX); float num3 = Clean(pivotX); return num + (num2 - num) * num3; } public static float PointAnchorY(float anchorMinY, float anchorMaxY, float pivotY) { float num = Clean(anchorMinY); float num2 = Clean(anchorMaxY); float num3 = Clean(pivotY); return num + (num2 - num) * num3; } public static bool SameAnchor(float left, float right) { if (float.IsNaN(left) || float.IsNaN(right) || float.IsInfinity(left) || float.IsInfinity(right)) { return false; } return Math.Abs(left - right) <= 0.0005f; } public static bool TryLeftmostEdge(float[] edges, int count, out float leftmost) { leftmost = 0f; if (edges == null) { return false; } bool flag = false; int num = ((count < edges.Length) ? count : edges.Length); for (int i = 0; i < num; i++) { float num2 = edges[i]; if (!float.IsNaN(num2) && !float.IsInfinity(num2) && (!flag || num2 < leftmost)) { leftmost = num2; flag = true; } } return flag; } public static bool TryParentLocalX(float worldX, float parentWorldX, float parentLossyScaleX, out float localX) { localX = 0f; if (float.IsNaN(worldX) || float.IsInfinity(worldX)) { return false; } if (float.IsNaN(parentWorldX) || float.IsInfinity(parentWorldX)) { return false; } if (float.IsNaN(parentLossyScaleX) || float.IsInfinity(parentLossyScaleX)) { return false; } if (Math.Abs(parentLossyScaleX) <= 1E-06f) { return false; } float num = (worldX - parentWorldX) / parentLossyScaleX; if (float.IsNaN(num) || float.IsInfinity(num)) { return false; } localX = num; return true; } public static float ColumnLimit(float nameLeftEdge, float labelWidth, float gap) { if (!Finite(nameLeftEdge) || !Finite(labelWidth)) { return float.NaN; } float num = ((labelWidth > 0f) ? labelWidth : 0f); float num2 = ((Finite(gap) && gap > 0f) ? gap : 0f); float num3 = nameLeftEdge - num - num2; if (!Finite(num3)) { return float.NaN; } return num3; } public static bool TryColumnLeftEdge(float[] nameLeftEdges, float[] labelWidths, float[] gaps, int count, out float leftEdge) { leftEdge = 0f; if (nameLeftEdges == null || labelWidths == null || gaps == null) { return false; } int num = Math.Min(count, Math.Min(nameLeftEdges.Length, Math.Min(labelWidths.Length, gaps.Length))); bool flag = false; for (int i = 0; i < num; i++) { float num2 = ColumnLimit(nameLeftEdges[i], labelWidths[i], gaps[i]); if (Finite(num2) && (!flag || num2 < leftEdge)) { leftEdge = num2; flag = true; } } return flag; } public static float AnchorReferenceLocalX(float parentRectXMin, float parentRectWidth, float anchorX) { return Clean(parentRectXMin) + Clean(parentRectWidth) * Clean(anchorX); } public static bool TryPlaceLeftEdge(float columnWorldX, float parentWorldX, float parentLossyScaleX, float parentRectXMin, float parentRectWidth, float anchorX, out float anchoredPositionX) { anchoredPositionX = 0f; if (!Finite(parentRectXMin) || !Finite(parentRectWidth) || !Finite(anchorX)) { return false; } if (!TryParentLocalX(columnWorldX, parentWorldX, parentLossyScaleX, out var localX)) { return false; } float num = localX - AnchorReferenceLocalX(parentRectXMin, parentRectWidth, anchorX); if (!Finite(num)) { return false; } anchoredPositionX = num; return true; } public static float PlacedLeftEdge(float anchoredPositionX, float parentRectXMin, float parentRectWidth, float anchorX) { return Clean(anchoredPositionX) + AnchorReferenceLocalX(parentRectXMin, parentRectWidth, anchorX); } private static bool Finite(float value) { if (!float.IsNaN(value)) { return !float.IsInfinity(value); } return false; } public static float FontScaleToMatchGlyphHeight(float nativeHeight, float labelHeight) { if (float.IsNaN(nativeHeight) || float.IsInfinity(nativeHeight) || nativeHeight <= 0f) { return 1f; } if (float.IsNaN(labelHeight) || float.IsInfinity(labelHeight) || labelHeight <= 0f) { return 1f; } float num = nativeHeight / labelHeight; if (float.IsNaN(num) || float.IsInfinity(num) || num <= 1f) { return 1f; } float num2 = num * 1.1f; if (!float.IsNaN(num2) && !float.IsInfinity(num2)) { return num2; } return num; } private static float Clean(float value) { if (float.IsNaN(value) || float.IsInfinity(value)) { return 0f; } return value; } private static float Sanitize(float value, float fallback, float min, float max) { if (float.IsNaN(value) || float.IsInfinity(value)) { return fallback; } return Clamp(value, min, max); } private static float Clamp(float value, float min, float max) { if (value < min) { return min; } if (value > max) { return max; } return value; } } internal sealed class TimerSlotRow { private const string LabelObjectName = "EquipmentTimersLabel"; private const int MeshRetryLimit = 3; private const int SurfaceCompareInterval = 15; private const float FontScaleEpsilon = 0.001f; private const float FontSizeEpsilon = 0.01f; private const float MaxFontScale = 8f; private const float MinGlyphHeight = 0.0001f; private readonly AnchorLatch _latch = new AnchorLatch(); private bool _visibleSampleArmed; private float _shownAt = float.NegativeInfinity; private int _invalidMeshReports; private string _pendingInvalidNote; private RectTransform _anchorRect; private RectTransform _labelRect; private string _text; private TimerRowTone _tone; private bool _dirtyColor = true; private int _meshRetries = 3; private bool _surfaceDirty = true; private int _surfaceTicks; private float _fontScale = 1f; private float _fontSize; private float _nativeGlyphHeight; private float _labelGlyphHeight; public InventorySlot Slot { get; } public PUI_InventoryItem UiItem { get; set; } public ItemEquippable Item { get; set; } public TimerKind Kind { get; set; } public TimerTracker Tracker { get; set; } public ReloadClock Clock { get; set; } public TextMeshPro Anchor { get; private set; } public TextMeshPro Label { get; private set; } public bool SampleLogged { get; set; } public int MeshLogged { get; set; } = -1; public bool HasLabel => (Object)(object)Label != (Object)null; public bool Alive { get { if ((Object)(object)Label != (Object)null) { return (Object)(object)Anchor != (Object)null; } return false; } } public TimerSlotRow(InventorySlot slot) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) Slot = slot; } internal static bool IsAlive(Object value) { if (value == (Object)null) { return false; } try { return value != (Object)null; } catch { return false; } } public static bool IsUsable(TextMeshPro value) { if (!IsAlive((Object)(object)value)) { return false; } try { return ((Component)value).gameObject.activeInHierarchy && ((Behaviour)value).enabled; } catch { return false; } } public bool EnsureLabel(TextMeshPro candidate, TimerStyle style, float now) { bool flag = IsUsable(candidate); bool flag2 = IsUsable(Anchor); if ((Object)(object)Label == (Object)null) { if (!flag) { return false; } return CreateLabel(candidate, style); } try { if (flag && HasParent(candidate)) { long num = ((Il2CppObjectBase)candidate).Pointer.ToInt64(); if (_latch.ShouldAdopt(num, flag2, now) && RebindAnchor(candidate, style)) { _latch.Commit(num); } } else { _latch.CancelPending(); } if (!flag && !flag2) { return false; } EnsureSurface(style); return true; } catch { DestroyLabel(); return false; } } private bool CreateLabel(TextMeshPro anchor, TimerStyle style) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown GameObject val = null; try { RectTransform val2 = ((Il2CppObjectBase)anchor.transform).TryCast<RectTransform>(); if ((Object)(object)val2 == (Object)null) { return false; } val = new GameObject("EquipmentTimersLabel"); try { val.SetActive(false); } catch { } val.transform.SetParent(anchor.transform.parent, false); TextMeshPro val3 = val.AddComponent<TextMeshPro>(); if ((Object)(object)val3 == (Object)null) { Object.Destroy((Object)(object)val); return false; } try { Renderer renderer = val3.renderer; if ((Object)(object)renderer != (Object)null) { renderer.enabled = false; } } catch { } _anchorRect = val2; Anchor = anchor; Label = val3; CopyFontFrom(anchor, style); ((TMP_Text)val3).text = string.Empty; HideRenderer(); ClearMeshSafe(); try { Renderer renderer2 = val3.renderer; Renderer renderer3 = anchor.renderer; if ((Object)(object)renderer2 != (Object)null && (Object)(object)renderer3 != (Object)null) { renderer2.sortingLayerID = renderer3.sortingLayerID; renderer2.sortingOrder = renderer3.sortingOrder; } } catch { } _labelRect = ((Il2CppObjectBase)val3.transform).TryCast<RectTransform>(); if (!SurfaceSync.CanApplyLayout((Object)(object)_labelRect != (Object)null)) { DestroyLabel(); return false; } ApplyRectStyle(anchor, val2, style); _surfaceDirty = true; _text = null; _tone = TimerRowTone.Neutral; _dirtyColor = true; _meshRetries = 3; _latch.Hold(((Il2CppObjectBase)anchor).Pointer.ToInt64()); try { ((Component)val3).gameObject.layer = ((Component)anchor).gameObject.layer; } catch { } try { ((Component)val3).gameObject.SetActive(false); } catch { } _visibleSampleArmed = false; SyncTransform(style); return true; } catch { if ((Object)(object)val != (Object)null) { try { Object.Destroy((Object)(object)val); } catch { } } Label = null; Anchor = null; _labelRect = null; _anchorRect = null; return false; } } private bool RebindAnchor(TextMeshPro anchor, TimerStyle style) { if ((Object)(object)Label == (Object)null) { return false; } RectTransform val; try { val = ((Il2CppObjectBase)anchor.transform).TryCast<RectTransform>(); } catch { return false; } if ((Object)(object)val == (Object)null) { return false; } Transform parent; try { parent = anchor.transform.parent; } catch { return false; } if ((Object)(object)parent == (Object)null) { return false; } try { Transform parent2 = Label.transform.parent; if ((Object)(object)parent2 == (Object)null || ((Il2CppObjectBase)parent2).Pointer != ((Il2CppObjectBase)parent).Pointer) { Label.transform.SetParent(parent, false); } } catch { return false; } try { ((Component)Label).gameObject.layer = ((Component)anchor).gameObject.layer; } catch { } HideRenderer(); ClearMeshSafe(); Anchor = anchor; _anchorRect = val; CopyFontFrom(anchor, style); ApplyRectStyle(anchor, val, style); _surfaceDirty = true; _text = null; _dirtyColor = true; _meshRetries = 0; SyncTransform(style); ForceMeshUpdate(); return true; } private static bool HasParent(TextMeshPro value) { if (!IsAlive((Object)(object)value)) { return false; } try { return (Object)(object)value.transform.parent != (Object)null; } catch { return false; } } private void EnsureSurface(TimerStyle style) { if ((Object)(object)Label == (Object)null) { return; } try { if (!((Behaviour)Label).enabled) { ((Behaviour)Label).enabled = true; } } catch { } try { Renderer renderer = Label.renderer; if ((Object)(object)renderer != (Object)null && !renderer.enabled) { renderer.enabled = true; } } catch { } try { if (IsAlive((Object)(object)Anchor) && ((Component)Label).gameObject.layer != ((Component)Anchor).gameObject.layer) { ((Component)Label).gameObject.layer = ((Component)Anchor).gameObject.layer; } } catch { } if (_surfaceDirty || _surfaceTicks++ % 15 == 0) { _surfaceDirty = false; bool fontChanged = SyncFont(); SyncMaterial(out var materialChanged, out var shaderChanged); if (SurfaceSync.RequiresMeshRebuild(fontChanged, materialChanged, shaderChanged)) { ForceMeshUpdate(); } } EnsureMesh(); } private bool SyncFont() { try { TMP_FontAsset val = (IsAlive((Object)(object)Anchor) ? ((TMP_Text)Anchor).font : null); long nativePointer = (((Object)(object)val == (Object)null) ? 0 : ((Il2CppObjectBase)val).Pointer.ToInt64()); TMP_FontAsset val2 = (((Object)(object)Label == (Object)null) ? null : ((TMP_Text)Label).font); if (!SurfaceSync.NeedsSync(((Object)(object)val2 == (Object)null) ? 0 : ((Il2CppObjectBase)val2).Pointer.ToInt64(), nativePointer)) { return false; } ((TMP_Text)Label).font = val; ResetFontFit(); return true; } catch { return false; } } private void SyncMaterial(out bool materialChanged, out bool shaderChanged) { materialChanged = false; shaderChanged = false; try { Material val = (IsAlive((Object)(object)Anchor) ? ((TMP_Text)Anchor).fontSharedMaterial : null); long nativePointer = (((Object)(object)val == (Object)null) ? 0 : ((Il2CppObjectBase)val).Pointer.ToInt64()); if ((Object)(object)val == (Object)null && (Object)(object)Label != (Object)null && (Object)(object)((TMP_Text)Label).font != (Object)null) { try { val = ((TMP_Asset)((TMP_Text)Label).font).material; nativePointer = (((Object)(object)val == (Object)null) ? 0 : ((Il2CppObjectBase)val).Pointer.ToInt64()); } catch { val = null; nativePointer = 0L; } } Material val2 = (((Object)(object)Label == (Object)null) ? null : ((TMP_Text)Label).fontSharedMaterial); if (SurfaceSync.NeedsSync(((Object)(object)val2 == (Object)null) ? 0 : ((Il2CppObjectBase)val2).Pointer.ToInt64(), nativePointer)) { ((TMP_Text)Label).fontSharedMaterial = val; materialChanged = true; val2 = val; } if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val == (Object)null)) { long num = 0L; long num2 = 0L; try { num = (((Object)(object)val2.shader == (Object)null) ? 0 : ((Il2CppObjectBase)val2.shader).Pointer.ToInt64()); } catch { num = 0L; } try { num2 = (((Object)(object)val.shader == (Object)null) ? 0 : ((Il2CppObjectBase)val.shader).Pointer.ToInt64()); } catch { num2 = 0L; } if (SurfaceSync.NeedsShaderSync(num, num2)) { ((TMP_Text)Label).fontSharedMaterial = val; shaderChanged = true; } } } catch { } } private void CopyFontFrom(TextMeshPro anchor, TimerStyle style) { //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Label == (Object)null) { return; } try { if ((Object)(object)((TMP_Text)anchor).font != (Object)null) { ((TMP_Text)Label).font = ((TMP_Text)anchor).font; } } catch { } try { Material fontSharedMaterial = ((TMP_Text)anchor).fontSharedMaterial; if ((Object)(object)fontSharedMaterial != (Object)null) { ((TMP_Text)Label).fontSharedMaterial = fontSharedMaterial; } else if ((Object)(object)((TMP_Text)Label).font != (Object)null) { ((TMP_Text)Label).fontSharedMaterial = ((TMP_Asset)((TMP_Text)Label).font).material; } } catch { } try { ((TMP_Text)Label).fontSize = ((TMP_Text)anchor).fontSize; _fontSize = ((TMP_Text)anchor).fontSize; } catch { } ResetFontFit(); try { ((TMP_Text)Label).fontStyle = ((TMP_Text)anchor).fontStyle; } catch { } try { ((TMP_Text)Label).alignment = (TextAlignmentOptions)513; } catch { } try { ((TMP_Text)Label).enableWordWrapping = false; } catch { } try { ((TMP_Text)Label).enableAutoSizing = false; } catch { } try { ((TMP_Text)Label).overflowMode = (TextOverflowModes)0; } catch { } try { ((Graphic)Label).raycastTarget = false; } catch { } try { ((TMP_Text)Label).richText = false; } catch { } try { ((Graphic)Label).color = style.Neutral(((Graphic)anchor).color); } catch { } } private void ApplyRectStyle(TextMeshPro anchor, RectTransform anchorRect, TimerStyle style) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: 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_004f: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_0062: 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_00f8: 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_007f: 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_0123: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_labelRect == (Object)null || (Object)(object)anchorRect == (Object)null) { return; } try { bool flag = false; Vector2 val = PointAnchorOf(anchorRect); if (!TimerLayout.SameAnchor(_labelRect.anchorMin.x, val.x) || !TimerLayout.SameAnchor(_labelRect.anchorMin.y, val.y) || !TimerLayout.SameAnchor(_labelRect.anchorMax.x, val.x) || !TimerLayout.SameAnchor(_labelRect.anchorMax.y, val.y)) { _labelRect.anchorMin = val; _labelRect.anchorMax = val; flag = true; } if (!TimerLayout.SameAnchor(_labelRect.pivot.x, 0f) || !TimerLayout.SameAnchor(_labelRect.pivot.y, 0.5f)) { _labelRect.pivot = new Vector2(0f, 0.5f); flag = true; } float fontSize = EffectiveFontSize(anchor); float num = TimerLayout.LabelWidth(fontSize, style.WidthRatio, style.MinWidth); Rect rect = anchorRect.rect; Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor(num, LabelHeight(((Rect)(ref rect)).height, fontSize)); if (flag || !TimerLayout.SameAnchor(_labelRect.sizeDelta.x, val2.x) || !TimerLayout.SameAnchor(_labelRect.sizeDelta.y, val2.y)) { _labelRect.sizeDelta = val2; } } catch { } } private void ActivateForMeshBuild() { if ((Object)(object)Label == (Object)null) { return; } DisableRendererOnly(); try { if (!((Component)Label).gameObject.activeSelf) { ((Component)Label).gameObject.SetActive(true); } } catch (Exception ex) { ReportInvalidMesh("activate:" + ex.GetType().Name); } DisableRendererOnly(); } private void DisableRendererOnly() { if ((Object)(object)Label == (Object)null) { return; } try { Renderer renderer = Label.renderer; if ((Object)(object)renderer != (Object)null && renderer.enabled) { renderer.enabled = false; } } catch { } } private void ForceMeshUpdate() { if ((Object)(object)Label == (Object)null) { return; } if (VisibilityPolicy.HasText(_text)) { ActivateForMeshBuild(); } try { ((TMP_Text)Label).havePropertiesChanged = true; } catch (Exception ex) { ReportInvalidMesh("props:" + ex.GetType().Name); } try { ((Graphic)Label).SetAllDirty(); } catch (Exception ex2) { ReportInvalidMesh("dirty:" + ex2.GetType().Name); } try { ((TMP_Text)Label).ForceMeshUpdate(true, true); } catch (Exception ex3) { ReportInvalidMesh("force:" + ex3.GetType().Name); } } private void EnsureMesh() { if (!((Object)(object)Label == (Object)null) && VisibilityPolicy.HasText(_text) && VisibilityPolicy.CanRetryMesh(_meshRetries) && !VisibilityPolicy.CanShow(CharacterCount(), VertexCount())) { DisableRendererOnly(); _meshRetries++; ForceMeshUpdate(); } } private void HideRenderer() { if ((Object)(object)Label == (Object)null) { return; } DisableRendererOnly(); try { if (((Component)Label).gameObject.activeSelf) { ((Component)Label).gameObject.SetActive(false); } } catch { } } private void ClearMeshSafe() { if ((Object)(object)Label == (Object)null) { return; } try { ((TMP_Text)Label).ClearMesh(); return; } catch (Exception ex) { ReportInvalidMesh("clear:" + ex.GetType().Name); } try { ((TMP_Text)Label).ClearMesh(false); } catch (Exception ex2) { ReportInvalidMesh("clear2:" + ex2.GetType().Name); } } private void HideAndClear() { HideRenderer(); if (CharacterCount() > 0 || VertexCount() > 0) { ClearMeshSafe(); } _visibleSampleArmed = false; } private bool ShowOnlyWhenValid(float now) { if ((Object)(object)Label == (Object)null) { return false; } int num = CharacterCount(); int num2 = VertexCount(); if (!VisibilityPolicy.ShouldShow(!string.IsNullOrEmpty(_text), num, num2)) { DisableRendererOnly(); if (num2 > 0 || num > 0) { ClearMeshSafe(); } ReportInvalidMesh("chars=" + num + " vtx=" + num2); return false; } try { Renderer renderer = Label.renderer; if ((Object)(object)renderer != (Object)null && !renderer.enabled) { renderer.enabled = true; } } catch { } try { if (!((Component)Label).gameObject.activeSelf) { ((Component)Label).gameObject.SetActive(true); } } catch { } if (!SampleLogged && !_visibleSampleArmed) { _visibleSampleArmed = true; _shownAt = now; } return true; } public void SyncLayout(TimerStyle style) { //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_00db: 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_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Label == (Object)null || (Object)(object)Anchor == (Object)null) { return; } try { if ((Object)(object)_anchorRect == (Object)null) { _anchorRect = ((Il2CppObjectBase)Anchor.transform).TryCast<RectTransform>(); } if ((Object)(object)_labelRect == (Object)null) { _labelRect = ((Il2CppObjectBase)Label.transform).TryCast<RectTransform>(); } if ((Object)(object)_anchorRect == (Object)null || (Object)(object)_labelRect == (Object)null) { DestroyLabel(); return; } SyncLocalScale(); FitFontToNative(); ApplyRectStyle(Anchor, _anchorRect, style); Vector2 val = PointAnchorOf(_anchorRect); if (!TimerLayout.SameAnchor(_labelRect.anchorMin.x, val.x) || !TimerLayout.SameAnchor(_labelRect.anchorMin.y, val.y) || !TimerLayout.SameAnchor(_labelRect.anchorMax.x, val.x) || !TimerLayout.SameAnchor(_labelRect.anchorMax.y, val.y)) { _labelRect.anchorMin = val; _labelRect.anchorMax = val; } } catch { DestroyLabel(); } } public void SyncTransform(TimerStyle style) { SyncLayout(style); PlaceOnColumn(style, float.NaN); } public void PlaceOnColumn(TimerStyle style, float columnWorldX) { //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_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: 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) if ((Object)(object)Label == (Object)null || (Object)(object)Anchor == (Object)null || (Object)(object)_anchorRect == (Object)null || (Object)(object)_labelRect == (Object)null) { return; } try { Vector2 anchoredPosition = _anchorRect.anchoredPosition; Rect rect = _anchorRect.rect; Vector2 pivot = _anchorRect.pivot; float gap = TimerLayout.Gap(((TMP_Text)Anchor).fontSize, style.GapRatio, style.MinGap, style.MaxGap); float num = _labelRect.anchoredPosition.x; float anchoredX2; if (TrySharedColumnLocal(columnWorldX, out var anchoredX)) { num = anchoredX; } else if (TryFallbackAnchoredX(style, anchoredPosition.x, rect, pivot.x, gap, out anchoredX2)) { num = anchoredX2; } _labelRect.anchoredPosition = new Vector2(num, TimerLayout.LabelAnchoredY(anchoredPosition.y, ((Rect)(ref rect)).height, pivot.y)); } catch { DestroyLabel(); } } public bool TryMeasureNativeLeftEdge(out float worldX) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: 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_00da: Unknown result type (might be due to invalid IL or missing references) worldX = 0f; if ((Object)(object)_anchorRect == (Object)null || !IsAlive((Object)(object)Anchor)) { return false; } try { Bounds textBounds = ((TMP_Text)Anchor).textBounds; Vector3 val = default(Vector3); if (((Bounds)(ref textBounds)).size.x > 0.0001f) { ((Vector3)(ref val))..ctor(((Bounds)(ref textBounds)).min.x, ((Bounds)(ref textBounds)).center.y, 0f); } else { Rect rect = _anchorRect.rect; if (!(((Rect)(ref rect)).width > 0f)) { return false; } ((Vector3)(ref val))..ctor(((Rect)(ref rect)).xMin, ((Rect)(ref rect)).center.y, 0f); } Vector3 val2 = Anchor.transform.TransformPoint(val); if (float.IsNaN(val2.x) || float.IsInfinity(val2.x)) { return false; } worldX = val2.x; return true; } catch { return false; } } public bool TryMeasureColumnVote(TimerStyle style, out float nameLeftEdge, out float labelWidth, out float gap) { //IL_0061: Unknown result type (might be due to invalid IL or missing references) nameLeftEdge = 0f; labelWidth = 0f; gap = 0f; if ((Object)(object)Label == (Object)null || (Object)(object)_labelRect == (Object)null) { return false; } if (!VisibilityPolicy.HasText(_text)) { return false; } if (!TryMeasureNativeLeftEdge(out nameLeftEdge)) { return false; } if (!TryMeasureLabelWidthLocal(out var width)) { return false; } float num; float fontSize; try { num = Math.Abs(((Transform)_labelRect).lossyScale.x); fontSize = (((Object)(object)Anchor == (Object)null) ? 0f : ((TMP_Text)Anchor).fontSize); } catch { return false; } if (float.IsNaN(num) || float.IsInfinity(num) || !(num > 0f)) { return false; } float num2 = TimerLayout.Gap(fontSize, style.GapRatio, style.MinGap, style.MaxGap); labelWidth = width * num; gap = num2 * num; if (!float.IsNaN(labelWidth) && !float.IsInfinity(labelWidth) && !float.IsNaN(gap)) { return !float.IsInfinity(gap); } return false; } private bool TryMeasureLabelWidthLocal(out float width) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_004e: 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_0074: Unknown result type (might be due to invalid IL or missing references) width = 0f; if ((Object)(object)Label == (Object)null || (Object)(object)_labelRect == (Object)null) { return false; } bool flag = false; float num = 0f; try { Bounds textBounds = ((TMP_Text)Label).textBounds; if (((Bounds)(ref textBounds)).size.x > 0.0001f && !float.IsNaN(((Bounds)(ref textBounds)).size.x) && !float.IsInfinity(((Bounds)(ref textBounds)).size.x)) { num = ((Bounds)(ref textBounds)).size.x; flag = true; } } catch { flag = false; } if (flag) { width = ((num > 0f) ? num : 0f); } else { try { Rect rect = _labelRect.rect; width = Math.Abs(((Rect)(ref rect)).width); } catch { width = 0f; } } if (float.IsNaN(width) || float.IsInfinity(width) || !(width > 0f)) { return false; } return true; } private bool TrySharedColumnLocal(float columnWorldX, out float anchoredX) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_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_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) anchoredX = 0f; if (float.IsNaN(columnWorldX) || float.IsInfinity(columnWorldX)) { return false; } try { RectTransform val = ParentRect(); if ((Object)(object)val == (Object)null) { return false; } Rect rect = val.rect; Vector2 anchorMin = _labelRect.anchorMin; return TimerLayout.TryPlaceLeftEdge(columnWorldX, ((Transform)val).position.x, ((Transform)val).lossyScale.x, ((Rect)(ref rect)).xMin, ((Rect)(ref rect)).width, anchorMin.x, out anchoredX); } catch { return false; } } private bool TryFallbackAnchoredX(TimerStyle style, float nativeAnchoredX, Rect nativeBounds, float nativePivotX, float gap, out float anchoredX) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) anchoredX = 0f; try { RectTransform val = ParentRect(); if ((Object)(object)val == (Object)null) { return false; } Rect rect = val.rect; Vector2 anchorMin = _labelRect.anchorMin; if (!TryMeasureLabelWidthLocal(out var width)) { width = TimerLayout.LabelWidth(EffectiveFontSize(Anchor), style.WidthRatio, style.MinWidth); } float delta; float num = ((!TryGlyphLeftDelta(out delta)) ? TimerLayout.LabelAnchoredX(nativeAnchoredX, ((Rect)(ref nativeBounds)).width, nativePivotX, 0f) : TimerLayout.LabelAnchoredXFromGlyph(nativeAnchoredX, delta, 0f)); float num2 = TimerLayout.AnchorReferenceLocalX(((Rect)(ref rect)).xMin, ((Rect)(ref rect)).width, anchorMin.x); float num3 = num - gap - width - num2; if (float.IsNaN(num3) || float.IsInfinity(num3)) { return false; } anchoredX = num3; return true; } catch { return false; } } private RectTransform ParentRect() { try { if ((Object)(object)_labelRect == (Object)null) { return null; } Transform parent = ((Transform)_labelRect).parent; if ((Object)(object)parent == (Object)null) { return null; } return ((Il2CppObjectBase)parent).TryCast<RectTransform>(); } catch { return null; } } private void SyncLocalScale() { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Label == (Object)null || !IsAlive((Object)(object)Anchor)) { return; } Vector3 localScale; Vector3 localScale2; try { localScale = Anchor.transform.localScale; localScale2 = Label.transform.localScale; } catch { return; } if (SameScale(localScale2, localScale)) { return; } try { Label.transform.localScale = localScale; } catch { } } private static bool SameScale(Vector3 left, Vector3 right) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) if (Math.Abs(left.x - right.x) <= 0.0005f && Math.Abs(left.y - right.y) <= 0.0005f) { return Math.Abs(left.z - right.z) <= 0.0005f; } return false; } private void FitFontToNative() { if ((Object)(object)Label == (Object)null || !IsAlive((Object)(object)Anchor)) { return; } float fontSize; try { fontSize = ((TMP_Text)Anchor).fontSize; } catch { return; } if (float.IsNaN(fontSize) || float.IsInfinity(fontSize) || fontSize <= 0f) { return; } if (_text == "--") { _nativeGlyphHeight = 0f; _labelGlyphHeight = 0f; ApplyFontSize(fontSize * _fontScale); return; } float height = 0f; float height2 = 0f; bool flag = MeasureGlyphHeight(Anchor, out height); if (flag) { flag = MeasureGlyphHeight(Label, out height2); } if (flag) { flag = SameFontAsNative(); } _nativeGlyphHeight = (flag ? height : 0f); _labelGlyphHeight = (flag ? height2 : 0f); if (flag) { float num = TimerLayout.FontScaleToMatchGlyphHeight(height, height2); if (num > 1.001f) { float num2 = _fontScale * num; _fontScale = ((num2 > 8f) ? 8f : num2); } } ApplyFontSize(fontSize * _fontScale); } private static bool MeasureGlyphHeight(TextMeshPro text, out float height) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) height = 0f; if (!IsAlive((Object)(object)text)) { return false; } try { Bounds textBounds = ((TMP_Text)text).textBounds; float num = Math.Abs(((Bounds)(ref textBounds)).size.y); float num2 = Math.Abs(text.transform.lossyScale.y); if (float.IsNaN(num) || float.IsInfinity(num) || num <= 0.0001f) { return false; } if (float.IsNaN(num2) || float.IsInfinity(num2) || num2 <= 0.0001f) { return false; } height = num * num2; return true; } catch { return false; } } private bool SameFontAsNative() { try { TMP_FontAsset val = (IsAlive((Object)(object)Anchor) ? ((TMP_Text)Anchor).font : null); TMP_FontAsset val2 = (((Object)(object)Label == (Object)null) ? null : ((TMP_Text)Label).font); if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null) { return false; } return ((Il2CppObjectBase)val).Pointer == ((Il2CppObjectBase)val2).Pointer; } catch { return false; } } private void ApplyFontSize(float size) { if ((Object)(object)Label == (Object)null || float.IsNaN(size) || float.IsInfinity(size) || size <= 0f) { return; } float fontSize; try { fontSize = ((TMP_Text)Label).fontSize; } catch { return; } if (Math.Abs(fontSize - size) <= 0.01f) { _fontSize = fontSize; return; } try { ((TMP_Text)Label).fontSize = size; } catch { return; } _fontSize = size; _meshRetries = 0; ForceMeshUpdate(); } private void ResetFontFit() { _fontScale = 1f; _nativeGlyphHeight = 0f; _labelGlyphHeight = 0f; } private string DescribeFontFit() { StringBuilder stringBuilder = new StringBuilder(96); float num = 0f; try { num = (((Object)(object)Label == (Object)null) ? 0f : ((TMP_Text)Label).fontSize); } catch { num = 0f; } float num2 = 0f; try { num2 = (IsAlive((Object)(object)Anchor) ? ((TMP_Text)Anchor).fontSize : 0f); } catch { num2 = 0f; } stringBuilder.Append(" fontSize=").Append(F(num)); stringBuilder.Append(" native.fontSize=").Append(F(num2)); stringBuilder.Append(" nativeGlyphHeight=").Append(F(_nativeGlyphHeight)); stringBuilder.Append(" labelGlyphHeight=").Append(F(_labelGlyphHeight)); stringBuilder.Append(" fontScale=").Append(F(_fontScale)); return stringBuilder.ToString(); } private float EffectiveFontSize(TextMeshPro anchor) { if (_fontSize > 0f) { return _fontSize; } try { return ((Object)(object)anchor == (Object)null) ? 0f : ((TMP_Text)anchor).fontSize; } catch { return 0f; } } public string DescribeGeometry() { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_03f2: Unknown result type (might be due to invalid IL or missing references) //IL_03f7: Unknown result type (might be due to invalid IL or missing references) //IL_0406: Unknown result type (might be due to invalid IL or missing references) //IL_0423: Unknown result type (might be due to invalid IL or missing references) //IL_0440: Unknown result type (might be due to invalid IL or missing references) //IL_045d: Unknown result type (might be due to invalid IL or missing references) //IL_04a3: Unknown result type (might be due to invalid IL or missing references) //IL_04c2: Unknown result type (might be due to invalid IL or missing references) //IL_04e1: Unknown result type (might be due to invalid IL or missing references) //IL_02a3: Unknown result type (might be due to invalid IL or missing references) //IL_02a8: Unknown result type (might be due to invalid IL or missing references) //IL_0369: Unknown result type (might be due to invalid IL or missing references) //IL_036e: Unknown result type (might be due to invalid IL or missing references) //IL_038b: Unknown result type (might be due to invalid IL or missing references) //IL_038d: Unknown result type (might be due to invalid IL or missing references) //IL_037b: Unknown result type (might be due to invalid IL or missing references) //IL_037d: Unknown result type (might be due to invalid IL or missing references) //IL_0382: Unknown result type (might be due to invalid IL or missing references) //IL_0392: Unknown result type (might be due to invalid IL or missing references) //IL_039f: Unknown result type (might be due to invalid IL or missing references) //IL_03b7: Unknown result type (might be due to invalid IL or missing references) RectTransform labelRect = _labelRect; if ((Object)(object)labelRect == (Object)null) { return "label=none"; } StringBuilder stringBuilder = new StringBuilder(320); try { stringBuilder.Append("ancMin=").Append(V2(labelRect.anchorMin)); } catch { stringBuilder.Append("ancMin=?"); } try { stringBuilder.Append(" ancMax=").Append(V2(labelRect.anchorMax)); } catch { stringBuilder.Append(" ancMax=?"); } try { stringBuilder.Append(" pivot=").Append(V2(labelRect.pivot)); } catch { stringBuilder.Append(" pivot=?"); } try { stringBuilder.Append(" anchored=").Append(V2(labelRect.anchoredPosition)); } catch { stringBuilder.Append(" anchored=?"); } try { stringBuilder.Append(" sizeDelta=").Append(V2(labelRect.sizeDelta)); } catch { stringBuilder.Append(" sizeDelta=?"); } try { Rect rect = labelRect.rect; stringBuilder.Append(" rect=").Append(F(((Rect)(ref rect)).x)).Append(',') .Append(F(((Rect)(ref rect)).y)) .Append(',') .Append(F(((Rect)(ref rect)).width)) .Append(',') .Append(F(((Rect)(ref rect)).height)); } catch { stringBuilder.Append(" rect=?"); } try { Vector3 lossyScale = ((Transform)labelRect).lossyScale; stringBuilder.Append(" scale=").Append(F(lossyScale.x)).Append(',') .Append(F(lossyScale.y)) .Append(',') .Append(F(lossyScale.z)); } catch { stringBuilder.Append(" scale=?"); } try { stringBuilder.Append(" active=").Append(((Component)labelRect).gameObject.activeInHierarchy ? "1" : "0"); } catch { stringBuilder.Append(" active=?"); } try { stringBuilder.Append(" enabled=").Append(((Object)(object)Label != (Object)null && ((Behaviour)Label).enabled) ? "1" : "0"); } catch { stringBuilder.Append(" enabled=?"); } try { Canvas val = (((Object)(object)Label == (Object)null) ? null : ((Graphic)Label).canvas); stringBuilder.Append(" canvas=").Append(((Object)(object)val == (Object)null) ? "none" : ((object)val.renderMode/*cast due to .constrained prefix*/).ToString()); } catch { stringBuilder.Append(" canvas=?"); } try { CanvasGroup val2 = (((Object)(object)Label == (Object)null) ? null : ((Component)Label).GetComponentInParent<CanvasGroup>()); stringBuilder.Append(" group=").Append(((Object)(object)val2 == (Object)null) ? "none" : F(val2.alpha)); } catch { stringBuilder.Append(" group=?"); } try { Canvas val3 = (((Object)(object)Label == (Object)null) ? null : ((Graphic)Label).canvas); Camera val4 = (((Object)(object)val3 == (Object)null) ? null : val3.worldCamera); Vector3 position = ((Transform)labelRect).position; Vector3 val5 = (((Object)(object)val4 != (Object)null) ? val4.WorldToScreenPoint(position) : Vector2.op_Implicit(RectTransformUtility.WorldToScreenPoint((Camera)null, position))); stringBuilder.Append(" screen=").Append(F(val5.x)).Append(',') .Append(F(val5.y)); } catch { stringBuilder.Append(" screen=?"); } try { if ((Object)(object)Label != (Object)null) { Bounds textBounds = ((TMP_Text)Label).textBounds; stringBuilder.Append(" glyph=").Append(F(((Bounds)(ref textBounds)).center.x)).Append(',') .Append(F(((Bounds)(ref textBounds)).center.y)) .Append(',') .Append(F(((Bounds)(ref textBounds)).size.x)) .Append(',') .Append(F(((Bounds)(ref textBounds)).size.y)); } } catch { stringBuilder.Append(" glyph=?"); } try { if ((Object)(object)_anchorRect != (Object)null) { stringBuilder.Append(" native.anc=").Append(V2(_anchorRect.anchorMin)).Append("..") .Append(V2(_anchorRect.anchorMax)) .Append(" pv=") .Append(V2(_anchorRect.pivot)); } } catch { } try { stringBuilder.Append(" text='").Append((_text == null) ? string.Empty : _text).Append("'"); } catch { stringBuilder.Append(" text=?"); } stringBuilder.Append(' ').Append(DescribeSurface()); return stringBuilder.ToString(); } public string DescribeSurface() { if ((Object)(object)Label == (Object)null) { return "surface=none"; } StringBuilder stringBuilder = new StringBuilder(160); stringBuilder.Append("chars=").Append(CharacterCount()); stringBuilder.Append(" vtx=").Append(VertexCount()); try { Renderer renderer = Label.renderer; stringBuilder.Append(" rend=").Append(((Object)(object)renderer == (Object)null) ? "none" : (renderer.enabled ? "1" : "0")); stringBuilder.Append(" vis=").Append(((Object)(object)renderer == (Object)null) ? "none" : (renderer.isVisible ? "1" : "0")); } catch { stringBuilder.Append(" rend=? vis=?"); } try { stringBuilder.Append(" font=").Append(((Object)(object)((TMP_Text)Label).font == (Object)null) ? "none" : ((Object)((TMP_Text)Label).font).name); } catch { stringBuilder.Append(" font=?"); } try { stringBuilder.Append(" mat=").Append(((Object)(object)((TMP_Text)Label).fontSharedMaterial == (Object)null) ? "none" : ((Object)((TMP_Text)Label).fontSharedMaterial).name); } catch { stringBuilder.Append(" mat=?"); } try { Material fontSharedMaterial = ((TMP_Text)Label).fontSharedMaterial; stringBuilder.Append(" shader=").Append(((Object)(object)fontSharedMaterial == (Object)null || (Object)(object)fontSharedMaterial.shader == (Object)null) ? "none" : ((Object)fontSharedMaterial.shader).name); } catch { stringBuilder.Append(" shader=?"); } return stringBuilder.ToString(); } public string TakeVisibleSample(float now) { //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) if ((Object)(object)Label == (Object)null || (Object)(object)Anchor == (Object)null) { return null; } if (!VisibilityPolicy.CanReportVisibleSample(SampleLogged, _visibleSampleArmed, _shownAt, now, IsActiveInHierarchy(), CharacterCount(), VertexCount())) { return null; } SampleLogged = true; _visibleSampleArmed = false; return "[hud] slot " + ((object)Slot/*cast due to .constrained prefix*/).ToString() + " visible sample; " + DescribeVisibleState(); } public string TakeInvalidMeshNote() { string pendingInvalidNote = _pendingInvalidNote; _pendingInvalidNote = null; return pendingInvalidNote; } private void ReportInvalidMesh(string reason) { //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 (_invalidMeshReports < 3) { _invalidMeshReports++; _pendingInvalidNote = "[hud] slot " + ((object)Slot/*cast due to .constrained prefix*/).ToString() + " label kept hidden; " + reason; } } private bool IsActiveInHierarchy() { if ((Object)(object)Label == (Object)null) { return false; } try { return ((Component)Label).gameObject.activeInHierarchy; } catch { return false; } } public string DescribeVisibleState() { //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_0201: Unknown result type (might be due to invalid IL or missing references) StringBuilder stringBuilder = new StringBuilder(256); try { stringBuilder.Append("text='").Append((_text == null) ? string.Empty : _text).Append('\''); } catch { stringBuilder.Append("text=?"); } try { stringBuilder.Append(" activeInHierarchy=").Append(((Object)(object)Label != (Object)null && ((Component)Label).gameObject.activeInHierarchy) ? "1" : "0"); } catch { stringBuilder.Append(" activeInHierarchy=?"); } stringBuilder.Append(" chars=").Append(CharacterCount()); stringBuilder.Append(" vtx=").Append(VertexCount()); try { Renderer val = (((Object)(object)Label == (Object)null) ? null : Label.renderer); stringBuilder.Append(" rend=").Append(((Object)(object)val == (Object)null) ? "none" : (val.enabled ? "1" : "0")); stringBuilder.Append(" vis=").Append(((Object)(object)val == (Object)null) ? "none" : (val.isVisible ? "1" : "0")); } catch { stringBuilder.Append(" rend=? vis=?"); } try { Mesh val2 = (((Object)(object)Label == (Object)null) ? null : ((TMP_Text)Label).mesh); if ((Object)(object)val2 == (Object)null) { stringBuilder.Append(" bounds=none"); } else { Bounds bounds = val2.bounds; stringBuilder.Append(" bounds=").Append(F(((Bounds)(ref bounds)).center.x)).Append(',') .Append(F(((Bounds)(ref bounds)).center.y)) .Append(',') .Append(F(((Bounds)(ref bounds)).size.x)) .Append(',') .Append(F(((Bounds)(ref bounds)