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 XRays v0.1.0
plugins/XRays.dll
Decompiled 2 weeks ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Jotunn.Managers; using TMPro; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.UI; using YamlDotNet.Serialization; using YamlDotNet.Serialization.NamingConventions; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("XRays")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("XRays")] [assembly: AssemblyCopyright("Copyright © 2021")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")] [assembly: AssemblyFileVersion("0.1.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.1.0.0")] namespace XRays; internal class Category { public const string NameKeyPrefix = "name:"; public string Key; public string Label; public string Description; public Type[] Types; public string[] NameContains; public string[] NameStartsWith; public string[] NameExcludes; public string[] NameMatches; public string[] NameExcludesMatches; public Func<List<GameObject>> RootProvider; public bool SkipLocalPlayer; private static readonly Dictionary<string, Regex> NamePatterns = new Dictionary<string, Regex>(StringComparer.Ordinal); public bool IsNameCategory { get { if (Key != null) { return Key.StartsWith("name:", StringComparison.Ordinal); } return false; } } public string Name { get { if (!IsNameCategory) { return Label; } return Key.Substring("name:".Length); } } public bool HasNameMatch { get { if (!IsNameCategory && (NameContains == null || NameContains.Length == 0) && (NameStartsWith == null || NameStartsWith.Length == 0)) { if (NameMatches != null) { return NameMatches.Length != 0; } return false; } return true; } } public bool MatchesName(string objectName) { if (string.IsNullOrEmpty(objectName)) { return false; } if (MatchesExclude(objectName)) { return false; } if (IsNameCategory) { return string.Equals(objectName, Name, StringComparison.Ordinal); } if (HasPrefix(objectName)) { return true; } if (ContainsAny(objectName, NameContains)) { return true; } return MatchesAnyPattern(objectName, NameMatches); } public bool MatchesExclude(string objectName) { if (!ContainsAny(objectName, NameExcludes)) { return MatchesAnyPattern(objectName, NameExcludesMatches); } return true; } private static bool ContainsAny(string objectName, string[] patterns) { if (string.IsNullOrEmpty(objectName) || patterns == null) { return false; } foreach (string value in patterns) { if (!string.IsNullOrEmpty(value) && objectName.IndexOf(value, StringComparison.OrdinalIgnoreCase) >= 0) { return true; } } return false; } private static bool MatchesAnyPattern(string objectName, string[] patterns) { if (string.IsNullOrEmpty(objectName) || patterns == null) { return false; } foreach (string text in patterns) { if (string.IsNullOrEmpty(text)) { continue; } if (!NamePatterns.TryGetValue(text, out var value)) { try { value = new Regex(text, RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.CultureInvariant); } catch (ArgumentException) { value = null; if ((Object)(object)XRays.Instance != (Object)null) { XRays.Instance.Log.LogError((object)("XRays: bad name pattern, it matches nothing: " + text)); } } NamePatterns[text] = value; } if (value != null && value.IsMatch(objectName)) { return true; } } return false; } private bool HasPrefix(string objectName) { if (NameStartsWith == null) { return false; } string[] nameStartsWith = NameStartsWith; foreach (string value in nameStartsWith) { if (!string.IsNullOrEmpty(value) && objectName.StartsWith(value, StringComparison.OrdinalIgnoreCase)) { return true; } } return false; } public static Category ForName(string objectName) { return new Category { Key = "name:" + objectName, Label = objectName, Types = Array.Empty<Type>() }; } } internal static class Categories { private class NameScan { public float Time; public readonly List<GameObject> Roots = new List<GameObject>(); } public const string CreaturesKey = "creatures"; public static readonly Category[] BuiltIn; public static readonly Category[] DisplayOrder; private static readonly Dictionary<string, Category> Registry; public const float DefaultNameScanInterval = 4f; private static readonly Dictionary<string, NameScan> NameScans; public static IEnumerable<Category> All => Registry.Values; private static Category[] SortByLabel(Category[] source) { Category[] obj = (Category[])source.Clone(); Array.Sort(obj, (Category a, Category b) => string.CompareOrdinal(a.Label, b.Label)); return obj; } public static float NameScanDuration() { XRays instance = XRays.Instance; if (!((Object)(object)instance != (Object)null) || instance.NameScanInterval == null) { return 4f; } return instance.NameScanInterval.Value; } static Categories() { BuiltIn = new Category[11] { new Category { Key = "trees", Label = "Trees", Description = "Every tree, plus the stubs, roots and branches that only carry a Destructible, matched by name.", Types = new Type[2] { typeof(TreeBase), typeof(TreeLog) } }, new Category { Key = "ores", Label = "Ores", Description = "The ore veins themselves: copper, tin, iron, silver, obsidian, meteorite, flametal, sulfur, gold and coal, plus the pieces of the giant corpses (petrified bones, ancient armour, swords, soft tissue). Only the name tells them apart: the game marks an ore and a plain stone with the same components, and a broken giant piece carries MineRock5 like a plain stone." }, new Category { Key = "rocks", Label = "Rocks", Description = "Boulders, stones and cliffs, plus every mineable rock that is no ore (MineRock5 and MineRock), matched by component and by name.", Types = new Type[2] { typeof(MineRock5), typeof(MineRock) } }, new Category { Key = "pickable", Label = "Pickable resources", Description = "What can be gathered by hand: berries, mushrooms, feathers and the rest (Pickable).", Types = new Type[2] { typeof(Pickable), typeof(PickableItem) } }, new Category { Key = "build", Label = "Build pieces", Description = "Everything that can be built by hand: walls, floors, furniture and workstations (Piece and WearNTear).", Types = new Type[2] { typeof(WearNTear), typeof(Piece) } }, new Category { Key = "creatures", Label = "Creatures", Description = "The animals and the monsters (Character), plus the fish and the birds, with the bars the game draws over them.", Types = new Type[3] { typeof(Character), typeof(Fish), typeof(RandomFlyingBird) }, SkipLocalPlayer = true }, new Category { Key = "items", Label = "Ground items", Description = "What lies on the ground: every dropped item and resource (ItemDrop).", Types = new Type[1] { typeof(ItemDrop) } }, new Category { Key = "plants", Label = "Crops", Description = "The plants you grow: carrots, turnips, onions, anything carrying a Plant component.", Types = new Type[1] { typeof(Plant) } }, new Category { Key = "spawners", Label = "Spawners", Description = "The spawners, the nests and piles, the evil hearts and the holes that open on approach.", Types = new Type[3] { typeof(CreatureSpawner), typeof(SpawnArea), typeof(TriggerSpawner) } }, new Category { Key = "clutter", Label = "Grass / vegetation", Description = "The clutter growing in the world: bushes, grass patches, ferns, reeds, moss, mushrooms and flowers.", Types = new Type[1] { typeof(InstanceRenderer) }, RootProvider = GrassRoots }, new Category { Key = "locations", Label = "Locations", Description = "The structures the game places on its own: ruins, dungeon entrances and everything a Location carries.", Types = new Type[2] { typeof(LocationProxy), typeof(Location) } } }; DisplayOrder = SortByLabel(BuiltIn); Registry = new Dictionary<string, Category>(); NameScans = new Dictionary<string, NameScan>(); Category[] builtIn = BuiltIn; foreach (Category category in builtIn) { Registry[category.Key] = category; } } public static bool TryGet(string key, out Category category) { return Registry.TryGetValue(key, out category); } public static void Register(Category category) { if (category != null && !string.IsNullOrEmpty(category.Key)) { Registry[category.Key] = category; } } public static void Invalidate(string key) { if (!string.IsNullOrEmpty(key)) { NameScans.Remove(key); } } public static List<GameObject> CollectRoots(Category category) { List<GameObject> list = new List<GameObject>(); HashSet<int> hashSet = new HashSet<int>(); if (category == null) { return list; } long stamp = ReconcileTiming.Stamp(); AddProvidedRoots(category, list, hashSet); AddTypedRoots(category, list, hashSet); ReconcileTiming.AddSince("of which collect", stamp); if (category.HasNameMatch) { foreach (GameObject item in NameScanOf(category)) { if ((Object)(object)item != (Object)null && hashSet.Add(((Object)item).GetInstanceID())) { list.Add(item); } } } return list; } public static int Count(Category category) { return CollectRoots(category).Count; } public static List<GameObject> GrassRoots() { List<GameObject> list = new List<GameObject>(); Transform val = GrassRoot(); if ((Object)(object)val != (Object)null) { list.Add(((Component)val).gameObject); } return list; } public static Transform GrassRoot() { ClutterSystem val = ClutterSystem.instance; if ((Object)(object)val == (Object)null) { Object[] array = Object.FindObjectsByType(typeof(ClutterSystem), (FindObjectsSortMode)0); foreach (Object obj in array) { Object obj2 = ((obj is Component) ? obj : null); val = (ClutterSystem)(object)((obj2 is ClutterSystem) ? obj2 : null); if ((Object)(object)val != (Object)null) { break; } } } if (!((Object)(object)val != (Object)null)) { return null; } return ((Component)val).transform.Find("grassroot"); } public static Transform GrassItem(Transform transform) { Transform val = GrassRoot(); if ((Object)(object)val == (Object)null || (Object)(object)transform == (Object)null || ((Object)(object)transform != (Object)(object)val && !transform.IsChildOf(val))) { return null; } Transform val2 = transform; while ((Object)(object)val2 != (Object)(object)val && (Object)(object)val2.parent != (Object)null && (Object)(object)val2.parent != (Object)(object)val) { val2 = val2.parent; } return val2; } private static void AddProvidedRoots(Category category, List<GameObject> roots, HashSet<int> seen) { if (category.RootProvider == null) { return; } List<GameObject> list = category.RootProvider(); if (list == null) { return; } foreach (GameObject item in list) { if ((Object)(object)item != (Object)null && seen.Add(((Object)item).GetInstanceID())) { roots.Add(item); } } } private static void AddTypedRoots(Category category, List<GameObject> roots, HashSet<int> seen) { if (category.Types == null) { return; } Type[] types = category.Types; for (int i = 0; i < types.Length; i++) { Object[] array = Object.FindObjectsByType(types[i], (FindObjectsSortMode)0); foreach (Object obj in array) { Component val = (Component)(object)((obj is Component) ? obj : null); if ((Object)(object)val == (Object)null) { continue; } Player val2 = (Player)(object)((val is Player) ? val : null); if (!category.SkipLocalPlayer || !((Object)(object)val2 != (Object)null) || !((Object)(object)val2 == (Object)(object)Player.m_localPlayer)) { GameObject gameObject = val.gameObject; if (!category.MatchesExclude(((Object)gameObject).name) && seen.Add(((Object)gameObject).GetInstanceID())) { roots.Add(gameObject); } } } } } private static List<GameObject> NameScanOf(Category category) { if (NameScans.TryGetValue(category.Key, out var value) && Time.realtimeSinceStartup - value.Time < NameScanDuration()) { return value.Roots; } value = new NameScan { Time = Time.realtimeSinceStartup }; long stamp = ReconcileTiming.Stamp(); AddNamedRoots(category, value.Roots); ReconcileTiming.AddSince("of which names", stamp); NameScans[category.Key] = value; return value.Roots; } private static void AddNamedRoots(Category category, List<GameObject> roots) { HashSet<int> hashSet = new HashSet<int>(); HashSet<Transform> roots2 = ForeignRoots(category); Object[] array = Object.FindObjectsByType(typeof(Transform), (FindObjectsSortMode)0); foreach (Object obj in array) { Transform val = (Transform)(object)((obj is Transform) ? obj : null); if (!((Object)(object)val == (Object)null) && category.MatchesName(((Object)val).name) && !IsUnderAny(val, roots2) && TypedOwner(((Component)val).gameObject) == null && !HasMatchingParent(val, category) && hashSet.Add(((Object)((Component)val).gameObject).GetInstanceID())) { roots.Add(((Component)val).gameObject); } } } private static HashSet<Transform> ForeignRoots(Category category) { HashSet<Transform> hashSet = null; foreach (Category item in All) { if (item == category || item.RootProvider == null) { continue; } List<GameObject> list = item.RootProvider(); if (list == null) { continue; } foreach (GameObject item2 in list) { if (!((Object)(object)item2 == (Object)null)) { if (hashSet == null) { hashSet = new HashSet<Transform>(); } hashSet.Add(item2.transform); } } } return hashSet; } private static bool IsUnderAny(Transform transform, HashSet<Transform> roots) { if (roots == null || (Object)(object)transform == (Object)null) { return false; } Transform val = transform; while ((Object)(object)val != (Object)null) { if (roots.Contains(val)) { return true; } val = val.parent; } return false; } private static bool HasMatchingParent(Transform transform, Category category) { Transform parent = transform.parent; while ((Object)(object)parent != (Object)null) { if (category.MatchesName(((Object)parent).name) && TypedOwner(((Component)parent).gameObject) == null) { return true; } parent = parent.parent; } return false; } private static Category TypedOwner(GameObject go) { Category[] builtIn = BuiltIn; foreach (Category category in builtIn) { if (category.Types == null || category.MatchesExclude(((Object)go).name)) { continue; } Type[] types = category.Types; foreach (Type type in types) { if ((Object)(object)go.GetComponent(type) != (Object)null) { return category; } } } return null; } } internal static class NameRulesFile { private class Rules { public string[] NameContains { get; set; } public string[] NameStartsWith { get; set; } public string[] NameExcludes { get; set; } public string[] NameMatches { get; set; } public string[] NameExcludesMatches { get; set; } } internal const string DefaultFileName = "orax.XRays.names.yaml"; private const float CheckInterval = 0.5f; private static readonly Regex VersionLine = new Regex("^version[ \\t]*:[^\\r\\n]*", RegexOptions.Multiline | RegexOptions.Compiled); private static readonly IDeserializer Reader = ((BuilderSkeleton<DeserializerBuilder>)new DeserializerBuilder()).WithNamingConvention(CamelCaseNamingConvention.Instance).Build(); private static readonly HashSet<string> KnownKeys = KnownCategoryKeys(); private static string loadedName; private static string configPath; private static DateTime readDate; private static float checkTimer; public static void Load() { loadedName = CurrentName(); string text = null; DateTime before = DateTime.MinValue; bool flag = false; try { if (loadedName.IndexOfAny(Path.GetInvalidPathChars()) >= 0) { throw new ArgumentException("the file name holds characters a path cannot have"); } text = Path.Combine(Paths.ConfigPath, loadedName); before = File.GetLastWriteTimeUtc(text); string text2 = (File.Exists(text) ? File.ReadAllText(text) : null); if (text2 == null || VersionOf(text2) != "0.1.0") { text2 = Refresh(text, text2, ref before); } if (text2 != null) { Apply(Reader.Deserialize<Dictionary<string, Rules>>(VersionLine.Replace(text2, ""))); flag = true; XRays instance = XRays.Instance; if (instance != null) { instance.Log.LogInfo((object)("Name rules read from " + loadedName + ".")); } } else { Apply(null); XRays instance2 = XRays.Instance; if (instance2 != null) { instance2.Log.LogError((object)("XRays: " + loadedName + " is missing everywhere (BepInEx\\plugins, beside the mod and in BepInEx\\scripts): every category has no name rule.")); } } } catch (Exception ex) { XRays instance3 = XRays.Instance; if (instance3 != null) { instance3.Log.LogError((object)("XRays: " + loadedName + " could not be read, the rules stay as they are: " + ex)); } } finally { configPath = text ?? configPath; if (flag) { readDate = before; } else if (configPath != null) { readDate = File.GetLastWriteTimeUtc(configPath); } } } public static void Tick(float deltaTime) { checkTimer += deltaTime; if (!(checkTimer < 0.5f)) { checkTimer = 0f; if (CurrentName() != loadedName) { Load(); } else if (configPath != null && !(File.GetLastWriteTimeUtc(configPath) == readDate)) { Load(); } } } private static string Refresh(string path, string text, ref DateTime before) { string text2 = ShippedFile(); if (text2 == null) { if (text != null) { XRays instance = XRays.Instance; if (instance != null) { instance.Log.LogWarning((object)("XRays: the shipped " + loadedName + " could not be found, the file of the config folder could not be replaced.")); } } return text; } string text3 = Stamp(File.ReadAllText(text2), "0.1.0"); File.WriteAllText(path, text3); before = File.GetLastWriteTimeUtc(path); XRays instance2 = XRays.Instance; if (instance2 != null) { instance2.Log.LogInfo((object)((text != null) ? ("Name rules file " + loadedName + " is written for another version of the mod: replaced by the shipped one.") : ("Name rules file copied to " + loadedName + "."))); } return text3; } private static string ShippedFile() { foreach (string item in ShippedDirectories()) { string text = Path.Combine(item, loadedName); if (File.Exists(text)) { return text; } } return null; } private static IEnumerable<string> ShippedDirectories() { yield return Paths.PluginPath; string location = Assembly.GetExecutingAssembly().Location; if (!string.IsNullOrEmpty(location)) { yield return Path.GetDirectoryName(location); } yield return Path.Combine(Paths.BepInExRootPath, "scripts"); } private static string VersionOf(string text) { Match match = VersionLine.Match(text); if (!match.Success) { return null; } string text2 = match.Value.Substring(match.Value.IndexOf(':') + 1).Trim(); int i; for (i = 0; i < text2.Length && !char.IsWhiteSpace(text2[i]); i++) { } return text2.Substring(0, i).Trim('"', '\''); } private static string Stamp(string text, string version) { string line = "version: " + version; if (VersionLine.IsMatch(text)) { return VersionLine.Replace(text, (Match match) => line); } return line + Environment.NewLine + text; } private static string CurrentName() { string text = (((Object)(object)XRays.Instance != (Object)null && XRays.Instance.NameRulesFileName != null) ? XRays.Instance.NameRulesFileName.Value : null); if (!string.IsNullOrWhiteSpace(text)) { return text.Trim(); } return "orax.XRays.names.yaml"; } private static void Apply(Dictionary<string, Rules> read) { if (read == null) { read = new Dictionary<string, Rules>(); } Category[] builtIn = Categories.BuiltIn; foreach (Category category in builtIn) { read.TryGetValue(category.Key, out var value); category.NameContains = value?.NameContains; category.NameStartsWith = value?.NameStartsWith; category.NameExcludes = value?.NameExcludes; category.NameMatches = value?.NameMatches; category.NameExcludesMatches = value?.NameExcludesMatches; } foreach (string key in read.Keys) { if (!KnownKeys.Contains(key)) { XRays instance = XRays.Instance; if (instance != null) { instance.Log.LogWarning((object)("XRays: " + loadedName + " holds no category named \"" + key + "\".")); } } } } private static HashSet<string> KnownCategoryKeys() { HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal); Category[] builtIn = Categories.BuiltIn; foreach (Category category in builtIn) { hashSet.Add(category.Key); } return hashSet; } } internal class Panel { private class CategoryRow { public Category Category; public Toggle Toggle; public Text Label; public Text Count; } private class LayerOption { public Toggle Toggle; public Text Label; public float Width; } private const float PanelWidth = 470f; private const float LeftMargin = -215f; private const float RightMargin = 215f; private const float ToggleSize = 26f; private const float RefreshInterval = 0.4f; private const float CountInterval = 1.5f; private const string SaveTip = "Writes the options ticked right now to the config. The saved setup is never applied by itself, not even when the game starts: it only comes back with the \"Restore setup\" button."; private const string RestoreTip = "Ticks back the options written with \"Save setup\", right away. Nothing of it runs while the game loads, so this button is the only way the saved setup is applied."; private const string TooltipsTip = "Shows the little box describing a row while the pointer rests on it. Turning it off takes every box away."; private const float MinPanelHeight = 360f; private const float MaxPanelHeight = 1200f; private const float BottomPadding = 8f; private const float MinViewportHeight = 160f; private const float ScrollbarInset = 6f; private const float ScrollbarWidth = 10f; private const float LayerRowHeight = 30f; private const float LayerLabelGap = 6f; private const float LayerItemGap = 14f; private const float LayerLineWidth = 430f; private const int LayerFontSize = 14; private readonly XRays plugin; private readonly VisibilityManager visibility; private readonly List<CategoryRow> categoryRows = new List<CategoryRow>(); private GameObject root; private Transform container; private RectTransform viewportRect; private RectTransform contentRect; private RectTransform scrollbarRect; private float headerHeight; private float contentHeight; private float builtHeight; private Toggle terrainToggle; private Toggle waterToggle; private Toggle cloudsToggle; private Toggle mistToggle; private Toggle playerToggle; private Toggle hudToggle; private Toggle tooltipsToggle; private Button revealButton; private Text cursorText; private Text objectsText; private Tooltip tip; private float refreshTimer; private float countTimer; private int countCursor; internal static readonly Color BodyColor = new Color(0.93f, 0.88f, 0.79f, 1f); private Transform Parent { get { if (!((Object)(object)container != (Object)null)) { return root.transform; } return container; } } public bool IsOpen { get { if ((Object)(object)root != (Object)null) { return root.activeSelf; } return false; } } public bool IsVisible { get { if (IsOpen && root.activeInHierarchy && (Object)(object)cursorText != (Object)null) { return ((Behaviour)cursorText).isActiveAndEnabled; } return false; } } public string CursorText { get { if (!((Object)(object)cursorText != (Object)null)) { return null; } return cursorText.text; } } public Panel(XRays owner, VisibilityManager manager) { plugin = owner; visibility = manager; } public void Toggle() { if (IsOpen) { Close(); } else { Open(); } } public void Open() { if ((!((Object)(object)root == (Object)null) || Build()) && !((Object)(object)root == (Object)null)) { root.SetActive(true); GUIManager.BlockInput(true); Refresh(); RefreshCounts(); } } public void Close() { if ((Object)(object)root != (Object)null && root.activeSelf) { root.SetActive(false); } GUIManager.BlockInput(false); if (tip != null) { tip.Reset(); } } public void Invalidate() { root = null; container = null; tip = null; viewportRect = null; contentRect = null; scrollbarRect = null; headerHeight = 0f; contentHeight = 0f; builtHeight = 0f; terrainToggle = null; waterToggle = null; cloudsToggle = null; mistToggle = null; playerToggle = null; hudToggle = null; tooltipsToggle = null; revealButton = null; cursorText = null; objectsText = null; countCursor = 0; categoryRows.Clear(); } public void Tick(float deltaTime) { if (IsOpen) { refreshTimer += deltaTime; if (refreshTimer >= 0.4f) { refreshTimer = 0f; Refresh(); } countTimer += deltaTime; if (countTimer >= 1.5f) { countTimer = 0f; TickCounts(); } if (plugin.ShowTooltips.Value) { tip.Tick(deltaTime); } else { tip.Reset(); } } } public void Refresh() { if (!IsOpen) { return; } float num = Mathf.Clamp(plugin.PanelHeight.Value, 360f, 1200f); if (!Mathf.Approximately(num, builtHeight)) { ApplyHeight(num); } terrainToggle.SetIsOnWithoutNotify(visibility.TerrainHidden); waterToggle.SetIsOnWithoutNotify(visibility.WaterHidden); cloudsToggle.SetIsOnWithoutNotify(visibility.CloudsHidden); mistToggle.SetIsOnWithoutNotify(visibility.MistHidden); playerToggle.SetIsOnWithoutNotify(visibility.PlayerHidden); hudToggle.SetIsOnWithoutNotify(visibility.HudHidden); tooltipsToggle.SetIsOnWithoutNotify(plugin.ShowTooltips.Value); foreach (CategoryRow categoryRow in categoryRows) { categoryRow.Toggle.SetIsOnWithoutNotify(visibility.IsCategoryHidden(categoryRow.Category.Key)); } SetButtonLabel(revealButton, visibility.IsRevealing ? "Restore" : (visibility.AnyOptionChecked ? "Reveal" : "Hide")); objectsText.text = "Hidden objects: " + visibility.HiddenRootCount + " Other: " + visibility.OffListCount; if (!PointerOverPanel()) { cursorText.text = PickService.Describe(plugin.PickDistance.Value, visibility); } } private bool PointerOverPanel() { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)root != (Object)null) { return RectTransformUtility.RectangleContainsScreenPoint(root.GetComponent<RectTransform>(), Vector2.op_Implicit(Input.mousePosition)); } return false; } public void RefreshCounts() { if (!IsOpen) { return; } foreach (CategoryRow categoryRow in categoryRows) { categoryRow.Count.text = Categories.Count(categoryRow.Category).ToString(); } } public void TickCounts() { if (IsOpen && categoryRows.Count != 0) { countCursor %= categoryRows.Count; CategoryRow categoryRow = categoryRows[countCursor++]; categoryRow.Count.text = Categories.Count(categoryRow.Category).ToString(); } } private bool Build() { try { return BuildPanel(); } catch (Exception ex) { if ((Object)(object)root != (Object)null) { Object.Destroy((Object)(object)root); } Invalidate(); plugin.Log.LogError((object)("XRays panel: build failed: " + ex)); return false; } } private bool BuildPanel() { //IL_00c5: 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_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01b8: Expected O, but got Unknown //IL_01ef: Unknown result type (might be due to invalid IL or missing references) //IL_0379: Unknown result type (might be due to invalid IL or missing references) //IL_03ab: Unknown result type (might be due to invalid IL or missing references) //IL_048b: Unknown result type (might be due to invalid IL or missing references) //IL_04eb: Unknown result type (might be due to invalid IL or missing references) //IL_04f5: Expected O, but got Unknown //IL_053a: Unknown result type (might be due to invalid IL or missing references) //IL_0544: Expected O, but got Unknown //IL_05a7: Unknown result type (might be due to invalid IL or missing references) //IL_0623: Unknown result type (might be due to invalid IL or missing references) //IL_062d: Expected O, but got Unknown //IL_067d: Unknown result type (might be due to invalid IL or missing references) //IL_0687: Expected O, but got Unknown //IL_06cc: Unknown result type (might be due to invalid IL or missing references) //IL_06d6: Expected O, but got Unknown //IL_070d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)GUIManager.CustomGUIFront == (Object)null) { plugin.Log.LogWarning((object)"XRays panel: Jötunn interface not available yet"); return false; } GUIManager instance = GUIManager.Instance; float cursor = 14f; float[] array = new float[7 + Categories.DisplayOrder.Length]; array[0] = Row(44f); headerHeight = cursor + 8f; cursor = 6f; array[1] = Row(80f); builtHeight = Mathf.Clamp(plugin.PanelHeight.Value, 360f, 1200f); root = instance.CreateWoodpanel(GUIManager.CustomGUIFront.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(280f, 0f), 470f, builtHeight, true); if ((Object)(object)root == (Object)null) { plugin.Log.LogError((object)"XRays panel: woodpanel creation failed"); return false; } categoryRows.Clear(); container = root.transform; tip = new Tooltip(root.GetComponent<RectTransform>()); MakeText("XRays", -215f, array[0], 300f, 30f, 22, instance.ValheimOrange, (TextAnchor)3, instance.AveriaSerifBold); Button val = MakeButton("Close", 215f, array[0], 96f, 30f); ((UnityEvent)val.onClick).AddListener(new UnityAction(Close)); tip.Attach(((Component)val).gameObject, "Closes the panel (Escape by default)."); MakeScrollArea(); cursorText = MakeText("Under the cursor: —", -215f, array[1], 430f, 80f, 13, BodyColor, (TextAnchor)3, instance.AveriaSerif); cursor += 10f; cursor = MakeLayerOptions(instance, cursor); for (int i = 0; i < Categories.DisplayOrder.Length; i++) { array[2 + i] = Row(26f); } array[2 + Categories.DisplayOrder.Length] = Row(30f); array[3 + Categories.DisplayOrder.Length] = Row(36f); array[4 + Categories.DisplayOrder.Length] = Row(26f); array[5 + Categories.DisplayOrder.Length] = Row(34f); array[6 + Categories.DisplayOrder.Length] = Row(100f); contentHeight = cursor + 16f; ApplyHeight(builtHeight); for (int j = 0; j < Categories.DisplayOrder.Length; j++) { Category category = Categories.DisplayOrder[j]; float y = array[2 + j]; CategoryRow categoryRow = new CategoryRow { Category = category, Toggle = MakeToggle(-215f, y, visibility.IsCategoryHidden(category.Key), delegate(bool v) { OnCategoryToggle(category, v); }) }; categoryRow.Label = MakeText(category.Label, -179f, y, 250f, 26f, 15, BodyColor, (TextAnchor)3, instance.AveriaSerif); categoryRow.Count = MakeText("0", 215f, y, 120f, 26f, 14, BodyColor, (TextAnchor)5, instance.AveriaSerif, rightAlign: true); tip.Attach(((Component)categoryRow.Toggle).gameObject, category.Description); tip.Attach(((Component)categoryRow.Label).gameObject, category.Description); tip.Attach(((Component)categoryRow.Count).gameObject, category.Description); categoryRows.Add(categoryRow); } int num = 2 + Categories.DisplayOrder.Length; int num2 = num + 1; int num3 = num2 + 1; int num4 = num3 + 1; int num5 = num4 + 1; objectsText = MakeText("Hidden objects: 0 Other: 0", -215f, array[num], 230f, 30f, 14, BodyColor, (TextAnchor)3, instance.AveriaSerif); tip.Attach(((Component)objectsText).gameObject, "The object roots currently invisible (ticked categories, objects picked one by one, Hide all), and what is hidden without a row of its own in this list."); Button val2 = MakeButton("Save setup", -5f, array[num2], 210f, 24f); ((UnityEvent)val2.onClick).AddListener(new UnityAction(OnSaveSetup)); tip.Attach(((Component)val2).gameObject, "Writes the options ticked right now to the config. The saved setup is never applied by itself, not even when the game starts: it only comes back with the \"Restore setup\" button."); Button val3 = MakeButton("Restore setup", 215f, array[num2], 210f, 24f); ((UnityEvent)val3.onClick).AddListener(new UnityAction(OnRestoreSetup)); tip.Attach(((Component)val3).gameObject, "Ticks back the options written with \"Save setup\", right away. Nothing of it runs while the game loads, so this button is the only way the saved setup is applied."); tooltipsToggle = MakeToggle(-215f, array[num3], plugin.ShowTooltips.Value, OnTooltipsToggle); Text val4 = MakeText("Show tooltips", -179f, array[num3], 380f, 26f, 15, BodyColor, (TextAnchor)3, instance.AveriaSerif); tip.Attach(((Component)tooltipsToggle).gameObject, "Shows the little box describing a row while the pointer rests on it. Turning it off takes every box away."); tip.Attach(((Component)val4).gameObject, "Shows the little box describing a row while the pointer rests on it. Turning it off takes every box away."); revealButton = MakeButton("Reveal", 15f, array[num4], 90f, 30f); ((UnityEvent)revealButton.onClick).AddListener(new UnityAction(OnToggleReveal)); tip.Attach(((Component)revealButton).gameObject, RevealTip); Button val5 = MakeButton("Hide all", 115f, array[num4], 90f, 30f); ((UnityEvent)val5.onClick).AddListener(new UnityAction(OnHideAll)); tip.Attach(((Component)val5).gameObject, "Checks every option of the list at once: terrain, water, clouds, mist, character, HUD and every category. It also replaces the setup the reveal would bring back."); Button val6 = MakeButton("Show all", 215f, array[num4], 90f, 30f); ((UnityEvent)val6.onClick).AddListener(new UnityAction(OnRestoreAll)); tip.Attach(((Component)val6).gameObject, "Everything back on screen: every option unchecked and the objects picked one by one shown again. It also replaces the setup the reveal would bring back."); string content = PluginHelpText(); MakeText(content, -215f, array[num5], 430f, 100f, 13, BodyColor, (TextAnchor)3, instance.AveriaSerif); container = null; return true; float Row(float height) { float result = 0f - (cursor + height / 2f); cursor += height; return result; } } private float MakeLayerOptions(GUIManager gui, float top) { LayerOption[] array = new LayerOption[6] { MakeLayerOption(gui, "Clouds", "The clouds of the sky: the big planes and the horizon cylinder, the particle clouds and the distant mist clouds.", visibility.CloudsHidden, delegate(bool v) { visibility.SetClouds(v); Refresh(); }), MakeLayerOption(gui, "HUD", "The whole in-game HUD: health, stamina and eitr bars, hot bar, mini map, crosshair, hints and panels.", visibility.HudHidden, delegate(bool v) { visibility.SetHud(v); Refresh(); }), MakeLayerOption(gui, "Mist", "The mist and the fog: ground mist, weather fog, distant fog planes, ocean mist, the Mistlands mist and the distance fog of the game.", visibility.MistHidden, delegate(bool v) { visibility.SetMist(v); Refresh(); }), MakeLayerOption(gui, "Player", "Your own character — body, armor and held item — out of the picture. Renderers only; the camera and the colliders stay.", visibility.PlayerHidden, delegate(bool v) { visibility.SetPlayer(v); Refresh(); }), MakeLayerOption(gui, "Terrain", "The ground itself: the loaded zones, the sea bed and the horizon, taken away so you can see through it.", visibility.TerrainHidden, delegate(bool v) { visibility.SetTerrain(v); Refresh(); }), MakeLayerOption(gui, "Water", "The water: the surface of the loaded zones and the sea drawn beyond them.", visibility.WaterHidden, delegate(bool v) { visibility.SetWater(v); Refresh(); }) }; cloudsToggle = array[0].Toggle; hudToggle = array[1].Toggle; mistToggle = array[2].Toggle; playerToggle = array[3].Toggle; terrainToggle = array[4].Toggle; waterToggle = array[5].Toggle; float num = 0f; for (int num2 = 0; num2 < array.Length; num2++) { num += array[num2].Width + ((num2 > 0) ? 14f : 0f); } int num3 = ((num <= 430f) ? array.Length : ((array.Length + 1) / 2)); float y = 0f - (top + 15f); PlaceLayers(array, 0, num3, y); top += 30f; if (num3 < array.Length) { y = 0f - (top + 15f); PlaceLayers(array, num3, array.Length - num3, y); top += 30f; } return top; } private LayerOption MakeLayerOption(GUIManager gui, string label, string tipText, bool shown, Action<bool> onChanged) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_007a: 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) LayerOption layerOption = new LayerOption { Toggle = MakeToggle(-215f, 0f, shown, onChanged), Label = MakeText(label, -215f, 0f, 300f, 26f, 14, BodyColor, (TextAnchor)3, gui.AveriaSerif) }; HorizontalWrapMode horizontalOverflow = layerOption.Label.horizontalOverflow; layerOption.Label.horizontalOverflow = (HorizontalWrapMode)1; float preferredWidth = layerOption.Label.preferredWidth; layerOption.Label.horizontalOverflow = horizontalOverflow; ((Graphic)layerOption.Label).rectTransform.sizeDelta = new Vector2(preferredWidth + 6f, 26f); layerOption.Width = 32f + preferredWidth; tip.Attach(((Component)layerOption.Toggle).gameObject, tipText); tip.Attach(((Component)layerOption.Label).gameObject, tipText); return layerOption; } private static void PlaceLayers(LayerOption[] options, int from, int count, float y) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) float num = -215f; for (int i = from; i < from + count; i++) { LayerOption layerOption = options[i]; ((RectTransform)((Component)layerOption.Toggle).transform).anchoredPosition = new Vector2(num, y); ((Graphic)layerOption.Label).rectTransform.anchoredPosition = new Vector2(num + 26f + 6f, y); num += layerOption.Width + 14f; } } private void MakeScrollArea() { //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Expected O, but got Unknown //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Expected O, but got Unknown //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: 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_00fd: 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) float viewportHeight = GetViewportHeight(builtHeight); GameObject val = new GameObject("XRaysViewport", new Type[5] { typeof(RectTransform), typeof(CanvasRenderer), typeof(Image), typeof(RectMask2D), typeof(ScrollRect) }); viewportRect = (RectTransform)val.transform; ((Transform)viewportRect).SetParent(root.transform, false); viewportRect.anchorMin = new Vector2(0.5f, 1f); viewportRect.anchorMax = new Vector2(0.5f, 1f); viewportRect.pivot = new Vector2(0.5f, 1f); viewportRect.anchoredPosition = new Vector2(0f, 0f - headerHeight); viewportRect.sizeDelta = new Vector2(470f, viewportHeight); Image component = val.GetComponent<Image>(); ((Graphic)component).color = new Color(0f, 0f, 0f, 0f); ((Graphic)component).raycastTarget = true; contentRect = MakeContentRect(viewportHeight); ScrollRect component2 = val.GetComponent<ScrollRect>(); component2.content = contentRect; component2.viewport = viewportRect; component2.horizontal = false; component2.vertical = true; component2.movementType = (MovementType)2; component2.inertia = false; component2.scrollSensitivity = 30f; component2.verticalNormalizedPosition = 1f; Scrollbar verticalScrollbar = MakeScrollbar(viewportHeight); component2.verticalScrollbar = verticalScrollbar; component2.verticalScrollbarVisibility = (ScrollbarVisibility)1; component2.verticalScrollbarSpacing = 4f; container = (Transform)(object)contentRect; } private RectTransform MakeContentRect(float viewportHeight) { //IL_0018: 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_0027: 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_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Expected O, but got Unknown RectTransform val = (RectTransform)new GameObject("XRaysContent", new Type[1] { typeof(RectTransform) }).transform; ((Transform)val).SetParent((Transform)(object)viewportRect, false); val.anchorMin = new Vector2(0.5f, 1f); val.anchorMax = new Vector2(0.5f, 1f); val.pivot = new Vector2(0.5f, 1f); val.anchoredPosition = Vector2.zero; val.sizeDelta = new Vector2(470f, Mathf.Max(contentHeight, viewportHeight)); return val; } private Scrollbar MakeScrollbar(float viewportHeight) { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Expected O, but got Unknown //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Expected O, but got Unknown //IL_007d: 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_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Expected O, but got Unknown //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: Unknown result type (might be due to invalid IL or missing references) //IL_01c4: Unknown result type (might be due to invalid IL or missing references) //IL_01ea: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Unknown result type (might be due to invalid IL or missing references) //IL_0212: Unknown result type (might be due to invalid IL or missing references) //IL_0232: Unknown result type (might be due to invalid IL or missing references) //IL_023e: Unknown result type (might be due to invalid IL or missing references) //IL_025e: Unknown result type (might be due to invalid IL or missing references) //IL_0275: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("XRaysScrollbar", new Type[4] { typeof(RectTransform), typeof(CanvasRenderer), typeof(Image), typeof(Scrollbar) }); scrollbarRect = (RectTransform)val.transform; ((Transform)scrollbarRect).SetParent(root.transform, false); scrollbarRect.anchorMin = new Vector2(1f, 1f); scrollbarRect.anchorMax = new Vector2(1f, 1f); scrollbarRect.pivot = new Vector2(1f, 0.5f); scrollbarRect.anchoredPosition = new Vector2(-6f, 0f - (headerHeight + viewportHeight / 2f)); scrollbarRect.sizeDelta = new Vector2(10f, viewportHeight); ((Graphic)val.GetComponent<Image>()).color = new Color(0f, 0f, 0f, 0.4f); GameObject val2 = new GameObject("Handle", new Type[3] { typeof(RectTransform), typeof(CanvasRenderer), typeof(Image) }); RectTransform val3 = (RectTransform)val2.transform; ((Transform)val3).SetParent((Transform)(object)scrollbarRect, false); val3.anchorMin = new Vector2(0f, 0f); val3.anchorMax = new Vector2(1f, 1f); val3.offsetMin = new Vector2(1f, 2f); val3.offsetMax = new Vector2(-1f, -2f); Image component = val2.GetComponent<Image>(); ((Graphic)component).color = BodyColor; Scrollbar component2 = val.GetComponent<Scrollbar>(); component2.handleRect = val3; ((Selectable)component2).targetGraphic = (Graphic)(object)component; component2.direction = (Direction)2; ColorBlock colors = ((Selectable)component2).colors; ((ColorBlock)(ref colors)).normalColor = BodyColor; ((ColorBlock)(ref colors)).highlightedColor = new Color(1f, 0.96f, 0.88f, 1f); ((ColorBlock)(ref colors)).pressedColor = new Color(0.76f, 0.7f, 0.6f, 1f); ((ColorBlock)(ref colors)).selectedColor = BodyColor; ((ColorBlock)(ref colors)).disabledColor = new Color(0.5f, 0.5f, 0.5f, 0.8f); ((ColorBlock)(ref colors)).fadeDuration = 0.1f; ((Selectable)component2).colors = colors; return component2; } private float GetViewportHeight(float panelHeight) { return Mathf.Max(160f, panelHeight - headerHeight - 8f); } private void ApplyHeight(float height) { //IL_0020: 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_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) builtHeight = height; float viewportHeight = GetViewportHeight(height); root.GetComponent<RectTransform>().sizeDelta = new Vector2(470f, height); viewportRect.anchoredPosition = new Vector2(0f, 0f - headerHeight); viewportRect.sizeDelta = new Vector2(470f, viewportHeight); contentRect.sizeDelta = new Vector2(470f, Mathf.Max(contentHeight, viewportHeight)); scrollbarRect.anchoredPosition = new Vector2(-6f, 0f - (headerHeight + viewportHeight / 2f)); scrollbarRect.sizeDelta = new Vector2(10f, viewportHeight); } private string RevealTip() { if (visibility.IsRevealing) { return "Brings back the setup that was on before the reveal; anything ticked while the reveal was on is kept."; } if (!visibility.AnyOptionChecked) { return "Nothing is checked: the first press checks every option of the list instead."; } return "Shows everything the checked options are hiding; the next press brings that exact setup back."; } private string PluginHelpText() { List<string> list = new List<string>(); AddHelpLine(list, (XRays.Instance.KeyPanel, "panel"), (XRays.Instance.KeyClose, "close"), (XRays.Instance.KeyHud, "hud")); AddHelpLine(list, (XRays.Instance.KeyTerrain, "terrain"), (XRays.Instance.KeyWater, "water"), (XRays.Instance.KeyClouds, "clouds")); AddHelpLine(list, (XRays.Instance.KeyMist, "mist"), (XRays.Instance.KeyPlayer, "player"), (XRays.Instance.KeyReveal, "reveal / restore")); AddHelpLine(list, (XRays.Instance.KeyPick, "hide object under cursor")); AddHelpLine(list, (XRays.Instance.KeyPickCategory, "whole category under the cursor")); return string.Join("\n", list); } private static void AddHelpLine(List<string> lines, params (ConfigEntry<KeyboardShortcut> key, string label)[] hotkeys) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) List<string> list = new List<string>(); for (int i = 0; i < hotkeys.Length; i++) { var (val, text) = hotkeys[i]; if (!((object)val.Value/*cast due to .constrained prefix*/).Equals((object?)KeyboardShortcut.Empty)) { list.Add(((object)val.Value/*cast due to .constrained prefix*/).ToString() + " : " + text); } } if (list.Count > 0) { lines.Add(string.Join(" · ", list)); } } private void OnCategoryToggle(Category category, bool hidden) { visibility.SetCategory(category, hidden); Refresh(); } private void OnSaveSetup() { plugin.SaveSetup(); } private void OnRestoreSetup() { plugin.RestoreSetup(); Refresh(); } private void OnTooltipsToggle(bool show) { plugin.ShowTooltips.Value = show; } private void OnRestoreAll() { visibility.RestoreAll(); Refresh(); } private void OnToggleReveal() { visibility.ToggleChecked(); Refresh(); } private static void SetButtonLabel(Button button, string label) { Text val = (((Object)(object)button != (Object)null) ? ((Component)button).GetComponentInChildren<Text>(true) : null); if ((Object)(object)val != (Object)null && val.text != label) { val.text = label; } } private void OnHideAll() { visibility.HideAll(); Refresh(); } private Text MakeText(string content, float x, float y, float width, float height, int fontSize, Color color, TextAnchor alignment, Font font, bool rightAlign = false) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) GameObject obj = GUIManager.Instance.CreateText(content, Parent, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), Vector2.zero, font, fontSize, color, true, Color.black, width, height, false); RectTransform component = obj.GetComponent<RectTransform>(); component.pivot = (rightAlign ? new Vector2(1f, 0.5f) : new Vector2(0f, 0.5f)); component.anchoredPosition = new Vector2(x, y); Text component2 = obj.GetComponent<Text>(); component2.alignment = alignment; component2.verticalOverflow = (VerticalWrapMode)1; component2.horizontalOverflow = (HorizontalWrapMode)0; return component2; } private Button MakeButton(string label, float x, float y, float width, float height) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0049: 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) GameObject obj = GUIManager.Instance.CreateButton(label, Parent, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), Vector2.zero, width, height); RectTransform component = obj.GetComponent<RectTransform>(); component.pivot = new Vector2(1f, 0.5f); component.anchoredPosition = new Vector2(x, y); Button component2 = obj.GetComponent<Button>(); GUIManager.Instance.ApplyButtonStyle(component2, 14); return component2; } private Toggle MakeToggle(float x, float y, bool initial, Action<bool> onChanged) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: 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) GameObject obj = GUIManager.Instance.CreateToggle(Parent, 26f, 26f); RectTransform component = obj.GetComponent<RectTransform>(); component.anchorMin = new Vector2(0.5f, 1f); component.anchorMax = new Vector2(0.5f, 1f); component.pivot = new Vector2(0f, 0.5f); component.anchoredPosition = new Vector2(x, y); Toggle component2 = obj.GetComponent<Toggle>(); component2.SetIsOnWithoutNotify(initial); if (onChanged != null) { ((UnityEvent<bool>)(object)component2.onValueChanged).AddListener((UnityAction<bool>)delegate(bool value) { onChanged(value); }); } return component2; } } [HarmonyPatch(typeof(Menu), "UpdateNavigation")] internal static class Patch_MenuNavigation { private static void Postfix() { PauseMenuEntry.WireNavigation(); } } [HarmonyPatch(typeof(Menu), "Show")] internal static class Patch_MenuShow { private static void Postfix(Menu __instance) { PauseMenuEntry.Add(__instance); } } internal static class PauseMenuEntry { private const string EntryLabel = "XRays"; private const string EntryName = "XRaysEntry"; private static Button entryButton; private static Menu pauseMenu; private static Selectable belowSettings; private static bool failed; internal static void Add(Menu menu) { try { pauseMenu = menu; XRays instance = XRays.Instance; if ((Object)(object)instance == (Object)null) { return; } instance.EndMenuCloseGrace(); if (!instance.Enable.Value) { Forget("Enable is off"); return; } if ((Object)(object)entryButton == (Object)null) { entryButton = Build(menu); } if ((Object)(object)entryButton != (Object)null) { WireNavigation(); } } catch (Exception ex) { if (!failed) { failed = true; XRays instance2 = XRays.Instance; if (instance2 != null) { instance2.Log.LogError((object)("Pause menu entry: " + ex)); } } } } internal static void OnSettingChanged() { Menu val = pauseMenu; if ((Object)(object)val != (Object)null) { Add(val); } } internal static void WireNavigation() { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) Button val = entryButton; if ((Object)(object)val == (Object)null) { return; } Button val2 = SettingsButton(); if (!((Object)(object)val2 == (Object)null)) { Navigation navigation = ((Selectable)val2).navigation; if (!((Object)(object)((Navigation)(ref navigation)).selectOnDown == (Object)(object)val)) { navigation = ((Selectable)val2).navigation; belowSettings = ((Navigation)(ref navigation)).selectOnDown; Navigation navigation2 = ((Selectable)val).navigation; ((Navigation)(ref navigation2)).mode = (Mode)4; ((Navigation)(ref navigation2)).selectOnUp = (Selectable)(object)val2; ((Navigation)(ref navigation2)).selectOnDown = belowSettings; ((Selectable)val).navigation = navigation2; Navigation navigation3 = ((Selectable)val2).navigation; ((Navigation)(ref navigation3)).selectOnDown = (Selectable)(object)val; ((Selectable)val2).navigation = navigation3; } } } private static void OnClicked() { XRays instance = XRays.Instance; if (!((Object)(object)instance == (Object)null) && instance.Enable.Value && instance.Panel != null) { instance.BeginMenuCloseGrace(); if ((Object)(object)pauseMenu != (Object)null) { pauseMenu.Hide(); } instance.Panel.Open(); } } private static Button Build(Menu menu) { //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Expected O, but got Unknown //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Expected O, but got Unknown Button settingsButton = menu.m_settingsButton; Transform val = (((Object)(object)settingsButton != (Object)null) ? ((Component)settingsButton).transform.parent : null); if ((Object)(object)settingsButton == (Object)null || (Object)(object)val == (Object)null) { return Fail("Menu carries no Settings button to take the shape of."); } GameObject val2 = Object.Instantiate<GameObject>(((Component)settingsButton).gameObject, val); ((Object)val2).name = "XRaysEntry"; val2.SetActive(true); Button component = val2.GetComponent<Button>(); if ((Object)(object)component == (Object)null) { Object.Destroy((Object)(object)val2); return Fail("The button taken as a shape carries no Button."); } component.onClick = new ButtonClickedEvent(); ((UnityEvent)component.onClick).AddListener(new UnityAction(OnClicked)); ((Selectable)component).interactable = true; SetLabel(val2); val2.transform.SetSiblingIndex(((Component)settingsButton).transform.GetSiblingIndex() + 1); XRays instance = XRays.Instance; if (instance != null) { instance.Log.LogInfo((object)"Pause menu: entry added (XRays)."); } return component; } private static void Forget(string why) { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: 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_0050: Unknown result type (might be due to invalid IL or missing references) Button val = entryButton; entryButton = null; if ((Object)(object)val == (Object)null) { return; } Button val2 = SettingsButton(); if ((Object)(object)val2 != (Object)null) { Navigation navigation = ((Selectable)val2).navigation; if ((Object)(object)((Navigation)(ref navigation)).selectOnDown == (Object)(object)val) { Navigation navigation2 = ((Selectable)val2).navigation; ((Navigation)(ref navigation2)).selectOnDown = belowSettings; ((Selectable)val2).navigation = navigation2; } } Navigation navigation3 = ((Selectable)val).navigation; ((Navigation)(ref navigation3)).selectOnUp = null; ((Navigation)(ref navigation3)).selectOnDown = null; ((Selectable)val).navigation = navigation3; XRays instance = XRays.Instance; if (instance != null) { instance.Log.LogInfo((object)("Pause menu: entry removed (" + why + ").")); } Object.Destroy((Object)(object)((Component)val).gameObject); belowSettings = null; } internal static void Cleanup() { try { Forget("plugin unloaded"); } catch (Exception ex) { XRays instance = XRays.Instance; if (instance != null) { instance.Log.LogError((object)("Pause menu cleanup: " + ex)); } } } private static Button SettingsButton() { if (!((Object)(object)pauseMenu != (Object)null)) { return null; } return pauseMenu.m_settingsButton; } private static void SetLabel(GameObject entry) { TMP_Text componentInChildren = entry.GetComponentInChildren<TMP_Text>(true); if ((Object)(object)componentInChildren != (Object)null && !string.Equals(componentInChildren.text, "XRays", StringComparison.Ordinal)) { componentInChildren.text = "XRays"; } Text componentInChildren2 = entry.GetComponentInChildren<Text>(true); if ((Object)(object)componentInChildren2 != (Object)null && !string.Equals(componentInChildren2.text, "XRays", StringComparison.Ordinal)) { componentInChildren2.text = "XRays"; } } private static Button Fail(string reason) { if (!failed) { failed = true; XRays instance = XRays.Instance; if (instance != null) { instance.Log.LogWarning((object)("Pause menu: no XRays entry - " + reason)); } } return null; } } internal enum PickKind { None, Terrain, Water, Object } internal class PickResult { public PickKind Kind; public Category Category; public GameObject Root; public string Name; public bool Hidden; public Vector3 Position; public float Distance; public Type MatchedType; public string MatchedName; public string MatchedRoot; public string HitPath; } internal static class PickService { public static PickResult Pick(float maxDistance, VisibilityManager visibility) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: 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_0074: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) Camera camera = GetCamera(); if ((Object)(object)camera == (Object)null || visibility == null) { return null; } RaycastHit[] array = Physics.RaycastAll(camera.ScreenPointToRay(Vector2.op_Implicit(GetPointerPosition())), maxDistance, -1, (QueryTriggerInteraction)1); if (array.Length == 0) { return null; } Array.Sort(array, (RaycastHit a, RaycastHit b) => ((RaycastHit)(ref a)).distance.CompareTo(((RaycastHit)(ref b)).distance)); Player localPlayer = Player.m_localPlayer; PickResult pickResult = null; RaycastHit[] array2 = array; for (int num = 0; num < array2.Length; num++) { RaycastHit val = array2[num]; Transform val2 = (((Object)(object)((RaycastHit)(ref val)).collider != (Object)null) ? ((Component)((RaycastHit)(ref val)).collider).transform : null); if ((Object)(object)val2 == (Object)null || ((Object)(object)localPlayer != (Object)null && val2.IsChildOf(((Component)localPlayer).transform))) { continue; } PickResult pickResult2 = Classify(val2); if (pickResult2 == null) { continue; } pickResult2.Distance = ((RaycastHit)(ref val)).distance; pickResult2.Position = ((pickResult2.Kind == PickKind.Object && (Object)(object)pickResult2.Root != (Object)null) ? pickResult2.Root.transform.position : ((RaycastHit)(ref val)).point); pickResult2.HitPath = BuildHitPath(val2, pickResult2.Root); if (pickResult2.Kind == PickKind.Terrain) { if (!visibility.TerrainHidden) { return pickResult2; } continue; } if (pickResult2.Kind == PickKind.Water) { if (!visibility.WaterHidden) { return pickResult2; } continue; } if (visibility.IsRootHidden(pickResult2.Root)) { pickResult2.Hidden = true; if (pickResult == null) { pickResult = pickResult2; } continue; } return pickResult2; } return pickResult; } public static string Describe(float maxDistance, VisibilityManager visibility) { PickResult pickResult = Pick(maxDistance, visibility); if (pickResult == null) { return "Under the cursor: none"; } string text = "Under the cursor: " + pickResult.Kind switch { PickKind.Terrain => "Terrain", PickKind.Water => "Water", _ => pickResult.Name, }; if (pickResult.Category != null) { text = text + " · Category: " + pickResult.Category.Label; } if (pickResult.Hidden || ((Object)(object)pickResult.Root != (Object)null && visibility.IsRootHidden(pickResult.Root))) { text += " · hidden"; } return text + "\n" + TypesLine(pickResult) + "\n" + HitLine(pickResult) + "\n" + Details(pickResult); } private static string HitLine(PickResult pick) { string text = pick.HitPath; if (string.IsNullOrEmpty(text)) { text = (((Object)(object)pick.Root != (Object)null) ? ((Object)pick.Root).name : pick.Name); } return "Hit: " + text; } private static string TypesLine(PickResult pick) { if (pick.Kind == PickKind.Terrain) { return "Game type: Heightmap"; } if (pick.Kind == PickKind.Water) { return "Game type: WaterVolume"; } Category category = pick.Category; if (category == null) { return "Game type: none"; } if (category.IsNameCategory) { return "Game type: none · category created by name"; } string text = "none"; if (category.Types != null && category.Types.Length != 0) { string[] array = new string[category.Types.Length]; for (int i = 0; i < category.Types.Length; i++) { array[i] = category.Types[i].Name; } text = string.Join(", ", array); } if (category.HasNameMatch) { text += " + names"; } string text2 = ((pick.MatchedType != null) ? pick.MatchedType.Name : ((pick.MatchedName != null) ? ("name (\"" + pick.MatchedName + "\")") : ((pick.MatchedRoot == null) ? "?" : pick.MatchedRoot))); return "Game types: " + text + " · match: " + text2; } private static string Details(PickResult pick) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0018: 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_0044: Unknown result type (might be due to invalid IL or missing references) Vector3 position = pick.Position; return "Pos (" + Format(position.x) + ", " + Format(position.y) + ", " + Format(position.z) + ") · " + Format(pick.Distance) + " m"; } private static string Format(float value) { return value.ToString("0.0", CultureInfo.InvariantCulture); } private static PickResult Classify(Transform start) { Transform val = start; while ((Object)(object)val != (Object)null) { if ((Object)(object)((Component)val).GetComponent<ClutterSystem>() != (Object)null || (Object)(object)((Component)val).GetComponent<EnvMan>() != (Object)null) { return null; } if ((Object)(object)((Component)val).GetComponent<Heightmap>() != (Object)null) { return new PickResult { Kind = PickKind.Terrain, Root = ((Component)val).gameObject, Name = "Terrain", MatchedType = typeof(Heightmap) }; } if ((Object)(object)((Component)val).GetComponent<WaterVolume>() != (Object)null || IsWaterSurface(val)) { return new PickResult { Kind = PickKind.Water, Root = ((Component)val).gameObject, Name = "Water", MatchedType = typeof(WaterVolume) }; } Category[] builtIn = Categories.BuiltIn; foreach (Category category in builtIn) { if (category.Types == null || category.MatchesExclude(((Object)val).name)) { continue; } Type[] types = category.Types; foreach (Type type in types) { if ((Object)(object)((Component)val).GetComponent(type) != (Object)null) { return new PickResult { Kind = PickKind.Object, Category = category, Root = ((Component)val).gameObject, Name = ((Object)val).name, MatchedType = type }; } } } Transform val2 = Categories.GrassItem(val); if ((Object)(object)val2 != (Object)null) { return GrassResult(val2); } if ((Object)(object)((Component)val).GetComponent<ZNetView>() != (Object)null || (Object)(object)((Component)val).GetComponent<LODGroup>() != (Object)null) { return ObjectResult(val); } if ((Object)(object)val.parent == (Object)null) { return ObjectResult(val); } val = val.parent; } return null; } private static bool IsWaterSurface(Transform current) { if ((Object)(object)((Component)current).GetComponent<Water>() != (Object)null) { return true; } return string.Equals(((Object)current).name, "WaterSurface", StringComparison.OrdinalIgnoreCase); } private static PickResult GrassResult(Transform item) { Categories.TryGet("clutter", out var category); PickResult pickResult = new PickResult { Kind = PickKind.Object, Category = category, Root = ((Component)item).gameObject, Name = ((Object)item).name }; if ((Object)(object)((Component)item).GetComponent<InstanceRenderer>() != (Object)null) { pickResult.MatchedType = typeof(InstanceRenderer); } else if (category != null && category.MatchesName(((Object)item).name)) { pickResult.MatchedName = ((Object)item).name; } else { pickResult.MatchedRoot = "grass root"; } return pickResult; } private static PickResult ObjectResult(Transform current) { Category[] builtIn = Categories.BuiltIn; foreach (Category category in builtIn) { if (category.MatchesName(((Object)current).name)) { return new PickResult { Kind = PickKind.Object, Category = category, Root = ((Component)current).gameObject, Name = ((Object)current).name, MatchedName = ((Object)current).name }; } } return new PickResult { Kind = PickKind.Object, Category = Category.ForName(((Object)current).name), Root = ((Component)current).gameObject, Name = ((Object)current).name }; } private static string BuildHitPath(Transform hit, GameObject root) { List<string> list = new List<string>(6); Transform val = (((Object)(object)root != (Object)null) ? root.transform : null); Transform val2 = hit; while ((Object)(object)val2 != (Object)null) { list.Add(((Object)val2).name); if ((Object)(object)val2 == (Object)(object)val || list.Count >= 6) { break; } val2 = val2.parent; } list.Reverse(); return string.Join("/", list); } private static Camera GetCamera() { Camera val = Camera.main; if ((Object)(object)val == (Object)null && (Object)(object)GameCamera.instance != (Object)null) { val = ((Component)GameCamera.instance).GetComponentInChildren<Camera>(true); } return val; } private static Vector2 GetPointerPosition() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Invalid comparison between Unknown and I4 //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) if ((int)Cursor.lockState == 1) { return new Vector2((float)Screen.width * 0.5f, (float)Screen.height * 0.5f); } return Vector2.op_Implicit(Input.mousePosition); } } internal static class ReconcileTiming { private class Stat { public long Count; public double Sum; public double Min; public double Max; public void Add(double value) { if (Count == 0L || value < Min) { Min = value; } if (Count == 0L || value > Max) { Max = value; } Count++; Sum += value; } public void Reset() { Count = 0L; Sum = 0.0; Min = 0.0; Max = 0.0; } } public static bool Enabled; private const float LogInterval = 1f; private static readonly string[] PhaseNames; private static readonly Dictionary<string, Stat> Phases; private static readonly Stat Total; private static readonly Stopwatch Watch; private static readonly StringBuilder Line; private static double lastMark; private static long passes; private static float windowTimer; static ReconcileTiming() { PhaseNames = new string[9] { "terrain", "water", "clouds", "mist", "player", "roots", "of which collect", "of which names", "apply" }; Phases = new Dictionary<string, Stat>(StringComparer.Ordinal); Total = new Stat(); Watch = new Stopwatch(); Line = new StringBuilder(320); string[] phaseNames = PhaseNames; foreach (string key in phaseNames) { Phases[key] = new Stat(); } } public static void Begin() { if (Enabled) { Watch.Restart(); lastMark = 0.0; passes++; } } public static void Mark(string name) { if (Enabled && passes != 0L) { double totalMilliseconds = Watch.Elapsed.TotalMilliseconds; double value = totalMilliseconds - lastMark; lastMark = totalMilliseconds; Total.Add(value); Of(name).Add(value); } } public static long Stamp() { if (!Enabled) { return 0L; } return Stopwatch.GetTimestamp(); } public static void AddSince(string name, long stamp) { if (Enabled && stamp != 0L && passes != 0L) { double value = (double)(Stopwatch.GetTimestamp() - stamp) * 1000.0 / (double)Stopwatch.Frequency; Of(name).Add(value); } } public static void Tick(float deltaTime) { if (!Enabled) { if (windowTimer > 0f || passes > 0) { Reset(); } return; } windowTimer += deltaTime; if (!(windowTimer < 1f)) { if (passes > 0) { Write(windowTimer); } Reset(); } } private static Stat Of(string name) { if (!Phases.TryGetValue(name, out var value)) { value = new Stat(); Phases[name] = value; } return value; } private static void Reset() { windowTimer = 0f; passes = 0L; lastMark = 0.0; Total.Reset(); string[] phaseNames = PhaseNames; foreach (string key in phaseNames) { Phases[key].Reset(); } } private static void Write(float seconds) { Line.Length = 0; Line.Append("Reconcile timing over "); Line.Append(seconds.ToString("0.0", CultureInfo.InvariantCulture)); Line.Append(" s ("); Line.Append(passes); Line.Append((passes == 1) ? " pass), all in ms: " : " passes), all in ms: "); Append(Line, "total", Total); string[] phaseNames = PhaseNames; foreach (string text in phaseNames) { Stat stat = Phases[text]; if (stat.Count != 0L) { Line.Append(" | "); Append(Line, text, stat); } } XRays instance = XRays.Instance; if (instance != null) { instance.Log.LogInfo((object)Line.ToString()); } } private static void Append(StringBuilder builder, string name, Stat stat) { builder.Append(name); builder.Append(' '); builder.Append((stat.Sum / (double)stat.Count).ToString("0.0", CultureInfo.InvariantCulture)); builder.Append(" ("); builder.Append(stat.Min.ToString("0.0", CultureInfo.InvariantCulture)); builder.Append('-'); builder.Append(stat.Max.ToString("0.0", CultureInfo.InvariantCulture)); builder.Append(')'); } } internal class Tooltip { private const float ShowDelay = 0.4f; private const float HideDelay = 0.15f; private const float Gap = 10f; private const float Margin = 6f; private const float TextWidth = 320f; private const float PaddingX = 9f; private const float PaddingY = 6f; private const int FontSize = 13; private readonly RectTransform area; private readonly RectTransform box; private readonly Text label; private GameObject hovered; private Func<string> source; private float wait; private bool shown; public Tooltip(RectTransform panel) { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Expected O, but got Unknown //IL_0073: 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_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) area = panel; GameObject val = new GameObject("XRaysTip", new Type[3] { typeof(RectTransform), typeof(CanvasRenderer), typeof(Image) }); box = val.GetComponent<RectTransform>(); ((Transform)box).SetParent((Transform)(object)area, false); box.anchorMin = new Vector2(0.5f, 0.5f); box.anchorMax = new Vector2(0.5f, 0.5f); box.pivot = new Vector2(0f, 1f); Image component = val.GetComponent<Image>(); ((Graphic)component).color = new Color(0.09f, 0.07f, 0.05f, 0.96f); ((Graphic)component).raycastTarget = false; label = MakeText(val.transform); ((Graphic)label).raycastTarget = false; val.SetActive(false); } public void Attach(GameObject target, string text) { if (!string.IsNullOrEmpty(text)) { Attach(target, () => text); } } public void Attach(GameObject target, Func<string> text) { //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Expected O, but got Unknown //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) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Expected O, but got Unknown if (!((Object)(object)target == (Object)null) && text != null) { EventTrigger val = target.GetComponent<EventTrigger>(); if ((Object)(object)val == (Object)null) { val = target.AddComponent<EventTrigger>(); } Entry val2 = new Entry { eventID = (EventTriggerType)0 }; ((UnityEvent<BaseEventData>)(object)val2.callback).AddListener((UnityAction<BaseEventData>)delegate { Hover(target, text); }); val.triggers.Add(val2); Entry val3 = new Entry { eventID = (EventTriggerType)1 }; ((UnityEvent<BaseEventData>)(object)val3.callback).AddListener((UnityAction<BaseEventData>)delegate { Leave(target); }); val.triggers.Add(val3); } } public void Reset() { hovered = null; source = null; wait = 0f; Hide(); } public void Tick(float deltaTime) { string text = (((Object)(object)hovered != (Object)null && source != null) ? source() : null); if (string.IsNullOrEmpty(text)) { if (shown) { wait += deltaTime; if (wait >= 0.15f) { Hide(); } } return; } wait += deltaTime; if (!shown) { if (wait < 0.4f) { return; } Show(); } SetText(text); Place(); } private void Hover(GameObject target, Func<string> text) { hovered = target; source = text; wait = 0f; } private void Leave(GameObject target) { if (!((Object)(object)hovered != (Object)(object)target)) { hovered = null; source = null; wait = 0f; } } private void Show() { shown = true; ((Transform)box).SetAsLastSibling(); ((Component)box).gameObject.SetActive(true); } private void Hide() { shown = false; ((Component)box).gameObject.SetActive(false); label.text = string.Empty; } private void SetText(string text) { //IL_006b: Unknown result type (might be due to invalid IL or missing references) if (!(text == label.text)) { label.text = text; ((Graphic)label).rectTransform.SetSizeWithCurrentAnchors((Axis)0, 320f); float num = Mathf.Ceil(label.preferredHeight); ((Graphic)label).rectTransform.SetSizeWithCurrentAnchors((Axis)1, num); box.sizeDelta = new Vector2(338f, num + 12f); } } private void Place() { //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_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0117: 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) Vector2 val = default(Vector2); if (RectTransformUtility.ScreenPointToLocalPointInRectangle(area, Vector2.op_Implicit(Input.mousePosition), (Camera)null, ref val)) { Rect rect = area.rect; float x = box.sizeDelta.x; float y = box.sizeDelta.y; float num = val.x + 10f; if (num + x > ((Rect)(ref rect)).xMax - 6f) { num = val.x - 10f - x; } float num2 = val.y - 10f; if (num2 - y < ((Rect)(ref rect)).yMin + 6f) { num2 = val.y + 10f; } num = Mathf.Clamp(num, ((Rect)(ref rect)).xMin + 6f, ((Rect)(ref rect)).xMax - 6f - x); num2 = Mathf.Clamp(num2, ((Rect)(ref rect)).yMin + 6f + y, ((Rect)(ref rect)).yMax - 6f); box.anchoredPosition = new Vector2(num - ((Rect)(ref rect)).center.x, num2 - ((Rect)(ref rect)).center.y); } } private Text MakeText(Transform parent) { //IL_0015: 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_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) GameObject obj = GUIManager.Instance.CreateText(string.Empty, parent, new Vector2(0f, 1f), new Vector2(0f, 1f), Vector2.zero, GUIManager.Instance.AveriaSerif, 13, Panel.BodyColor, true, Color.black, 320f, 19f, false); RectTransform component = obj.GetComponent<RectTransform>(); component.pivot = new Vector2(0f, 1f); component.anchoredPosition = new Vector2(9f, -6f); Text component2 = obj.GetComponent<Text>(); component2.alignment = (TextAnchor)3; component2.verticalOverflow = (VerticalWrapMode)1; component2.horizontalOverflow = (HorizontalWrapMode)0; return component2; } } internal class VisibilityManager { private struct RendererState { public bool Enabled; public bool ForceOff; public RendererState(bool enabled, bool forceOff) { Enabled = enabled; ForceOff = forceOff; } } private class CachedRoot { public GameObject Root; public Renderer[] Renderers; public InstanceRenderer[] Instances; public int NextPass; public void Collect(GameObject go, int nextPass) { Root = go; Renderers = go.GetComponentsInChildren<Renderer>(true); Instances = go.GetComponentsInChildren<InstanceRenderer>(true); NextPass = nextPass; } } public const float DefaultUpdateInterval = 2f; public float UpdateInterval = 2f; private const int RendererBuckets = 10; private readonly Dictionary<int, Renderer> hiddenRenderers = new Dictionary<int, Renderer>(); private readonly Dictionary<int, RendererState> rendererStates = new Dictionary<int, RendererState>(); private readonly Dictionary<int, InstanceRenderer> hiddenInstances = new Dictionary<int, InstanceRenderer>(); private readonly Dictionary<int, bool> instanceStates = new Dictionary<int, bool>(); private readonly Dictionary<int, CachedRoot> rendererCache = new Dictionary<int, CachedRoot>(); private readonly List<int> deadRoots = new List<int>(); private int passCounter; private int staggerCounter; private readonly Dictionary<int, GameObject> individualObjects = new Dictionary<int, GameObject>(); private readonly HashSet<string> hiddenCategories = new HashSet<string>(); private readonly HashSet<int> hiddenRoots = new HashSet<int>(); private float refreshTimer; private CanvasGroup enemyHudGroup; private float enemyHudAlpha = 1f; private bool enemyHudRaycasts = true; private bool fogTaken; private bool fogOriginal = true; public const int WorldOptionCount = 6; private bool[] revealedFrom; private const float NotVisibleThreshold = 1000f; public bool TerrainHidden { get; private set; } public bool WaterHidden { get; private set; } public bool CloudsHidden { get; private set; } public bool MistHidden { get; private set; } public bool PlayerHidden { get; private set; } public bool AnyActive { get { if (!TerrainHidden && !WaterHidden && !CloudsHidden && !MistHidden && !PlayerHidden && hiddenCategories.Count <= 0) { return individualObjects.Count > 0; } return true; } } public int HiddenRootCount => hiddenRoots.Count; public int IndividualCount => individualObjects.Count; public int OffListCount => individualObjects.Count + HiddenNameCategoryCount; public int HiddenNameCategoryCount { get { int num = 0; foreach (string hiddenCategory in hiddenCategories) { if (hiddenCategory.StartsWith("name:")) { num++; } } return num; } } public bool HudHidden { get; private set; } public bool IsRevealing => revealedFrom != null; public bool AnyOptionChecked { get { if (TerrainHidden || WaterHidden || CloudsHidden || MistHidden || PlayerHidden || HudHidden) { return true; } Category[] builtIn = Categories.BuiltIn; foreach (Category category in builtIn) { if (hiddenCategories.Contains(category.Key)) { return true; } } return false; } } public void SetTerrain(bool hidden) { if (TerrainHidden != hidden) { TerrainHidden = hidden; Reconcile(); } } public void ToggleTerrain() { SetTerrain(!TerrainHidden); } public void SetWater(bool hidden) { if (WaterHidden != hidden) { WaterHidden = hidden; Reconcile(); } } public void ToggleWater() { SetWater(!WaterHidden); } public void SetClouds(bool hidden) { if (CloudsHidden != hidden) { CloudsHidden = hidden; Reconcile(); } } public void ToggleClouds() { SetClouds(!CloudsHidden); } public void SetMist(bool hidden) { if (MistHidden != hidden) { MistHidden = hidden; Reconcile(); } } public void ToggleMist() { SetMist(!MistHidden); } public void SetPlayer(bool hidden) { if (PlayerHidden != hidden) { PlayerHidden = hidden; Reconcile(); } } public void TogglePlayer() { SetPlayer(!PlayerHidden); } public void SetHud(bool hidden) { if (HudHidden != hidden) { HudHidden = hidden; ApplyHud(); } } public void ToggleHud() { SetHud(!HudHidden); } public bool IsCategoryHidden(string key) { if (!string.IsNullOrEmpty(key)) { return hiddenCategories.Contains(key); } return false; } public int SetCategory(Category category, bool hidden) { if (category == null) { return 0; } Categories.Register(category); Categories.Invalidate(category.Key); int count = Categories.CollectRoots(category).Count; if (hidden) { hiddenCategories.Add(category.Key); } else { hiddenCategories.Remove(category.Key); } Reconcile(); return count; } public bool ToggleObject(GameObject go) { if ((Object)(object)go == (Object)null) { return false; } int instanceID = ((Object)go).GetInstanceID(); bool num = !individualObjects.ContainsKey(instanceID); if (num) { individualObjects[instanceID] = go; } else { individualObjects.Remove(instanceID); } Reconcile(); return num; } public bool IsObjectHidden(GameObject go) { Transform val = (((Object)(object)go != (Object)null) ? go.transform : null); while ((Object)(object)val != (Object)null) { if (individualObjects.ContainsKey(((Object)((Component)val).gameObject).GetInstanceID())) { return true; } val = val.parent; } return false; } public bool IsRootHidden(GameObject go) { Transform val = (((Object)(object)go != (Object)null) ? go.transform : null); while ((Object)(object)val != (Object)null) { if (hiddenRoots.Contains(((Object)((Component)val).gameObject).GetInstanceID())) { return true; } val = val.parent; } return false; } public void RestoreAll() { TerrainHidden = false; WaterHidden = false; CloudsHidden = false; MistHidden = false; PlayerHidden = false; hiddenCategories.Clear(); individualObjects.Clear(); revealedFrom = null; SetHud(hidden: false); Reconcile(); } public void HideAll() { TerrainHidden = true; WaterHidden = true; CloudsHidden = true; MistHidden = true; PlayerHidden = true; foreach (Category item in Categories.All) { hiddenCategories.Add(item.Key); } revealedFrom = null; SetHud(hidden: true); Reconcile(); } public void ToggleChecked() { bool[] array = CaptureOptions(); if (revealedFrom == null) { bool anyOptionChecked = AnyOptionChecked; revealedFrom = array; ApplyOptions(Filled(array, !anyOptionChecked)); return; } bool[] array2 = (bool[])revealedFrom.Clone(); for (int i = 0; i < array2.Length; i++) { array2[i] = array2[i] || array[i]; } revealedFrom = null; ApplyOptions(array2); } public bool[] CaptureOptions() { bool[] array = new bool[6 + Categories.BuiltIn.Length]; array[0] = TerrainHidden; array[1] = WaterHidden; array[2] = CloudsHidden; array[3] = MistHidden; array[4] = PlayerHidden; array[5] = HudHidden; for (int i = 0; i < Categories.BuiltIn.Length; i++) { array[6 + i] = IsCategoryHidden(Categories.BuiltIn[i].Key); } return array; } public void ApplyOptions(bool[] state) { TerrainHidden = state[0]; WaterHidden = state[1]; CloudsHidden = state[2]; MistHidden = state[3]; PlayerHidden = state[4]; if (HudHidden != state[5]) { HudHidden = state[5]; ApplyHud(); } for (int i = 0; i < Categories.BuiltIn.Length; i++) { string key = Categories.BuiltIn[i].Key; if (state[6 + i]) { hiddenCategories.Add(key); } else { hiddenCategories.Remove(key); } } Reconcile(); } private static bool[] Filled(bool[] from, bool value) { bool[] array = new bool[from.Length]; for (int i = 0; i < array.Length; i++) { array[i] = value; } return array; } public void Tick(float deltaTime) { ReconcileTiming.Tick(deltaTime); ApplyEnemyHud(); if (HudHidden) { ApplyHud(); } if (AnyActive) { refreshTimer += deltaTime; if (!(refreshTimer < UpdateInterval)) { refreshTimer = 0f; Reconcile(); } } } public void Reconcile() { ReconcileTiming.Begin(); passCounter++; HashSet<int> excluded = CollectWaterSurfaceIds(); Dictionary<int, Renderer> dictionary = new Dictionary<int, Renderer>(); Dictionary<int, InstanceRenderer> wantedInstances = new Dictionary<int, InstanceRenderer>(); HashSet<int> hashSet = new HashSet<int>(); if (TerrainHidden) { foreach (Heightmap item in CollectHeightmaps()) { AddRenderers(((Object)(object)item != (Object)null) ? ((Component)item).gameObject : null, dictionary, wantedInstances, excluded); } TerrainLod[] array = Object.FindObjectsByType<TerrainLod>((FindObjectsSortMode)0); foreach (TerrainLod val in array) { AddRenderers(((Object)(object)val != (Object)null) ? ((Component)val).gameObject : null, dictionary, wantedInstances, excluded); } ReconcileTiming.Mark("terrain"); } if (WaterHidden) { foreach (WaterVolume item2 in CollectWaterVolumes()) { if ((Object)(object)item2 != (Object)null && (Object)(object)item2.m_waterSurface != (Object)null) { dictionary[((Object)item2.m_waterSurface).GetInstanceID()] = (Renderer)(object)item2.m_waterSurface; } } foreach (GameObject item3 in CollectOceanRoots()) { AddRenderers(item3, dictionary, wantedInstances, excluded); } ReconcileTiming.Mark("water"); } if (CloudsHidden) { foreach (GameObject item4 in CollectCloudRoots()) { AddRenderers(item4, dictionary, wantedInstances, null); } EnvMan instance = EnvMan.instance; if ((Object)(object)instance != (Object)null) { AddWanted((Renderer)(object)instance.m_clouds, dictionary); AddWanted((Renderer)(object)instance.m_rainClouds, dictionary); AddWanted((Renderer)(object)instance.m_rainCloudsDownside, dictionary); } ReconcileTiming.Mark("clouds"); } if (MistHidden) { foreach (GameObject item5 in CollectMistRoots()) { AddRenderers(item5, dictionary, wantedInstances, null); } MistEmitter[] array2 = Object.FindObjectsByType<MistEmitter>((FindObjectsSortMode)0); foreach (MistEmitter val2 in array2) { AddRenderers(((Component)val2).gameObject, dictionary, wantedInstances, null); if ((Object)(object)val2.m_psystem != (Object)null) { AddWanted(((Component)val2.m_psystem).GetComponent<Renderer>(), dictionary); } } ParticleMist[] array3 = Object.FindObjectsByType<ParticleMist>((FindObjectsSortMode)0); foreach (ParticleMist val3 in array3) { AddRenderers(((Component)val3).gameObject, dictionary, wantedInstances, null); } ReconcileTiming.Mark("mist"); } if (PlayerHidden) { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null) { AddRenderers(((Component)localPlayer).gameObject, dictionary, wantedInstances, excluded, fresh: true); } ReconcileTiming.Mark("player"); } foreach (string hiddenCategory in hiddenCategories) { if (!Categories.TryGet(hiddenCategory, out var category)) { continue; } foreach (GameObject item6 in Categories.CollectRoots(category)) { if (!((Object)(object)item6 == (Object)null)) { hashSet.Add(((Object)item6).GetInstanceID()); AddRenderers(item6, dictionary, wantedInstances, excluded); } } } foreach (KeyValuePair<int, GameObject> individualObject in individualObjects) { GameObject value = individualObject.Value; if (!((Object)(object)value == (Object)null)) { hashSet.Add(individualObject.Key); AddRenderers(value, dictionary, wantedInstances, excluded); } } hiddenRoots.Clear(); hiddenRoots.UnionWith(hashSet); PurgeRendererCache(); ReconcileTiming.Mark("roots"); Apply(dictionary, wantedInstances); ApplyEnemyHud(); ApplyFog(); ReconcileTiming.Mark("apply"); } private void ApplyHud() { //IL_0064: 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) Hud instance = Hud.instance; GameObject val = (((Object)(object)instance != (Object)null) ? instance.m_rootObject : null); if ((Object)(object)val == (Object)null) { return; } if (HudHidden) { if (val.activeSelf) { val.SetActive(false); } KeepPauseMenuOnScreen(); return; } if (instance.m_userHidden) { instance.m_userHidden = false; } if (!val.activeSelf) { val.SetActive(true); } if (val.transform.localPosition.x >= 1000f) { val.transform.localPosition = Vector3.zero; } } private void ApplyEnemyHud() { bool flag = HudHidden || IsCategoryHidden("creatures"); CanvasGroup val = enemyHudGroup; if (!flag && (Object)(object)val == (Object)null) { return; } EnemyHud instance = EnemyHud.instance; GameObject val2 = (((Object)(object)instance != (Object)null) ? instance.m_hudRoot : null); if ((Object)(object)val2 == (Object)null) { return; } if ((Object)(object)val == (Object)null) { enemyHudGroup = null; } else if ((Object)(object)((Component)val).gameObject != (Object)(object)val2) { enemyHudGroup = null; val = null; } if (!flag) { if ((Object)(object)val != (Object)null) { val.alpha = enemyHudAlpha; val.blocksRaycasts = enemyHudRaycasts; enemyHudGroup = null; } return; } if ((Object)(object)val == (Object)null) { val = val2.GetComponent<CanvasGroup>(); if ((Object)(object)val == (Object)null) { enemyHudAlpha = 1f; enemyHudRaycasts = true; val = val2.AddComponent<CanvasGroup>(); } else { enemyHudAlpha = val.alpha; enemyHudRaycasts = val.blocksRaycasts; } enemyHudGroup = val; } if (val.alpha != 0f) { val.alpha = 0f; } if (val.blocksRaycasts) { val.blocksRaycasts = false; } } private static void KeepPauseMenuOnScreen() { //IL_0024: 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) Menu instance = Menu.instance; if (!((Object)(object)instance == (Object)null) && !((Object)(object)instance.m_root == (Object)null) && instance.m_root.localPosition.x >= 1000f) { instance.m_root.localPosition = Vector3.zero; } } private static IEnumerable<Heightmap> CollectHeightmaps() { List<IMonoUpdater> instances = Heightmap.Instances; if (instances != null && instances.Count > 0) { List<Heightmap> list = new List<Heightmap>(instances.Count); foreach (IMonoUpdater item in instances) { Heightmap val = (Heightmap)(object)((item is Heightmap) ? item : null); if ((Object)(object)val != (Object)null) { list.Add(val); } } if (list.Count > 0) { return list; } } return Object.FindObjectsByType<Heightmap>((FindObjectsSortMode)0); } private static IEnumerable<WaterVolume> CollectWaterVolumes() { List<WaterVolume> instances = WaterVolume.Instances; if (instances != null && instances.Count > 0) { return instances; } return Object.FindObjectsByType<WaterVolume>((FindObjectsSortMode)0); } private static HashSet<int> CollectWaterSurfaceIds() { HashSet<int> hashSet = new HashSet<int>(); foreach (WaterVolume item in CollectWaterVolumes()) { if ((Object)(object)item != (Object)null && (Object)(object)item.m_waterSurface != (Object)null) { hashSet.Add(((Object)item.m_waterSurface).GetInstanceID()); } } return hashSet; } priva