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 ValheimArchitect v0.5.19
BepInEx\plugins\ValheimArchitect\ValheimArchitect.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; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.Rendering; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [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 ValheimArchitect { internal sealed class ArchitectFeatures { private const string Section = "Функции"; public readonly FeatureToggle ResourceCalculator; public readonly FeatureToggle AlignmentLines; public readonly FeatureToggle PinAlignmentGrid; public readonly FeatureToggle GhostLayout; public readonly IReadOnlyList<FeatureToggle> All; public ArchitectFeatures(ConfigFile config) { ResourceCalculator = Bind(config, "Калькулятор ресурсов", "Показывает общее количество ресурсов, необходимое для текущего фантомного макета."); AlignmentLines = Bind(config, "Лазерный уровень", "Показывает уровень земли по сетке 1×1 м и помогает выровнять участок перед строительством."); PinAlignmentGrid = Bind(config, "Закрепить уровень", "Фиксирует текущую высоту лазерного уровня. F10 переключает закрепление."); GhostLayout = Bind(config, "Фантомный макет", "Позволяет планировать строительство без расхода ресурсов. Детали макета отображаются синим цветом и не становятся настоящими постройками. Для удобства при больших проектах можно использовать отдельный мод со свободной камерой."); All = new List<FeatureToggle> { ResourceCalculator, AlignmentLines, PinAlignmentGrid, GhostLayout }; } private static FeatureToggle Bind(ConfigFile config, string label, string description) { ConfigEntry<bool> config2 = config.Bind<bool>("Функции", label, false, description); return new FeatureToggle(label, description, config2); } } internal sealed class ArchitectMenu { private const int WindowId = 170335943; private readonly ArchitectFeatures _features; private Rect _windowRect = new Rect(0f, 0f, 760f, 680f); private bool _visible; private bool _sizeInitialized; private FeatureToggle _hovered; public bool IsVisible => _visible; public ArchitectMenu(ArchitectFeatures features) { //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) _features = features; } public void Toggle() { _visible = !_visible; _hovered = null; } public void Draw() { //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Expected O, but got Unknown //IL_0146: 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) ArchitectStyle.EnsureInitialized(); if (_features.GhostLayout.Value) { DrawGhostBanner(); } if (_visible) { if (!_sizeInitialized) { ((Rect)(ref _windowRect)).width = 760f; ((Rect)(ref _windowRect)).height = 680f; ((Rect)(ref _windowRect)).x = ((float)Screen.width - ((Rect)(ref _windowRect)).width) / 2f; ((Rect)(ref _windowRect)).y = ((float)Screen.height - ((Rect)(ref _windowRect)).height) / 2f; _sizeInitialized = true; } else { ((Rect)(ref _windowRect)).x = Mathf.Clamp(((Rect)(ref _windowRect)).x, 10f, Mathf.Max(10f, (float)Screen.width - ((Rect)(ref _windowRect)).width - 10f)); ((Rect)(ref _windowRect)).y = Mathf.Clamp(((Rect)(ref _windowRect)).y, 10f, Mathf.Max(10f, (float)Screen.height - ((Rect)(ref _windowRect)).height - 10f)); } _windowRect = GUI.Window(170335943, _windowRect, new WindowFunction(DrawWindow), GUIContent.none, ArchitectStyle.Window); } } private void DrawGhostBanner() { //IL_0025: 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_0081: 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) float num = 760f; float num2 = 82f; float num3 = ((float)Screen.width - num) * 0.5f; float num4 = 18f; GUI.Box(new Rect(num3, num4, num, num2), GUIContent.none, ArchitectStyle.Tooltip); GUI.Label(new Rect(num3 + 18f, num4 + 8f, num - 36f, 26f), "ФАНТОМНЫЙ МАКЕТ", ArchitectStyle.Title); GUI.Label(new Rect(num3 + 18f, num4 + 36f, num - 36f, 16f), "Планирование без расхода ресурсов", ArchitectStyle.Subtitle); ValheimArchitectPlugin instance = ValheimArchitectPlugin.Instance; int num5 = (((Object)(object)instance != (Object)null && instance.Ghost != null) ? instance.Ghost.BlueprintCount : 0); GUI.Label(new Rect(num3 + 18f, num4 + 57f, num - 36f, 14f), $"Деталей: {num5} • F11 — очистить макет", ArchitectStyle.Small); } private void DrawWindow(int id) { //IL_0027: 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_008f: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_01de: Unknown result type (might be due to invalid IL or missing references) //IL_01e3: Unknown result type (might be due to invalid IL or missing references) //IL_0201: Unknown result type (might be due to invalid IL or missing references) //IL_0229: Unknown result type (might be due to invalid IL or missing references) //IL_022e: Unknown result type (might be due to invalid IL or missing references) //IL_0253: Unknown result type (might be due to invalid IL or missing references) //IL_0289: Unknown result type (might be due to invalid IL or missing references) //IL_02c2: Unknown result type (might be due to invalid IL or missing references) _hovered = null; GUI.Box(new Rect(16f, 16f, ((Rect)(ref _windowRect)).width - 32f, 82f), GUIContent.none, ArchitectStyle.Header); GUI.Label(new Rect(32f, 24f, ((Rect)(ref _windowRect)).width - 64f, 32f), "VALHEIM ARCHITECT", ArchitectStyle.Title); GUI.Label(new Rect(32f, 58f, ((Rect)(ref _windowRect)).width - 64f, 18f), "СТРОИТЕЛЬНЫЙ ИНСТРУМЕНТ", ArchitectStyle.Subtitle); if (GUI.Button(new Rect(((Rect)(ref _windowRect)).width - 50f, 28f, 26f, 26f), "×", ArchitectStyle.Close)) { _visible = false; return; } GUILayout.BeginArea(new Rect(22f, 112f, ((Rect)(ref _windowRect)).width - 44f, ((Rect)(ref _windowRect)).height - 132f)); GUILayout.Label("ПЛАНИРОВАНИЕ", ArchitectStyle.Section, Array.Empty<GUILayoutOption>()); GUILayout.Space(6f); DrawFeature(_features.GhostLayout, "◆"); DrawFeature(_features.ResourceCalculator, "◇"); GUILayout.Space(14f); GUILayout.Label("ВЫРАВНИВАНИЕ", ArchitectStyle.Section, Array.Empty<GUILayoutOption>()); GUILayout.Space(6f); DrawFeature(_features.AlignmentLines, "╋"); DrawFeature(_features.PinAlignmentGrid, "□"); GUILayout.Space(14f); DrawTooltipPanel(); GUILayout.Space(10f); Rect rect = GUILayoutUtility.GetRect(0f, 18f); GUI.Label(new Rect(0f, ((Rect)(ref rect)).y, ((Rect)(ref _windowRect)).width - 48f, 18f), "F10 — закрепить / открепить уровень • F8 — закрыть", ArchitectStyle.Hint); GUILayout.Space(6f); rect = GUILayoutUtility.GetRect(0f, 46f); float y = ((Rect)(ref rect)).y; GUI.Box(new Rect(0f, y, ((Rect)(ref _windowRect)).width - 48f, 44f), GUIContent.none, ArchitectStyle.Tooltip); GUI.Label(new Rect(10f, y + 4f, ((Rect)(ref _windowRect)).width - 68f, 36f), "* Демонстрационный прототип. Мод создан при помощи ИИ для проверки и демонстрации идеи.", ArchitectStyle.Credits); GUILayout.EndArea(); GUI.DragWindow(new Rect(20f, 16f, ((Rect)(ref _windowRect)).width - 92f, 82f)); } private void DrawFeature(FeatureToggle feature, string icon) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) Rect rect = GUILayoutUtility.GetRect(0f, 60f, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) }); GUIStyle val = (feature.Value ? ArchitectStyle.FeatureOn : ArchitectStyle.Feature); if (GUI.Button(rect, feature.Label, val)) { feature.Value = !feature.Value; } GUIStyle val2 = (feature.Value ? ArchitectStyle.FeatureIconOn : ArchitectStyle.FeatureIcon); GUI.Label(new Rect(((Rect)(ref rect)).x + 12f, ((Rect)(ref rect)).y + 8f, 26f, ((Rect)(ref rect)).height - 16f), icon, val2); GUI.Label(new Rect(((Rect)(ref rect)).xMax - 82f, ((Rect)(ref rect)).y + 14f, 64f, 26f), feature.Value ? "ВКЛ" : "ВЫКЛ", feature.Value ? ArchitectStyle.StateOn : ArchitectStyle.StateOff); if (((Rect)(ref rect)).Contains(Event.current.mousePosition)) { _hovered = feature; } } private void DrawTooltipPanel() { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_012d: 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_00a6: Unknown result type (might be due to invalid IL or missing references) Rect rect = GUILayoutUtility.GetRect(0f, 142f, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) }); GUI.Box(rect, GUIContent.none, ArchitectStyle.Tooltip); if (_hovered == null) { GUI.Label(new Rect(((Rect)(ref rect)).x + 14f, ((Rect)(ref rect)).y + 12f, ((Rect)(ref rect)).width - 28f, 22f), "ПОДСКАЗКА", ArchitectStyle.TooltipTitle); GUI.Label(new Rect(((Rect)(ref rect)).x + 14f, ((Rect)(ref rect)).y + 40f, ((Rect)(ref rect)).width - 28f, 70f), "Наведите курсор на функцию, чтобы увидеть, что она делает.", ArchitectStyle.TooltipBody); } else { GUI.Label(new Rect(((Rect)(ref rect)).x + 14f, ((Rect)(ref rect)).y + 10f, ((Rect)(ref rect)).width - 28f, 24f), _hovered.Label, ArchitectStyle.TooltipTitle); GUI.Label(new Rect(((Rect)(ref rect)).x + 14f, ((Rect)(ref rect)).y + 38f, ((Rect)(ref rect)).width - 28f, 84f), _hovered.Description, ArchitectStyle.TooltipBody); } } } internal static class ArchitectStyle { public static readonly Color WoodDark = new Color(0.07f, 0.04f, 0.02f, 0.985f); public static readonly Color Wood = new Color(0.12f, 0.067f, 0.032f, 0.99f); public static readonly Color WoodLight = new Color(0.17f, 0.095f, 0.045f, 1f); public static readonly Color WoodHover = new Color(0.205f, 0.115f, 0.052f, 1f); public static readonly Color WoodPressed = new Color(0.25f, 0.14f, 0.06f, 1f); public static readonly Color Bronze = new Color(0.45f, 0.27f, 0.1f, 1f); public static readonly Color BronzeBright = new Color(0.73f, 0.47f, 0.16f, 1f); public static readonly Color Gold = new Color(0.88f, 0.69f, 0.27f, 1f); public static readonly Color GoldBright = new Color(1f, 0.84f, 0.42f, 1f); public static readonly Color Text = new Color(0.94f, 0.89f, 0.78f, 1f); public static readonly Color Muted = new Color(0.66f, 0.59f, 0.47f, 1f); public static readonly Color Dim = new Color(0.45f, 0.39f, 0.3f, 1f); public static readonly Color Blue = new Color(0.34f, 0.82f, 0.96f, 1f); public static readonly Color BlueSoft = new Color(0.1f, 0.18f, 0.21f, 1f); private static GUIStyle _window; private static GUIStyle _windowCompact; private static GUIStyle _header; private static GUIStyle _headerCompact; private static GUIStyle _title; private static GUIStyle _subtitle; private static GUIStyle _section; private static GUIStyle _feature; private static GUIStyle _featureOn; private static GUIStyle _featureIcon; private static GUIStyle _featureIconOn; private static GUIStyle _state; private static GUIStyle _stateOn; private static GUIStyle _stateOff; private static GUIStyle _hint; private static GUIStyle _tooltip; private static GUIStyle _tooltipTitle; private static GUIStyle _tooltipBody; private static GUIStyle _small; private static GUIStyle _credits; private static GUIStyle _resourceName; private static GUIStyle _resourceAmount; private static GUIStyle _resourceHeader; private static GUIStyle _close; private static GUIStyle _closeSmall; private static GUIStyle _resourceRowA; private static GUIStyle _resourceRowB; private static bool _initialized; public static GUIStyle Window => _window; public static GUIStyle WindowCompact => _windowCompact; public static GUIStyle Header => _header; public static GUIStyle HeaderCompact => _headerCompact; public static GUIStyle Title => _title; public static GUIStyle Subtitle => _subtitle; public static GUIStyle Section => _section; public static GUIStyle Feature => _feature; public static GUIStyle FeatureOn => _featureOn; public static GUIStyle FeatureIcon => _featureIcon; public static GUIStyle FeatureIconOn => _featureIconOn; public static GUIStyle StateOn => _stateOn; public static GUIStyle StateOff => _stateOff; public static GUIStyle Hint => _hint; public static GUIStyle Tooltip => _tooltip; public static GUIStyle TooltipTitle => _tooltipTitle; public static GUIStyle TooltipBody => _tooltipBody; public static GUIStyle Small => _small; public static GUIStyle Credits => _credits; public static GUIStyle ResourceName => _resourceName; public static GUIStyle ResourceAmount => _resourceAmount; public static GUIStyle ResourceHeader => _resourceHeader; public static GUIStyle Close => _close; public static GUIStyle CloseSmall => _closeSmall; public static GUIStyle ResourceRowA => _resourceRowA; public static GUIStyle ResourceRowB => _resourceRowB; public static void EnsureInitialized() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Expected O, but got Unknown //IL_006a: 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_0084: 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_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: 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_00ed: Expected O, but got Unknown //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_00fc: 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_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Expected O, but got Unknown //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Expected O, but got Unknown //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01af: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_01ec: Unknown result type (might be due to invalid IL or missing references) //IL_0211: 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_022b: Unknown result type (might be due to invalid IL or missing references) //IL_024f: 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_0276: Unknown result type (might be due to invalid IL or missing references) //IL_0280: Expected O, but got Unknown //IL_0284: Unknown result type (might be due to invalid IL or missing references) //IL_0298: Unknown result type (might be due to invalid IL or missing references) //IL_02ac: Unknown result type (might be due to invalid IL or missing references) //IL_02c0: Unknown result type (might be due to invalid IL or missing references) //IL_02db: Unknown result type (might be due to invalid IL or missing references) //IL_02e5: Expected O, but got Unknown //IL_02e9: Unknown result type (might be due to invalid IL or missing references) //IL_02fd: Unknown result type (might be due to invalid IL or missing references) //IL_0311: Unknown result type (might be due to invalid IL or missing references) //IL_0335: Unknown result type (might be due to invalid IL or missing references) //IL_034e: Unknown result type (might be due to invalid IL or missing references) //IL_0353: Unknown result type (might be due to invalid IL or missing references) //IL_0358: Unknown result type (might be due to invalid IL or missing references) //IL_037e: Unknown result type (might be due to invalid IL or missing references) //IL_0397: Unknown result type (might be due to invalid IL or missing references) //IL_039c: Unknown result type (might be due to invalid IL or missing references) //IL_03a1: Unknown result type (might be due to invalid IL or missing references) //IL_03c7: Unknown result type (might be due to invalid IL or missing references) //IL_03cc: Unknown result type (might be due to invalid IL or missing references) //IL_03f5: Unknown result type (might be due to invalid IL or missing references) //IL_03fa: Unknown result type (might be due to invalid IL or missing references) if (!_initialized) { _window = MakeFramedBox(WoodDark, Bronze, 4, 0.98f); _window.padding = new RectOffset(18, 18, 18, 16); _windowCompact = MakeFramedBox(WoodDark, Bronze, 4, 0.985f); _windowCompact.padding = new RectOffset(16, 16, 16, 14); _header = MakeFramedBox(Wood, BronzeBright, 3, 1f); _headerCompact = MakeFramedBox(Wood, BronzeBright, 3, 1f); _title = MakeLabel(24, (FontStyle)1, (TextAnchor)4, GoldBright, wrap: false); _subtitle = MakeLabel(11, (FontStyle)0, (TextAnchor)4, Muted, wrap: false); _section = MakeLabel(11, (FontStyle)1, (TextAnchor)3, Gold, wrap: false); _section.padding = new RectOffset(4, 0, 0, 0); _feature = MakeButton(Wood, WoodHover, WoodPressed, Text, 13, 44); _featureOn = MakeButton(new Color(0.17f, 0.12f, 0.065f, 1f), new Color(0.22f, 0.15f, 0.075f, 1f), new Color(0.29f, 0.19f, 0.09f, 1f), GoldBright, 13, 44); _feature.padding = new RectOffset(44, 88, 0, 0); _featureOn.padding = new RectOffset(44, 88, 0, 0); _featureIcon = MakeLabel(16, (FontStyle)1, (TextAnchor)4, BronzeBright, wrap: false); _featureIconOn = MakeLabel(16, (FontStyle)1, (TextAnchor)4, GoldBright, wrap: false); _state = MakeLabel(10, (FontStyle)1, (TextAnchor)4, Muted, wrap: false); _stateOn = MakePill(new Color(0.12f, 0.2f, 0.22f, 1f), Blue, 10); _stateOff = MakePill(new Color(0.12f, 0.075f, 0.035f, 1f), Muted, 10); _hint = MakeLabel(10, (FontStyle)0, (TextAnchor)4, Dim, wrap: false); _tooltip = MakeFramedBox(new Color(0.055f, 0.032f, 0.017f, 0.985f), Bronze, 2, 1f); _tooltip.padding = new RectOffset(14, 14, 11, 10); _tooltipTitle = MakeLabel(12, (FontStyle)1, (TextAnchor)3, GoldBright, wrap: false); _tooltipBody = MakeLabel(11, (FontStyle)0, (TextAnchor)0, Text, wrap: true); _small = MakeLabel(9, (FontStyle)0, (TextAnchor)4, Muted, wrap: false); _credits = MakeLabel(13, (FontStyle)1, (TextAnchor)4, GoldBright, wrap: true); _credits.padding = new RectOffset(10, 10, 2, 2); _resourceHeader = MakeLabel(16, (FontStyle)1, (TextAnchor)4, GoldBright, wrap: false); _resourceName = MakeLabel(13, (FontStyle)0, (TextAnchor)3, Text, wrap: false); _resourceAmount = MakeLabel(15, (FontStyle)1, (TextAnchor)5, GoldBright, wrap: false); _close = MakeButton(new Color(0.18f, 0.1f, 0.045f, 1f), new Color(0.29f, 0.17f, 0.07f, 1f), Bronze, Muted, 14, 0); _closeSmall = MakeButton(new Color(0.18f, 0.1f, 0.045f, 1f), new Color(0.29f, 0.17f, 0.07f, 1f), Bronze, Muted, 12, 0); _resourceRowA = MakeFramedBox(new Color(0.11f, 0.062f, 0.03f, 0.94f), Bronze, 1, 1f); _resourceRowB = MakeFramedBox(new Color(0.14f, 0.08f, 0.037f, 0.94f), BronzeSoft(), 1, 1f); _initialized = true; } } private static Color BronzeSoft() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) return new Color(0.3f, 0.17f, 0.065f, 1f); } private static GUIStyle MakeLabel(int size, FontStyle style, TextAnchor anchor, Color color, bool wrap) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: 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_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_001e: 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_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Expected O, but got Unknown //IL_0047: 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_0056: Expected O, but got Unknown //IL_0057: Expected O, but got Unknown GUIStyle val = new GUIStyle(GUI.skin.label) { fontSize = size, fontStyle = style, alignment = anchor, wordWrap = wrap }; val.normal.textColor = color; val.padding = new RectOffset(0, 0, 0, 0); val.margin = new RectOffset(0, 0, 0, 0); return val; } private static GUIStyle MakeButton(Color normal, Color hover, Color active, Color textColor, int fontSize, int dummy) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001e: 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_002b: 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_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0048: 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_004f: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008c: 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_00a5: Expected O, but got Unknown //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Expected O, but got Unknown //IL_00b5: Expected O, but got Unknown GUIStyle val = new GUIStyle(GUI.skin.button) { fontSize = fontSize, fontStyle = (FontStyle)1, alignment = (TextAnchor)3 }; val.normal.background = FramedTexture(normal, Bronze, 2); val.normal.textColor = textColor; val.hover.background = FramedTexture(hover, BronzeBright, 2); val.hover.textColor = GoldBright; val.active.background = FramedTexture(active, BronzeBright, 2); val.active.textColor = Color.white; val.border = new RectOffset(2, 2, 2, 2); val.margin = new RectOffset(0, 0, 4, 4); return val; } private static GUIStyle MakePill(Color bg, Color text, int fontSize) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: 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_001d: 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_002a: 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_003b: 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_0047: 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_0056: Expected O, but got Unknown //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_0065: Expected O, but got Unknown //IL_0066: Expected O, but got Unknown GUIStyle val = new GUIStyle(GUI.skin.label) { fontSize = fontSize, fontStyle = (FontStyle)1, alignment = (TextAnchor)4 }; val.normal.background = FramedTexture(bg, Bronze, 1); val.normal.textColor = text; val.border = new RectOffset(1, 1, 1, 1); val.padding = new RectOffset(8, 8, 3, 3); return val; } private static GUIStyle MakeFramedBox(Color fill, Color border, int thickness, float alpha) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Expected O, but got Unknown //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected O, but got Unknown //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Expected O, but got Unknown //IL_0067: Expected O, but got Unknown GUIStyle val = new GUIStyle(GUI.skin.box); val.normal.background = FramedTexture(new Color(fill.r, fill.g, fill.b, alpha), border, thickness); val.border = new RectOffset(thickness, thickness, thickness, thickness); val.padding = new RectOffset(0, 0, 0, 0); val.margin = new RectOffset(0, 0, 0, 0); return val; } private static Texture2D FramedTexture(Color fill, Color border, int thickness) { //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_0013: 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_0022: Expected O, but got Unknown //IL_00ad: 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_007a: 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_00a0: 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_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) Texture2D val = new Texture2D(48, 48, (TextureFormat)4, false) { hideFlags = (HideFlags)61, filterMode = (FilterMode)1, wrapMode = (TextureWrapMode)1 }; for (int i = 0; i < 48; i++) { float num = (Mathf.Sin((float)i * 0.55f) + Mathf.Sin((float)i * 0.17f)) * 0.012f; for (int j = 0; j < 48; j++) { Color val2 = (Color)((j < thickness || i < thickness || j >= 48 - thickness || i >= 48 - thickness) ? border : new Color(Mathf.Clamp01(fill.r + num), Mathf.Clamp01(fill.g + num * 0.7f), Mathf.Clamp01(fill.b + num * 0.45f), fill.a)); val.SetPixel(j, i, val2); } } val.Apply(); return val; } } internal sealed class BuildAssistController : IDisposable { private readonly ArchitectFeatures _features; private Camera _camera; private Material _lineMaterial; private bool _disposed; private bool _anchorValid; private bool _lastPinned; private Vector3 _anchor; private readonly bool[,] _blockedCells = new bool[12, 12]; private float _obstacleCheckTimer; private const float ObstacleCheckInterval = 0.12f; private const int CellCount = 12; private const float GridSize = 1f; private const int Half = 6; private const float PlaneLift = 0.035f; private const float ObstacleProbeHeight = 0.62f; public BuildAssistController(ArchitectFeatures features) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Expected O, but got Unknown //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown _features = features; Camera.onPostRender = (CameraCallback)Delegate.Combine((Delegate?)(object)Camera.onPostRender, (Delegate?)new CameraCallback(OnPostRender)); } public void Update() { if (_disposed) { return; } if ((Object)(object)_camera == (Object)null) { _camera = Camera.main; } if (!_features.AlignmentLines.Value) { _anchorValid = false; _lastPinned = false; Array.Clear(_blockedCells, 0, _blockedCells.Length); return; } if (_features.PinAlignmentGrid.Value && !_lastPinned) { CaptureAnchor(); } else if (!_features.PinAlignmentGrid.Value && _lastPinned) { _anchorValid = false; } _lastPinned = _features.PinAlignmentGrid.Value; if (!_features.PinAlignmentGrid.Value) { UpdateFollowAnchor(); } if (_anchorValid) { _obstacleCheckTimer -= Time.unscaledDeltaTime; if (_obstacleCheckTimer <= 0f) { _obstacleCheckTimer = 0.12f; RefreshBlockedCells(); } } } public bool TryGetAnchor(out Vector3 anchor) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) anchor = _anchor; return _anchorValid; } public void TogglePinned() { _features.PinAlignmentGrid.Value = !_features.PinAlignmentGrid.Value; if (_features.PinAlignmentGrid.Value) { CaptureAnchor(); } else { _anchorValid = false; } _lastPinned = _features.PinAlignmentGrid.Value; _obstacleCheckTimer = 0f; } private void CaptureAnchor() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0025: 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_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null)) { Vector3 position = ((Component)localPlayer).transform.position; float playerFootHeight = GetPlayerFootHeight(localPlayer); _anchor = new Vector3(position.x, playerFootHeight, position.z); _anchorValid = true; _obstacleCheckTimer = 0f; } } private void UpdateFollowAnchor() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0025: 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_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null)) { Vector3 position = ((Component)localPlayer).transform.position; float playerFootHeight = GetPlayerFootHeight(localPlayer); _anchor = new Vector3(position.x, playerFootHeight, position.z); _anchorValid = true; } } private void OnPostRender(Camera current) { if (!_disposed && _features.AlignmentLines.Value && !((Object)(object)current == (Object)null)) { if ((Object)(object)_camera == (Object)null) { _camera = Camera.main; } if (!((Object)(object)_camera == (Object)null) && !((Object)(object)current != (Object)(object)_camera) && _anchorValid) { DrawAlignmentLines(current); } } } private void DrawAlignmentLines(Camera current) { //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0099: 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_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_022c: Unknown result type (might be due to invalid IL or missing references) //IL_022d: Unknown result type (might be due to invalid IL or missing references) //IL_0237: Unknown result type (might be due to invalid IL or missing references) //IL_023c: Unknown result type (might be due to invalid IL or missing references) //IL_0246: Unknown result type (might be due to invalid IL or missing references) //IL_0247: Unknown result type (might be due to invalid IL or missing references) //IL_0251: Unknown result type (might be due to invalid IL or missing references) //IL_0256: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_0182: 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_018f: 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_0108: 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_01e2: Unknown result type (might be due to invalid IL or missing references) EnsureLineMaterial(); if ((Object)(object)_lineMaterial == (Object)null) { return; } Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(_anchor.x, _anchor.y + 0.035f, _anchor.z); _lineMaterial.SetPass(0); GL.Begin(1); float num = 6f; Vector3 val2 = default(Vector3); Vector3 end = default(Vector3); for (int i = 0; i <= 12; i++) { float num2 = 0f - num + (float)i * 1f; int num3 = i - 1; int num4 = i; for (int j = 0; j < 12; j++) { ((Vector3)(ref val2))..ctor(val.x - num + (float)j * 1f, val.y, val.z + num2); ((Vector3)(ref end))..ctor(val2.x + 1f, val.y, val2.z); bool blocked = (num3 >= 0 && num3 < 12 && _blockedCells[j, num3]) || (num4 >= 0 && num4 < 12 && _blockedCells[j, num4]); DrawSegment(val2, end, blocked, i == 6); } } Vector3 val3 = default(Vector3); Vector3 end2 = default(Vector3); for (int k = 0; k <= 12; k++) { float num5 = 0f - num + (float)k * 1f; int num6 = k - 1; int num7 = k; for (int l = 0; l < 12; l++) { ((Vector3)(ref val3))..ctor(val.x + num5, val.y, val.z - num + (float)l * 1f); ((Vector3)(ref end2))..ctor(val3.x, val.y, val3.z + 1f); bool blocked2 = (num6 >= 0 && num6 < 12 && _blockedCells[num6, l]) || (num7 >= 0 && num7 < 12 && _blockedCells[num7, l]); DrawSegment(val3, end2, blocked2, k == 6); } } GL.Color(new Color(0.35f, 0.95f, 1f, 1f)); GL.Vertex(val + Vector3.down * 1.25f); GL.Vertex(val + Vector3.up * 1.25f); GL.End(); } private void RefreshBlockedCells() { //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: 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_0117: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || !_anchorValid) { return; } float y = _anchor.y; float num = 6f; Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(0.47f, 0.31f, 0.47f); int num2 = -5; Array.Clear(_blockedCells, 0, _blockedCells.Length); for (int i = 0; i < 12; i++) { for (int j = 0; j < 12; j++) { float num3 = _anchor.x - num + ((float)i + 0.5f) * 1f; float num4 = _anchor.z - num + ((float)j + 0.5f) * 1f; Collider[] array = Physics.OverlapBox(new Vector3(num3, y + 0.035f + 0.31f, num4), val, Quaternion.identity, num2, (QueryTriggerInteraction)1); bool flag = false; foreach (Collider val2 in array) { if (!((Object)(object)val2 == (Object)null) && !((Object)(object)((Component)val2).transform == (Object)(object)((Component)localPlayer).transform) && !((Component)val2).transform.IsChildOf(((Component)localPlayer).transform)) { Bounds bounds = val2.bounds; if (((Bounds)(ref bounds)).max.y > y + 0.035f + 0.02f) { flag = true; break; } } } _blockedCells[i, j] = flag; } } } private float GetPlayerFootHeight(Player player) { //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_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_0118: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0107: 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_00c3: Unknown result type (might be due to invalid IL or missing references) RaycastHit[] array = Physics.RaycastAll(((Component)player).transform.position + Vector3.up * 0.6f, Vector3.down, 3f, -5, (QueryTriggerInteraction)1); float num = float.NegativeInfinity; for (int i = 0; i < array.Length; i++) { Collider collider = ((RaycastHit)(ref array[i])).collider; if (!((Object)(object)collider == (Object)null) && !((Object)(object)((Component)collider).transform == (Object)(object)((Component)player).transform) && !((Component)collider).transform.IsChildOf(((Component)player).transform) && ((RaycastHit)(ref array[i])).point.y <= ((Component)player).transform.position.y + 0.5f && ((RaycastHit)(ref array[i])).point.y > num) { num = ((RaycastHit)(ref array[i])).point.y; } } if (num > float.NegativeInfinity) { return num; } Collider component = ((Component)player).GetComponent<Collider>(); if ((Object)(object)component != (Object)null && component.enabled) { Bounds bounds = component.bounds; return ((Bounds)(ref bounds)).min.y; } return ((Component)player).transform.position.y - 0.9f; } private void DrawSegment(Vector3 start, Vector3 end, bool blocked, bool center) { //IL_0051: 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_0061: 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_001b: Unknown result type (might be due to invalid IL or missing references) GL.Color(blocked ? new Color(1f, 0.1f, 0.1f, 1f) : (center ? new Color(0.35f, 0.95f, 1f, 1f) : new Color(1f, 0.9f, 0.25f, 1f))); GL.Vertex(start); GL.Vertex(end); } private void EnsureLineMaterial() { //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_0038: Expected O, but got Unknown if (!((Object)(object)_lineMaterial != (Object)null)) { Shader val = Shader.Find("Hidden/Internal-Colored"); if (!((Object)(object)val == (Object)null)) { _lineMaterial = new Material(val) { hideFlags = (HideFlags)61 }; _lineMaterial.SetInt("_SrcBlend", 5); _lineMaterial.SetInt("_DstBlend", 10); _lineMaterial.SetInt("_Cull", 0); _lineMaterial.SetInt("_ZWrite", 0); _lineMaterial.SetInt("_ZTest", 8); } } } public void Dispose() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Expected O, but got Unknown //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown if (!_disposed) { _disposed = true; Camera.onPostRender = (CameraCallback)Delegate.Remove((Delegate?)(object)Camera.onPostRender, (Delegate?)new CameraCallback(OnPostRender)); if ((Object)(object)_lineMaterial != (Object)null) { Object.Destroy((Object)(object)_lineMaterial); _lineMaterial = null; } } } } internal sealed class FeatureToggle { public string Label { get; } public string Description { get; } public ConfigEntry<bool> Config { get; } public bool Value { get { return Config.Value; } set { Config.Value = value; } } public FeatureToggle(string label, string description, ConfigEntry<bool> config) { Label = label; Description = description; Config = config; } } internal sealed class GhostLayoutController : IDisposable { private sealed class BlueprintPiece { public string PrefabName; public Vector3 Position; public Quaternion Rotation; } [HarmonyPatch(typeof(ZNetView), "Awake")] private static class ZNetViewGhostSpawnPatch { private static bool Prefix() { return !IsGhostSpawnInProgress; } } [HarmonyPatch] private static class PlayerHaveRequirementsPatch { private static IEnumerable<MethodBase> TargetMethods() { MethodInfo[] methods = typeof(Player).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { if (!(methodInfo.Name != "HaveRequirements") && !(methodInfo.ReturnType != typeof(bool))) { ParameterInfo[] parameters = methodInfo.GetParameters(); if (parameters.Length != 0 && parameters[0].ParameterType == typeof(Piece)) { yield return methodInfo; } } } } private static bool Prefix(Player __instance, object[] __args, ref bool __result) { if (!IsGhostModeActive(__instance)) { return true; } Piece val = null; if (__args != null) { foreach (object obj in __args) { Piece val2 = (Piece)((obj is Piece) ? obj : null); if (val2 != null) { val = val2; break; } } } if ((Object)(object)val == (Object)null || !IsPieceUnlocked(__instance, val)) { return true; } __result = true; return false; } } [HarmonyPatch] private static class PlayerConsumeResourcesPatch { private static IEnumerable<MethodBase> TargetMethods() { MethodInfo[] methods = typeof(Player).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { if (methodInfo.Name == "ConsumeResources") { yield return methodInfo; } } } private static bool Prefix(Player __instance) { if (!IsGhostModeActive(__instance)) { return true; } Piece val = null; try { val = __instance.GetSelectedPiece(); } catch { return true; } if ((Object)(object)val == (Object)null || !IsPieceUnlocked(__instance, val)) { return true; } return false; } } [HarmonyPatch] private static class PlayerGetPlaceDurabilityPatch { private static IEnumerable<MethodBase> TargetMethods() { MethodInfo[] methods = typeof(Player).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { if (!(methodInfo.Name != "GetPlaceDurability") && !(methodInfo.ReturnType != typeof(float))) { ParameterInfo[] parameters = methodInfo.GetParameters(); if (parameters.Length == 1 && parameters[0].ParameterType == typeof(ItemData)) { yield return methodInfo; } } } } private static bool Prefix(ItemData __0, ref float __result) { if (!IsGhostBuildToolItem(__0)) { return true; } __result = 0f; return false; } } [HarmonyPatch] private static class HumanoidDrainEquippedItemDurabilityPatch { private static IEnumerable<MethodBase> TargetMethods() { MethodInfo[] methods = typeof(Humanoid).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { if (!(methodInfo.Name != "DrainEquipedItemDurability")) { ParameterInfo[] parameters = methodInfo.GetParameters(); if (parameters.Length >= 1 && parameters[0].ParameterType == typeof(ItemData)) { yield return methodInfo; } } } } private static bool Prefix(Humanoid __instance, object[] __args) { if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer) { return true; } ItemData item = null; if (__args != null) { foreach (object obj in __args) { ItemData val = (ItemData)((obj is ItemData) ? obj : null); if (val != null) { item = val; break; } } } if (!IsGhostBuildToolItem(item)) { return true; } return false; } } [HarmonyPatch] private static class PlayerCheckCanRemovePiecePatch { private static IEnumerable<MethodBase> TargetMethods() { MethodInfo[] methods = typeof(Player).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { if (methodInfo.Name == "CheckCanRemovePiece" && methodInfo.ReturnType == typeof(bool)) { yield return methodInfo; } } } private static bool Prefix(Player __instance, object[] __args, ref bool __result) { if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer) { return true; } Piece val = null; if (__args != null) { foreach (object obj in __args) { Piece val2 = (Piece)((obj is Piece) ? obj : null); if (val2 != null) { val = val2; break; } } } if ((Object)(object)val != (Object)null && ValheimArchitectPlugin.Instance?.Ghost != null && ValheimArchitectPlugin.Instance.Ghost.IsGhostPiece(val)) { __result = true; return false; } return true; } } [HarmonyPatch] private static class PlayerRemovePiecePatch { private static IEnumerable<MethodBase> TargetMethods() { MethodInfo[] methods = typeof(Player).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { if (methodInfo.Name == "RemovePiece" && methodInfo.ReturnType == typeof(bool)) { yield return methodInfo; } } } private static bool Prefix(Player __instance, ref bool __result) { if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer) { return true; } GhostLayoutController ghostLayoutController = ValheimArchitectPlugin.Instance?.Ghost; if (ghostLayoutController == null) { return true; } if (ghostLayoutController.TryRemoveGhostUnderCrosshair(__instance)) { __result = true; return false; } return true; } } [HarmonyPatch(typeof(Player), "PlacePiece")] private static class PlayerPlacePiecePatch { private static bool Prefix(Player __instance, Piece piece, Vector3 pos, Quaternion rot, bool doAttack) { //IL_003b: 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) if (!IsGhostModeActive(__instance)) { return true; } ValheimArchitectPlugin instance = ValheimArchitectPlugin.Instance; if (instance?.Ghost == null || (Object)(object)piece == (Object)null) { return true; } if (!IsPieceUnlocked(__instance, piece)) { return true; } instance.Ghost.CreateGhost(piece, pos, rot, saveToBlueprint: true); return false; } } private readonly ArchitectFeatures _features; private readonly Harmony _harmony; private readonly List<GameObject> _ghosts = new List<GameObject>(); private readonly Dictionary<GameObject, BlueprintPiece> _ghostToBlueprint = new Dictionary<GameObject, BlueprintPiece>(); private readonly List<BlueprintPiece> _blueprint = new List<BlueprintPiece>(); private readonly List<string> _pieceNames = new List<string>(); private readonly string _blueprintFile; private bool _disposed; private int _blueprintRevision; private readonly Dictionary<string, List<ResourceCostLine>> _resourceCostCache = new Dictionary<string, List<ResourceCostLine>>(StringComparer.Ordinal); private readonly Dictionary<string, Piece> _prefabPieceCache = new Dictionary<string, Piece>(StringComparer.Ordinal); private readonly Dictionary<string, string> _localizedNameCache = new Dictionary<string, string>(StringComparer.Ordinal); private bool _loadedForCurrentScene; private bool _lastGhostMode; private int _loadCooldownFrames; private const string HarmonyId = "ValheimArchitect.GhostLayout"; internal static bool IsGhostSpawnInProgress; private static MethodInfo _isRecipeKnownMethod; private static FieldInfo _knownRecipesField; private static MethodInfo _localizeMethod; private static object _localizeInstance; public IReadOnlyList<string> PieceNames => _pieceNames; public int GhostCount => _ghosts.Count; public int BlueprintCount => _blueprint.Count; public int BlueprintRevision => _blueprintRevision; public bool HasSavedBlueprint { get { if (File.Exists(_blueprintFile)) { return _blueprint.Count > 0; } return false; } } public GhostLayoutController(ArchitectFeatures features) { //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Expected O, but got Unknown _features = features; _harmony = new Harmony("ValheimArchitect.GhostLayout"); _harmony.PatchAll(typeof(GhostLayoutController).Assembly); string text = Path.Combine(Paths.ConfigPath, "ValheimArchitect"); Directory.CreateDirectory(text); _blueprintFile = Path.Combine(text, "LastBlueprint.va"); LoadBlueprintFile(); _lastGhostMode = _features.GhostLayout.Value; SceneManager.sceneUnloaded += OnSceneUnloaded; SceneManager.sceneLoaded += OnSceneLoaded; } private static bool IsGhostModeActive(Player player) { ValheimArchitectPlugin instance = ValheimArchitectPlugin.Instance; if ((Object)(object)instance != (Object)null && instance.Ghost != null && instance.Features != null && instance.Features.GhostLayout.Value && (Object)(object)player != (Object)null) { return (Object)(object)player == (Object)(object)Player.m_localPlayer; } return false; } private static bool IsPieceUnlocked(Player player, Piece piece) { if ((Object)(object)player == (Object)null || (Object)(object)piece == (Object)null || string.IsNullOrWhiteSpace(piece.m_name)) { return false; } try { if (_isRecipeKnownMethod == null) { _isRecipeKnownMethod = typeof(Player).GetMethod("IsRecipeKnown", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(string) }, null); } if (_isRecipeKnownMethod != null && _isRecipeKnownMethod.Invoke(player, new object[1] { piece.m_name }) is bool result) { return result; } } catch { } try { if (_knownRecipesField == null) { _knownRecipesField = typeof(Player).GetField("m_knownRecipes", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } if (_knownRecipesField?.GetValue(player) is IEnumerable enumerable) { foreach (object item in enumerable) { if (item is string a && string.Equals(a, piece.m_name, StringComparison.Ordinal)) { return true; } } } } catch { } return false; } public void Update() { if (_disposed) { return; } bool value = _features.GhostLayout.Value; if (Input.GetKeyDown((KeyCode)292) && value) { ClearAndForgetBlueprint(); } if (value != _lastGhostMode) { _lastGhostMode = value; if (value) { _loadedForCurrentScene = false; _loadCooldownFrames = 10; } else { DestroyGhostObjectsOnly(); } } if (value && !_loadedForCurrentScene) { if (_loadCooldownFrames > 0) { _loadCooldownFrames--; } else { TryRestoreBlueprint(); } } } private void OnSceneLoaded(Scene scene, LoadSceneMode mode) { _loadedForCurrentScene = false; _loadCooldownFrames = 30; } private static bool IsGhostBuildToolItem(ItemData item) { if (item == null || item.m_shared == null || (Object)(object)item.m_shared.m_buildPieces == (Object)null) { return false; } Player localPlayer = Player.m_localPlayer; if (!IsGhostModeActive(localPlayer)) { return false; } try { Piece selectedPiece = localPlayer.GetSelectedPiece(); return (Object)(object)selectedPiece != (Object)null && IsPieceUnlocked(localPlayer, selectedPiece); } catch { return false; } } private void CreateGhost(Piece source, Vector3 position, Quaternion rotation, bool saveToBlueprint, BlueprintPiece existingBlueprint = null) { //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: 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) if ((Object)(object)source == (Object)null || (Object)(object)((Component)source).gameObject == (Object)null) { return; } string text = ((Object)((Component)source).gameObject).name.Replace("(Clone)", string.Empty).Trim(); if (string.IsNullOrWhiteSpace(text)) { text = ((Object)source).name.Replace("(Clone)", string.Empty).Trim(); } GameObject val; try { IsGhostSpawnInProgress = true; val = Object.Instantiate<GameObject>(((Component)source).gameObject, position, rotation); } catch (Exception arg) { ValheimArchitectPlugin.Log.LogError((object)$"Ghost instantiate failed: {arg}"); return; } finally { IsGhostSpawnInProgress = false; } PrepareGhostVisual(val); _ghosts.Add(val); _pieceNames.Add(text); BlueprintPiece blueprintPiece = existingBlueprint; if (blueprintPiece == null && saveToBlueprint) { blueprintPiece = new BlueprintPiece { PrefabName = text, Position = position, Rotation = rotation }; _blueprint.Add(blueprintPiece); _blueprintRevision++; SaveBlueprintFile(); } if (blueprintPiece != null) { _ghostToBlueprint[val] = blueprintPiece; } } private static void PrepareGhostVisual(GameObject ghost) { if ((Object)(object)ghost == (Object)null) { return; } ((Object)ghost).name = "[ValheimArchitect Ghost] " + ((Object)ghost).name; ((Object)ghost).hideFlags = (HideFlags)61; Behaviour[] componentsInChildren = ghost.GetComponentsInChildren<Behaviour>(true); foreach (Behaviour val in componentsInChildren) { if ((Object)(object)val != (Object)null && !(val is Piece)) { val.enabled = false; } } int num = LayerMask.NameToLayer("piece_nonsolid"); int num2 = LayerMask.NameToLayer("piece"); int num3 = ((num >= 0) ? num : num2); if (num3 >= 0) { SetLayerRecursively(ghost.transform, num3); } Collider[] componentsInChildren2 = ghost.GetComponentsInChildren<Collider>(true); foreach (Collider val2 in componentsInChildren2) { if ((Object)(object)val2 != (Object)null) { val2.enabled = true; val2.isTrigger = false; } } Rigidbody[] componentsInChildren3 = ghost.GetComponentsInChildren<Rigidbody>(true); foreach (Rigidbody val3 in componentsInChildren3) { if ((Object)(object)val3 != (Object)null) { val3.isKinematic = true; val3.detectCollisions = false; } } ZNetView[] componentsInChildren4 = ghost.GetComponentsInChildren<ZNetView>(true); for (int i = 0; i < componentsInChildren4.Length; i++) { Object.Destroy((Object)(object)componentsInChildren4[i]); } WearNTear[] componentsInChildren5 = ghost.GetComponentsInChildren<WearNTear>(true); for (int i = 0; i < componentsInChildren5.Length; i++) { Object.Destroy((Object)(object)componentsInChildren5[i]); } ApplyGhostMaterials(ghost); } private static void SetLayerRecursively(Transform root, int layer) { ((Component)root).gameObject.layer = layer; for (int i = 0; i < root.childCount; i++) { SetLayerRecursively(root.GetChild(i), layer); } } private static void ApplyGhostMaterials(GameObject ghost) { //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Expected O, but got Unknown //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Expected O, but got Unknown if ((Object)(object)ghost == (Object)null) { return; } Renderer[] componentsInChildren = ghost.GetComponentsInChildren<Renderer>(true); foreach (Renderer val in componentsInChildren) { if ((Object)(object)val == (Object)null) { continue; } Material[] sharedMaterials = val.sharedMaterials; Material[] array = (Material[])(object)new Material[sharedMaterials.Length]; for (int j = 0; j < sharedMaterials.Length; j++) { Material val2 = sharedMaterials[j]; if ((Object)(object)val2 == (Object)null) { continue; } Material val3 = null; try { val3 = new Material(val2); ConfigureGhostMaterial(val3); } catch { val3 = null; } if ((Object)(object)val3 == (Object)null) { Shader val4 = Shader.Find("Unlit/Transparent") ?? Shader.Find("Legacy Shaders/Transparent/Diffuse") ?? Shader.Find("Standard"); if ((Object)(object)val4 != (Object)null) { try { val3 = new Material(val4); if (val2.HasProperty("_MainTex") && val3.HasProperty("_MainTex")) { val3.SetTexture("_MainTex", val2.GetTexture("_MainTex")); } if (val2.HasProperty("_BaseMap") && val3.HasProperty("_BaseMap")) { val3.SetTexture("_BaseMap", val2.GetTexture("_BaseMap")); } ConfigureGhostMaterial(val3); } catch { val3 = null; } } } array[j] = val3 ?? val2; } val.materials = array; val.receiveShadows = false; val.shadowCastingMode = (ShadowCastingMode)0; } } private static void ConfigureGhostMaterial(Material mat) { //IL_003a: 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_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_007c: 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_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0124: 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_0164: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)mat == (Object)null)) { Color val = default(Color); ((Color)(ref val))..ctor(0.42f, 0.88f, 1f, 0.58f); bool flag = false; if (mat.HasProperty("_BaseColor")) { Color color = mat.GetColor("_BaseColor"); color.r = Mathf.Lerp(color.r, val.r, 0.55f); color.g = Mathf.Lerp(color.g, val.g, 0.55f); color.b = Mathf.Lerp(color.b, val.b, 0.55f); color.a = val.a; mat.SetColor("_BaseColor", color); flag = true; } if (mat.HasProperty("_Color")) { Color color2 = mat.GetColor("_Color"); color2.r = Mathf.Lerp(color2.r, val.r, 0.55f); color2.g = Mathf.Lerp(color2.g, val.g, 0.55f); color2.b = Mathf.Lerp(color2.b, val.b, 0.55f); color2.a = val.a; mat.SetColor("_Color", color2); flag = true; } if (mat.HasProperty("_EmissionColor")) { mat.SetColor("_EmissionColor", new Color(0.1f, 0.55f, 0.75f, 1f)); mat.EnableKeyword("_EMISSION"); } if (mat.HasProperty("_Mode")) { mat.SetFloat("_Mode", 3f); } if (mat.HasProperty("_Surface")) { mat.SetFloat("_Surface", 1f); } if (mat.HasProperty("_Blend")) { mat.SetFloat("_Blend", 0f); } if (mat.HasProperty("_SrcBlend")) { mat.SetInt("_SrcBlend", 5); } if (mat.HasProperty("_DstBlend")) { mat.SetInt("_DstBlend", 10); } if (mat.HasProperty("_ZWrite")) { mat.SetInt("_ZWrite", 0); } if (mat.HasProperty("_AlphaClip")) { mat.SetFloat("_AlphaClip", 0f); } if (mat.HasProperty("_Cutoff")) { mat.SetFloat("_Cutoff", 0f); } mat.DisableKeyword("_ALPHATEST_ON"); mat.EnableKeyword("_ALPHABLEND_ON"); mat.EnableKeyword("_SURFACE_TYPE_TRANSPARENT"); mat.renderQueue = 3000; if (!flag) { mat.renderQueue = -1; } } } internal bool IsGhostPiece(Piece piece) { if ((Object)(object)piece == (Object)null) { return false; } if ((Object)(object)((Component)piece).gameObject == (Object)null) { return false; } foreach (GameObject ghost in _ghosts) { if (!((Object)(object)ghost == (Object)null) && ((Object)(object)((Component)piece).transform == (Object)(object)ghost.transform || ((Component)piece).transform.IsChildOf(ghost.transform))) { return true; } } return false; } internal bool TryRemoveGhostUnderCrosshair(Player player) { //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: 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_00fc: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null || (Object)(object)GameCamera.instance == (Object)null || !Object.op_Implicit((Object)(object)GameCamera.instance) || _ghosts.Count == 0) { return false; } try { int num = -5; FieldInfo fieldInfo = AccessTools.Field(typeof(Player), "m_removeRayMask"); if (fieldInfo != null) { num = (int)fieldInfo.GetValue(player); } float num2 = 4f; FieldInfo fieldInfo2 = AccessTools.Field(typeof(Player), "m_maxPlaceDistance"); if (fieldInfo2 != null) { num2 = Mathf.Max(1f, (float)fieldInfo2.GetValue(player)); } Vector3 position = ((Component)GameCamera.instance).transform.position; Vector3 forward = ((Component)GameCamera.instance).transform.forward; RaycastHit[] array = Physics.RaycastAll(position, forward, num2, num); Array.Sort(array, (RaycastHit a, RaycastHit b) => ((RaycastHit)(ref a)).distance.CompareTo(((RaycastHit)(ref b)).distance)); RaycastHit[] array2 = array; for (int num3 = 0; num3 < array2.Length; num3++) { RaycastHit val = array2[num3]; if (!((Object)(object)((RaycastHit)(ref val)).collider == (Object)null)) { GameObject gameObject = ((Component)((RaycastHit)(ref val)).collider).gameObject; while ((Object)(object)gameObject != (Object)null && !IsTrackedGhostRoot(gameObject) && !((Object)(object)gameObject.transform.parent == (Object)null)) { gameObject = ((Component)gameObject.transform.parent).gameObject; } if (!((Object)(object)gameObject == (Object)null) && IsTrackedGhostRoot(gameObject)) { return RemoveGhostObject(gameObject); } } } } catch (Exception ex) { ValheimArchitectPlugin.Log.LogWarning((object)("Ghost removal check failed: " + ex.Message)); } return false; } private bool IsTrackedGhostRoot(GameObject go) { if ((Object)(object)go != (Object)null) { return _ghosts.Contains(go); } return false; } private bool RemoveGhostObject(GameObject ghost) { if ((Object)(object)ghost == (Object)null) { return false; } if (!_ghostToBlueprint.TryGetValue(ghost, out var value) || value == null) { value = FindBlueprintRecordForGhost(ghost); } int num = ((value != null) ? _blueprint.IndexOf(value) : (-1)); if (value != null) { _blueprint.Remove(value); _blueprintRevision++; } _ghostToBlueprint.Remove(ghost); _ghosts.Remove(ghost); if (num >= 0 && num < _pieceNames.Count) { _pieceNames.RemoveAt(num); } Object.Destroy((Object)(object)ghost); SaveBlueprintFile(); return true; } private BlueprintPiece FindBlueprintRecordForGhost(GameObject ghost) { //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ghost == (Object)null) { return null; } string b = ((Object)ghost).name.Replace("[ValheimArchitect Ghost] ", string.Empty).Replace("(Clone)", string.Empty).Trim(); BlueprintPiece result = null; float num = 0.08f; foreach (BlueprintPiece item in _blueprint) { if (string.Equals(item.PrefabName, b, StringComparison.Ordinal)) { float num2 = Vector3.Distance(item.Position, ghost.transform.position); if (num2 < num) { num = num2; result = item; } } } return result; } private void TryRestoreBlueprint() { //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) if (_blueprint.Count == 0) { _loadedForCurrentScene = true; } else { if ((Object)(object)Player.m_localPlayer == (Object)null) { return; } ZNetScene val = Object.FindObjectOfType<ZNetScene>(); if ((Object)(object)val == (Object)null) { return; } int num = 0; int num2 = 0; foreach (BlueprintPiece item in _blueprint) { GameObject val2 = FindPrefab(val, item.PrefabName); Piece val3 = (((Object)(object)val2 != (Object)null) ? val2.GetComponent<Piece>() : null); if (!((Object)(object)val3 == (Object)null)) { if (!IsPieceUnlocked(Player.m_localPlayer, val3)) { num2++; continue; } CreateGhost(val3, item.Position, item.Rotation, saveToBlueprint: false, item); num++; } } _loadedForCurrentScene = true; ValheimArchitectPlugin.Log.LogInfo((object)$"Blueprint restored: {num}/{_blueprint.Count} ghost pieces. Hidden locked pieces: {num2}."); } } private static GameObject FindPrefab(ZNetScene znet, string prefabName) { if ((Object)(object)znet == (Object)null || string.IsNullOrWhiteSpace(prefabName)) { return null; } try { MethodInfo method = typeof(ZNetScene).GetMethod("GetPrefab", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(string) }, null); if (method != null) { object? obj = method.Invoke(znet, new object[1] { prefabName }); return (GameObject)((obj is GameObject) ? obj : null); } } catch { } Transform[] componentsInChildren = ((Component)znet).GetComponentsInChildren<Transform>(true); foreach (Transform val in componentsInChildren) { if ((Object)(object)val != (Object)null && ((Object)val).name == prefabName) { return ((Component)val).gameObject; } } return null; } internal List<ResourceCostLine> GetResourceCosts() { Dictionary<string, int> dictionary = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase); Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || _blueprint.Count == 0) { return new List<ResourceCostLine>(); } ZNetScene val = Object.FindObjectOfType<ZNetScene>(); if ((Object)(object)val == (Object)null) { return new List<ResourceCostLine>(); } Dictionary<string, int> dictionary2 = new Dictionary<string, int>(StringComparer.Ordinal); foreach (BlueprintPiece item in _blueprint) { if (!string.IsNullOrWhiteSpace(item.PrefabName)) { dictionary2.TryGetValue(item.PrefabName, out var value); dictionary2[item.PrefabName] = value + 1; } } foreach (KeyValuePair<string, int> item2 in dictionary2) { Piece cachedPiece = GetCachedPiece(val, item2.Key); if ((Object)(object)cachedPiece == (Object)null || !IsPieceUnlocked(localPlayer, cachedPiece)) { continue; } foreach (ResourceCostLine item3 in GetCachedResourceCostsForPrefab(item2.Key, cachedPiece)) { if (!dictionary.ContainsKey(item3.Name)) { dictionary[item3.Name] = 0; } dictionary[item3.Name] += item3.Amount * item2.Value; } } List<ResourceCostLine> list = new List<ResourceCostLine>(); foreach (KeyValuePair<string, int> item4 in dictionary) { list.Add(new ResourceCostLine(item4.Key, item4.Value)); } list.Sort((ResourceCostLine a, ResourceCostLine b) => string.Compare(a.Name, b.Name, StringComparison.CurrentCultureIgnoreCase)); return list; } private Piece GetCachedPiece(ZNetScene znet, string prefabName) { if (_prefabPieceCache.TryGetValue(prefabName, out var value) && (Object)(object)value != (Object)null) { return value; } GameObject val = FindPrefab(znet, prefabName); Piece val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<Piece>() : null); _prefabPieceCache[prefabName] = val2; return val2; } private List<ResourceCostLine> GetCachedResourceCostsForPrefab(string prefabName, Piece piece) { if (_resourceCostCache.TryGetValue(prefabName, out var value)) { return value; } List<ResourceCostLine> list = new List<ResourceCostLine>(); try { if (GetMemberValue(piece, "m_resources") is IEnumerable enumerable) { foreach (object item in enumerable) { if (item == null) { continue; } int intMember = GetIntMember(item, "m_amount"); if (intMember <= 0) { continue; } object memberValue = GetMemberValue(item, "m_resItem"); string resourceName = GetResourceDisplayName(memberValue); if (!string.IsNullOrWhiteSpace(resourceName)) { ResourceCostLine resourceCostLine = list.Find((ResourceCostLine x) => string.Equals(x.Name, resourceName, StringComparison.OrdinalIgnoreCase)); if (resourceCostLine != null) { resourceCostLine.Amount += intMember; } else { list.Add(new ResourceCostLine(resourceName, intMember)); } } } } } catch (Exception ex) { ValheimArchitectPlugin.Log.LogWarning((object)("Resource calculator failed for '" + prefabName + "': " + ex.Message)); } _resourceCostCache[prefabName] = list; return list; } internal static int GetKnownRecipeSignature(Player player) { if ((Object)(object)player == (Object)null) { return 0; } try { if (_knownRecipesField == null) { _knownRecipesField = typeof(Player).GetField("m_knownRecipes", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } if (!(_knownRecipesField?.GetValue(player) is IEnumerable enumerable)) { return 0; } int num = 17; foreach (object item in enumerable) { num = ((!(item is string obj)) ? (num * 31 + (item?.GetHashCode() ?? 0)) : (num * 31 + StringComparer.Ordinal.GetHashCode(obj))); } return num; } catch { return 0; } } private static object GetMemberValue(object target, string memberName) { if (target == null) { return null; } Type type = target.GetType(); FieldInfo field = type.GetField(memberName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { return field.GetValue(target); } PropertyInfo property = type.GetProperty(memberName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (property != null && property.CanRead) { return property.GetValue(target, null); } return null; } private static int GetIntMember(object target, string memberName) { object memberValue = GetMemberValue(target, memberName); if (memberValue == null) { return 0; } try { return Convert.ToInt32(memberValue, CultureInfo.InvariantCulture); } catch { return 0; } } private string GetResourceDisplayName(object itemDrop) { if (itemDrop == null) { return null; } string text = GetMemberValue(GetMemberValue(GetMemberValue(itemDrop, "m_itemData"), "m_shared"), "m_name") as string; if (string.IsNullOrWhiteSpace(text)) { return null; } text = text.Trim(); if (_localizedNameCache.TryGetValue(text, out var value)) { return value; } string text2 = null; try { Type type = AccessTools.TypeByName("Localization"); if (type != null) { if (_localizeMethod == null) { MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { if (string.Equals(methodInfo.Name, "Localize", StringComparison.Ordinal)) { ParameterInfo[] parameters = methodInfo.GetParameters(); if (parameters.Length == 1 && parameters[0].ParameterType == typeof(string) && methodInfo.ReturnType == typeof(string)) { _localizeMethod = methodInfo; break; } } } } if (_localizeInstance == null) { _localizeInstance = type.GetField("instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(null); } if (_localizeMethod != null && _localizeInstance != null) { text2 = _localizeMethod.Invoke(_localizeInstance, new object[1] { text }) as string; if ((string.IsNullOrWhiteSpace(text2) || string.Equals(text2, text, StringComparison.Ordinal)) && !text.StartsWith("$", StringComparison.Ordinal)) { text2 = _localizeMethod.Invoke(_localizeInstance, new object[1] { "$item_" + text.ToLowerInvariant() }) as string; } } } } catch { text2 = null; } string text3 = StripRichText(text2 ?? string.Empty).Trim(); if (string.IsNullOrWhiteSpace(text3) || string.Equals(text3, text, StringComparison.Ordinal)) { text3 = RussianResourceName(text); if (string.IsNullOrWhiteSpace(text3)) { text3 = text.TrimStart('$'); if (text3.StartsWith("item_", StringComparison.OrdinalIgnoreCase)) { text3 = text3.Substring(5); } text3 = text3.Replace('_', ' '); if (!string.IsNullOrWhiteSpace(text3)) { text3 = char.ToUpper(text3[0]) + text3.Substring(1); } } } _localizedNameCache[text] = text3; return text3; } private static string RussianResourceName(string rawName) { if (string.IsNullOrWhiteSpace(rawName)) { return null; } string text = rawName.Trim().TrimStart('$'); if (text.StartsWith("item_", StringComparison.OrdinalIgnoreCase)) { text = text.Substring(5); } return text.ToLowerInvariant() switch { "wood" => "Древесина", "finewood" => "Тонкая древесина", "corewood" => "Цельная древесина", "yggdrasilwood" => "Древесина Иггдрасиля", "stone" => "Камень", "resin" => "Смола", "coal" => "Уголь", "iron" => "Железо", "ironscrap" => "Железный лом", "bronze" => "Бронза", "copper" => "Медь", "tin" => "Олово", "silver" => "Серебро", "blackmetal" => "Чёрный металл", "ancientbark" => "Древняя кора", "tar" => "Дёготь", "crystal" => "Кристалл", "flametal" => "Огненный металл", "blackmarble" => "Чёрный мрамор", "bronzenails" => "Бронзовые гвозди", "ironnails" => "Железные гвозди", "surtlingcore" => "Ядро суртлинга", "trollhide" => "Шкура тролля", "sulfurnstone" => "Серный камень", "sulfurstone" => "Серный камень", "proustitepowder" => "Порошок прустита", "barberkit" => "Набор парикмахера", "witheredbone" => "Иссохшая кость", "chain" => "Цепь", "eitr" => "Эйтр", "refinedeitr" => "Очищенный эйтр", "sap" => "Сок", "softtissue" => "Мягкая ткань", "blackcore" => "Чёрное ядро", "mandible" => "Нижняя челюсть", "needle" => "Игла", "guck" => "Слизь", "bilebag" => "Желчный мешок", "bloodbag" => "Кровяной мешок", "jotunpuffs" => "Пуховка йотунов", "yggdrasilpith" => "Сердцевина Иггдрасиля", "crystals" => "Кристаллы", "greydwarfeye" => "Глаз грейдворфа", "flax" => "Лён", "linen" => "Льняная нить", "witheringbone" => "Иссохшая кость", _ => null, }; } private static string StripRichText(string value) { if (string.IsNullOrWhiteSpace(value)) { return value; } return Regex.Replace(value, "<.*?>", string.Empty); } private void SaveBlueprintFile() { try { using StreamWriter streamWriter = new StreamWriter(_blueprintFile, append: false); streamWriter.WriteLine("VALHEIM_ARCHITECT_BLUEPRINT_V1"); foreach (BlueprintPiece item in _blueprint) { streamWriter.Write(item.PrefabName.Replace("\t", "_")); streamWriter.Write('\t'); streamWriter.Write(item.Position.x.ToString("R", CultureInfo.InvariantCulture)); streamWriter.Write('\t'); streamWriter.Write(item.Position.y.ToString("R", CultureInfo.InvariantCulture)); streamWriter.Write('\t'); streamWriter.Write(item.Position.z.ToString("R", CultureInfo.InvariantCulture)); streamWriter.Write('\t'); streamWriter.Write(item.Rotation.x.ToString("R", CultureInfo.InvariantCulture)); streamWriter.Write('\t'); streamWriter.Write(item.Rotation.y.ToString("R", CultureInfo.InvariantCulture)); streamWriter.Write('\t'); streamWriter.Write(item.Rotation.z.ToString("R", CultureInfo.InvariantCulture)); streamWriter.Write('\t'); streamWriter.WriteLine(item.Rotation.w.ToString("R", CultureInfo.InvariantCulture)); } } catch (Exception ex) { ValheimArchitectPlugin.Log.LogError((object)("Could not save blueprint: " + ex.Message)); } } private void LoadBlueprintFile() { //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) _blueprint.Clear(); _pieceNames.Clear(); if (!File.Exists(_blueprintFile)) { return; } try { string[] array = File.ReadAllLines(_blueprintFile); if (array.Length == 0 || array[0].Trim() != "VALHEIM_ARCHITECT_BLUEPRINT_V1") { return; } for (int i = 1; i < array.Length; i++) { if (!string.IsNullOrWhiteSpace(array[i])) { string[] array2 = array[i].Split('\t'); if (array2.Length == 8 && float.TryParse(array2[1], NumberStyles.Float, CultureInfo.InvariantCulture, out var result) && float.TryParse(array2[2], NumberStyles.Float, CultureInfo.InvariantCulture, out var result2) && float.TryParse(array2[3], NumberStyles.Float, CultureInfo.InvariantCulture, out var result3) && float.TryParse(array2[4], NumberStyles.Float, CultureInfo.InvariantCulture, out var result4) && float.TryParse(array2[5], NumberStyles.Float, CultureInfo.InvariantCulture, out var result5) && float.TryParse(array2[6], NumberStyles.Float, CultureInfo.InvariantCulture, out var result6) && float.TryParse(array2[7], NumberStyles.Float, CultureInfo.InvariantCulture, out var result7)) { _blueprint.Add(new BlueprintPiece { PrefabName = array2[0], Position = new Vector3(result, result2, result3), Rotation = new Quaternion(result4, result5, result6, result7) }); _pieceNames.Add(array2[0]); } } } _blueprintRevision++; ValheimArchitectPlugin.Log.LogInfo((object)$"Blueprint loaded from disk: {_blueprint.Count} pieces."); } catch (Exception ex) { ValheimArchitectPlugin.Log.LogError((object)("Could not load blueprint: " + ex.Message)); } } private void DestroyGhostObjectsOnly() { for (int num = _ghosts.Count - 1; num >= 0; num--) { if ((Object)(object)_ghosts[num] != (Object)null) { Object.Destroy((Object)(object)_ghosts[num]); } } _ghosts.Clear(); _ghostToBlueprint.Clear(); } public void ClearAndForgetBlueprint() { DestroyGhostObjectsOnly(); _blueprint.Clear(); _pieceNames.Clear(); _blueprintRevision++; _loadedForCurrentScene = true; try { if (File.Exists(_blueprintFile)) { File.Delete(_blueprintFile); } } catch (Exception ex) { ValheimArchitectPlugin.Log.LogError((object)("Could not delete blueprint: " + ex.Message)); } } private void OnSceneUnloaded(Scene scene) { DestroyGhostObjectsOnly(); _loadedForCurrentScene = false; } public void Dispose() { if (!_disposed) { _disposed = true; SceneManager.sceneUnloaded -= OnSceneUnloaded; SceneManager.sceneLoaded -= OnSceneLoaded; DestroyGhostObjectsOnly(); _harmony.UnpatchSelf(); } } } internal static class GhostSkillPatch { [HarmonyPatch] private static class RaiseSkillPatch { private static IEnumerable<MethodBase> TargetMethods() { Type[] array = new Type[2] { AccessTools.TypeByName("Skills"), AccessTools.TypeByName("Player") }; Type[] array2 = array; foreach (Type type in array2) { if (type == null) { continue; } MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { if (string.Equals(methodInfo.Name, "RaiseSkill", StringComparison.Ordinal)) { yield return methodInfo; } } } } private static bool Prefix(object[] __args) { if (!IsGhostModeActive()) { return true; } if (__args == null) { return true; } foreach (object obj in __args) { if (obj != null) { if (obj is string a && string.Equals(a, "Building", StringComparison.OrdinalIgnoreCase)) { return false; } Type type = obj.GetType(); if (type.IsEnum && string.Equals(Enum.GetName(type, obj), "Building", StringComparison.OrdinalIgnoreCase)) { return false; } } } return true; } } internal static bool IsGhostModeActive() { ValheimArchitectPlugin instance = ValheimArchitectPlugin.Instance; if ((Object)(object)instance != (Object)null && instance.Ghost != null && instance.Features != null && instance.Features.GhostLayout.Value) { return (Object)(object)Player.m_localPlayer != (Object)null; } return false; } } [BepInPlugin("ValheimArchitect", "Valheim Architect", "0.5.19")] public sealed class ValheimArchitectPlugin : BaseUnityPlugin { internal static ManualLogSource Log; private ArchitectFeatures _features; private ArchitectMenu _menu; private BuildAssistController _assist; private ResourceCalculatorController _calculator; internal GhostLayoutController Ghost { get; private set; } internal ArchitectFeatures Features => _features; internal BuildAssistController Assist => _assist; internal static ValheimArchitectPlugin Instance { get; private set; } private void Awake() { Log = ((BaseUnityPlugin)this).Logger; Instance = this; _features = new ArchitectFeatures(((BaseUnityPlugin)this).Config); _menu = new ArchitectMenu(_features); _assist = new BuildAssistController(_features); Ghost = new GhostLayoutController(_features); _calculator = new ResourceCalculatorController(_features, Ghost); Log.LogInfo((object)"Plugin loaded"); Log.LogInfo((object)"Valheim Architect 0.5.19: persistent ghost blueprint + snap + resource calculator; F8 menu"); } private void Update() { if (Input.GetKeyDown((KeyCode)289)) { _menu.Toggle(); } if (Input.GetKeyDown((KeyCode)291) && _features.AlignmentLines.Value) { _assist.TogglePinned(); } _assist.Update(); Ghost?.Update(); _calculator?.Update(); } private void OnGUI() { _menu.Draw(); _calculator?.Draw(); } private void OnDestroy() { Ghost?.Dispose(); if (_assist != null) { _assist.Dispose(); } Instance = null; } } internal static class PluginInfo { public const string PLUGIN_GUID = "ValheimArchitect"; public const string PLUGIN_NAME = "Valheim Architect"; public const string PLUGIN_VERSION = "0.5.19"; } internal sealed class ResourceCalculatorController { private const int WindowId = 170335953; private readonly ArchitectFeatures _features; private readonly GhostLayoutController _ghost; private Rect _rect = new Rect(0f, 0f, 380f, 410f); private Vector2 _scroll; private List<ResourceCostLine> _costs = new List<ResourceCostLine>(); private bool _initialized; private int _lastBlueprintRevision = -1; private int _lastRecipeSignature; private bool _hasRecipeSignature; private bool _recalculationPending; private float _recipeSignatureTimer; private bool _dragging; public ResourceCalculatorController(ArchitectFeatures features, GhostLayoutController ghost) { //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) _features = features; _ghost = ghost; } public void Update() { if (!_features.ResourceCalculator.Value) { _recalculationPending = false; _dragging = false; return; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return; } if (_lastBlueprintRevision != _ghost.BlueprintRevision) { _lastBlueprintRevision = _ghost.BlueprintRevision; _recalculationPending = true; } _recipeSignatureTimer -= Time.unscaledDeltaTime; if (_recipeSignatureTimer <= 0f) { _recipeSignatureTimer = 1f; int knownRecipeSignature = GhostLayoutController.GetKnownRecipeSignature(localPlayer); if (!_hasRecipeSignature || knownRecipeSignature != _lastRecipeSignature) { _lastRecipeSignature = knownRecipeSignature; _hasRecipeSignature = true; _recalculationPending = true; } } if (_recalculationPending) { _recalculationPending = false; _costs = _ghost.GetResourceCosts(); } } public void Draw() { //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Expected O, but got Unknown //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) if (_features.ResourceCalculator.Value) { ArchitectStyle.EnsureInitialized(); if (!_initialized) { ((Rect)(ref _rect)).width = 380f; ((Rect)(ref _rect)).height = 410f; ((Rect)(ref _rect)).x = Mathf.Max(12f, (float)Screen.width - ((Rect)(ref _rect)).width - 24f); ((Rect)(ref _rect)).y = 18f; _initialized = true; } ((Rect)(ref _rect)).x = Mathf.Clamp(((Rect)(ref _rect)).x, 8f, Mathf.Max(8f, (float)Screen.width - ((Rect)(ref _rect)).width - 8f)); ((Rect)(ref _rect)).y = Mathf.Clamp(((Rect)(ref _rect)).y, 8f, Mathf.Max(8f, (float)Screen.height - ((Rect)(ref _rect)).height - 8f)); _rect = GUI.Window(170335953, _rect, new WindowFunction(DrawCalculatorWindow), GUIContent.none, ArchitectStyle.WindowCompact); } } private void DrawCalculatorWindow(int id) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_008b: 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_0102: 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_01e3: Unknown result type (might be due to invalid IL or missing references) //IL_01e5: Unknown result type (might be due to invalid IL or missing references) //IL_0202: Unknown result type (might be due to invalid IL or missing references) //IL_0207: Unknown result type (might be due to invalid IL or missing references) //IL_020c: 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_024d: Unknown result type (might be due to invalid IL or missing references) //IL_029f: Unknown result type (might be due to invalid IL or missing references) //IL_02e1: Unknown result type (might be due to invalid IL or missing references) Rect val = default(Rect); ((Rect)(ref val))..ctor(14f, 14f, ((Rect)(ref _rect)).width - 28f, 74f); GUI.Box(val, GUIContent.none, ArchitectStyle.HeaderCompact); GUI.Label(new Rect(28f, 21f, ((Rect)(ref _rect)).width - 56f, 30f), "КАЛЬКУЛЯТОР МАКЕТА", ArchitectStyle.ResourceHeader); GUI.Label(new Rect(28f, 51f, ((Rect)(ref _rect)).width - 56f, 18f), $"Деталей в макете: {_ghost.BlueprintCount}", ArchitectStyle.Small); if (GUI.Button(new Rect(((Rect)(ref _rect)).width - 42f, 28f, 22f, 22f), "×", ArchitectStyle.CloseSmall)) { _features.ResourceCalculator.Value = false; GUIUtility.ExitGUI(); return; } HandleHeaderDrag(val); if (_ghost.BlueprintCount == 0) { GUI.Label(new Rect(24f, 108f, ((Rect)(ref _rect)).width - 48f, 42f), "Макет пуст.", ArchitectStyle.ResourceName); return; } if (_costs.Count == 0) { GUI.Label(new Rect(24f, 108f, ((Rect)(ref _rect)).width - 48f, 72f), "Нет доступных ресурсов для деталей этого макета.", ArchitectStyle.ResourceName); return; } Rect val2 = default(Rect); ((Rect)(ref val2))..ctor(18f, 100f, ((Rect)(ref _rect)).width - 36f, ((Rect)(ref _rect)).height - 116f); float num = Mathf.Max(230f, (float)_costs.Count * 46f + 14f); _scroll = GUI.BeginScrollView(val2, _scroll, new Rect(0f, 0f, ((Rect)(ref val2)).width - 18f, num)); float num2 = 8f; Rect val3 = default(Rect); for (int i = 0; i < _costs.Count; i++) { ResourceCostLine resourceCostLine = _costs[i]; ((Rect)(ref val3))..ctor(0f, num2, ((Rect)(ref val2)).width - 18f, 40f); GUI.Box(val3, GUIContent.none, (i % 2 == 0) ? ArchitectStyle.ResourceRowA : ArchitectStyle.ResourceRowB); GUI.Label(new Rect(((Rect)(ref val3)).x + 14f, ((Rect)(ref val3)).y + 2f, ((Rect)(ref val3)).width - 100f, ((Rect)(ref val3)).height - 4f), resourceCostLine.Name, ArchitectStyle.ResourceName); GUI.Label(new Rect(((Rect)(ref val3)).xMax - 72f, ((Rect)(ref val3)).y + 2f, 60f, ((Rect)(ref val3)).height - 4f), resourceCostLine.Amount.ToString(), ArchitectStyle.ResourceAmount); num2 += 46f; } GUI.EndScrollView(); } private void HandleHeaderDrag(Rect headerRect) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Invalid comparison between Unknown and I4 //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Invalid comparison between Unknown and I4