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 BuildMenu v0.3.13
plugins/BuildMenu.dll
Decompiled 2 days ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.Events; using UnityEngine.Rendering; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace BuildMenu { internal sealed class Sub { public string Key; public string Ru; public string En; public Group Group; public string Name(bool russian) { if (!russian) { return En; } return Ru; } } internal sealed class Group { public string Key; public string Ru; public string En; public readonly List<Sub> Subs = new List<Sub>(); public string Name(bool russian) { if (!russian) { return En; } return Ru; } } internal static class Catalog { public static readonly List<Group> Groups; private static readonly Dictionary<string, Sub> byKey; static Catalog() { Groups = new List<Group>(); byKey = new Dictionary<string, Sub>(StringComparer.OrdinalIgnoreCase); Add("crafting", "Ремесло", "Crafting", ("stations", "Верстаки и станции", "Workbenches and stations"), ("upgrades", "Улучшения станций", "Station upgrades"), ("smelting", "Плавильни и производство", "Smelters and production"), ("kitchen", "Кухня", "Kitchen")); Add("building", "Строительство", "Building", ("floor", "Полы", "Floors"), ("wall", "Стены", "Walls"), ("roof", "Крыши", "Roofs"), ("stairs", "Лестницы и пандусы", "Stairs and ramps"), ("beam", "Балки и столбы", "Beams and poles"), ("door", "Двери и ворота", "Doors and gates"), ("window", "Окна", "Windows"), ("arch", "Арки", "Arches"), ("fence", "Заборы", "Fences"), ("defense", "Оборона", "Defense"), ("other", "Прочее", "Other")); Add("interior", "Интерьер", "Interior", ("furniture", "Мебель", "Furniture"), ("light", "Освещение", "Lighting"), ("decor", "Декор", "Decoration")); Add("travel", "Перемещение", "Travel", ("transport", "Транспорт", "Transport"), ("portal", "Порталы", "Portals")); Add("storage", "Хранилище", "Storage", ("storage", "Хранилище", "Storage")); Add("misc", "Разное", "Miscellaneous", ("misc", "Разное", "Miscellaneous")); } private static void Add(string key, string ru, string en, params (string key, string ru, string en)[] subs) { Group obj = new Group { Key = key, Ru = ru, En = en }; for (int i = 0; i < subs.Length; i++) { (string, string, string) tuple = subs[i]; AddSub(obj, tuple.Item1, tuple.Item2, tuple.Item3); } Groups.Add(obj); } private static Sub AddSub(Group g, string key, string ru, string en) { Sub sub = new Sub { Key = key, Ru = ru, En = en, Group = g }; g.Subs.Add(sub); byKey[key] = sub; return sub; } public static Sub ToolSub(string key, string name) { Sub sub = Find(key); if (sub != null) { return sub; } Group obj = Groups.FirstOrDefault((Group x) => x.Key == "tools"); if (obj == null) { obj = new Group { Key = "tools", Ru = "Другие инструменты", En = "Other tools" }; Groups.Add(obj); } return AddSub(obj, key, name, name); } public static Sub Find(string key) { if (key == null || !byKey.TryGetValue(key, out var value)) { return null; } return value; } public static Sub FindOrCreate(string text) { text = text.Trim(); Sub sub = Find(text) ?? Groups.SelectMany((Group g) => g.Subs).FirstOrDefault((Sub s) => string.Equals(s.Ru, text, StringComparison.OrdinalIgnoreCase) || string.Equals(s.En, text, StringComparison.OrdinalIgnoreCase)); if (sub != null || text.Length == 0) { return sub; } string groupName = ""; string text2 = text; int num = text.IndexOf('/'); if (num > 0) { groupName = text.Substring(0, num).Trim(); text2 = text.Substring(num + 1).Trim(); } Group obj = ((groupName.Length == 0) ? Groups.First((Group g) => g.Key == "misc") : Groups.FirstOrDefault((Group g) => string.Equals(g.Key, groupName, StringComparison.OrdinalIgnoreCase) || string.Equals(g.Ru, groupName, StringComparison.OrdinalIgnoreCase) || string.Equals(g.En, groupName, StringComparison.OrdinalIgnoreCase))); if (obj == null) { obj = new Group { Key = groupName, Ru = groupName, En = groupName }; Groups.Add(obj); } return Find(text2) ?? AddSub(obj, text2, text2, text2); } private static bool Any(string words, params string[] parts) { return parts.Any(words.Contains); } public static List<string> Classify(PieceFacts f) { return new List<string> { One(f) }; } private static string One(PieceFacts f) { string words = f.Words; if (f.Has("TeleportWorld")) { return "portal"; } if ((!f.Has("Vagon") || !f.Tagged("Defense")) && (f.Has("Ship") || f.Has("Vagon") || f.Tagged("Transport"))) { return "transport"; } if (f.Has("Container") && !f.Has("Incinerator")) { return "storage"; } if (Any(words, "forge", "foundry") && f.Has("CookingStation")) { return "smelting"; } if (f.Has("CookingStation") || f.Has("Fermenter") || f.Tagged("Food") || f.Tagged("Meads") || f.Tagged("Feasts") || Any(words, "cauldron", "oven")) { return "kitchen"; } if (f.Has("StationExtension")) { return "upgrades"; } if (f.Has("CraftingStation")) { return "stations"; } if (!f.Tagged("Furniture") && (f.Has("Smelter") || f.Has("Beehive") || f.Has("SapCollector") || f.Has("Windmill") || f.Has("Incinerator") || f.Has("WispSpawner"))) { return "smelting"; } if (f.Tagged("Lighting") || f.Has("Fireplace") || f.Has("Demister")) { return "light"; } if (f.Tagged("Furniture") || f.Has("Bed") || f.Has("Chair") || f.Comfort.StartsWith("Bed") || f.Comfort.StartsWith("Chair") || f.Comfort.StartsWith("Table")) { return "furniture"; } bool flag = f.Tagged("Floor") || f.Tagged("Wall") || f.Tagged("Roof") || f.Tagged("Stairs") || f.Tagged("Doors") || f.Tagged("Architecture"); bool flag2 = f.Usage.Split('|').Any((string t) => t.Length > 0 && t != "Misc"); bool flag3 = flag || f.Category == "BuildingWorkbench" || f.Category == "BuildingStonecutter" || (!flag2 && Any(words, "floor", "wall", "roof", "beam", "pole", "stair", "door", "gate", "window", "fence")); if (!flag3 && (f.Tagged("Defense") || f.Has("Trap") || f.Has("Turret") || f.Has("ShieldGenerator") || f.Has("PrivateArea") || Any(words, "stake", "spike"))) { return "defense"; } bool flag4 = f.Tagged("Decor") || Starts(Names(f), "adornment", "ornament", "decoration", "украшен", "орнамент"); if ((flag3 && (!flag4 || flag)) || (f.Tagged("Building") && !flag4)) { return Kind(f, flag); } if (f.Tagged("Decor") || f.Tagged("Stacks") || f.Has("ItemStand") || f.Has("ArmorStand") || f.Has("Sign") || Any(f.Comfort, "Banner", "Carpet", "Display", "Decor", "Garland") || flag4) { return "decor"; } if (f.Tagged("Defense")) { return "defense"; } return "misc"; } private static string[] Names(PieceFacts f) { string text = f.NameEn + " " + f.NameRu; string text2 = ((f.NameEn.Length > 0) ? f.NameEn : f.NameRu); if (text2.Length == 0 || text2.StartsWith("[")) { text = text + " " + f.Prefab.Replace('_', ' '); } return text.ToLowerInvariant().Split(new char[14] { ' ', '-', '(', ')', '[', ']', '«', '»', '"', '\'', '°', ',', '.', '/' }, StringSplitOptions.RemoveEmptyEntries); } private static bool Starts(string[] words, params string[] stems) { return words.Any((string x) => stems.Any((string s) => x.StartsWith(s, StringComparison.Ordinal))); } private static bool Is(string[] words, params string[] whole) { return words.Any((string x) => whole.Contains(x)); } private static string Kind(PieceFacts f, bool shaped) { string[] words = Names(f); if (f.Tagged("Defense") || Starts(words, "stake", "spike", "drawbridge", "palisade", "частокол", "шип", "подъёмн", "подъемн")) { return "defense"; } if (Starts(words, "window", "shutter", "glass", "crystal", "окн", "окош", "ставн", "створк", "стекл", "хрустал", "кристал")) { return "window"; } if (f.Tagged("Doors") || f.Has("Door") || Starts(words, "door", "gate", "hatch", "trapdoor", "дверь", "двери", "дверн", "дверц", "дверей", "ворот", "люк", "калитк")) { return "door"; } if (f.Tagged("Stairs") || Starts(words, "stair", "staircase", "ladder", "ramp", "steps", "лестн", "ступен", "пандус", "трап", "стремянк")) { return "stairs"; } bool flag = Starts(words, "cross", "wall", "крест", "стен", "полустен"); if (f.Tagged("Roof") || (!shaped && !flag && Starts(words, "roof", "ridge", "shingle", "thatch", "крыш", "кровл", "конёк", "конек", "черепиц", "солом"))) { return "roof"; } if (Starts(words, "arch", "арк", "арочн")) { return "arch"; } if (Starts(words, "fence", "railing", "rail", "забор", "огражд", "ограда", "перил", "изгород")) { return "fence"; } if ((f.Tagged("Floor") && !f.Tagged("Wall")) || (!shaped && (Is(words, "пол", "пола", "полы") || Starts(words, "floor", "настил", "помост", "platform", "платформ")))) { return "floor"; } if (f.Tagged("Wall") || Starts(words, "wall", "divider", "panel", "block", "cube", "стен", "полустен", "перегород", "панел", "блок", "куб")) { return "wall"; } if (f.Tagged("Architecture") || Starts(words, "beam", "pole", "pillar", "column", "post", "cross", "spire", "log", "балк", "столб", "колонн", "брус", "опор", "крест", "стойк", "шпил", "бревн")) { return "beam"; } float num = Math.Max(f.SizeX, f.SizeZ); float num2 = Math.Min(f.SizeX, f.SizeZ); if (num > 0f && f.SizeY > 1.5f * num) { return "beam"; } if (f.SizeY > 0f && f.SizeY < 0.5f && num2 >= 0.9f) { return "floor"; } if (num2 > 0f && num2 < 0.6f && num >= 0.9f && f.SizeY >= 0.9f) { return "wall"; } return "other"; } } internal static class Cells { private sealed class Look { public Piece Piece; public TMP_Text Caption; public Transform Badge; public Image BadgeImage; public TMP_Text Letter; public RawImage Still; public bool Done; public int Frame; } private const float Pad = 4f; private const float Badge = 20f; private static readonly Dictionary<BuildUiPieceButton, Look> looks = new Dictionary<BuildUiPieceButton, Look>(); private static readonly List<BuildUiPieceButton> pending = new List<BuildUiPieceButton>(); internal static readonly Stopwatch SetupClock = new Stopwatch(); internal static readonly Stopwatch FillClock = new Stopwatch(); internal static int SetUp; internal static int Filled; private static readonly Color Selected = new Color(1f, 0.62f, 0.22f); private const double BudgetMs = 2.0; private const double FillBudgetMs = 1.5; private static readonly Stopwatch clock = new Stopwatch(); private static float nextScan; private static readonly Vector3[] corners = (Vector3[])(object)new Vector3[4]; internal static int Pending => pending.Count; internal static string Name(Piece piece) { Localization instance = Localization.instance; string name = piece.m_name; string text = instance.Localize(name); if (!text.StartsWith("[")) { return text; } int num = name.Length; while (num > 0 && char.IsDigit(name[num - 1])) { num--; } if (num < name.Length) { string text2 = name.Substring(0, num).TrimEnd('_'); string text3 = name.Substring(num); string[] array = new string[3] { "26", "45", "67" }; foreach (string text4 in array) { if (!(text4 != text3)) { continue; } string[] array2 = new string[2] { text2 + text4, text2 + "_" + text4 }; foreach (string text5 in array2) { string text6 = instance.Localize(text5); if (!text6.StartsWith("[") && text6.Contains(text4)) { return text6.Replace(text4, text3); } } } } string text7 = Utils.GetPrefabName(((Component)piece).gameObject).Replace('_', ' ').Trim(); if (text7.Length <= 0) { return text; } return char.ToUpperInvariant(text7[0]) + text7.Substring(1); } internal static void Decorate(BuildUiPieceButton button) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: 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_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: 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_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_0147: 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_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Unknown result type (might be due to invalid IL or missing references) Piece piece = button.Piece; if ((Object)(object)piece == (Object)null) { return; } SetupClock.Start(); try { float num = Plugin.CellSizes[Plugin.CellStep.Value]; RectTransform val = (RectTransform)((Component)button.m_icon).transform; if ((Object)(object)((Component)button).transform.parent == (Object)(object)Window.Ui?.m_specialButtonsContainer) { val.anchorMin = Vector2.zero; val.anchorMax = Vector2.one; val.pivot = new Vector2(0.5f, 0.5f); val.offsetMin = new Vector2(6f, 6f); val.offsetMax = new Vector2(-6f, -6f); return; } if ((Object)(object)((Transform)val).parent == (Object)(object)((Component)button).transform) { Vector2 anchorMin = (val.anchorMax = new Vector2(0.5f, 1f)); val.anchorMin = anchorMin; val.pivot = new Vector2(0.5f, 1f); val.sizeDelta = new Vector2(num - 8f, num - 8f); val.anchoredPosition = new Vector2(0f, -4f); } Button component = ((Component)button).GetComponent<Button>(); if ((Object)(object)component != (Object)null) { ColorBlock colors = ((Selectable)component).colors; if (((ColorBlock)(ref colors)).selectedColor != Selected) { ColorBlock colors2 = ((Selectable)component).colors; ((ColorBlock)(ref colors2)).highlightedColor = new Color(1f, 0.78f, 0.5f); ((ColorBlock)(ref colors2)).selectedColor = Selected; ((ColorBlock)(ref colors2)).pressedColor = new Color(1f, 0.55f, 0.15f); ((Selectable)component).colors = colors2; } } if (!looks.TryGetValue(button, out var value)) { value = (looks[button] = new Look()); } if ((Object)(object)value.Piece != (Object)(object)piece) { if ((Object)(object)value.Caption != (Object)null) { ((Component)value.Caption).gameObject.SetActive(false); } if ((Object)(object)value.Badge != (Object)null) { ((Component)value.Badge).gameObject.SetActive(false); } if ((Object)(object)value.Still != (Object)null) { value.Still.texture = null; Show(button, value.Still); } } value.Piece = piece; value.Done = false; value.Frame = Time.frameCount; if (!pending.Contains(button)) { pending.Add(button); } SetUp++; } finally { SetupClock.Stop(); } } private static void Fill(BuildUiPieceButton button, Look look) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_0200: Unknown result type (might be due to invalid IL or missing references) //IL_0207: Expected O, but got Unknown //IL_0221: Unknown result type (might be due to invalid IL or missing references) //IL_0226: Unknown result type (might be due to invalid IL or missing references) //IL_0227: Unknown result type (might be due to invalid IL or missing references) //IL_0228: Unknown result type (might be due to invalid IL or missing references) //IL_023a: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Unknown result type (might be due to invalid IL or missing references) //IL_0243: Unknown result type (might be due to invalid IL or missing references) //IL_0244: Unknown result type (might be due to invalid IL or missing references) //IL_024b: Unknown result type (might be due to invalid IL or missing references) //IL_0252: Unknown result type (might be due to invalid IL or missing references) //IL_025d: Unknown result type (might be due to invalid IL or missing references) //IL_0271: Unknown result type (might be due to invalid IL or missing references) //IL_02ba: Unknown result type (might be due to invalid IL or missing references) //IL_02e0: Unknown result type (might be due to invalid IL or missing references) //IL_02e5: Unknown result type (might be due to invalid IL or missing references) //IL_02e6: Unknown result type (might be due to invalid IL or missing references) //IL_02f0: Unknown result type (might be due to invalid IL or missing references) //IL_02f1: Unknown result type (might be due to invalid IL or missing references) //IL_02fb: Unknown result type (might be due to invalid IL or missing references) //IL_02fc: Unknown result type (might be due to invalid IL or missing references) //IL_0301: Unknown result type (might be due to invalid IL or missing references) //IL_0302: Unknown result type (might be due to invalid IL or missing references) //IL_0309: Unknown result type (might be due to invalid IL or missing references) //IL_037b: Unknown result type (might be due to invalid IL or missing references) //IL_0374: Unknown result type (might be due to invalid IL or missing references) //IL_04d8: Unknown result type (might be due to invalid IL or missing references) //IL_04dd: Unknown result type (might be due to invalid IL or missing references) //IL_04df: Unknown result type (might be due to invalid IL or missing references) //IL_04e9: 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: Unknown result type (might be due to invalid IL or missing references) //IL_04f7: Unknown result type (might be due to invalid IL or missing references) //IL_0501: Unknown result type (might be due to invalid IL or missing references) //IL_0503: Unknown result type (might be due to invalid IL or missing references) //IL_050e: Unknown result type (might be due to invalid IL or missing references) //IL_0483: Unknown result type (might be due to invalid IL or missing references) //IL_0488: Unknown result type (might be due to invalid IL or missing references) //IL_049a: Unknown result type (might be due to invalid IL or missing references) Piece piece = look.Piece; float num = Plugin.CellSizes[Plugin.CellStep.Value]; bool value = Plugin.Captions.Value; RectTransform val = (RectTransform)((Component)button.m_icon).transform; bool flag = piece.m_repairPiece || piece.m_removePiece; bool flag2 = value && !flag; TMP_Text val2 = look.Caption; if (flag2 && (Object)(object)val2 == (Object)null) { val2 = Window.Text(((Component)button).transform, "BuildMenu caption", 13f, (TextAlignmentOptions)258, new Color(0.93f, 0.9f, 0.84f)); val2.textWrappingMode = (TextWrappingModes)1; val2.overflowMode = (TextOverflowModes)1; val2.lineSpacing = -18f; RectTransform val3 = (RectTransform)val2.transform; val3.anchorMin = new Vector2(0f, 0f); val3.anchorMax = new Vector2(1f, 0f); val3.pivot = new Vector2(0.5f, 0f); val3.sizeDelta = new Vector2(-4f, 32f); val3.anchoredPosition = new Vector2(0f, 2f); look.Caption = val2; } if ((Object)(object)val2 != (Object)null) { if (flag2) { float num2 = ((num >= 84f) ? 14f : 12.5f); if (val2.fontSize != num2) { val2.fontSize = num2; } string text = Name(piece); if (val2.text != text) { val2.text = text; } } if (((Component)val2).gameObject.activeSelf != flag2) { ((Component)val2).gameObject.SetActive(flag2); } } Sub sub = (flag ? null : Sorting.Main(piece)); bool flag3 = Plugin.Badges.Value && sub != null; if (flag3 && (Object)(object)look.Badge == (Object)null) { GameObject val4 = new GameObject("BuildMenu badge", new Type[1] { typeof(RectTransform) }); val4.transform.SetParent(((Component)button).transform, false); RectTransform val5 = (RectTransform)val4.transform; Vector2 val6 = default(Vector2); ((Vector2)(ref val6))..ctor(0f, 1f); val5.pivot = val6; Vector2 anchorMin = (val5.anchorMax = val6); val5.anchorMin = anchorMin; val5.anchoredPosition = new Vector2(3f, -3f); val5.sizeDelta = new Vector2(20f, 20f); look.BadgeImage = val4.AddComponent<Image>(); ((Graphic)look.BadgeImage).raycastTarget = false; look.Letter = Window.Text(val4.transform, "letter", 13f, (TextAlignmentOptions)514, new Color(1f, 0.85f, 0.55f)); look.Letter.fontStyle = (FontStyles)1; RectTransform val8 = (RectTransform)look.Letter.transform; val8.anchorMin = Vector2.zero; val8.anchorMax = Vector2.one; anchorMin = (val8.offsetMax = Vector2.zero); val8.offsetMin = anchorMin; look.Badge = val4.transform; } if ((Object)(object)look.Badge != (Object)null) { if (flag3) { Sprite val9 = Icons.For(sub.Key); look.BadgeImage.sprite = val9; ((Graphic)look.BadgeImage).color = (Color)(((Object)(object)val9 != (Object)null) ? Color.white : new Color(0f, 0f, 0f, 0.55f)); bool flag4 = (Object)(object)val9 == (Object)null; if (((Component)look.Letter).gameObject.activeSelf != flag4) { ((Component)look.Letter).gameObject.SetActive(flag4); } if (flag4) { string text2 = sub.Name(Plugin.Russian).Substring(0, 1).ToUpperInvariant(); if (look.Letter.text != text2) { look.Letter.text = text2; } } if (look.Badge.GetSiblingIndex() != ((Component)button).transform.childCount - 1) { look.Badge.SetAsLastSibling(); } } if (((Component)look.Badge).gameObject.activeSelf != flag3) { ((Component)look.Badge).gameObject.SetActive(flag3); } } RawImage val10 = look.Still; bool flag5 = Plugin.GridModels.Value && sub != null; if (flag5 && (Object)(object)val10 == (Object)null) { GameObject val11 = new GameObject("BuildMenu still", new Type[1] { typeof(RectTransform) }); val11.transform.SetParent(((Component)button).transform, false); val10 = val11.AddComponent<RawImage>(); ((Graphic)val10).raycastTarget = false; val11.transform.SetSiblingIndex(((Transform)val).GetSiblingIndex() + 1); look.Still = val10; } if ((Object)(object)val10 != (Object)null) { RectTransform val12 = (RectTransform)((Component)val10).transform; val12.anchorMin = val.anchorMin; val12.anchorMax = val.anchorMax; val12.pivot = val.pivot; val12.sizeDelta = val.sizeDelta; val12.anchoredPosition = val.anchoredPosition; if (((Component)val10).gameObject.activeSelf != flag5) { ((Component)val10).gameObject.SetActive(flag5); } val10.texture = (flag5 ? Preview.Cached(piece) : null); nextScan = 0f; } Show(button, val10); look.Done = true; Filled++; } private static void Show(BuildUiPieceButton button, RawImage still) { bool flag = (Object)(object)still != (Object)null && ((Component)still).gameObject.activeSelf && (Object)(object)still.texture != (Object)null; if ((Object)(object)still != (Object)null) { ((Behaviour)still).enabled = flag; } ((Behaviour)button.m_icon).enabled = !flag; } internal static void Update(List<BuildUiPieceButton> buttons, RectTransform viewport) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Expected O, but got Unknown //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) if (pending.Count > 0) { FillPending(viewport); } if (!Plugin.GridModels.Value || Time.unscaledTime < nextScan) { return; } Rect val = WorldRect(viewport); bool flag = false; int num = 0; clock.Restart(); foreach (BuildUiPieceButton button in buttons) { if ((Object)(object)button == (Object)null || (Object)(object)button.Piece == (Object)null || !((Component)button).gameObject.activeInHierarchy || !looks.TryGetValue(button, out var value) || !value.Done) { continue; } RawImage still = value.Still; if ((Object)(object)still == (Object)null || !((Component)still).gameObject.activeSelf) { continue; } if ((Object)(object)still.texture == (Object)null && ((Rect)(ref val)).Overlaps(WorldRect((RectTransform)((Component)button).transform))) { if (num == 0 || clock.Elapsed.TotalMilliseconds < 2.0) { still.texture = Preview.Still(button.Piece, 128); num++; } else { flag = true; } } Show(button, still); ((Graphic)still).color = (Color)((((Graphic)button.m_icon).color == Color.white) ? Color.white : new Color(0.7f, 0.7f, 0.7f, 0.8f)); } nextScan = Time.unscaledTime + (flag ? 0f : 0.15f); } private static void FillPending(RectTransform viewport) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Expected O, but got Unknown //IL_0095: Unknown result type (might be due to invalid IL or missing references) FillClock.Start(); try { int frameCount = Time.frameCount; Rect val = WorldRect(viewport); for (int num = pending.Count - 1; num >= 0; num--) { BuildUiPieceButton val2 = pending[num]; if ((Object)(object)val2 == (Object)null || !looks.TryGetValue(val2, out var value) || value.Done || (Object)(object)val2.Piece == (Object)null) { pending.RemoveAt(num); } else if (value.Frame < frameCount && ((Component)val2).gameObject.activeInHierarchy && ((Rect)(ref val)).Overlaps(WorldRect((RectTransform)((Component)val2).transform))) { Fill(val2, value); pending.RemoveAt(num); } } clock.Restart(); int num2 = pending.Count - 1; while (num2 >= 0 && clock.Elapsed.TotalMilliseconds < 1.5) { BuildUiPieceButton val3 = pending[num2]; if ((Object)(object)val3 == (Object)null || !looks.TryGetValue(val3, out var value2) || value2.Done || (Object)(object)val3.Piece == (Object)null) { pending.RemoveAt(num2); } else if (value2.Frame < frameCount) { Fill(val3, value2); pending.RemoveAt(num2); } num2--; } } finally { FillClock.Stop(); } } private static Rect WorldRect(RectTransform rt) { //IL_004b: Unknown result type (might be due to invalid IL or missing references) rt.GetWorldCorners(corners); return Rect.MinMaxRect(corners[0].x, corners[0].y, corners[2].x, corners[2].y); } } [HarmonyPatch(typeof(BuildUiPieceButton), "Setup")] internal static class CellHook { private static void Postfix(BuildUiPieceButton __instance) { if (!Plugin.Enabled.Value) { return; } try { Cells.Decorate(__instance); } catch (Exception ex) { Plugin.Warn("cell: " + ex.Message); } } } internal sealed class PieceFacts { public string Tool = ""; public string Prefab = ""; public string Token = ""; public string NameRu = ""; public string NameEn = ""; public string Category = ""; public string Usage = ""; public string Station = ""; public string Material = ""; public string Comfort = ""; public string Components = ""; public string Resources = ""; public int CategoryId; public float SizeX; public float SizeY; public float SizeZ; public float SnapX; public float SnapY; public float SnapZ; public int Snaps; public bool Ground; public bool Water; public bool Upgrade; public bool Enabled = true; private HashSet<string> components; private HashSet<string> tags; private string words; private static readonly string[] Columns = new string[20] { "tool", "prefab", "token", "name_ru", "name_en", "category", "category_id", "usage", "station", "material", "comfort", "components", "resources", "size", "snaps", "snap_spread", "ground", "water", "upgrade", "enabled" }; public string Words => words ?? (words = (Prefab + " " + NameEn + " " + NameRu).ToLowerInvariant()); public static string Header => string.Join("\t", Columns); public bool Has(string component) { return (components ?? (components = Split(Components))).Contains(component); } public bool Tagged(string tag) { return (tags ?? (tags = Split(Usage))).Contains(tag); } private static HashSet<string> Split(string s) { return new HashSet<string>(s.Split(new char[2] { '|', ' ' }, StringSplitOptions.RemoveEmptyEntries)); } private static string F(float v) { return v.ToString("0.##", CultureInfo.InvariantCulture); } private static string V(float x, float y, float z) { return F(x) + " " + F(y) + " " + F(z); } private static string Clean(string s) { return (s ?? "").Replace('\t', ' ').Replace('\n', ' ').Replace('\r', ' '); } public string ToTsv() { return string.Join("\t", new string[20] { Tool, Prefab, Token, NameRu, NameEn, Category, CategoryId.ToString(), Usage, Station, Material, Comfort, Components, Resources, V(SizeX, SizeY, SizeZ), Snaps.ToString(), V(SnapX, SnapY, SnapZ), Ground ? "1" : "0", Water ? "1" : "0", Upgrade ? "1" : "0", Enabled ? "1" : "0" }.Select(Clean)); } public static PieceFacts FromTsv(string line, string header) { string[] names = header.Split('\t'); string[] cells = line.Split('\t'); float[] array = Vec("size"); float[] array2 = Vec("snap_spread"); int.TryParse(Cell("category_id"), out var result); int.TryParse(Cell("snaps"), out var result2); return new PieceFacts { Tool = Cell("tool"), Prefab = Cell("prefab"), Token = Cell("token"), NameRu = Cell("name_ru"), NameEn = Cell("name_en"), Category = Cell("category"), CategoryId = result, Usage = Cell("usage"), Station = Cell("station"), Material = Cell("material"), Comfort = Cell("comfort"), Components = Cell("components"), Resources = Cell("resources"), SizeX = array[0], SizeY = array[1], SizeZ = array[2], Snaps = result2, SnapX = array2[0], SnapY = array2[1], SnapZ = array2[2], Ground = (Cell("ground") == "1"), Water = (Cell("water") == "1"), Upgrade = (Cell("upgrade") == "1"), Enabled = (Cell("enabled") != "0") }; string Cell(string name) { int num = Array.IndexOf(names, name); if (num < 0 || num >= cells.Length) { return ""; } return cells[num]; } float[] Vec(string name) { string[] array3 = Cell(name).Split(' '); float[] array4 = new float[3]; for (int i = 0; i < 3 && i < array3.Length; i++) { float.TryParse(array3[i], NumberStyles.Float, CultureInfo.InvariantCulture, out array4[i]); } return array4; } } } internal static class FactsReader { private static readonly HashSet<string> Noise = new HashSet<string> { "Piece", "ZNetView", "WearNTear", "ZSyncTransform", "ZSyncAnimation", "LightFlicker", "LightLod", "StaticTarget", "TerrainModifier", "EffectFade", "SnapToGround", "LodFadeInOut", "TimedDestruction", "InstanceRenderer", "Odin", "PieceBuildable" }; public static PieceFacts Read(Piece piece, string tool, Func<string, string> localize) { //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Expected I4, but got Unknown //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_02d2: Unknown result type (might be due to invalid IL or missing references) //IL_02d7: Unknown result type (might be due to invalid IL or missing references) //IL_03f2: Unknown result type (might be due to invalid IL or missing references) //IL_03f7: Unknown result type (might be due to invalid IL or missing references) //IL_03fb: Unknown result type (might be due to invalid IL or missing references) //IL_040d: Unknown result type (might be due to invalid IL or missing references) //IL_0412: Unknown result type (might be due to invalid IL or missing references) //IL_0416: Unknown result type (might be due to invalid IL or missing references) //IL_0428: Unknown result type (might be due to invalid IL or missing references) //IL_042d: Unknown result type (might be due to invalid IL or missing references) //IL_0431: Unknown result type (might be due to invalid IL or missing references) //IL_0321: Unknown result type (might be due to invalid IL or missing references) //IL_032a: Unknown result type (might be due to invalid IL or missing references) //IL_032f: Unknown result type (might be due to invalid IL or missing references) //IL_0334: Unknown result type (might be due to invalid IL or missing references) //IL_0338: Unknown result type (might be due to invalid IL or missing references) //IL_033d: Unknown result type (might be due to invalid IL or missing references) //IL_034b: Unknown result type (might be due to invalid IL or missing references) //IL_0352: Unknown result type (might be due to invalid IL or missing references) //IL_047f: Unknown result type (might be due to invalid IL or missing references) //IL_0484: Unknown result type (might be due to invalid IL or missing references) //IL_0378: Unknown result type (might be due to invalid IL or missing references) //IL_037d: Unknown result type (might be due to invalid IL or missing references) //IL_0382: Unknown result type (might be due to invalid IL or missing references) //IL_0387: Unknown result type (might be due to invalid IL or missing references) //IL_038c: Unknown result type (might be due to invalid IL or missing references) //IL_03ae: Unknown result type (might be due to invalid IL or missing references) //IL_03b3: Unknown result type (might be due to invalid IL or missing references) //IL_03b7: Unknown result type (might be due to invalid IL or missing references) //IL_03c0: Unknown result type (might be due to invalid IL or missing references) //IL_0399: Unknown result type (might be due to invalid IL or missing references) //IL_039b: Unknown result type (might be due to invalid IL or missing references) //IL_03a0: Unknown result type (might be due to invalid IL or missing references) GameObject gameObject = ((Component)piece).gameObject; PieceFacts pieceFacts = new PieceFacts { Tool = tool, Prefab = ((Object)gameObject).name, Token = piece.m_name, NameRu = localize(piece.m_name), CategoryId = (int)piece.m_category, Category = ((object)Unsafe.As<PieceCategory, PieceCategory>(ref piece.m_category)/*cast due to .constrained prefix*/).ToString(), Usage = string.Join("|", from UsageTagFlags t in Enum.GetValues(typeof(UsageTagFlags)) where (piece.m_usage & t) > 0 select t), Station = (((Object)(object)piece.m_craftingStation != (Object)null) ? localize(piece.m_craftingStation.m_name) : ""), Comfort = (((int)piece.m_comfortGroup != 0 || piece.m_comfort > 0) ? $"{piece.m_comfortGroup} {piece.m_comfort}" : ""), Resources = string.Join(", ", from r in piece.m_resources where (Object)(object)r.m_resItem != (Object)null select $"{localize(r.m_resItem.m_itemData.m_shared.m_name)}×{r.m_amount}"), Ground = (piece.m_groundPiece || piece.m_groundOnly), Water = piece.m_waterPiece, Upgrade = piece.m_isUpgrade, Enabled = piece.m_enabled }; WearNTear component = gameObject.GetComponent<WearNTear>(); if ((Object)(object)component != (Object)null) { pieceFacts.Material = ((object)Unsafe.As<MaterialType, MaterialType>(ref component.m_materialType)/*cast due to .constrained prefix*/).ToString(); } pieceFacts.Components = string.Join("|", from n in (from c in gameObject.GetComponentsInChildren<MonoBehaviour>(true) where (Object)(object)c != (Object)null select ((object)c).GetType().Name into n where !Noise.Contains(n) select n).Distinct() orderby n select n); Matrix4x4 worldToLocalMatrix = gameObject.transform.worldToLocalMatrix; Bounds? val = null; MeshFilter[] componentsInChildren = gameObject.GetComponentsInChildren<MeshFilter>(true); foreach (MeshFilter val2 in componentsInChildren) { Mesh sharedMesh = val2.sharedMesh; if ((Object)(object)sharedMesh == (Object)null || (Object)(object)((Component)val2).GetComponent<MeshRenderer>() == (Object)null) { continue; } Matrix4x4 val3 = worldToLocalMatrix * ((Component)val2).transform.localToWorldMatrix; Bounds bounds = sharedMesh.bounds; for (int num2 = 0; num2 < 8; num2++) { Vector3 val4 = ((Matrix4x4)(ref val3)).MultiplyPoint3x4(((Bounds)(ref bounds)).center + Vector3.Scale(((Bounds)(ref bounds)).extents, new Vector3((float)(((num2 & 1) != 0) ? 1 : (-1)), (float)(((num2 & 2) != 0) ? 1 : (-1)), (float)(((num2 & 4) != 0) ? 1 : (-1))))); if (!val.HasValue) { val = new Bounds(val4, Vector3.zero); continue; } Bounds value = val.Value; ((Bounds)(ref value)).Encapsulate(val4); val = value; } } if (val.HasValue) { Bounds value2 = val.Value; pieceFacts.SizeX = ((Bounds)(ref value2)).size.x; value2 = val.Value; pieceFacts.SizeY = ((Bounds)(ref value2)).size.y; value2 = val.Value; pieceFacts.SizeZ = ((Bounds)(ref value2)).size.z; } List<Vector3> list = new List<Vector3>(); Transform[] componentsInChildren2 = gameObject.GetComponentsInChildren<Transform>(true); foreach (Transform val5 in componentsInChildren2) { if ((Object)(object)val5 != (Object)(object)gameObject.transform && ((Component)val5).CompareTag("snappoint")) { list.Add(((Matrix4x4)(ref worldToLocalMatrix)).MultiplyPoint3x4(val5.position)); } } pieceFacts.Snaps = list.Count; if (list.Count > 0) { pieceFacts.SnapX = list.Max((Vector3 p) => p.x) - list.Min((Vector3 p) => p.x); pieceFacts.SnapY = list.Max((Vector3 p) => p.y) - list.Min((Vector3 p) => p.y); pieceFacts.SnapZ = list.Max((Vector3 p) => p.z) - list.Min((Vector3 p) => p.z); } return pieceFacts; } } internal static class Glyphs { private static Sprite magnifier; private static Sprite clock; public static Sprite Magnifier() { return magnifier ?? (magnifier = Draw("magnifier", delegate(int x, int y) { float num = Dist(x, y, 13f, 19f); bool num2 = num >= 7.5f && num <= 11f; float num3 = Mathf.Clamp01(((float)(x - 20) * 1f + (float)(12 - y) * 1f) / 2f / 8f); float cx = 20f + num3 * 8f; float cy = 12f - num3 * 8f; bool flag = Dist(x, y, cx, cy) <= 2.6f && x >= 19; return num2 || flag; })); } public static Sprite Clock() { return clock ?? (clock = Draw("clock", delegate(int x, int y) { float num = Dist(x, y, 16f, 16f); bool num2 = num >= 11f && num <= 14f; bool flag = (float)Math.Abs(x - 16) <= 1.4f && y >= 16 && y <= 24; bool flag2 = (float)Math.Abs(y - 16) <= 1.4f && x >= 16 && x <= 23; return num2 || flag || flag2; })); } private static float Dist(float x, float y, float cx, float cy) { return Mathf.Sqrt((x - cx) * (x - cx) + (y - cy) * (y - cy)); } private static Sprite Draw(string name, Func<int, int, bool> on) { //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_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) Texture2D val = new Texture2D(32, 32, (TextureFormat)4, false) { filterMode = (FilterMode)1, wrapMode = (TextureWrapMode)1, name = "BuildMenu " + name }; Color32[] array = (Color32[])(object)new Color32[1024]; for (int i = 0; i < 32; i++) { for (int j = 0; j < 32; j++) { array[i * 32 + j] = (on(j, i) ? new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue) : new Color32((byte)0, (byte)0, (byte)0, (byte)0)); } } val.SetPixels32(array); val.Apply(); Sprite obj = Sprite.Create(val, new Rect(0f, 0f, 32f, 32f), new Vector2(0.5f, 0.5f), 100f); ((Object)obj).name = name; return obj; } } internal static class Ground { private static PieceTable table; private static bool ground; internal static bool InHand() { Player localPlayer = Player.m_localPlayer; PieceTable val = (((Object)(object)localPlayer != (Object)null) ? localPlayer.m_buildPieces : null); if ((Object)(object)val == (Object)null) { return false; } if ((Object)(object)val == (Object)(object)table) { return ground; } table = val; int num = 0; int num2 = 0; foreach (GameObject piece in val.m_pieces) { if (!((Object)(object)piece == (Object)null)) { num++; if ((Object)(object)piece.GetComponent<TerrainOp>() != (Object)null || (Object)(object)piece.GetComponent<TerrainModifier>() != (Object)null || (Object)(object)piece.GetComponent<Plant>() != (Object)null) { num2++; } } } ground = num > 0 && num2 * 2 >= num; return ground; } } [HarmonyPatch(typeof(BuildUi), "Awake")] internal static class TreeTab { private static void Postfix(BuildUi __instance) { try { if (Plugin.Enabled.Value && __instance.m_pieceLists.Count != 0) { __instance.m_pieceLists[0] = (IPieceList)(object)new TreeList(__instance.m_pieceLists[0].DisplayName); Window.Attach(__instance); } } catch (Exception ex) { Plugin.Warn("build window: " + ex); } } } [HarmonyPatch(typeof(BuildUi), "OpenBuildMenu")] internal static class OpenTiming { private static readonly Stopwatch clock = new Stopwatch(); internal static int Buttons; private static void Prefix() { if (Plugin.Enabled.Value) { Cells.SetupClock.Reset(); Cells.FillClock.Reset(); Cells.SetUp = 0; Cells.Filled = 0; Tags.Clock.Reset(); TreeList.Clock.Reset(); Sorting.Read = 0; clock.Restart(); } } private static void Postfix(BuildUi __instance) { if (Plugin.Enabled.Value) { clock.Stop(); Buttons = __instance.m_pieceButtons.Count; Window.Opened(clock.Elapsed.TotalMilliseconds, $"{Buttons} cells ({Cells.SetUp} set up, {Cells.SetupClock.Elapsed.TotalMilliseconds:0} ms), tags {Tags.Clock.Elapsed.TotalMilliseconds:0} ms, " + $"tree {TreeList.Clock.Elapsed.TotalMilliseconds:0} ms ({Sorting.Read} pieces read)"); } } } [HarmonyPatch(typeof(BuildUi), "UpdateTagButtons")] internal static class ShowAllCount { private static void Postfix(BuildUi __instance) { if (!Plugin.Enabled.Value) { return; } try { Tags.Decorate(__instance.m_showAllTagsButton); } catch (Exception ex) { Plugin.Warn("show all: " + ex.Message); } } } [HarmonyPatch(typeof(BuildUi), "UpdatePieceButtons")] internal static class GridWidth { private static void Postfix() { if (Plugin.Enabled.Value) { Window.ApplyGrid(); } } } [HarmonyPatch(typeof(BuildUi), "UpdateSearch")] internal static class MaterialFilter { private static void Postfix(BuildUi __instance) { if (!Plugin.Enabled.Value || !Materials.Active) { return; } bool flag = false; foreach (BuildUiPieceButton pieceButton in __instance.m_pieceButtons) { if ((Object)(object)pieceButton != (Object)null && ((Component)pieceButton).gameObject.activeSelf && !Materials.Pass(pieceButton.Piece)) { ((Component)pieceButton).gameObject.SetActive(false); flag = true; } } if (flag) { __instance.ConfigureButtonNavigation(); } } } [HarmonyPatch(typeof(BuildUi), "SelectPieceList")] internal static class TabTip { private static void Postfix() { Window.HideTip(); } } [HarmonyPatch(typeof(BuildUi), "OnSelectTag")] internal static class GroupToggle { private static bool rebuilding; private static void Prefix(BuildUi __instance, int tagId) { if (rebuilding || !(__instance.m_pieceLists[__instance.m_currentPieceList] is TreeList) || !TreeList.IsGroup(tagId)) { return; } Group obj = TreeList.GroupOf(tagId); if (obj != null) { if (__instance.m_currentTagId == tagId && TreeList.Open.Contains(obj.Key)) { TreeList.Open.Remove(obj.Key); return; } TreeList.Open.Clear(); TreeList.Open.Add(obj.Key); } } private static void Postfix(BuildUi __instance, int tagId) { if (!rebuilding) { Window.HideTip(); } if (rebuilding || !(__instance.m_pieceLists[__instance.m_currentPieceList] is TreeList) || !TreeList.IsGroup(tagId)) { return; } rebuilding = true; try { __instance.UpdateTagButtons(true); } finally { rebuilding = false; } } } internal static class Icons { private static readonly Dictionary<string, Sprite> cache = new Dictionary<string, Sprite>(StringComparer.OrdinalIgnoreCase); private static readonly Dictionary<string, string> Samples = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase) { { "crafting", "piece_workbench" }, { "stations", "piece_workbench" }, { "upgrades", "forge_ext1" }, { "smelting", "smelter" }, { "kitchen", "piece_cauldron" }, { "building", "woodwall" }, { "floor", "wood_floor" }, { "wall", "woodwall" }, { "roof", "wood_roof" }, { "stairs", "wood_stair" }, { "beam", "wood_beam" }, { "door", "wood_door" }, { "window", "wood_window" }, { "arch", "stone_arch" }, { "fence", "wood_fence" }, { "defense", "piece_sharpstakes" }, { "other", "blackmarble_tip" }, { "interior", "piece_chair02" }, { "furniture", "piece_chair02" }, { "light", "piece_groundtorch_wood" }, { "decor", "piece_banner01" }, { "travel", "Karve" }, { "transport", "Cart" }, { "portal", "portal_wood" }, { "storage", "piece_chest_wood" }, { "misc", "piece_ArcheryTarget" } }; private static IEnumerable<string> Folders() { yield return Path.Combine(Plugin.Folder, "icons"); yield return Path.Combine(Path.Combine(Plugin.Folder, "BuildMenu"), "icons"); } public static Sprite Get(string key) { //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Expected O, but got Unknown //IL_00a2: 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) if (string.IsNullOrEmpty(key)) { return null; } if (cache.TryGetValue(key, out var value)) { return value; } value = null; foreach (string item in Folders()) { string text = Path.Combine(item, key + ".png"); if (!File.Exists(text)) { continue; } try { Texture2D val = new Texture2D(2, 2, (TextureFormat)4, true) { name = "BuildMenu icon " + key }; if (!ImageConversion.LoadImage(val, File.ReadAllBytes(text))) { continue; } ((Texture)val).wrapMode = (TextureWrapMode)1; ((Texture)val).filterMode = (FilterMode)2; value = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f); break; } catch (Exception ex) { Plugin.Warn("icon " + text + ": " + ex.Message); } } cache[key] = value; return value; } public static void Reload() { cache.Clear(); } public static Sprite For(string key) { Sprite val = Get(key); if ((Object)(object)val == (Object)null && key != null && key.StartsWith("tool_")) { return Merge.ToolIcon(key); } if ((Object)(object)val == (Object)null && key == "tools") { return Merge.ToolIcon("tool_Hammer"); } if ((Object)(object)val != (Object)null || key == null || !Samples.TryGetValue(key, out var value) || (Object)(object)ZNetScene.instance == (Object)null) { return val; } GameObject prefab = ZNetScene.instance.GetPrefab(value); Piece val2 = ((prefab != null) ? prefab.GetComponent<Piece>() : null); if (!((Object)(object)val2 != (Object)null)) { return null; } return val2.m_icon; } } internal static class Materials { public enum Family { None, Wood, Stone, Metal } public static Family ChosenFamily; public static string ChosenItem; private static readonly Dictionary<string, (string item, Family family)> cache = new Dictionary<string, (string, Family)>(); public static bool Active { get { if (ChosenFamily == Family.None) { return ChosenItem != null; } return true; } } public static event Action Changed; public static string MainItem(Piece piece) { return Info(piece).item; } public static Family FamilyOf(Piece piece) { return Info(piece).family; } private static (string item, Family family) Info(Piece piece) { //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Expected I4, but got Unknown string name = ((Object)((Component)piece).gameObject).name; if (cache.TryGetValue(name, out (string, Family) value)) { return value; } Requirement val = null; Requirement[] resources = piece.m_resources; foreach (Requirement val2 in resources) { if (val2 != null && (Object)(object)val2.m_resItem != (Object)null && (val == null || val2.m_amount > val.m_amount)) { val = val2; } } string text = ((val != null) ? ((Object)((Component)val.m_resItem).gameObject).name : null); Family family = ByName(text); if (family == Family.None) { WearNTear component = ((Component)piece).GetComponent<WearNTear>(); if ((Object)(object)component != (Object)null) { MaterialType materialType = component.m_materialType; switch ((int)materialType) { case 0: case 3: case 8: family = Family.Wood; break; case 1: case 4: case 5: family = Family.Stone; break; case 2: family = Family.Metal; break; } } } return cache[name] = (text, family); } private static Family ByName(string item) { if (item == null) { return Family.None; } string w = item.ToLowerInvariant(); if (Any(new string[5] { "wood", "log", "bark", "timber", "plank" })) { return Family.Wood; } if (Any(new string[6] { "stone", "marble", "grausten", "flint", "obsidian", "crystal" })) { return Family.Stone; } if (Any(new string[9] { "copper", "bronze", "iron", "silver", "metal", "tin", "flametal", "nail", "chain" })) { return Family.Metal; } return Family.None; bool Any(params string[] parts) { return parts.Any(w.Contains); } } public static bool Pass(Piece piece) { if ((Object)(object)piece == (Object)null || piece.m_repairPiece || piece.m_removePiece || !Active) { return true; } if (ChosenItem != null) { return MainItem(piece) == ChosenItem; } return FamilyOf(piece) == ChosenFamily; } public static void Choose(Family family) { ChosenFamily = ((ChosenFamily != family || ChosenItem != null) ? family : Family.None); ChosenItem = null; Materials.Changed?.Invoke(); } public static void Choose(string item) { ChosenItem = ((ChosenItem == item) ? null : item); ChosenFamily = Family.None; Materials.Changed?.Invoke(); } public static List<(string item, Sprite icon, string name, int count)> InUse(PieceTable table) { List<(string, Sprite, string, int)> list = new List<(string, Sprite, string, int)>(); if ((Object)(object)table == (Object)null || (Object)(object)ObjectDB.instance == (Object)null) { return list; } foreach (IGrouping<string, Piece> item in from g in table.m_availablePieces.Where((Piece p) => (Object)(object)p != (Object)null && !p.m_repairPiece && !p.m_removePiece).GroupBy(MainItem) where g.Key != null orderby g.Count() descending select g) { GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(item.Key); ItemDrop val = ((itemPrefab != null) ? itemPrefab.GetComponent<ItemDrop>() : null); if (!((Object)(object)val == (Object)null)) { list.Add((item.Key, val.m_itemData.GetIcon(), Localization.instance.Localize(val.m_itemData.m_shared.m_name), item.Count())); } } return list; } public static Sprite Icon(Family family) { string text = family switch { Family.Stone => "Stone", Family.Wood => "Wood", _ => "Iron", }; object obj; if (!((Object)(object)ObjectDB.instance != (Object)null)) { obj = null; } else { GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(text); obj = ((itemPrefab != null) ? itemPrefab.GetComponent<ItemDrop>() : null); } ItemDrop val = (ItemDrop)obj; if (!((Object)(object)val != (Object)null)) { return null; } return val.m_itemData.GetIcon(); } public static string Name(Family family) { return family switch { Family.Wood => Plugin.T("Дерево: всё из дерева", "Wood: everything of wood"), Family.Stone => Plugin.T("Камень: всё из камня", "Stone: everything of stone"), Family.Metal => Plugin.T("Металл: всё из металлов", "Metal: everything of metal"), _ => "", }; } } internal static class Merge { private sealed class Tool { public string Prefab; public string Name; public string Mod; public PieceTable Table; public ConfigEntry<bool> On; public Sub Sub; public readonly List<GameObject> Added = new List<GameObject>(); } private static readonly HashSet<string> Vanilla = new HashSet<string> { "Hammer", "Hoe", "Cultivator", "Feaster" }; private static readonly Dictionary<string, Tool> tools = new Dictionary<string, Tool>(); private static readonly Dictionary<string, Tool> sourceOf = new Dictionary<string, Tool>(); private static PieceTable hammer; private static bool dirty = true; public static void Apply() { ObjectDB instance = ObjectDB.instance; if ((Object)(object)instance == (Object)null) { return; } GameObject itemPrefab = instance.GetItemPrefab("Hammer"); PieceTable val = ((itemPrefab == null) ? null : itemPrefab.GetComponent<ItemDrop>()?.m_itemData.m_shared.m_buildPieces); if ((Object)(object)val == (Object)null) { return; } if ((Object)(object)val != (Object)(object)hammer) { hammer = val; dirty = true; foreach (Tool value in tools.Values) { value.Added.Clear(); } sourceOf.Clear(); } foreach (GameObject item in instance.m_items) { if ((Object)(object)item == (Object)null || Vanilla.Contains(((Object)item).name) || tools.ContainsKey(((Object)item).name)) { continue; } ItemDrop component = item.GetComponent<ItemDrop>(); PieceTable val2 = (((Object)(object)component != (Object)null) ? component.m_itemData.m_shared.m_buildPieces : null); if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val2 == (Object)(object)hammer)) { try { Discover(((Object)item).name, component, val2); } catch (Exception ex) { Plugin.Warn("merge " + ((Object)item).name + ": " + ex.Message); } } } if (!dirty) { return; } dirty = false; foreach (Tool value2 in tools.Values) { if (value2.On.Value) { foreach (GameObject piece in value2.Table.m_pieces) { Piece val3 = (((Object)(object)piece != (Object)null) ? piece.GetComponent<Piece>() : null); if (!((Object)(object)val3 == (Object)null) && !val3.m_repairPiece && !val3.m_removePiece && !hammer.m_pieces.Contains(piece)) { hammer.m_pieces.Add(piece); value2.Added.Add(piece); sourceOf[((Object)piece).name] = value2; } } } else { if (value2.Added.Count <= 0) { continue; } foreach (GameObject item2 in value2.Added) { hammer.m_pieces.Remove(item2); if ((Object)(object)item2 != (Object)null) { sourceOf.Remove(((Object)item2).name); } } value2.Added.Clear(); } } Sorting.Forget(); Plugin.Log("merged tools: " + ((tools.Count == 0) ? "none found" : string.Join(", ", tools.Values.Select((Tool t) => string.Format("{0} {1} ({2} in the hammer)", t.Prefab, t.On.Value ? "on" : "off", t.Added.Count))))); } private static void Discover(string prefab, ItemDrop drop, PieceTable table) { int num = table.m_pieces.Count(delegate(GameObject go) { if ((Object)(object)go != (Object)null) { Piece component = go.GetComponent<Piece>(); if (component != null && !component.m_repairPiece) { return !component.m_removePiece; } } return false; }); Tool tool = new Tool { Prefab = prefab, Table = table, Name = Localization.instance.Localize(drop.m_itemData.m_shared.m_name), Mod = ModOf(prefab) }; tool.On = Plugin.Cfg.Bind<bool>("Merge tools", prefab, false, $"Merge into our hammer: \"{tool.Name}\" from {tool.Mod}, {num} pieces. On - these pieces are built from the BuildMenu hammer " + "(the mod's very pieces: its station, resources and effects), in the tree also under Other tools. The tool itself keeps working." + ((prefab.IndexOf("hoe", StringComparison.OrdinalIgnoreCase) >= 0) ? " A terrain tool: its mod may expect it in hand, merging is not advised." : "") + "\n" + $"Объединить с нашим молотком: «{tool.Name}» из мода {tool.Mod}, построек: {num}. Включено — эти постройки доступны из молотка BuildMenu " + "(те же постройки мода: станция, ресурсы и эффекты как у него), в дереве — «Другие инструменты». Сам инструмент работает как прежде." + ((prefab.IndexOf("hoe", StringComparison.OrdinalIgnoreCase) >= 0) ? " Это инструмент рельефа: мод может ждать его в руке, объединять не советуем." : "")); tool.On.SettingChanged += delegate { dirty = true; try { if ((Object)(object)Player.m_localPlayer != (Object)null) { Player.m_localPlayer.UpdateAvailablePiecesList(); } } catch (Exception ex) { Plugin.Warn("merge refresh: " + ex.Message); } }; tool.Sub = Catalog.ToolSub("tool_" + prefab, tool.Name); tools[prefab] = tool; dirty = true; } private static string ModOf(string prefab) { try { Type type = AccessTools.TypeByName("Jotunn.Managers.ItemManager"); object obj = type?.GetProperty("Instance")?.GetValue(null); object obj2 = ((obj == null) ? null : AccessTools.Method(type, "GetItem", new Type[1] { typeof(string) }, (Type[])null)?.Invoke(obj, new object[1] { prefab })); object obj3 = obj2?.GetType().GetProperty("SourceMod")?.GetValue(obj2); string text = obj3?.GetType().GetProperty("Name")?.GetValue(obj3) as string; if (!string.IsNullOrEmpty(text)) { return text; } } catch { } return Plugin.T("(мод не определён)", "(unknown mod)"); } public static Sub SubOf(Piece piece) { if (!((Object)(object)piece != (Object)null) || !sourceOf.TryGetValue(((Object)((Component)piece).gameObject).name, out var value)) { return null; } return value.Sub; } public static string Source(Piece piece) { if (!((Object)(object)piece != (Object)null) || !sourceOf.TryGetValue(((Object)((Component)piece).gameObject).name, out var value)) { return null; } return value.Mod + " (" + value.Name + ")"; } public static Sprite ToolIcon(string subKey) { if (subKey == null || !subKey.StartsWith("tool_")) { return null; } object obj; if (!((Object)(object)ObjectDB.instance != (Object)null)) { obj = null; } else { GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(subKey.Substring(5)); obj = ((itemPrefab != null) ? itemPrefab.GetComponent<ItemDrop>() : null); } ItemDrop val = (ItemDrop)obj; if (!((Object)(object)val != (Object)null)) { return null; } return val.m_itemData.GetIcon(); } } [HarmonyPatch(typeof(Player), "UpdateAvailablePiecesList")] internal static class MergeHook { private static void Prefix() { if (!Plugin.Enabled.Value) { return; } try { Merge.Apply(); } catch (Exception ex) { Plugin.Warn("merge: " + ex.Message); } } } [BepInPlugin("chistix.buildmenu", "BuildMenu", "0.3.13")] public sealed class Plugin : BaseUnityPlugin { public const string Guid = "chistix.buildmenu"; public const string Version = "0.3.13"; private static ManualLogSource log; internal static ConfigFile Cfg; internal static string Folder; internal static readonly int[] CellSizes = new int[7] { 56, 64, 72, 84, 96, 112, 128 }; internal static readonly int[] Presets = new int[4] { 0, 2, 4, 6 }; internal static ConfigEntry<bool> Enabled; internal static ConfigEntry<bool> Captions; internal static ConfigEntry<bool> Badges; internal static ConfigEntry<bool> Grid3D; internal static ConfigEntry<bool> Preview3D; internal static ConfigEntry<bool> GroundGrid3D; internal static ConfigEntry<bool> GroundPreview3D; internal static ConfigEntry<bool> ShowPrefab; internal static ConfigEntry<bool> DebugLog; internal static ConfigEntry<int> CellStep; internal static ConfigEntry<int> WindowSize; internal static readonly Vector2Int[] WindowSizes = (Vector2Int[])(object)new Vector2Int[3] { new Vector2Int(1500, 800), new Vector2Int(1760, 960), new Vector2Int(1960, 1080) }; internal const float TagListWidth = 290f; internal static ConfigEntry<bool> GridModels { get { if (!Ground.InHand()) { return Grid3D; } return GroundGrid3D; } } internal static ConfigEntry<bool> TooltipModels { get { if (!Ground.InHand()) { return Preview3D; } return GroundPreview3D; } } internal static bool Russian { get { if (Localization.instance != null) { return Localization.instance.GetSelectedLanguage() == "Russian"; } return false; } } private void Awake() { //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Expected O, but got Unknown //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Expected O, but got Unknown //IL_01ec: Unknown result type (might be due to invalid IL or missing references) log = ((BaseUnityPlugin)this).Logger; Cfg = ((BaseUnityPlugin)this).Config; Folder = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location); Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "The new build menu (category tree, grid with captions, tooltip with 3D). Off - the game's own menu (after a restart).\nНовое меню стройки (дерево категорий, сетка с подписями, подсказка с 3D). Выключено — родное меню игры (после перезапуска)."); CellStep = ((BaseUnityPlugin)this).Config.Bind<int>("Grid", "CellSize", 2, new ConfigDescription("Grid cell size, 0-6 (the menu's four Grid size buttons: 0, 2, 4, 6).\nРазмер ячеек сетки, шаг 0–6 (в меню — четыре кнопки «Размер сетки»: 0, 2, 4, 6).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, CellSizes.Length - 1), Array.Empty<object>())); WindowSize = ((BaseUnityPlugin)this).Config.Bind<int>("General", "WindowSize", 1, new ConfigDescription("Window size: 0 smaller, 1 medium, 2 large (after a restart).\nРазмер окна: 0 — поменьше, 1 — средний, 2 — крупный (после перезапуска).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, WindowSizes.Length - 1), Array.Empty<object>())); Captions = ((BaseUnityPlugin)this).Config.Bind<bool>("Grid", "Captions", true, "Names under the pieces' icons.\nПодписи под значками деталей."); Badges = ((BaseUnityPlugin)this).Config.Bind<bool>("Grid", "CategoryIcon", true, "The subcategory's badge in the cell's corner.\nЗначок подкатегории в углу ячейки."); Grid3D = ((BaseUnityPlugin)this).Config.Bind<bool>("Grid", "Models3D", false, "3D snapshots of the pieces in the grid instead of the game's icons (made a little each frame for cells in view, then kept in memory).\n3D-снимки деталей в сетке вместо значков игры (снимаются понемногу за кадр для видимых ячеек, потом из памяти)."); Preview3D = ((BaseUnityPlugin)this).Config.Bind<bool>("Tooltip", "Preview3D", true, "A live turning model of the piece in the tooltip (else the game's icon).\nЖивая поворотная модель детали в подсказке (иначе — значок игры)."); GroundGrid3D = ((BaseUnityPlugin)this).Config.Bind<bool>("Grid", "GroundModels3D", false, "The same for the ground tools (hoe, cultivator and the like): 3D snapshots in the grid instead of the game's icons.\nТо же для инструментов земли (мотыга, культиватор и подобные): 3D-снимки в сетке вместо значков игры."); GroundPreview3D = ((BaseUnityPlugin)this).Config.Bind<bool>("Tooltip", "GroundPreview3D", false, "The same for the ground tools (hoe, cultivator and the like): a turning model in the tooltip instead of the game's icon.\nТо же для инструментов земли (мотыга, культиватор и подобные): поворотная модель в подсказке вместо значка игры."); ShowPrefab = ((BaseUnityPlugin)this).Config.Bind<bool>("Tooltip", "ShowPrefab", false, "Show the piece's prefab name in the tooltip (for the categories file).\nПоказывать в подсказке имя prefab детали (для файла подкатегорий)."); DebugLog = ((BaseUnityPlugin)this).Config.Bind<bool>("Advanced", "DebugLog", false, "More details in the log.\nПодробности в журнал."); ((BaseUnityPlugin)this).Config.SettingChanged += delegate(object _, SettingChangedEventArgs args) { if (args.ChangedSetting.Definition.Section != "Advanced" && (object)args.ChangedSetting != Enabled) { Window.Refresh(); } }; new Harmony("chistix.buildmenu").PatchAll(typeof(Plugin).Assembly); Log("BuildMenu 0.3.13"); } private void OnDestroy() { Preview.Clear(); } internal static string T(string ru, string en) { if (!Russian) { return en; } return ru; } internal static void Log(string text) { ManualLogSource obj = log; if (obj != null) { obj.LogInfo((object)text); } } internal static void Warn(string text) { ManualLogSource obj = log; if (obj != null) { obj.LogWarning((object)text); } } internal static void Debug(string text) { if (DebugLog != null && DebugLog.Value) { ManualLogSource obj = log; if (obj != null) { obj.LogInfo((object)text); } } } } internal static class Preview { private static GameObject rig; private static GameObject model; private static Camera cam; private static Light light; private static Light fill; private static RenderTexture live; private static string shown; private static float yaw; private static readonly Vector3 Place = new Vector3(0f, -20000f, 0f); private static int layer = -1; private static readonly Dictionary<int, (Vector3 centre, float radius)> spheres = new Dictionary<int, (Vector3, float)>(); private static float sinceDrawn; private static readonly int sunDir = Shader.PropertyToID("_SunDir"); private static readonly int sunColor = Shader.PropertyToID("_SunColor"); private static readonly int ambientColor = Shader.PropertyToID("_AmbientColor"); private static readonly int wet = Shader.PropertyToID("_Wet"); private static readonly Color Key = new Color(0.9f, 0.87f, 0.82f); private static readonly Color Ambient = new Color(0.46f, 0.46f, 0.48f); private const int MaxStills = 512; private static readonly Dictionary<string, RenderTexture> stills = new Dictionary<string, RenderTexture>(); private static readonly LinkedList<string> used = new LinkedList<string>(); public static RenderTexture Texture => live; public static int StillCount => stills.Count; private static int Layer() { if (layer >= 0) { return layer; } for (int num = 31; num >= 8; num--) { if (string.IsNullOrEmpty(LayerMask.LayerToName(num))) { return layer = num; } } return layer = 31; } private static void Setup() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown //IL_0031: 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_0045: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: Unknown result type (might be due to invalid IL or missing references) //IL_01e0: Unknown result type (might be due to invalid IL or missing references) //IL_0222: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)rig != (Object)null)) { rig = new GameObject("BuildMenu preview"); Object.DontDestroyOnLoad((Object)(object)rig); rig.transform.position = Place; GameObject val = new GameObject("camera"); val.transform.SetParent(rig.transform, false); cam = val.AddComponent<Camera>(); ((Behaviour)cam).enabled = false; cam.cullingMask = 1 << Layer(); cam.clearFlags = (CameraClearFlags)2; cam.backgroundColor = new Color(0f, 0f, 0f, 0f); cam.fieldOfView = 28f; cam.nearClipPlane = 0.05f; cam.farClipPlane = 200f; cam.allowHDR = false; cam.allowMSAA = true; cam.useOcclusionCulling = false; GameObject val2 = new GameObject("light"); val2.transform.SetParent(rig.transform, false); val2.transform.rotation = Quaternion.Euler(40f, -35f, 0f); light = val2.AddComponent<Light>(); light.type = (LightType)1; light.intensity = 1.1f; light.color = new Color(1f, 0.95f, 0.88f); light.cullingMask = 1 << Layer(); light.shadows = (LightShadows)0; ((Behaviour)light).enabled = false; GameObject val3 = new GameObject("fill"); val3.transform.SetParent(rig.transform, false); val3.transform.rotation = Quaternion.Euler(20f, 150f, 0f); fill = val3.AddComponent<Light>(); fill.type = (LightType)1; fill.intensity = 0.45f; fill.color = new Color(0.75f, 0.82f, 1f); fill.cullingMask = 1 << Layer(); fill.shadows = (LightShadows)0; ((Behaviour)fill).enabled = false; } } private static GameObject Copy(GameObject prefab) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_01f4: Unknown result type (might be due to invalid IL or missing references) //IL_01f9: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Unknown result type (might be due to invalid IL or missing references) //IL_0216: Unknown result type (might be due to invalid IL or missing references) //IL_021e: Unknown result type (might be due to invalid IL or missing references) //IL_0223: Unknown result type (might be due to invalid IL or missing references) //IL_0228: Unknown result type (might be due to invalid IL or missing references) //IL_022a: Unknown result type (might be due to invalid IL or missing references) //IL_0233: Unknown result type (might be due to invalid IL or missing references) //IL_0238: Unknown result type (might be due to invalid IL or missing references) //IL_0242: Unknown result type (might be due to invalid IL or missing references) //IL_024a: Unknown result type (might be due to invalid IL or missing references) //IL_0254: Unknown result type (might be due to invalid IL or missing references) //IL_025c: Unknown result type (might be due to invalid IL or missing references) //IL_0266: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("model " + ((Object)prefab).name); val.layer = Layer(); val.transform.SetParent(rig.transform, false); HashSet<Transform> hashSet = new HashSet<Transform>(); WearNTear component = prefab.GetComponent<WearNTear>(); if ((Object)(object)component != (Object)null) { GameObject[] array = (GameObject[])(object)new GameObject[3] { component.m_worn, component.m_broken, component.m_wet }; foreach (GameObject val2 in array) { if ((Object)(object)val2 != (Object)null && (Object)(object)val2 != (Object)(object)component.m_new) { hashSet.Add(val2.transform); } } } LODGroup[] componentsInChildren = prefab.GetComponentsInChildren<LODGroup>(true); Renderer[] renderers; for (int i = 0; i < componentsInChildren.Length; i++) { LOD[] lODs = componentsInChildren[i].GetLODs(); for (int j = 1; j < lODs.Length; j++) { renderers = lODs[j].renderers; foreach (Renderer val3 in renderers) { if ((Object)(object)val3 != (Object)null && !lODs[0].renderers.Contains(val3)) { hashSet.Add(((Component)val3).transform); } } } } Matrix4x4 worldToLocalMatrix = prefab.transform.worldToLocalMatrix; renderers = prefab.GetComponentsInChildren<Renderer>(true); foreach (Renderer val4 in renderers) { if ((val4 is MeshRenderer || val4 is SkinnedMeshRenderer) && val4.enabled && On(((Component)val4).transform, prefab.transform) && !Skipped(((Component)val4).transform, hashSet)) { SkinnedMeshRenderer val5 = (SkinnedMeshRenderer)(object)((val4 is SkinnedMeshRenderer) ? val4 : null); object obj; if (val5 == null) { MeshFilter component2 = ((Component)val4).GetComponent<MeshFilter>(); obj = ((component2 != null) ? component2.sharedMesh : null); } else { obj = val5.sharedMesh; } Mesh val6 = (Mesh)obj; if (!((Object)(object)val6 == (Object)null)) { GameObject val7 = new GameObject(((Object)val4).name) { layer = Layer() }; val7.transform.SetParent(val.transform, false); Matrix4x4 val8 = worldToLocalMatrix * ((Component)val4).transform.localToWorldMatrix; val7.transform.localPosition = Vector4.op_Implicit(((Matrix4x4)(ref val8)).GetColumn(3)); val7.transform.localRotation = ((Matrix4x4)(ref val8)).rotation; val7.transform.localScale = ((Matrix4x4)(ref val8)).lossyScale; val7.AddComponent<MeshFilter>().sharedMesh = val6; MeshRenderer obj2 = val7.AddComponent<MeshRenderer>(); ((Renderer)obj2).sharedMaterials = val4.sharedMaterials; ((Renderer)obj2).shadowCastingMode = (ShadowCastingMode)0; ((Renderer)obj2).receiveShadows = false; } } } return val; } private static bool On(Transform t, Transform root) { while ((Object)(object)t != (Object)null) { if (!((Component)t).gameObject.activeSelf) { return false; } if ((Object)(object)t == (Object)(object)root) { break; } t = t.parent; } return true; } private static bool Skipped(Transform t, HashSet<Transform> skip) { while ((Object)(object)t != (Object)null) { if (skip.Contains(t)) { return true; } t = t.parent; } return false; } private static (Vector3 centre, float radius) Sphere(GameObject root) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002a: 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_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) int instanceID = ((Object)root).GetInstanceID(); if (spheres.TryGetValue(instanceID, out (Vector3, float) value)) { return value; } Quaternion localRotation = root.transform.localRotation; root.transform.localRotation = Quaternion.identity; Renderer[] componentsInChildren = root.GetComponentsInChildren<Renderer>(); Bounds val = (Bounds)((componentsInChildren.Length != 0) ? componentsInChildren[0].bounds : new Bounds(root.transform.position, Vector3.one * 0.2f)); Renderer[] array = componentsInChildren; foreach (Renderer val2 in array) { ((Bounds)(ref val)).Encapsulate(val2.bounds); } root.transform.localRotation = localRotation; Dictionary<int, (Vector3 centre, float radius)> dictionary = spheres; Vector3 item = root.transform.InverseTransformPoint(((Bounds)(ref val)).center); Vector3 extents = ((Bounds)(ref val)).extents; return dictionary[instanceID] = (item, Mathf.Max(((Vector3)(ref extents)).magnitude, 0.1f)); } private static void Frame(GameObject root, float turn) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0024: 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_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_006e: 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_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0089: 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_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) var (val, num) = Sphere(root); root.transform.localRotation = Quaternion.Euler(0f, turn, 0f); Vector3 val2 = root.transform.TransformPoint(val); float num2 = num / Mathf.Sin(cam.fieldOfView * 0.5f * ((float)Math.PI / 180f)) * 0.85f; Vector3 val3 = Quaternion.Euler(18f, 180f, 0f) * Vector3.back; ((Component)cam).transform.position = val2 + val3 * num2; ((Component)cam).transform.LookAt(val2); cam.nearClipPlane = Mathf.Max(0.02f, num2 - num * 1.5f); cam.farClipPlane = num2 + num * 1.5f; } public static void Show(Piece piece) { //IL_002e: 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_003a: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Expected O, but got Unknown if ((Object)(object)piece == (Object)null) { Hide(); return; } Setup(); if ((Object)(object)live == (Object)null) { live = new RenderTexture(320, 320, 24, (RenderTextureFormat)0) { antiAliasing = 2, name = "BuildMenu preview" }; live.Create(); } if (shown != ((Object)((Component)piece).gameObject).name || (Object)(object)model == (Object)null) { if ((Object)(object)model != (Object)null) { spheres.Remove(((Object)model).GetInstanceID()); Object.Destroy((Object)(object)model); } model = Copy(((Component)piece).gameObject); shown = ((Object)((Component)piece).gameObject).name; yaw = -30f; } model.SetActive(true); sinceDrawn = 1f; } public static void Hide() { if ((Object)(object)model != (Object)null) { model.SetActive(false); } } public static void Update(float dt) { if (!((Object)(object)model == (Object)null) && model.activeSelf && !((Object)(object)cam == (Object)null)) { yaw += dt * 24f; if (!((sinceDrawn += dt) < 1f / 24f)) { sinceDrawn = 0f; Frame(model, yaw); Render(live); } } } private static void Render(RenderTexture target) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: 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_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: 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_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_0067: 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_0080: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_01b1: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01d4: Unknown result type (might be due to invalid IL or missing references) Quaternion val = ((Component)cam).transform.rotation * Quaternion.Euler(30f, -35f, 0f); if ((Object)(object)light != (Object)null) { ((Component)light).transform.rotation = val; } if ((Object)(object)fill != (Object)null) { ((Component)fill).transform.rotation = ((Component)cam).transform.rotation * Quaternion.Euler(10f, 145f, 0f); } bool fog = RenderSettings.fog; AmbientMode ambientMode = RenderSettings.ambientMode; Color ambientLight = RenderSettings.ambientLight; Vector4 globalVector = Shader.GetGlobalVector(sunDir); Color globalColor = Shader.GetGlobalColor(sunColor); Color globalColor2 = Shader.GetGlobalColor(ambientColor); float globalFloat = Shader.GetGlobalFloat(wet); RenderSettings.fog = false; RenderSettings.ambientMode = (AmbientMode)3; RenderSettings.ambientLight = Ambient; Shader.SetGlobalVector(sunDir, Vector4.op_Implicit(-(val * Vector3.forward))); Shader.SetGlobalColor(sunColor, Key); Shader.SetGlobalColor(ambientColor, Ambient); Shader.SetGlobalFloat(wet, 0f); try { if ((Object)(object)light != (Object)null) { ((Behaviour)light).enabled = true; } if ((Object)(object)fill != (Object)null) { ((Behaviour)fill).enabled = true; } cam.targetTexture = target; cam.Render(); } finally { if ((Object)(object)light != (Object)null) { ((Behaviour)light).enabled = false; } if ((Object)(object)fill != (Object)null) { ((Behaviour)fill).enabled = false; } RenderSettings.fog = fog; RenderSettings.ambientMode = ambientMode; RenderSettings.ambientLight = ambientLight; Shader.SetGlobalVector(sunDir, globalVector); Shader.SetGlobalColor(sunColor, globalColor); Shader.SetGlobalColor(ambientColor, globalColor2); Shader.SetGlobalFloat(wet, globalFloat); cam.targetTexture = null; } } public static Texture Cached(Piece piece) { string name = ((Object)((Component)piece).gameObject).name; if (!stills.TryGetValue(name, out var value) || (Object)(object)value == (Object)null || !value.IsCreated()) { return null; } used.Remove(name); used.AddFirst(name); return (Texture)(object)value; } public static Texture Still(Piece piece, int size) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown Texture val = Cached(piece); if ((Object)(object)val != (Object)null) { return val; } Setup(); string name = ((Object)((Component)piece).gameObject).name; RenderTexture val2 = new RenderTexture(size, size, 0, (RenderTextureFormat)0) { name = "BuildMenu still " + name }; val2.Create(); RenderTexture temporary = RenderTexture.GetTemporary(size, size, 24, (RenderTextureFormat)0, (RenderTextureReadWrite)0, 4); bool active = (Object)(object)model != (Object)null && model.activeSelf; if ((Object)(object)model != (Object)null) { model.SetActive(false); } GameObject val3 = Copy(((Component)piece).gameObject); try { Frame(val3, -30f); Render(temporary); Graphics.Blit((Texture)(object)temporary, val2); } finally { spheres.Remove(((Object)val3).GetInstanceID()); Object.DestroyImmediate((Object)(object)val3); RenderTexture.ReleaseTemporary(temporary); if ((Object)(object)model != (Object)null) { model.SetActive(active); } } stills[name] = val2; used.AddFirst(name); while (stills.Count > 512) { Drop(used.Last.Value); } return (Texture)(object)val2; } private static void Drop(string name) { used.Remove(name); if (stills.TryGetValue(name, out var value) && (Object)(object)value != (Object)null) { value.Release(); Object.Destroy((Object)(object)value); } stills.Remove(name); } public static void ClearStills() { foreach (string item in stills.Keys.ToList()) { Drop(item); } } public static void Clear() { ClearStills(); if ((Object)(object)rig != (Object)null) { Object.Destroy((Object)(object)rig); } if ((Object)(object)live != (Object)null) { live.Release(); Object.Destroy((Object)(object)live); } rig = null; model = null; cam = null; live = null; shown = null; } } internal static class Sorting { private static readonly Dictionary<string, List<Sub>> cache = new Dictionary<string, List<Sub>>(); private static readonly List<(Regex prefab, List<string> subs)> overrides = new List<(Regex, List<string>)>(); private static DateTime overridesTime; internal static int Read; private const string Template = "# BuildMenu: подкатегории деталей вручную (для деталей других модов и для несогласных с автоматикой).\n# Строка: prefab = подкатегория[, подкатегория…]. Первая — своя (её значок в углу ячейки).\n# Prefab можно с *: piece_banner* = decor. Prefab детали — в подсказке меню при включённой настройке ShowPrefab.\n# Подкатегории (ключ или название):\n# Ремесло: stations (Верстаки и станции), upgrades (Улучшения станций), smelting (Плавильни и производство), kitchen (Кухня)\n# Строительство: floor (Полы), wall (Стены), roof (Крыши), stairs (Лестницы и пандусы), beam (Балки и столбы),\n# door (Двери и ворота), window (Окна), arch (Арки), fence (Заборы), defense (Оборона), other (Прочее)\n# Интерьер: furniture (Мебель), light (Освещение), decor (Декор)\n# Перемещение: transport (Транспорт), portal (Порталы)\n# Хранилище: storage Разное: misc\n# Новая подкатегория: «Группа/Название» (группа тоже может быть новой), например: piece_mymod_* = Разное/Мой мод\n# Значок подкатегории: icons\\<ключ>.png рядом с BuildMenu.dll (у новой ключ — её название).\n#\n# Building pieces by hand: prefab = subcategory[, subcategory…]; keys as above (or names); \"Group/Name\" makes a new one.\n#\n# wood_wall_log = wall, beam\n"; public static string OverridesPath => Path.Combine(Paths.ConfigPath, "chistix.buildmenu.categories.txt"); public static List<Sub> Of(Piece piece) { string name = ((Object)((Component)piece).gameObject).name; if (cache.TryGetValue(name, out var value)) { return value; } List<string> list = null; foreach (var @override in overrides) { if (@override.prefab.IsMatch(name)) { list = @override.subs; break; } } if (list == null) { try { list = Catalog.Classify(FactsReader.Read(piece, "", (Func<string, string>)Localization.instance.Localize)); Read++; } catch (Exception ex) { Plugin.Warn(name + ": " + ex.Message); list = new List<string> { "misc" }; } } value = (from s in list.Select(Catalog.FindOrCreate) where s != null select s).Distinct().ToList(); if (value.Count == 0) { value.Add(Catalog.Find("misc")); } Sub sub = Merge.SubOf(piece); if (sub != null && !value.Contains(sub)) { value.Add(sub); } cache[name] = value; return value; } public static Sub Main(Piece piece) { return Of(piece)[0]; } public static void Forget() { cache.Clear(); } public static void Refresh() { try { string overridesPath = OverridesPath; if (File.Exists(overridesPath) && File.GetLastWriteTimeUtc(overridesPath) == overridesTime) { return; } if (!File.Exists(overridesPath) || (File.ReadAllLines(overridesPath).All((string l) => l.Trim().Length == 0 || l.TrimStart().StartsWith("#")) && File.ReadAllText(overridesPath) != "# BuildMenu: подкатегории деталей вручную (для деталей других модов и для несогласных с автоматикой).\n# Строка: prefab = подкатегория[, подкатегория…]. Первая — своя (её значок в углу ячейки).\n# Prefab можно с *: piece_banner* = decor. Prefab детали — в подсказке меню при включённой настройке ShowPrefab.\n# Подкатегории (ключ или название):\n# Ремесло: stations (Верстаки и станции), upgrades (Улучшения станций), smelting (Плавильни и производство), kitchen (Кухня)\n# Строительство: floor (Полы), wall (Стены), roof (Крыши), stairs (Лестницы и пандусы), beam (Балки и столбы),\n# door (Двери и ворота), window (Окна), arch (Арки), fence (Заборы), defense (Оборона), other (Прочее)\n# Интерьер: furniture (Мебель), light (Освещение), decor (Декор)\n# Перемещение: transport (Транспорт), portal (Порталы)\n# Хранилище: storage Разное: misc\n# Новая подкатегория: «Группа/Название» (группа тоже может быть новой), например: piece_mymod_* = Разное/Мой мод\n# Значок подкатегории: icons\\<ключ>.png рядом с BuildMenu.dll (у новой ключ — её название).\n#\n# Building pieces by hand: prefab = subcategory[, subcategory…]; keys as above (or names); \"Group/Name\" makes a new one.\n#\n# wood_wall_log = wall, beam\n")) { File.WriteAllText(overridesPath, "# BuildMenu: подкатегории деталей вручную (для деталей других модов и для несогласных с автоматикой).\n# Строка: prefab = подкатегория[, подкатегория…]. Первая — своя (её значок в углу ячейки).\n# Prefab можно с *: piece_banner* = decor. Prefab детали — в подсказке меню при включённой настройке ShowPrefab.\n# Подкатегории (ключ или название):\n# Ремесло: stations (Верстаки и станции