Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of OttoLens v1.0.4
OttoLens.dll
Decompiled 5 days 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.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using OttoLens.Model; using OttoLens.Readers; using OttoLens.UI; using TMPro; using UnityEngine; using UnityEngine.PostProcessing; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("OttoLens")] [assembly: AssemblyCompany("potto007")] [assembly: AssemblyProduct("OttoLens")] [assembly: AssemblyCopyright("Copyright (c) 2026 Paul Otto")] [assembly: ComVisible(false)] [assembly: Guid("7c1d5a2e-3b64-4f1a-9e0c-6a2f5d8b1c47")] [assembly: AssemblyFileVersion("1.0.4")] [assembly: IgnoresAccessChecksTo("assembly_guiutils")] [assembly: IgnoresAccessChecksTo("assembly_utils")] [assembly: IgnoresAccessChecksTo("assembly_valheim")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.4.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] 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; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace OttoLens { internal static class LensDirt { private static readonly Dictionary<PostProcessingProfile, float> Originals = new Dictionary<PostProcessingProfile, float>(); internal static void Apply(CameraEffects? effects) { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)effects == (Object)null) { return; } PostProcessingBehaviour component = ((Component)effects).GetComponent<PostProcessingBehaviour>(); PostProcessingProfile val = (((Object)(object)component != (Object)null) ? component.profile : null); if (!((Object)(object)val == (Object)null) && val.bloom != null) { if (!Originals.TryGetValue(val, out var value)) { value = val.bloom.settings.lensDirt.intensity; Originals[val] = value; } Write(val, OttoLensPlugin.RemoveLensDirt.Value ? 0f : value); } } internal static void ApplyCurrent() { Apply(CameraEffects.instance); } internal static void Restore() { foreach (KeyValuePair<PostProcessingProfile, float> original in Originals) { if ((Object)(object)original.Key != (Object)null && original.Key.bloom != null) { Write(original.Key, original.Value); } } Originals.Clear(); } private static void Write(PostProcessingProfile profile, float intensity) { //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_000d: 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) Settings settings = profile.bloom.settings; if (!Mathf.Approximately(settings.lensDirt.intensity, intensity)) { settings.lensDirt.intensity = intensity; profile.bloom.settings = settings; } } } [HarmonyPatch] internal static class Patches { private static readonly HashSet<Type> LoggedExceptions = new HashSet<Type>(); private static GameObject? _lastHover; private static bool _lastPlaceMode; private static ILensReader? _lastReader; private static Component? _lastTarget; private static ILensReader? _wearNTearReader; [HarmonyPostfix] [HarmonyPatch(typeof(Hud), "UpdateCrosshair", new Type[] { typeof(Player), typeof(float) })] private static void UpdateCrosshairPostfix(Hud __instance, Player player) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) try { KeyCode value = OttoLensPlugin.ToggleKey.Value; if ((int)value != 0 && !KeyboardIsBusy() && Input.GetKeyDown(value)) { OttoLensPlugin.Enabled.Value = !OttoLensPlugin.Enabled.Value; } Frame(__instance, player); } catch (Exception ex) { LogOnce(ex); LensPanel.Instance?.SetTarget(null, null, null); } } [HarmonyPostfix] [HarmonyPatch(typeof(Hud), "OnDestroy")] private static void HudDestroyPostfix() { try { Teardown(); } catch (Exception ex) { LogOnce(ex); } } [HarmonyPostfix] [HarmonyPatch(typeof(CameraEffects), "Awake")] private static void CameraEffectsAwakePostfix(CameraEffects __instance) { try { LensDirt.Apply(__instance); } catch (Exception ex) { LogOnce(ex); } } internal static void Teardown() { _lastHover = null; _lastPlaceMode = false; _lastReader = null; _lastTarget = null; LensPanel.Release(); LensFormat.ClearCaches(); LensReaders.ClearLocalizedCaches(); ContainerReader.ClearOpenedChests(); } [HarmonyPostfix] [HarmonyPatch(typeof(InventoryGui), "Show")] private static void InventoryGuiShowPostfix(Container container) { try { if (!((Object)(object)container == (Object)null)) { Piece piece = container.m_piece; if (!((Object)(object)piece != (Object)null) || !piece.IsPlacedByPlayer()) { ContainerReader.RecordOpen(container); } } } catch (Exception ex) { LogOnce(ex); } } internal static void InvalidateHoverCache() { _lastHover = null; _lastReader = null; _lastTarget = null; } private static void Frame(Hud hud, Player player) { if (!OttoLensPlugin.Enabled.Value || (Object)(object)player == (Object)null || !hud.IsVisible() || InventoryGui.IsVisible()) { LensPanel.Instance?.SetTarget(null, null, null); return; } bool flag = ((Character)player).InPlaceMode(); GameObject val = ResolveHoverObject(player, flag); if ((Object)(object)val == (Object)null) { _lastHover = null; _lastPlaceMode = flag; _lastReader = null; _lastTarget = null; LensPanel.Instance?.SetTarget(null, null, null); return; } if ((Object)(object)val != (Object)(object)_lastHover || flag != _lastPlaceMode) { _lastHover = val; _lastPlaceMode = flag; ILensReader reader; Component target; if (flag) { Piece hoveringPiece = player.GetHoveringPiece(); WearNTear val2 = ((hoveringPiece != null) ? ((Component)hoveringPiece).GetComponentInParent<WearNTear>() : null); if (_wearNTearReader == null) { _wearNTearReader = LensReaders.All.FirstOrDefault((ILensReader r) => r is WearNTearReader); } if ((Object)(object)val2 != (Object)null && _wearNTearReader != null) { _lastReader = _wearNTearReader; _lastTarget = (Component?)(object)val2; } else { _lastReader = null; _lastTarget = null; } } else if (LensReaders.Resolve(val, out reader, out target)) { _lastReader = reader; _lastTarget = target; } else { _lastReader = null; _lastTarget = null; } } if (_lastReader != null && !_lastReader.Enabled) { _lastHover = null; _lastPlaceMode = flag; _lastReader = null; _lastTarget = null; LensPanel.Instance?.SetTarget(null, null, null); } else if (_lastReader == null || (Object)(object)_lastTarget == (Object)null) { LensPanel.Instance?.SetTarget(null, null, null); } else if (!LensReaders.PassesCoreGuards(_lastTarget, ((TMP_Text)hud.m_hoverName).text)) { LensPanel.Instance?.SetTarget(null, null, null); } else { LensPanel.Get()?.SetTarget(_lastTarget, _lastReader, val); } } private static GameObject? ResolveHoverObject(Player player, bool placeMode) { GameObject hoverObject = ((Humanoid)player).GetHoverObject(); if ((Object)(object)hoverObject != (Object)null) { return hoverObject; } if (!placeMode || OttoLensPlugin.ShowBuildPieces.Value == OttoLensPlugin.PieceStatus.Off) { return null; } Piece hoveringPiece = player.GetHoveringPiece(); if (!((Object)(object)hoveringPiece != (Object)null)) { return null; } return ((Component)hoveringPiece).gameObject; } private static bool KeyboardIsBusy() { if (!Console.IsVisible() && !TextInput.IsVisible() && !Minimap.InTextInput() && !Menu.IsVisible() && (!((Object)(object)Chat.instance != (Object)null) || !Chat.instance.HasFocus())) { if ((Object)(object)Hud.instance != (Object)null && (Object)(object)Hud.instance.m_buildUi != (Object)null) { return Hud.instance.m_buildUi.SearchFieldFocused; } return false; } return true; } private static void LogOnce(Exception ex) { if (LoggedExceptions.Add(ex.GetType())) { OttoLensPlugin.Log.LogWarning((object)("OttoLens hook failed with " + ex.GetType().Name + ": " + ex.Message + ". Further " + ex.GetType().Name + " reports are suppressed.\n" + ex.StackTrace)); } } } [BepInPlugin("potto007.OttoLens", "OttoLens", "1.0.4")] public class OttoLensPlugin : BaseUnityPlugin { public enum SortRows { Count, Slot } public enum PieceStatus { Off, WithHammer, Always } internal const string ModName = "OttoLens"; internal const string ModVersion = "1.0.4"; internal const string Author = "potto007"; internal const string ModGUID = "potto007.OttoLens"; internal static readonly ManualLogSource Log = Logger.CreateLogSource("OttoLens"); private readonly Harmony _harmony = new Harmony("potto007.OttoLens"); private const string PanelSection = "OttoLens"; private const string CameraSection = "Camera"; private const string TargetSection = "Targets"; private static readonly Version UnboundToggleKeySince = new Version(1, 0, 2); private static readonly Regex SavedByHeader = new Regex("^## Settings file was created by plugin .+ v(\\d+(?:\\.\\d+){1,3})"); internal static ConfigEntry<bool> Enabled = null; internal static ConfigEntry<KeyCode> ToggleKey = null; internal static ConfigEntry<int> OffsetX = null; internal static ConfigEntry<int> OffsetY = null; internal static ConfigEntry<int> PanelWidth = null; internal static ConfigEntry<float> GuiScale = null; internal static ConfigEntry<int> MaxRows = null; internal static ConfigEntry<SortRows> SortRowsBy = null; internal static ConfigEntry<bool> ShowNames = null; internal static ConfigEntry<bool> ShowFullHealth = null; internal static ConfigEntry<bool> AvoidHoverText = null; internal static ConfigEntry<int> RefreshHz = null; internal static ConfigEntry<float> FadeSeconds = null; internal static ConfigEntry<float> BackdropAlpha = null; internal static ConfigEntry<bool> ShowDays = null; internal static ConfigEntry<bool> RemoveLensDirt = null; internal static ConfigEntry<bool> HideUnopenedWorldChests = null; internal static ConfigEntry<bool> ShowContainers = null; internal static ConfigEntry<bool> ShowFires = null; internal static ConfigEntry<bool> ShowSmelters = null; internal static ConfigEntry<bool> ShowCooking = null; internal static ConfigEntry<bool> ShowFermenting = null; internal static ConfigEntry<bool> ShowPlants = null; internal static ConfigEntry<bool> ShowPickables = null; internal static ConfigEntry<bool> ShowRespawn = null; internal static ConfigEntry<PieceStatus> ShowBuildPieces = null; internal static ConfigEntry<bool> ShowMineables = null; internal static ConfigEntry<bool> ShowTreesAndRocks = null; internal static ConfigEntry<bool> ShowStands = null; internal static ConfigEntry<bool> ShowCreatures = null; internal static ConfigEntry<bool> ShowMisc = null; public void Awake() { BindConfig(); _harmony.PatchAll(typeof(OttoLensPlugin).Assembly); LensDirt.ApplyCurrent(); Log.LogInfo((object)"OttoLens 1.0.4 loaded."); } private Version? ReadSavedByVersion() { try { if (!File.Exists(((BaseUnityPlugin)this).Config.ConfigFilePath)) { return null; } using StreamReader streamReader = new StreamReader(((BaseUnityPlugin)this).Config.ConfigFilePath); Match match = SavedByHeader.Match(streamReader.ReadLine() ?? string.Empty); return match.Success ? new Version(match.Groups[1].Value) : null; } catch (Exception ex) { Log.LogWarning((object)("Could not read the version header of " + Path.GetFileName(((BaseUnityPlugin)this).Config.ConfigFilePath) + ": " + ex.Message)); return null; } } private static void MigrateToggleKey(Version? savedBy) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Invalid comparison between Unknown and I4 if (!(savedBy == null) && !(savedBy >= UnboundToggleKeySince) && (int)ToggleKey.Value == 104) { ToggleKey.Value = (KeyCode)0; Log.LogInfo((object)$"ToggleKey changed from H to None (unbound), the default since v{UnboundToggleKeySince.ToString(3)}. The config was last saved by v{savedBy}."); } } private void BindConfig() { //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Expected O, but got Unknown //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Expected O, but got Unknown //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Expected O, but got Unknown //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Expected O, but got Unknown //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Expected O, but got Unknown //IL_0208: Unknown result type (might be due to invalid IL or missing references) //IL_0212: Expected O, but got Unknown //IL_0245: Unknown result type (might be due to invalid IL or missing references) //IL_024f: Expected O, but got Unknown //IL_0282: Unknown result type (might be due to invalid IL or missing references) //IL_028c: Expected O, but got Unknown Version version = ReadSavedByVersion(); Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("OttoLens", "Enabled", true, "Master switch. Off hides the panel and skips every reader."); ToggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("OttoLens", "ToggleKey", (KeyCode)0, "Key that flips the master toggle at runtime. None (default) leaves it unbound."); OffsetX = ((BaseUnityPlugin)this).Config.Bind<int>("OttoLens", "OffsetX", 150, new ConfigDescription("Left edge of the panel, pixels right of screen centre.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(96, 600), Array.Empty<object>())); OffsetY = ((BaseUnityPlugin)this).Config.Bind<int>("OttoLens", "OffsetY", -32, new ConfigDescription("Top edge of the panel, pixels below screen centre (negative).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(-400, -16), Array.Empty<object>())); PanelWidth = ((BaseUnityPlugin)this).Config.Bind<int>("OttoLens", "PanelWidth", 300, new ConfigDescription("Fixed panel width in pixels.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(240, 420), Array.Empty<object>())); GuiScale = ((BaseUnityPlugin)this).Config.Bind<float>("OttoLens", "GuiScale", 1f, new ConfigDescription("Scale of the whole panel. 1.15 is a good value at 1440p.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.75f, 1.6f), Array.Empty<object>())); MaxRows = ((BaseUnityPlugin)this).Config.Bind<int>("OttoLens", "MaxRows", 10, new ConfigDescription("Item rows per block before 'and N more'. Also clamped to what fits on screen.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 16), Array.Empty<object>())); SortRowsBy = ((BaseUnityPlugin)this).Config.Bind<SortRows>("OttoLens", "SortRows", SortRows.Count, "Row order: Count sorts by count descending then name; Slot keeps the container's own order."); ShowNames = ((BaseUnityPlugin)this).Config.Bind<bool>("OttoLens", "ShowNames", true, "Show the item name column. Off shows icon and count only."); ShowFullHealth = ((BaseUnityPlugin)this).Config.Bind<bool>("OttoLens", "ShowFullHealth", false, "Show the Health row on a build piece at 100 percent."); AvoidHoverText = ((BaseUnityPlugin)this).Config.Bind<bool>("OttoLens", "AvoidHoverText", true, "Push the panel right when the vanilla hover line is wide enough to run under it."); RefreshHz = ((BaseUnityPlugin)this).Config.Bind<int>("OttoLens", "RefreshHz", 4, new ConfigDescription("Value refresh rate while the panel is visible.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 10), Array.Empty<object>())); FadeSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("OttoLens", "FadeSeconds", 0.08f, new ConfigDescription("Show and hide fade, in seconds.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 0.5f), Array.Empty<object>())); BackdropAlpha = ((BaseUnityPlugin)this).Config.Bind<float>("OttoLens", "BackdropAlpha", 0.88f, new ConfigDescription("Opacity of the panel plate.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 1f), Array.Empty<object>())); ShowDays = ((BaseUnityPlugin)this).Config.Bind<bool>("OttoLens", "ShowDays", true, "Add a game day figure to fuel and grow times that run longer than half a day."); RemoveLensDirt = ((BaseUnityPlugin)this).Config.Bind<bool>("Camera", "RemoveLensDirt", true, "The Eye of Odin makes all things clear. Removes the smudges that bloom draws over bright light."); HideUnopenedWorldChests = ((BaseUnityPlugin)this).Config.Bind<bool>("Targets", "HideUnopenedWorldChests", true, "Hide the contents of world-placed chests until the player has opened them once."); ShowContainers = ((BaseUnityPlugin)this).Config.Bind<bool>("Targets", "Containers", true, "Chests, carts and ship holds."); ShowFires = ((BaseUnityPlugin)this).Config.Bind<bool>("Targets", "Fires", true, "Fireplaces, hearths, torches and braziers."); ShowSmelters = ((BaseUnityPlugin)this).Config.Bind<bool>("Targets", "Smelters", true, "Smelters, kilns, blast furnaces and windmill fed smelters."); ShowCooking = ((BaseUnityPlugin)this).Config.Bind<bool>("Targets", "Cooking", true, "Cooking stations and ovens."); ShowFermenting = ((BaseUnityPlugin)this).Config.Bind<bool>("Targets", "Fermenting", true, "Fermenters, beehives and sap collectors."); ShowPlants = ((BaseUnityPlugin)this).Config.Bind<bool>("Targets", "Plants", true, "Planted crops and saplings."); ShowPickables = ((BaseUnityPlugin)this).Config.Bind<bool>("Targets", "Pickables", true, "Pickable plants and item piles."); ShowRespawn = ((BaseUnityPlugin)this).Config.Bind<bool>("Targets", "ShowRespawn", false, "Show the respawn countdown on an already picked pickable. Needs Pickables on."); ShowBuildPieces = ((BaseUnityPlugin)this).Config.Bind<PieceStatus>("Targets", "BuildPieces", PieceStatus.WithHammer, "Build piece health and support: Off, WithHammer (place mode only) or Always (any hovered piece)."); ShowMineables = ((BaseUnityPlugin)this).Config.Bind<bool>("Targets", "Mineables", true, "Mineable rocks (MineRock and MineRock5). On by default; rocks are Hoverable and cost no extra raycast."); ShowTreesAndRocks = ((BaseUnityPlugin)this).Config.Bind<bool>("Targets", "TreesAndRocks", false, "Trees, stumps and logs. Off by default: they are read from the vanilla hover, so this costs nothing while it is off and no extra raycast while it is on."); ShowStands = ((BaseUnityPlugin)this).Config.Bind<bool>("Targets", "Stands", true, "Item stands and armor stands."); ShowCreatures = ((BaseUnityPlugin)this).Config.Bind<bool>("Targets", "Creatures", true, "Tamed creatures and pets."); ShowMisc = ((BaseUnityPlugin)this).Config.Bind<bool>("Targets", "Misc", true, "Tombstones, wisp spawners, shield generators, feasts, ground items and crafting stations."); MigrateToggleKey(version); if (version != null && version < new Version("1.0.4")) { ((BaseUnityPlugin)this).Config.Save(); } MaxRows.SettingChanged += OnRebuildSettingChanged; ShowNames.SettingChanged += OnRebuildSettingChanged; SortRowsBy.SettingChanged += OnRebuildSettingChanged; Enabled.SettingChanged += OnEnabledChanged; RemoveLensDirt.SettingChanged += OnLensDirtChanged; ((BaseUnityPlugin)this).Config.SettingChanged += OnTargetSettingChanged; } private static void OnRebuildSettingChanged(object sender, EventArgs e) { LensPanel.RequestRebuild(); } private static void OnLensDirtChanged(object sender, EventArgs e) { LensDirt.ApplyCurrent(); } private static void OnTargetSettingChanged(object sender, SettingChangedEventArgs e) { if (e.ChangedSetting.Definition.Section == "Targets") { Patches.InvalidateHoverCache(); } } private static void OnEnabledChanged(object sender, EventArgs e) { if (!Enabled.Value) { LensPanel.Destroy(); } } private void OnDestroy() { try { Patches.Teardown(); LensFormat.UnhookLanguage(); LensReaders.UnhookLanguage(); LensDirt.Restore(); } catch (Exception arg) { Log.LogWarning((object)$"Teardown failed: {arg}"); } _harmony.UnpatchSelf(); } } public static class LensFormat { private static readonly Dictionary<string, string> NameCache = new Dictionary<string, string>(StringComparer.Ordinal); private static readonly CultureInfo Culture = CultureInfo.InvariantCulture; private static bool _languageHooked; public static string Time(float seconds) { if (seconds <= 0f || float.IsNaN(seconds)) { return "Ready"; } int num = Mathf.CeilToInt(seconds); if (num < 600) { return string.Format(Culture, "{0}:{1:00}", num / 60, num % 60); } if (num < 3600) { return string.Format(Culture, "{0}m {1}s", num / 60, num % 60); } return string.Format(Culture, "{0}h {1:00}m", num / 3600, num % 3600 / 60); } public static string TimeWithDays(float seconds) { string text = Time(seconds); if (seconds <= 0f || !OttoLensPlugin.ShowDays.Value) { return text; } EnvMan instance = EnvMan.instance; if ((Object)(object)instance == (Object)null || instance.m_dayLengthSec <= 0) { return text; } float num = seconds / (float)instance.m_dayLengthSec; if (num < 0.5f) { return text; } return string.Format(Culture, "{0} ({1:0.0} days)", text, num); } public static string Count(int current, int max) { if (max <= 0) { return current.ToString(Culture); } return string.Format(Culture, "{0}/{1}", current, max); } public static string Count(float current, int max) { return Count(Mathf.CeilToInt(current), max); } public static string Percent(float fraction) { return string.Format(Culture, "{0}%", Mathf.RoundToInt(Mathf.Clamp01(fraction) * 100f)); } public static string Free(int freeSlots) { return string.Format(Culture, "Free {0}", freeSlots); } public static LensColor Ramp(float fraction) { if (!(fraction > 0.5f)) { if (!(fraction > 0.15f)) { return LensColor.Bad; } return LensColor.Warn; } return LensColor.Good; } public static LensColor FillRamp(float fraction) { if (!(fraction >= 1f)) { if (!(fraction >= 0.9f)) { return LensColor.Dim; } return LensColor.Warn; } return LensColor.Bad; } public static string Name(string? token) { if (string.IsNullOrEmpty(token)) { return ""; } if (!_languageHooked) { _languageHooked = true; Localization.OnLanguageChange = (Action)Delegate.Combine(Localization.OnLanguageChange, new Action(ClearCaches)); } if (NameCache.TryGetValue(token, out string value)) { return value; } string text; try { Localization instance = Localization.instance; text = ((instance != null) ? instance.Localize(token) : StripToken(token)); if (text.Length == 0 || text.Contains("$") || text.Contains("MISSING KEY")) { text = StripToken(token); } } catch (Exception) { text = StripToken(token); } NameCache[token] = text; return text; } public static string Upper(string text) { return text.ToUpperInvariant(); } internal static void ClearCaches() { NameCache.Clear(); } internal static void UnhookLanguage() { if (_languageHooked) { Localization.OnLanguageChange = (Action)Delegate.Remove(Localization.OnLanguageChange, new Action(ClearCaches)); _languageHooked = false; } } private static string StripToken(string token) { return token.Replace("$", "").Replace('_', ' '); } } } namespace OttoLens.UI { internal sealed class LensPanel : MonoBehaviour { private sealed class TextSlot { public readonly TextMeshProUGUI Tmp; public readonly GameObject Go; private string _last = ""; private Color _lastColor; public TextSlot(TextMeshProUGUI tmp, Color color) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) Tmp = tmp; Go = ((Component)tmp).gameObject; _lastColor = color; } public void SetText(string text) { if (!string.Equals(text, _last, StringComparison.Ordinal)) { _last = text; ((TMP_Text)Tmp).text = text; } } public void SetColor(Color color) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_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_001c: Unknown result type (might be due to invalid IL or missing references) if (!(color == _lastColor)) { _lastColor = color; ((Graphic)Tmp).color = color; } } } private sealed class StatusRow { private readonly GameObject _go; private readonly TextSlot _label; private readonly GameObject _meter; private readonly RectTransform _fill; private readonly Image _fillImage; private readonly TextSlot _value; private float _lastFill = -1f; private Color _lastFillColor; public StatusRow(Transform parent, TMP_FontAsset font, bool primary) { //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: 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_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: Unknown result type (might be due to invalid IL or missing references) RectTransform val = NewRect(primary ? "StatusRow_0" : "StatusRow_n", parent); _go = ((Component)val).gameObject; SetPreferredHeight(val, primary ? 22f : 18f); AddRowLayout(val, 6f); _label = NewText("Label", (Transform)(object)val, font, 15f, (TextAlignmentOptions)4097, Palette.Body, ellipsis: true); LayoutElement obj = _label.Go.AddComponent<LayoutElement>(); obj.minWidth = 64f; obj.preferredWidth = 64f; RectTransform val2 = NewRect("Meter", (Transform)(object)val); _meter = ((Component)val2).gameObject; LayoutElement obj2 = ((Component)val2).gameObject.AddComponent<LayoutElement>(); obj2.preferredWidth = 120f; obj2.preferredHeight = (primary ? 10f : 6f); AddImage(val2, null, primary ? Palette.MeterTrack : Palette.RuleDim); _fill = NewRect("Fill", (Transform)(object)val2); _fill.anchorMin = new Vector2(0f, 0f); _fill.anchorMax = new Vector2(0f, 1f); _fill.pivot = new Vector2(0f, 0.5f); _fill.anchoredPosition = new Vector2(1f, 0f); _fill.sizeDelta = new Vector2(0f, -2f); _fillImage = AddImage(_fill, null, Palette.MeterGold); _lastFillColor = Palette.MeterGold; _value = NewText("Value", (Transform)(object)val, font, 15f, (TextAlignmentOptions)4100, Palette.Count, ellipsis: false); LayoutElement obj3 = _value.Go.AddComponent<LayoutElement>(); obj3.minWidth = 0f; obj3.flexibleWidth = 1f; _go.SetActive(false); } public bool Apply(LensMeter? meter, bool primary) { if (!meter.HasValue) { _go.SetActive(false); return false; } LensMeter value = meter.Value; _label.SetText(value.Label); _meter.SetActive(value.Fraction.HasValue); _go.SetActive(true); TickValues(meter, primary); return true; } public void TickValues(LensMeter? meter, bool primary) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_003f: 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_0097: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) if (!meter.HasValue) { return; } LensMeter value = meter.Value; _value.SetText(value.ValueText); Color val = Palette.Get(value.Color); _value.SetColor(primary ? val : Palette.Count); if (value.Fraction.HasValue) { float num = Mathf.Clamp01(value.Fraction.Value) * 118f; if (!Mathf.Approximately(num, _lastFill)) { _lastFill = num; _fill.sizeDelta = new Vector2(num, -2f); } if (val != _lastFillColor) { _lastFillColor = val; ((Graphic)_fillImage).color = val; } } } } private sealed class ItemRow { public readonly GameObject Go; private readonly Image _art; private readonly TextSlot _name; private readonly TextSlot _count; private readonly LayoutElement _countLe; private Sprite? _lastSprite; private bool _artEnabled; public ItemRow(Transform parent, TMP_FontAsset font, Sprite? tile) { //IL_0063: 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_0086: 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_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: 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) RectTransform val = NewRect("ItemRow", parent); Go = ((Component)val).gameObject; SetPreferredHeight(val, 32f); AddRowLayout(val, 8f); RectTransform val2 = NewRect("Icon", (Transform)(object)val); LayoutElement obj = ((Component)val2).gameObject.AddComponent<LayoutElement>(); obj.preferredWidth = 30f; obj.preferredHeight = 30f; AddImage(val2, tile, Palette.Slot); RectTransform val3 = NewRect("Art", (Transform)(object)val2); val3.anchorMin = Vector2.zero; val3.anchorMax = Vector2.one; val3.offsetMin = new Vector2(1f, 1f); val3.offsetMax = new Vector2(-1f, -1f); _art = AddImage(val3, null, Color.white); _art.preserveAspect = true; ((Behaviour)_art).enabled = false; _name = NewText("Name", (Transform)(object)val, font, 15f, (TextAlignmentOptions)4097, Palette.Body, ellipsis: true); SetFlexibleName(_name.Go); _count = NewText("Count", (Transform)(object)val, font, 15f, (TextAlignmentOptions)4100, Palette.Count, ellipsis: false); _countLe = _count.Go.AddComponent<LayoutElement>(); _countLe.minWidth = 48f; _countLe.preferredWidth = 48f; Go.SetActive(false); } public void Apply(LensItem item, bool showNames, bool output) { //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) if (item.Sprite != _lastSprite) { _lastSprite = item.Sprite; _art.sprite = item.Sprite; } bool flag = (Object)(object)item.Sprite != (Object)null; if (flag != _artEnabled) { _artEnabled = flag; ((Behaviour)_art).enabled = flag; } _name.SetText(item.Name); _name.Go.SetActive(showNames); _countLe.flexibleWidth = (showNames ? 0f : 1f); _count.SetColor(output ? Palette.MeterGood : Palette.Count); TickCount(item); Go.SetActive(true); } public void TickCount(LensItem item) { _count.SetText((item.Count > 0) ? item.Count.ToString(CultureInfo.InvariantCulture) : ""); } } private sealed class ItemBlockView { private readonly GameObject _go; private readonly ItemRow[] _rows; private readonly List<int> _order = new List<int>(16); private int _shown; public ItemBlockView(Transform parent, TMP_FontAsset font, int index) { //IL_0064: Unknown result type (might be due to invalid IL or missing references) RectTransform val = NewRect($"ItemBlock_{index}", parent); _go = ((Component)val).gameObject; AddColumnLayout(val, 1f, 0, 0); RectTransform rect = NewRect("BlockRule", (Transform)(object)val); SetPreferredHeight(rect, 2f); AddImage(rect, Probe(RuleNames), Palette.RuleDim); Sprite tile = Probe(TileNames); _rows = new ItemRow[16]; for (int i = 0; i < _rows.Length; i++) { _rows[i] = new ItemRow((Transform)(object)val, font, tile); } _go.SetActive(false); } public int Apply(LensItemBlock? block, int budget, bool showNames, ref int hidden) { if (block == null || block.Items.Count == 0 || budget <= 0) { if (block != null) { hidden += block.Items.Count; } _shown = 0; _go.SetActive(false); return 0; } List<LensItem> items = block.Items; _order.Clear(); for (int i = 0; i < items.Count; i++) { _order.Add(i); } if (!block.PreserveOrder && OttoLensPlugin.SortRowsBy.Value == OttoLensPlugin.SortRows.Count) { _order.Sort(delegate(int a, int b) { int num2 = items[b].Count.CompareTo(items[a].Count); return (num2 == 0) ? string.CompareOrdinal(items[a].Name, items[b].Name) : num2; }); } _shown = Mathf.Min(items.Count, Mathf.Min(budget, 16)); for (int num = 0; num < _rows.Length; num++) { if (num < _shown) { _rows[num].Apply(items[_order[num]], showNames, block.IsOutput); } else if (_rows[num].Go.activeSelf) { _rows[num].Go.SetActive(false); } } hidden += items.Count - _shown; _go.SetActive(true); return _shown; } public void Tick(LensItemBlock? block) { if (block == null || _shown == 0) { return; } List<LensItem> items = block.Items; for (int i = 0; i < _shown && i < _order.Count; i++) { int num = _order[i]; if (num < items.Count) { _rows[i].TickCount(items[num]); } } } } private static class Palette { public static readonly Color Panel = Hex(1511692, 0.88f); public static readonly Color Outline = Hex(722950, 0.7f); public static readonly Color EdgeGold = Hex(13215050, 1f); public static readonly Color TitleGold = Hex(14267483, 1f); public static readonly Color RuleGold = Hex(13214247, 0.85f); public static readonly Color RuleDim = Hex(7035454, 0.55f); public static readonly Color Body = Hex(14996919, 1f); public static readonly Color Count = Hex(15787727, 1f); public static readonly Color Dim = Hex(10259566, 1f); public static readonly Color Slot = Hex(986122, 0.55f); public static readonly Color MeterTrack = Hex(2760986, 0.9f); public static readonly Color MeterGood = Hex(7244605, 1f); public static readonly Color MeterGold = Hex(13214247, 1f); public static readonly Color MeterWarn = Hex(13138472, 1f); public static readonly Color MeterBad = Hex(11027514, 1f); public static Color Get(LensColor role) { //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_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_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_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) return (Color)(role switch { LensColor.Good => MeterGood, LensColor.Warn => MeterWarn, LensColor.Bad => MeterBad, LensColor.Dim => Dim, _ => MeterGold, }); } private static Color Hex(int rgb, float alpha) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) return new Color((float)((rgb >> 16) & 0xFF) / 255f, (float)((rgb >> 8) & 0xFF) / 255f, (float)(rgb & 0xFF) / 255f, alpha); } } private const int ItemRowsPerBlock = 16; private const int SecondaryRows = 2; private const float ItemRowHeight = 32f; private const float ItemRowStride = 33f; private const float MeterWidth = 120f; private const float MeterFillWidth = 118f; private static readonly Dictionary<string, Sprite?> SpriteCache = new Dictionary<string, Sprite>(StringComparer.Ordinal); private static readonly string[] PlateNames = new string[4] { "woodpanel_trophys", "woodpanel_settings", "panel_bkg_128", "darken_blob" }; private static readonly string[] RuleNames = new string[2] { "panel_separator", "divider" }; private static readonly string[] TileNames = new string[2] { "item_background", "inventory_slot" }; private static bool _probed; private static bool _rebuildRequested; private static bool _parentWarned; internal static LensPanel? Instance; private RectTransform _root; private CanvasGroup _group; private Image _plate; private TextSlot _title; private TextSlot _headline; private GameObject _statusBlock; private StatusRow[] _statusRows; private ItemBlockView[] _blocks; private GameObject _overflowBlock; private TextSlot _overflow; private TextSlot _footer; private Component? _target; private ILensReader? _reader; private GameObject? _hover; private string? _signature; private bool _visible; private Coroutine? _tick; private Coroutine? _fade; private int _tickHz; private WaitForSeconds? _tickWait; private float _nextRetry; private Component? _failedTarget; private ILensReader? _failedReader; private static readonly HashSet<(Type Reader, Type Exception)> LoggedReaderFailures = new HashSet<(Type, Type)>(); internal static LensPanel? Get() { //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) if ((Object)(object)Instance != (Object)null) { return Instance; } Hud instance = Hud.instance; if ((Object)(object)instance == (Object)null || (Object)(object)instance.m_rootObject == (Object)null || (Object)(object)instance.m_hoverName == (Object)null) { return null; } Transform transform = instance.m_rootObject.transform; if ((Object)(object)transform == (Object)null) { if (!_parentWarned) { _parentWarned = true; OttoLensPlugin.Log.LogWarning((object)"Hud root has no transform; the lens panel is disabled for this session."); } return null; } ProbeSprites(); GameObject val = new GameObject("OttoLensPanel", new Type[1] { typeof(RectTransform) }); val.transform.SetParent(transform, false); LensPanel lensPanel = val.AddComponent<LensPanel>(); lensPanel.Build(((TMP_Text)instance.m_hoverName).font); Instance = lensPanel; return lensPanel; } internal static void RequestRebuild() { _rebuildRequested = true; } internal static void Destroy() { LensPanel instance = Instance; Instance = null; if ((Object)(object)instance != (Object)null) { Object.Destroy((Object)(object)((Component)instance).gameObject); } } internal static void Release() { Destroy(); SpriteCache.Clear(); _probed = false; } internal void SetTarget(Component? target, ILensReader? reader, GameObject? hover) { if ((Object)(object)target == (Object)null || reader == null || (Object)(object)hover == (Object)null) { if (_visible) { BeginHide(); } _target = null; _reader = null; _hover = null; _failedTarget = null; _failedReader = null; } else if (target == _target) { bool flag = hover != _hover; _hover = hover; _reader = reader; if (_visible || Time.unscaledTime < _nextRetry) { if (flag && _visible) { Refresh(); } } else { _nextRetry = Time.unscaledTime + 1f / (float)Mathf.Clamp(OttoLensPlugin.RefreshHz.Value, 1, 10); Refresh(); } } else { _target = target; _reader = reader; _hover = hover; _signature = null; _nextRetry = 0f; _failedTarget = null; _failedReader = null; Refresh(); } } private void Refresh() { if ((Object)(object)_target == (Object)null || _reader == null || (Object)(object)_hover == (Object)null) { BeginHide(); return; } if (_target == _failedTarget && _reader == _failedReader) { BeginHide(); return; } ILensReader reader = _reader; LensReport lensReport; try { lensReport = reader.Read(_target, _hover); } catch (Exception ex) { _failedTarget = _target; _failedReader = reader; LogReaderFailure(reader, ex); lensReport = null; } if (lensReport == null || !lensReport.HasContent) { BeginHide(); return; } string text = lensReport.Signature(); if (_rebuildRequested || _signature == null || !string.Equals(text, _signature, StringComparison.Ordinal)) { _rebuildRequested = false; _signature = text; Rebuild(lensReport); } else { Tick(lensReport); } if (!_visible) { BeginShow(); } } private void Rebuild(LensReport report) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) ApplyGeometry(); bool value = OttoLensPlugin.ShowNames.Value; _title.SetText(LensFormat.Upper(report.Title)); _headline.SetText(report.Headline ?? ""); _headline.SetColor(Palette.Get(report.HeadlineColor)); _headline.Go.SetActive(!string.IsNullOrEmpty(report.Headline)); int num = 0; num += (_statusRows[0].Apply(report.PrimaryMeter, primary: true) ? 1 : 0); num += (_statusRows[1].Apply(report.Secondary1, primary: false) ? 1 : 0); num += (_statusRows[2].Apply(report.Secondary2, primary: false) ? 1 : 0); _statusBlock.SetActive(num > 0); int blocks = ((report.Block0 != null && report.Block0.Items.Count > 0) ? 1 : 0) + ((report.Block1 != null && report.Block1.Items.Count > 0) ? 1 : 0); int totalTypes = (report.Block0?.Items.Count ?? 0) + (report.Block1?.Items.Count ?? 0); bool overflowPossible; int rowsFit; int num2 = RowBudget(num, blocks, totalTypes, out overflowPossible, out rowsFit); int hidden = 0; int num3 = _blocks[0].Apply(report.Block0, num2, value, ref hidden); int budget = Mathf.Max(1, Mathf.Min(num2, rowsFit - num3)); _blocks[1].Apply(report.Block1, budget, value, ref hidden); bool flag = hidden > 0 && overflowPossible; bool flag2 = !string.IsNullOrEmpty(report.Footer); _overflow.SetText(flag ? $"and {hidden} more" : ""); _overflow.Go.SetActive(flag); _footer.SetText(report.Footer ?? ""); _footer.Go.SetActive(flag2); _overflowBlock.SetActive(flag || flag2); LayoutRebuilder.ForceRebuildLayoutImmediate(_root); } private void Tick(LensReport report) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) _headline.SetText(report.Headline ?? ""); _headline.SetColor(Palette.Get(report.HeadlineColor)); _statusRows[0].TickValues(report.PrimaryMeter, primary: true); _statusRows[1].TickValues(report.Secondary1, primary: false); _statusRows[2].TickValues(report.Secondary2, primary: false); _blocks[0].Tick(report.Block0); _blocks[1].Tick(report.Block1); _footer.SetText(report.Footer ?? ""); } private int RowBudget(int statusCount, int blocks, int totalTypes, out bool overflowPossible, out int rowsFit) { //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) int num = Mathf.Clamp(OttoLensPlugin.MaxRows.Value, 1, 16); float num2 = 44f; if (statusCount > 0) { num2 += 26f + 18f * (float)(statusCount - 1) + 2f * (float)statusCount + 2f; } num2 += (float)blocks * 5f; num2 += 42f; float num3 = 1080f; Transform parent = ((Transform)_root).parent; RectTransform val = (RectTransform)(object)((parent is RectTransform) ? parent : null); if (val != null) { Rect rect = val.rect; if (((Rect)(ref rect)).height > 0f) { rect = val.rect; num3 = ((Rect)(ref rect)).height; } } float num4 = Mathf.Min(OttoLensPlugin.OffsetY.Value, -16); float num5 = Mathf.Clamp(OttoLensPlugin.GuiScale.Value, 0.75f, 1.6f); rowsFit = Mathf.FloorToInt((num4 + num3 / 2f - 24f - num2 * num5) / (33f * num5)); int result = Mathf.Max(1, Mathf.Min(num, rowsFit)); if (totalTypes == num + 1 && rowsFit >= totalTypes && totalTypes <= 16) { overflowPossible = false; return totalTypes; } overflowPossible = true; return result; } private void ApplyGeometry() { //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) float num = Mathf.Max(OttoLensPlugin.OffsetX.Value, 96); float num2 = Mathf.Min(OttoLensPlugin.OffsetY.Value, -16); float num3 = Mathf.Clamp(OttoLensPlugin.PanelWidth.Value, 240, 420); float num4 = Mathf.Clamp(OttoLensPlugin.GuiScale.Value, 0.75f, 1.6f); if (OttoLensPlugin.AvoidHoverText.Value && (Object)(object)Hud.instance != (Object)null && (Object)(object)Hud.instance.m_hoverName != (Object)null) { float num5 = ((TMP_Text)Hud.instance.m_hoverName).preferredWidth / 2f + 16f; if (num5 > num) { num = num5; } } _root.anchoredPosition = new Vector2(num, num2); _root.sizeDelta = new Vector2(num3, _root.sizeDelta.y); ((Transform)_root).localScale = new Vector3(num4, num4, 1f); Color panel = Palette.Panel; panel.a = Mathf.Clamp(OttoLensPlugin.BackdropAlpha.Value, 0.5f, 1f); if (((Graphic)_plate).color != panel) { ((Graphic)_plate).color = panel; } } private void BeginShow() { _visible = true; ((Component)this).gameObject.SetActive(true); StartTick(); StartFade(1f, deactivateAtEnd: false); } private void BeginHide() { if (_visible) { _visible = false; _signature = null; StopTick(); if (((Component)this).gameObject.activeSelf) { StartFade(0f, deactivateAtEnd: true); } } } private void StartTick() { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown StopTick(); int num = Mathf.Clamp(OttoLensPlugin.RefreshHz.Value, 1, 10); if (_tickWait == null || num != _tickHz) { _tickHz = num; _tickWait = new WaitForSeconds(1f / (float)num); } _tick = ((MonoBehaviour)this).StartCoroutine(TickLoop()); } private void StopTick() { if (_tick != null) { ((MonoBehaviour)this).StopCoroutine(_tick); _tick = null; } } private IEnumerator TickLoop() { while (true) { yield return _tickWait; if ((Object)(object)_target == (Object)null) { break; } Refresh(); } BeginHide(); } private void StartFade(float to, bool deactivateAtEnd) { if (_fade != null) { ((MonoBehaviour)this).StopCoroutine(_fade); _fade = null; } float num = Mathf.Clamp(OttoLensPlugin.FadeSeconds.Value, 0f, 0.5f); if (num <= 0f) { _group.alpha = to; if (deactivateAtEnd) { ((Component)this).gameObject.SetActive(false); } } else { _fade = ((MonoBehaviour)this).StartCoroutine(FadeTo(to, num, deactivateAtEnd)); } } private IEnumerator FadeTo(float to, float seconds, bool deactivateAtEnd) { float from = _group.alpha; float t = 0f; while (t < seconds) { t += Time.unscaledDeltaTime; _group.alpha = Mathf.Lerp(from, to, t / seconds); yield return null; } _group.alpha = to; _fade = null; if (deactivateAtEnd) { ((Component)this).gameObject.SetActive(false); } } private void OnDestroy() { if (Instance == this) { Instance = null; } } private void Build(TMP_FontAsset font) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown //IL_0021: 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_0055: 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_008c: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Expected O, but got Unknown //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_01ce: Unknown result type (might be due to invalid IL or missing references) //IL_01e3: Unknown result type (might be due to invalid IL or missing references) //IL_01f8: Unknown result type (might be due to invalid IL or missing references) //IL_020d: Unknown result type (might be due to invalid IL or missing references) //IL_0218: Unknown result type (might be due to invalid IL or missing references) //IL_0224: Unknown result type (might be due to invalid IL or missing references) //IL_0279: Unknown result type (might be due to invalid IL or missing references) //IL_02ab: Unknown result type (might be due to invalid IL or missing references) //IL_02fa: Unknown result type (might be due to invalid IL or missing references) //IL_03ed: Unknown result type (might be due to invalid IL or missing references) //IL_040a: Unknown result type (might be due to invalid IL or missing references) //IL_043b: Unknown result type (might be due to invalid IL or missing references) //IL_044a: Expected O, but got Unknown //IL_045c: Unknown result type (might be due to invalid IL or missing references) //IL_047c: Unknown result type (might be due to invalid IL or missing references) //IL_048b: Expected O, but got Unknown _root = (RectTransform)((Component)this).transform; _root.anchorMin = new Vector2(0.5f, 0.5f); _root.anchorMax = new Vector2(0.5f, 0.5f); _root.pivot = new Vector2(0f, 1f); _root.sizeDelta = new Vector2(300f, 0f); Image obj = ((Component)this).gameObject.AddComponent<Image>(); obj.sprite = null; ((Graphic)obj).color = Palette.Outline; ((Graphic)obj).raycastTarget = false; _group = ((Component)this).gameObject.AddComponent<CanvasGroup>(); _group.alpha = 0f; _group.blocksRaycasts = false; _group.interactable = false; VerticalLayoutGroup obj2 = ((Component)this).gameObject.AddComponent<VerticalLayoutGroup>(); ((LayoutGroup)obj2).padding = new RectOffset(10, 10, 8, 8); ((HorizontalOrVerticalLayoutGroup)obj2).spacing = 2f; ((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandWidth = true; ((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandHeight = false; ((HorizontalOrVerticalLayoutGroup)obj2).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)obj2).childControlHeight = true; ((LayoutGroup)obj2).childAlignment = (TextAnchor)0; ContentSizeFitter obj3 = ((Component)this).gameObject.AddComponent<ContentSizeFitter>(); obj3.verticalFit = (FitMode)2; obj3.horizontalFit = (FitMode)0; RectTransform val = NewRect("Plate", (Transform)(object)_root); val.anchorMin = Vector2.zero; val.anchorMax = Vector2.one; val.offsetMin = new Vector2(1f, 1f); val.offsetMax = new Vector2(-1f, -1f); _plate = AddImage(val, Probe(PlateNames), Palette.Panel); ((Component)val).gameObject.AddComponent<LayoutElement>().ignoreLayout = true; RectTransform obj4 = NewRect("GoldEdge", (Transform)(object)_root); obj4.anchorMin = new Vector2(0f, 0f); obj4.anchorMax = new Vector2(0f, 1f); obj4.pivot = new Vector2(0f, 0.5f); obj4.sizeDelta = new Vector2(3f, 0f); obj4.anchoredPosition = Vector2.zero; AddImage(obj4, null, Palette.EdgeGold); ((Component)obj4).gameObject.AddComponent<LayoutElement>().ignoreLayout = true; RectTransform val2 = NewRect("TitleRow", (Transform)(object)_root); SetPreferredHeight(val2, 22f); AddRowLayout(val2, 6f); _title = NewText("Title", (Transform)(object)val2, font, 17f, (TextAlignmentOptions)4097, Palette.TitleGold, ellipsis: true); SetFlexibleName(_title.Go); _headline = NewText("Headline", (Transform)(object)val2, font, 15f, (TextAlignmentOptions)4100, Palette.TitleGold, ellipsis: false); _headline.Go.AddComponent<LayoutElement>().minWidth = 0f; RectTransform rect = NewRect("TitleRule", (Transform)(object)_root); SetPreferredHeight(rect, 2f); AddImage(rect, Probe(RuleNames), Palette.RuleGold); RectTransform val3 = NewRect("StatusBlock", (Transform)(object)_root); _statusBlock = ((Component)val3).gameObject; AddColumnLayout(val3, 2f, 2, 2); _statusRows = new StatusRow[3]; for (int i = 0; i < _statusRows.Length; i++) { _statusRows[i] = new StatusRow((Transform)(object)val3, font, i == 0); } _blocks = new ItemBlockView[2]; for (int j = 0; j < _blocks.Length; j++) { _blocks[j] = new ItemBlockView((Transform)(object)_root, font, j); } RectTransform val4 = NewRect("OverflowBlock", (Transform)(object)_root); _overflowBlock = ((Component)val4).gameObject; AddColumnLayout(val4, 1f, 0, 0); RectTransform rect2 = NewRect("BlockRule", (Transform)(object)val4); SetPreferredHeight(rect2, 2f); AddImage(rect2, Probe(RuleNames), Palette.RuleDim); _overflow = NewText("Overflow", (Transform)(object)val4, font, 14f, (TextAlignmentOptions)4097, Palette.Dim, ellipsis: true); ((TMP_Text)_overflow.Tmp).fontStyle = (FontStyles)2; SetPreferredHeight((RectTransform)_overflow.Go.transform, 18f); _footer = NewText("Footer", (Transform)(object)val4, font, 14f, (TextAlignmentOptions)4097, Palette.Dim, ellipsis: true); SetPreferredHeight((RectTransform)_footer.Go.transform, 18f); _statusBlock.SetActive(false); _overflowBlock.SetActive(false); ((Component)this).gameObject.SetActive(false); } private static void ProbeSprites() { if (_probed) { return; } _probed = true; HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal); string[] plateNames = PlateNames; foreach (string item in plateNames) { hashSet.Add(item); } plateNames = RuleNames; foreach (string item2 in plateNames) { hashSet.Add(item2); } plateNames = TileNames; foreach (string item3 in plateNames) { hashSet.Add(item3); } try { Sprite[] array = Resources.FindObjectsOfTypeAll<Sprite>(); foreach (Sprite val in array) { if ((Object)(object)val != (Object)null && hashSet.Contains(((Object)val).name) && !SpriteCache.ContainsKey(((Object)val).name)) { SpriteCache[((Object)val).name] = val; } } } catch (Exception ex) { OttoLensPlugin.Log.LogDebug((object)("Sprite probe failed: " + ex.GetType().Name + ": " + ex.Message)); } } private static Sprite? Probe(string[] names) { for (int i = 0; i < names.Length; i++) { if (SpriteCache.TryGetValue(names[i], out Sprite value) && (Object)(object)value != (Object)null) { return value; } } OttoLensPlugin.Log.LogDebug((object)("No vanilla sprite found for " + string.Join(", ", names) + "; drawing a plain quad.")); return null; } private static RectTransform NewRect(string name, Transform parent) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown RectTransform val = (RectTransform)new GameObject(name, new Type[1] { typeof(RectTransform) }).transform; ((Transform)val).SetParent(parent, false); return val; } private static Image AddImage(RectTransform rect, Sprite? sprite, Color color) { //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_0038: Unknown result type (might be due to invalid IL or missing references) Image obj = ((Component)rect).gameObject.AddComponent<Image>(); obj.sprite = sprite; obj.type = (Type)(((Object)(object)sprite != (Object)null && sprite.border != Vector4.zero) ? 1 : 0); ((Graphic)obj).color = color; ((Graphic)obj).raycastTarget = false; return obj; } private static void SetPreferredHeight(RectTransform rect, float height) { (((Component)rect).gameObject.GetComponent<LayoutElement>() ?? ((Component)rect).gameObject.AddComponent<LayoutElement>()).preferredHeight = height; } private static HorizontalLayoutGroup AddRowLayout(RectTransform rect, float spacing) { HorizontalLayoutGroup obj = ((Component)rect).gameObject.AddComponent<HorizontalLayoutGroup>(); ((HorizontalOrVerticalLayoutGroup)obj).spacing = spacing; ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandWidth = false; ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandHeight = false; ((HorizontalOrVerticalLayoutGroup)obj).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)obj).childControlHeight = true; ((LayoutGroup)obj).childAlignment = (TextAnchor)3; return obj; } private static VerticalLayoutGroup AddColumnLayout(RectTransform rect, float spacing, int padTop, int padBottom) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown VerticalLayoutGroup obj = ((Component)rect).gameObject.AddComponent<VerticalLayoutGroup>(); ((LayoutGroup)obj).padding = new RectOffset(0, 0, padTop, padBottom); ((HorizontalOrVerticalLayoutGroup)obj).spacing = spacing; ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandWidth = true; ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandHeight = false; ((HorizontalOrVerticalLayoutGroup)obj).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)obj).childControlHeight = true; ((LayoutGroup)obj).childAlignment = (TextAnchor)0; return obj; } private static void SetFlexibleName(GameObject go) { LayoutElement obj = go.GetComponent<LayoutElement>() ?? go.AddComponent<LayoutElement>(); obj.minWidth = 0f; obj.preferredWidth = 0f; obj.flexibleWidth = 1f; } private static TextSlot NewText(string name, Transform parent, TMP_FontAsset font, float size, TextAlignmentOptions align, Color color, bool ellipsis) { //IL_0042: 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_0080: Unknown result type (might be due to invalid IL or missing references) RectTransform obj = NewRect(name, parent); ((Component)obj).gameObject.SetActive(false); TextMeshProUGUI val = ((Component)obj).gameObject.AddComponent<TextMeshProUGUI>(); if ((Object)(object)font != (Object)null) { ((TMP_Text)val).font = font; } ((Component)obj).gameObject.SetActive(true); ((TMP_Text)val).fontSize = size; ((TMP_Text)val).alignment = align; ((Graphic)val).color = color; ((TMP_Text)val).richText = false; ((Graphic)val).raycastTarget = false; ((TMP_Text)val).textWrappingMode = (TextWrappingModes)0; ((TMP_Text)val).overflowMode = (TextOverflowModes)(ellipsis ? 1 : 0); ((TMP_Text)val).text = ""; return new TextSlot(val, color); } private static void LogReaderFailure(ILensReader reader, Exception ex) { Type type = reader.GetType(); if (LoggedReaderFailures.Add((type, ex.GetType()))) { OttoLensPlugin.Log.LogWarning((object)(type.Name + " threw " + ex.GetType().Name + ": " + ex.Message + ". Further " + ex.GetType().Name + " reports from " + type.Name + " are suppressed.\n" + ex.StackTrace)); } } } } namespace OttoLens.Readers { internal sealed class ArmorStandReader : ILensReader { private static int[] s_itemKeys = Array.Empty<int>(); private static int[] s_variantKeys = Array.Empty<int>(); private readonly LensReport _report = new LensReport(); private readonly LensItemBlock _block = new LensItemBlock(); private readonly List<LensItem> _pool = new List<LensItem>(); private readonly List<int> _order = new List<int>(); public Type TargetType => typeof(ArmorStand); public bool Enabled => OttoLensPlugin.ShowStands.Value; public LensReport? Read(Component target, GameObject hover) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown //IL_00ef: Unknown result type (might be due to invalid IL or missing references) ArmorStand val = (ArmorStand)target; ZNetView nview = val.m_nview; if ((Object)(object)nview == (Object)null || !nview.IsValid()) { return null; } if (!LensReaders.HasWardAccess((Component)(object)val)) { return null; } List<ArmorStandSlot> slots = val.m_slots; int count = slots.Count; if (count == 0) { return null; } EnsureKeys(count); ZDO zDO = nview.GetZDO(); List<int> order = _order; order.Clear(); int num = 0; int num2 = 0; for (int i = 0; i < count; i++) { int num3 = zDO.GetInt(s_itemKeys[i], 0); if (num3 == 0) { continue; } num++; int variant = zDO.GetInt(s_variantKeys[i], 0); if (!ItemStandReader.TryResolveItem(num3, variant, out string name, out Sprite sprite, out ItemType type)) { name = slots[i].m_currentItemName; if (name.Length == 0) { continue; } } LensItem lensItem = Pooled(num2); lensItem.Sprite = sprite; lensItem.Name = LensFormat.Name(name); lensItem.Count = 1; lensItem.Quality = 0; order.Add((Rank(type) << 8) | num2); num2++; } if (num2 == 0) { return null; } order.Sort(); LensReport report = _report; report.Reset(); report.Title = LensFormat.Name(val.m_name); LensItemBlock block = _block; block.Clear(); block.PreserveOrder = true; for (int j = 0; j < order.Count; j++) { block.Items.Add(_pool[order[j] & 0xFF]); } report.Block0 = block; report.Footer = LensFormat.Free(count - num); return report; } private LensItem Pooled(int index) { while (_pool.Count <= index) { _pool.Add(new LensItem()); } return _pool[index]; } private static void EnsureKeys(int count) { if (s_itemKeys.Length < count) { int[] array = new int[count]; int[] array2 = new int[count]; for (int i = 0; i < count; i++) { array[i] = StringExtensionMethods.GetStableHashCode(i + "_item"); array2[i] = StringExtensionMethods.GetStableHashCode(i + "_variant"); } s_itemKeys = array; s_variantKeys = array2; } } private static int Rank(ItemType type) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Expected I4, but got Unknown switch (type - 3) { case 0: case 1: case 11: case 12: case 16: case 17: case 19: return 0; case 2: return 1; case 3: return 2; case 4: return 3; case 8: return 4; case 14: return 5; case 15: return 6; default: return 7; } } } internal sealed class BeehiveReader : ILensReader { private static readonly Dictionary<int, Sprite?> SpriteCache = new Dictionary<int, Sprite>(); private readonly LensReport _report = new LensReport(); private readonly LensItemBlock _output = new LensItemBlock(); private const float StateCacheSeconds = 2f; private Beehive? _cachedHive; private float _cachedUntil; private bool _cachedBiomeOk; private bool _cachedSpaceOk; public Type TargetType => typeof(Beehive); public bool Enabled => OttoLensPlugin.ShowFermenting.Value; public LensReport? Read(Component target, GameObject hover) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown Beehive val = (Beehive)target; ZNetView nview = val.m_nview; if ((Object)(object)nview == (Object)null || !nview.IsValid()) { return null; } if (!LensReaders.HasWardAccess(target)) { return null; } ZDO zDO = nview.GetZDO(); int num = zDO.GetInt(ZDOVars.s_level, 0); int maxHoney = val.m_maxHoney; bool flag = maxHoney > 0 && num >= maxHoney; ReadState(val, out var biomeOk, out var spaceOk); bool flag2 = biomeOk && spaceOk; bool flag3 = flag2 && val.m_effectOnlyInDaylight && !EnvMan.IsDaylight(); LensReport report = _report; report.Reset(); report.Title = LensFormat.Name(val.m_name); if (flag) { report.Headline = "FULL"; report.HeadlineColor = LensColor.Good; } else if (!biomeOk) { report.Headline = "WRONG BIOME"; report.HeadlineColor = LensColor.Bad; } else if (!spaceOk) { report.Headline = "NO SPACE"; report.HeadlineColor = LensColor.Bad; } else if (flag3) { report.Headline = "ASLEEP"; report.HeadlineColor = LensColor.Dim; } else { report.Headline = "HAPPY"; report.HeadlineColor = LensColor.Gold; } float value = ((maxHoney > 0) ? Mathf.Clamp01((float)num / (float)maxHoney) : 0f); report.PrimaryMeter = LensReport.Meter("Honey", (maxHoney > 0) ? new float?(value) : ((float?)null), LensFormat.Count(num, maxHoney), (!flag) ? LensColor.Gold : LensColor.Good); if (!flag && flag2 && val.m_secPerUnit > 0f) { float num2 = zDO.GetFloat(ZDOVars.s_product, 0f); float num3 = Mathf.Max(0f, val.m_secPerUnit - num2); report.Secondary1 = LensReport.Meter("Next", Mathf.Clamp01(num3 / val.m_secPerUnit), LensFormat.Time(num3), flag3 ? LensColor.Dim : LensColor.Gold, drains: true); } if (num > 0 && (Object)(object)val.m_honeyItem != (Object)null) { ItemData itemData = val.m_honeyItem.m_itemData; _output.Clear(); _output.IsOutput = true; _output.Items.Add(new LensItem(GetSprite(((Object)((Component)val.m_honeyItem).gameObject).name, itemData), LensFormat.Name(itemData.m_shared.m_name), num)); report.Block1 = _output; } return report; } private void ReadState(Beehive hive, out bool biomeOk, out bool spaceOk) { float unscaledTime = Time.unscaledTime; if (hive != _cachedHive || unscaledTime >= _cachedUntil) { _cachedHive = hive; _cachedUntil = unscaledTime + 2f; _cachedBiomeOk = hive.CheckBiome(); _cachedSpaceOk = _cachedBiomeOk && hive.HaveFreeSpace(); } biomeOk = _cachedBiomeOk; spaceOk = _cachedSpaceOk; } private static Sprite? GetSprite(string prefabName, ItemData data) { int stableHashCode = StringExtensionMethods.GetStableHashCode(prefabName); if (SpriteCache.TryGetValue(stableHashCode, out Sprite value) && (Object)(object)value != (Object)null) { return value; } Sprite val = null; try { val = data.GetIcon(); } catch (Exception) { } SpriteCache[stableHashCode] = val; return val; } } internal sealed class ContainerReader : ILensReader { private const string HiddenFooter = "Contents unknown"; private static readonly Dictionary<string, Sprite?> IconCache = new Dictionary<string, Sprite>(StringComparer.Ordinal); private readonly LensReport _report = new LensReport(); private readonly LensItemBlock _block = new LensItemBlock(); private readonly Dictionary<string, LensItem> _groupIndex = new Dictionary<string, LensItem>(StringComparer.Ordinal); private readonly List<LensItem> _groups = new List<LensItem>(); private Container? _cachedContainer; private uint _cachedRevision; private int _cachedCount = -1; private int _cachedEpoch = -1; private string _cachedSignature = ""; private static string? _discoveredName; private static int _discoveredHash; private static readonly HashSet<ZDOID> _openedChests = new HashSet<ZDOID>(); public Type TargetType => typeof(Container); public bool Enabled => OttoLensPlugin.ShowContainers.Value; public LensReport? Read(Component target, GameObject hover) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Invalid comparison between Unknown and I4 Container val = (Container)target; ZNetView nview = val.m_nview; if ((Object)(object)nview == (Object)null || !nview.IsValid()) { return null; } ZDO zDO = nview.GetZDO(); if (zDO == null) { return null; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return null; } bool flag = (Object)(object)val.m_wagon != (Object)null || (Object)(object)((Component)val).GetComponentInParent<Ship>() != (Object)null; if (!flag && val.m_checkGuardStone && !LensReaders.HasWardAccess((Component)(object)val)) { return null; } if ((int)val.m_privacy != 2 && ((Object)(object)val.m_piece == (Object)null || !val.CheckAccess(localPlayer.GetPlayerID()))) { return null; } Inventory inventory = val.GetInventory(); if (inventory == null) { return null; } LensReport report = _report; report.Reset(); report.Title = LensFormat.Name(val.m_name); if (!flag && IsUnopenedWorldChest(val, zDO, localPlayer)) { report.Footer = "Contents unknown"; return report; } int num = inventory.NrOfItems(); int num2 = inventory.GetWidth() * inventory.GetHeight(); float num3 = ((num2 > 0) ? ((float)num / (float)num2) : 0f); LensColor color = LensFormat.FillRamp(num3); report.PrimaryMeter = LensReport.Meter("Slots", num3, LensFormat.Count(num, num2), color); report.Footer = LensFormat.Free(Math.Max(0, num2 - num)); if (num == 0) { report.Headline = "EMPTY"; report.HeadlineColor = LensColor.Dim; } else if (num3 >= 1f) { report.Headline = "FULL"; report.HeadlineColor = LensColor.Bad; } uint lastRevision = val.m_lastRevision; int localizationEpoch = LensReaders.LocalizationEpoch; if (val != _cachedContainer || lastRevision != _cachedRevision || num != _cachedCount || localizationEpoch != _cachedEpoch) { Regroup(inventory); _cachedContainer = val; _cachedRevision = lastRevision; _cachedCount = num; _cachedEpoch = localizationEpoch; _cachedSignature = lastRevision + ":" + num + ":" + localizationEpoch; } if (_groups.Count > 0) { _block.Clear(); _block.Items.AddRange(_groups); report.Block0 = _block; } report.ContentSignature = _cachedSignature; return report; } private static bool IsUnopenedWorldChest(Container container, ZDO zdo, Player player) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Invalid comparison between Unknown and I4 //IL_007b: Unknown result type (might be due to invalid IL or missing references) if (!OttoLensPlugin.HideUnopenedWorldChests.Value) { return false; } Piece piece = container.m_piece; if ((Object)(object)piece != (Object)null && piece.IsPlacedByPlayer()) { return false; } if ((int)container.m_discoverStat != 206) { string playerName = player.GetPlayerName(); if (!string.Equals(playerName, _discoveredName, StringComparison.Ordinal)) { _discoveredName = playerName; _discoveredHash = StringExtensionMethods.GetStableHashCode("Discovered_" + playerName); } return !zdo.GetBool(_discoveredHash, false); } return !_openedChests.Contains(zdo.m_uid); } internal static void RecordOpen(Container container) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) ZNetView nview = container.m_nview; if (!((Object)(object)nview == (Object)null) && nview.IsValid()) { ZDO zDO = nview.GetZDO(); if (zDO != null) { _openedChests.Add(zDO.m_uid); } } } internal static void ClearOpenedChests() { _openedChests.Clear(); } private void Regroup(Inventory inventory) { _groupIndex.Clear(); _groups.Clear(); List<ItemData> allItems = inventory.GetAllItems(); for (int i = 0; i < allItems.Count; i++) { ItemData val = allItems[i]; if (val == null || val.m_shared == null) { continue; } string text = val.m_shared.m_name ?? ""; if (_groupIndex.TryGetValue(text, out LensItem value)) { value.Count += val.m_stack; int num = ((val.m_quality > 1) ? val.m_quality : 0); if (num > value.Quality) { value.Quality = num; } } else { int quality = ((val.m_quality > 1) ? val.m_quality : 0); LensItem lensItem = new LensItem(Icon(val, text), LensFormat.Name(text), val.m_stack, quality); _groupIndex[text] = lensItem; _groups.Add(lensItem); } } } private static Sprite? Icon(ItemData item, string token) { string key = ((item.m_variant == 0) ? token : (token + "#" + item.m_variant)); if (IconCache.TryGetValue(key, out Sprite value) && (Object)(object)value != (Object)null) { return value; } Sprite val; try { val = item.GetIcon(); } catch (Exception) { val = null; } IconCache[key] = val; return val; } } internal sealed class CookingStationReader : ILensReader { private const int StatusDone = 1; private const int StatusBurnt = 2; private const int MaxSlots = 16; private static readonly int[] SlotKeys = BuildKeys("slot"); private static readonly int[] SlotStatusKeys = BuildKeys("slotstatus"); private static readonly Dictionary<string, Sprite?> SpriteCache = new Dictionary<string, Sprite>(StringComparer.Ordinal); private readonly LensReport _report = new LensReport(); private readonly LensItemBlock _cooking = new LensItemBlock(); private readonly LensItemBlock _done = new LensItemBlock(); public Type TargetType => typeof(CookingStation); public bool Enabled => OttoLensPlugin.ShowCooking.Value; public LensReport? Read(Component target, GameObject hover) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown CookingStation val = (CookingStation)target; ZNetView nview = val.m_nview; if ((Object)(object)nview == (Object)null || !nview.IsValid()) { return null; } ZDO zDO = nview.GetZDO(); if (zDO == null) { return null; } LensReport report = _report; report.Reset(); _cooking.Clear(); _done.Clear(); _cooking.PreserveOrder = true; _done.PreserveOrder = true; int num = ((val.m_slots != null) ? Mathf.Min(val.m_slots.Length, 16) : 0); int num2 = 0; bool flag = false; bool flag2 = false; bool flag3 = false; float num3 = float.MaxValue; float num4 = 0f; float num5 = float.MaxValue; for (int i = 0; i < num; i++) { string text = zDO.GetString(SlotKeys[i], ""); if (text.Length == 0) { continue; } num2++; float num6 = zDO.GetFloat(SlotKeys[i], 0f); int num7 = zDO.GetInt(SlotStatusKeys[i], 0); if (num7 == 2) { flag3 = true; AddSlot(_done, val.m_overCookedItem, text); continue; } ItemConversion val2 = FindConversion(val, text); if (val2 == null) { AddSlot(_cooking, null, text); flag = true; continue; } if (num7 == 1) { flag2 = true; AddSlot(_done, val2.m_to, text); if (val.m_canOvercookItems) { num5 = Mathf.Min(num5, val2.m_cookTime * 2f - num6); } continue; } flag = true; ItemDrop drop = ((text == ((Object)((Component)val2.m_from).gameObject).name) ? val2.m_from : val2.m_to); AddSlot(_cooking, drop, text); float num8 = val2.m_cookTime - num6; if (num8 < num3) { num3 = num8; num4 = val2.m_cookTime; } } if (num2 == 0 && !val.m_useFuel) { return null; } bool flag4 = val.m_requireFire && !val.IsFireLit(); float num9 = (val.m_useFuel ? val.GetFuel() : 0f); bool flag5 = val.m_useFuel && num9 <= 0f; bool flag6 = (val.m_requireFire && !flag4) || (val.m_useFuel && num9 > 0f && (val.m_useFueldWhileEmpty || flag)); report.Title = LensFormat.Name(val.m_name); if (flag4) { report.Headline = "NO FIRE"; report.HeadlineColor = LensColor.Bad; } else if (flag5) { report.Headline = "NO FUEL"; report.HeadlineColor = LensColor.Bad; } else if (flag) { report.Headline = "COOKING"; report.HeadlineColor = LensColor.Gold; } else if (flag2) { report.Headline = "READY"; report.HeadlineColor = LensColor.Good; } else if (flag3) { report.Headline = "BURNT"; report.HeadlineColor = LensColor.Bad; } LensMeter? lensMeter = null; if (flag) { if (flag6 && num3 < float.MaxValue) { float num10 = Mathf.Max(num3, 0f); float value = ((num4 > 0f) ? Mathf.Clamp01(num10 / num4) : 0f); lensMeter = LensReport.Meter("Next", value, LensFormat.Time(num10), (num10 > 0f) ? LensColor.Gold : LensColor.Good, drains: true); } } else if (flag2) { lensMeter = LensReport.Meter("Next", 0f, "Ready", LensColor.Good, drains: true); } LensMeter? lensMeter2 = null; if (flag6 && num5 < float.MaxValue) { string valueText = ((num5 > 0f) ? LensFormat.Time(num5) : "Now"); lensMeter2 = LensReport.Meter("Burns", null, valueText, LensColor.Warn, drains: true); } if (val.m_useFuel) { int num11 = Mathf.Max(val.m_maxFuel, 1); float num12 = Mathf.Clamp01(num9 / (float)num11); string label = (((Object)(object)val.m_fuelItem != (Object)null) ? LensFormat.Name(val.m_fuelItem.m_itemData.m_shared.m_name) : "Fuel"); report.PrimaryMeter = LensReport.Meter(label, num12, LensFormat.Count(num9, num11), LensFormat.Ramp(num12)); LensMeter? lensMeter3 = ((num9 > 0f) ? new LensMeter?(LensReport.Meter("Fuel", null, LensFormat.TimeWithDays(num9 * (float)val.m_secPerFuel), LensColor.Gold, drains: true)) : ((LensMeter?)null)); report.Secondary1 = lensMeter ?? lensMeter2 ?? lensMeter3; report.Secondary2 = ((!lensMeter.HasValue) ? (lensMeter2.HasValue ? lensMeter3 : ((LensMeter?)null)) : (lensMeter2 ?? lensMeter3)); } else { report.PrimaryMeter = lensMeter; report.Secondary1 = lensMeter2; } if (_cooking.Items.Count > 0) { _cooking.Label = "Cooking"; report.Block0 = _cooking; } if (_done.Items.Count > 0) { _done.Label = "Done"; _done.IsOutput = true; report.Block1 = _done; } if (num > 0) { report.Footer = LensFormat.Free(num - num2); } return report; } private static void AddSlot(LensItemBlock block, ItemDrop? drop, string prefabName) { List<LensItem> items = block.Items; string text = (((Object)(object)drop != (Object)null) ? LensFormat.Name(drop.m_itemData.m_shared.m_name) : LensFormat.Name(prefabName)); for (int i = 0; i < items.Count; i++) { if (items[i].Name == text) { items[i].Count++; return; } } items.Add(new LensItem(GetSprite(prefabName, drop), text, 1)); } private static ItemConversion? FindConversion(CookingStation station, string itemName) { List<ItemConversion> conversion = station.m_conversion; if (conversion == null) { return null; } for (int i = 0; i < conversion.Count; i++) { ItemConversion val = conversion[i]; if (val != null && !((Object)(object)val.m_from == (Object)null) && !((Object)(object)val.m_to == (Object)null) && (((Object)((Component)val.m_from).gameObject).name == itemName || ((Object)((Component)val.m_to).gameObject).name == itemName)) { return val; } } return null; } private static Sprite? GetSprite(string prefabName, ItemDrop? drop) { if (SpriteCache.TryGetValue(prefabName, out Sprite value) && (Object)(object)value != (Object)null) { return value; } if ((Object)(object)drop == (Object)null) { return null; } Sprite val; try { val = drop.m_itemData.GetIcon(); } catch (Exception) { val = null; } SpriteCache[prefabName] = val; return val; } private static int[] BuildKeys(string prefix) { int[] array = new int[16]; for (int i = 0; i < 16; i++) { array[i] = StringExtensionMethods.GetStableHashCode(prefix + i); } return array; } } internal sealed class CraftingStationReader : ILensReader { private static readonly Dictionary<string, Sprite?> IconCache = new Dictionary<string, Sprite>(StringComparer.Ordinal); private readonly LensReport _report = new LensReport(); private readonly LensItemBlock _block = new LensItemBlock(); private readonly Dictionary<string, LensItem> _groupIndex = new Dictionary<string, LensItem>(StringComparer.Ordinal); private readonly List<LensItem> _groups = new List<LensItem>(); private CraftingStation? _cachedStation; private Container? _cachedContainer; private const float RoofCacheSeconds = 2f; private CraftingStation? _roofStation; private float _roofUntil; private bool _roofOk; private Container? _groupedContainer; private uint _groupedRevision; private int _groupedCount = -1; private int _groupedEpoch = -1; public Type TargetType => typeof(CraftingStation); public bool Enabled => OttoLensPlugin.ShowMisc.Value; public LensReport? Read(Component target, GameObject hover) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown CraftingStation val = (CraftingStation)target; ZNetView nview = val.m_nview; if ((Object)(object)nview == (Object)null || !nview.IsValid()) { return null; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || !val.InUseDistance((Humanoid)(object)localPlayer)) { return null; } LensReport report = _report; report.Reset(); report.Title = LensFormat.Name(val.m_name); if (val.m_craftRequireFire && !val.m_haveFire) { report.Headline = "NO FIRE"; report.HeadlineColor = LensColor.Bad; } else if (val.m_craftRequireRoof && (Object)(object)val.m_roofCheckPoint != (Object)null && !HasRoof(val, localPlayer)) { report.Headline = "NO ROOF"; report.HeadlineColor = LensColor.Bad; } else { report.Headline = "READY"; report.HeadlineColor = LensColor.Good; } LensMeter value = LensReport.Meter("Level", null, val.GetLevel(false).ToString(CultureInfo.InvariantCulture), LensColor.Gold); Container val2 = FindContainer(val); if ((Object)(object)val2 == (Object)null || !CanReadContainer(val2, localPlayer)) { report.PrimaryMeter = value; return report; } Inventory inventory = val2.GetInventory(); ZDO val3 = (((Object)(object)val2.m_nview != (Object)null && val2.m_nview.IsValid()) ? val2.m_nview.GetZDO() : null); if (inventory == null || val3 == null) { report.PrimaryMeter = value; return report; } int num = inventory.GetWidth() * inventory.GetHeight(); int emptySlots = inventory.GetEmptySlots(); int num2 = num - emptySlots; float num3 = ((num > 0) ? Mathf.Clamp01((float)num2 / (float)num) : 0f); report.PrimaryMeter = LensReport.Meter("Slots", (num > 0) ? new float?(num3) : ((float?)null), LensFormat.Count(num2, num), LensFormat.FillRamp(num3)); report.Secondary1 = value; report.Footer = LensFormat.Free(emptySlots); if (num > 0 && emptySlots == 0) { report.Headline = "FULL"; report.HeadlineColor = LensColor.Bad; } List<ItemData> allItems = inventory.GetAllItems(); uint lastRevision = val2.m_lastRevision; int localizationEpoch = LensReaders.LocalizationEpoch; if ((Object)(object)_groupedContainer != (Object)(object)val2 || _groupedRevision != lastRevision || _groupedCount != allItems.Count || _groupedEpoch != localizationEpoch) { _groupedContainer = val2; _groupedRevision = lastRevision; _groupedCount = allItems.Count; _groupedEpoch = localizationEpoch; Regroup(allItems); } if (_groups.Count > 0) { LensItemBlock block = _block; block.Clear(); block.Label = "Contents"; block.Items.AddRange(_groups); report.Block0 = block; } report.ContentSignature = report.Title + "|" + lastRevision.ToString(CultureInfo.InvariantCulture) + "|" + allItems.Count.ToString(CultureInfo.InvariantCulture) + "|" + report.Headline; return report; } private Container? FindContainer(CraftingStation station) { if ((Object)(object)_cachedStation != (Object)(object)station) { _cachedStation = station; _cachedContainer = ((Component)station).GetComponentInChildren<Container>(); } return _cachedContainer; } private bool HasRoof(CraftingStation station, Player player) { float unscaledTime = Time.unscaledTime; if (station != _roofStation || unscaledTime >= _roofUntil) { _roofStation = station; _roofUntil = unscaledTime + 2f; _roofOk = station.CheckUsable(player, false); } return _roofOk; } private static bool CanReadContainer(Container container, Player player) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Invalid comparison between Unknown and I4 if (container.m_checkGuardStone && !LensReaders.HasWardAccess((Component)(object)container)) { return false; } if ((int)container.m_privacy != 2 && ((Object)(object)container.m_piece == (Object)null || !container.CheckAccess(player.GetPlayerID()))) { return false; } return true; } private void Regroup(List<ItemData> items) { _groupIndex.Clear(); _groups.Clear(); for (int i = 0; i < items.Count; i++) { ItemData val = items[i]; if (val != null && val.m_shared != null) { string name = val.m_shared.m_name; if (_groupIndex.TryGetValue(name, out LensItem value)) { value.Count += val.m_stack; continue; } value = new LensItem(Icon(val, name), LensFormat.Name(name), val.m_stack); _groupIndex[name] = value; _groups.Add(value); } } } private static Sprite? Icon(ItemData item, string token) { if (IconCache.TryGetValue(token, out Sprite value) && (Object)(object)value != (Object)null) { return value; } Sprite val; try { val = item.GetIcon(); } catch (Exception) { val = null; } IconCache[token] = val; return val; } } internal sealed class DestructibleReader : ILensReader { private readonly LensReport _report = new LensReport(); private static readonly Dictionary<string, string> TitleCache = new Dictionary<string, string>(StringComparer.Ordinal); private static readonly StringBuilder TitleBuilder = new StringBuilder(32); public Type TargetType => typeof(Destructible); public bool Enabled => OttoLensPlugin.ShowTreesAndRocks.Value; public LensReport? Read(Component target, GameObject hover) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown Destructible val = (Destructible)target; ZNetView nview = val.m_nview; if ((Object)(object)nview == (Object)null || !nview.IsValid()) { return null; } float num = ScaledMax(val.m_health); float num2 = nview.GetZDO().GetFloat(ZDOVars.s_health, num); if (num <= 0f || num2 <= 0f) { return null; } LensReport report = _report; report.Reset(); report.Title = TitleFor(((Component)val).gameObject); report.PrimaryMeter = HealthMeter(num2, num); report.Secondary1 = ToolTierMeter(val.m_minToolTier); return report; } internal static float ScaledMax(float baseHealth) { return baseHealth + (float)Game.m_worldLevel * baseHealth * Game.instance.m_worldLevelMineHPMultiplier; } internal static LensMeter HealthMeter(float current, float max) { float num = Mathf.Clamp01(current / max); return LensReport.Meter("Health", num, LensFormat.Percent(num), LensFormat.Ramp(num)); } internal static LensMeter? ToolTierMeter(int minToolTier) { if (minToolTier <= 0) { return null; } int num = HeldToolTier(); if (num < minToolTier) { string valueText = ((num < 0) ? $"{minToolTier} needed" : $"{minToolTier} needed, holding {num}"); return LensReport.Meter("Tool tier", null, valueText, LensColor.Bad); } return LensReport.Meter("Tool tier", null, minToolTier.ToString(), LensColor.Dim); } private static int HeldToolTier() { Player localPlayer = Player.m_localPlayer; return (((Object)(object)localPlayer != (Object)null) ? ((Humanoid)localPlayer).GetCurrentWeapon() : null)?.m_shared?.m_toolTier ?? (-1); } internal static string TitleFor(GameObject go) { Piece component = go.GetComponent<Piece>(); if ((Object)(object)component != (Object)null && !string.IsNullOrEmpty(component.m_name)) { return LensFormat.Name(component.m_name); } string prefabName = Utils.GetPrefabName(go); if (TitleCache.TryGetValue(prefabName, out string value)) { return value; } StringBuilder titleBuilder = TitleBuilder; titleBuilder.Clear(); string[] array = prefabName.Split(new char[1] { '_' }); for (int i = 0; i < array.Length; i++) { string text = array[i].TrimEnd('0', '1', '2', '3', '4', '5', '6', '7', '8', '9'); if (text.Length != 0) { if (titleBuilder.Length > 0) { titleBuilder.Append(' '); } titleBuilder.Append(text); } } string text2 = ((titleBuilder.Length > 0) ? titleBuilder.ToString() : prefabName); TitleCache[prefabName] = text2; return text2; } } internal sealed class FeastReader : ILensReader { private static readonly Dictionary<string, Sprite?> IconCache = new Dictionary<string, Sprite>(StringComparer.Ordinal); private readonly LensReport _report = new LensReport(); private readonly LensItemBlock _block = new LensItemBlock(); private readonly LensItem _item = new LensItem(); public Type TargetType => typeof(Feast); public bool Enabled => OttoLensPlugin.ShowMisc.Value; public LensReport? Read(Component target, GameObject hover) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown Feast val = (Feast)target; ZNetView nview = val.m_nview; if ((Object)(object)nview == (Object)null || !nview.IsValid()) { return null; } ItemDrop foodItem = val.m_foodItem; if ((Object)(object)foodItem == (Object)null || foodItem.m_itemData == null || foodItem.m_itemData.m_shared == null) { return null; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || !val.InUseDistance((Humanoid)(object)localPlayer)) { return null; } int stack = val.GetStack(); if (stack <= 0) { return null; } int eatStacks = val.m_eatStacks; float num = ((eatStacks > 0) ? Mathf.Clamp01((float)stack / (float)eatStacks) : 1f); string name = foodItem.m_itemData.m_shared.m_name; string text = LensFormat.Name(name); LensReport report = _report; report.Reset(); report.Title = text; report.PrimaryMeter = LensReport.Meter("Servings", (eatStacks > 0) ? new float?(num) : ((float?)null), LensFormat.Count(stack, eatStacks), LensFormat.Ramp(num)); LensItem item = _item; item.Sprite = Icon(foodItem.m_itemData, name); item.Name = text; item.Count = stack; item.Quality = 0; LensItemBlock block = _block; block.Clear(); block.Label = "Food"; block.Items.Add(item); report.Block0 = block; return report; } private static Sprite? Icon(ItemData item, string token) { if (IconCache.TryGetValue(token, out Sprite value) && (Object)(object)value != (Object)null) { return value; } Sprite val; try { val = item.GetIcon(); } catch (Exception) { val = null; } IconCache[token] = val; return val; } } internal sealed class FermenterReader : ILensReader { private static readonly Dictionary<int, Sprite?> SpriteCache = new Dictionary<int, Sprite>(); private readonly LensReport _report = new LensReport(); private readonly LensItemBlock _contents = new LensItemBlock(); private readonly LensItemBlock _output = new LensItemBlock(); public Type TargetType => typeof(Fermenter); public bool Enabled => OttoLensPlugin.ShowFermenting.Value; public LensReport? Read(Component target, GameObject hover) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown Fermenter val = (Fermenter)target; ZNetView nview = val.m_nview; if ((Object)(object)nview == (Object)null || !nview.IsValid()) { return null; } if (!LensReaders.HasWardAccess(target)) { return null; } ZDO zDO = nview.GetZDO(); int num = zDO.GetInt(ZDOVars.s_content, 0); if (num == 0) { return null; } long num2 = zDO.GetLong(ZDOVars.s_startTime, 0L); double num3 = ((num2 == 0L) ? 0.0 : (ZNet.instance.GetTime() - new DateTime(num2)).TotalSeconds); float fermentationDuration = val.m_fermentationDuration; bool flag = num3 > (double)fermentationDuration; float num4 = (flag ? 0f : Mathf.Max(0f, fermentationDuration - (float)num3)); bool flag2 = !flag && (!val.m_hasRoof || val.m_exposed); LensReport report = _report; report.Reset(); report.Title = LensFormat.Name(val.m_name); if (flag) { report.Headline = "READY"; report.HeadlineColor = LensColor.Good; } float value = ((fermentationDuration > 0f) ? Mathf.Clamp01(num4 / fermentationDuration) : 0f); LensColor color = ((!flag) ? (flag2 ? LensColor.Warn : LensColor.Gold) : LensColor.Good); report.PrimaryMeter = LensReport.Meter("Next", value, LensFormat.TimeWithDays(num4), color, drains: true); ItemConversion itemConversion = val.GetItemConversion(num); if (itemConversion == null) { return report; } if (!flag && (Object)(object)itemConversion.m_from != (Object)null) { _contents.Clear(); _contents.Items.Add(MakeItem(itemConversion.m_from, 1)); report.Block0 = _contents; } if ((Object)(object)itemConversion.m_to != (Object)null) { _output.Clear(); _output.Label = (flag ? null : "Makes"); _output.IsOutput = true; _output.Items.Add(MakeItem(itemConversion.m_to, itemConversion.m_producedItems)); report.Block1 = _output; } return report; } private static LensItem MakeItem(ItemDrop drop, int count) { ItemData itemData = drop.m_itemData; return new LensItem(GetSprite(((Object)((Component)drop).gameObject).name, itemData), LensFormat.Name(itemData.m_shared.m_name), count); } private static Sprite? GetSprite(string prefabName, ItemData data) { int stableHashCode = StringExtensionMethods.GetStableHashCode(prefabName); if (SpriteCache.TryGetValue(stableHashCode, out Sprite value) && (Object)(object)value != (Object)null) { return value; } Sprite val = null; try { val = data.GetIcon(); } catch (Exception) { } SpriteCache[stableHashCode] = val; return val; } } internal sealed class FireplaceReader : ILensReader { private const string FallbackFuelLabel = "Fuel"; private readonly LensReport _report = new LensReport(); public Type TargetType => typeof(Fireplace); public bool Enabled => OttoLensPlugin.ShowFires.Value; public LensReport? Read(Component target, GameObject hover) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown Fireplace val = (Fireplace)target; ZNetView nview = val.m_nview; if ((Object)(object)nview == (Object)null || !nview.IsValid()) { return null; } if (val.m_infiniteFuel) { return null; } ZDO zDO = nview.GetZDO(); float num = Mathf.Max(0f, zDO.GetFloat(ZDOVars.s_fuel, 0f));