Decompiled source of Quads Build Orders v1.14.2

plugins/BuildOrders.dll

Decompiled 12 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using DHack.Shared;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.Rendering;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyMetadata("AI_Assisted_Creation", "This assembly was partially or fully created with the assistance of Generative AI (Claude Code).")]
[assembly: AssemblyMetadata("AI_Model_Vendor", "Anthropic")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[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 BuildOrders
{
	[BepInPlugin("com.quad.buildorders", "BuildOrders", "1.14.2")]
	public class Plugin : BaseUnityPlugin
	{
		internal class FetchLine
		{
			public string Item;

			public string Name;

			public Sprite Icon;

			public GameObject Prefab;

			public int Need;

			public int InInventory;

			public int InChests;

			public int Take;

			public bool Short => Take > 0;
		}

		internal class Order
		{
			public string Id;

			public string Prefab;

			public string By;

			public Vector3 Pos;

			public Quaternion Rot;
		}

		private class Need
		{
			public string Item;

			public string Name;

			public int Amount;

			public ItemData Data;
		}

		private class HudPiece
		{
			public RectTransform Root;

			public string Shown;
		}

		private struct Line
		{
			public string Text;

			public float Size;

			public Color Color;

			public Line(string text, float size, Color color)
			{
				//IL_000f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0010: Unknown result type (might be due to invalid IL or missing references)
				Text = text;
				Size = size;
				Color = color;
			}
		}

		internal enum BridgeMaterial
		{
			Wood,
			CoreWood,
			Darkwood,
			Stone
		}

		internal enum BridgeSides
		{
			Rails,
			HalfWalls,
			None
		}

		internal enum BridgeSupports
		{
			Auto,
			Every2m,
			Every4m
		}

		internal enum BridgeShape
		{
			Straight,
			Arched
		}

		internal enum BridgeEnds
		{
			Sloped,
			Steps
		}

		internal class BridgeOptions
		{
			public int Width = 2;

			public BridgeMaterial Material;

			public BridgeSides Sides;

			public bool Roof;

			public bool Torches;

			public BridgeSupports Supports;

			public BridgeShape Shape;

			public BridgeEnds Ends;
		}

		private class BridgeKit
		{
			public string Name;

			public string Station;

			public string Deck;

			public float DeckThickness;

			public bool PillarUnderEverySlab;

			public string[] Posts;

			public float[] PostLengths;

			public string TallPost;

			public string Beam;

			public string Roof;

			public string RoofTop;

			public string Stair;

			public string[] HalfWall;

			public float[] HalfWallY;

			public float HalfWallInset;

			public float MaxDepth;
		}

		internal class BridgeDesign
		{
			public List<Entry> Entries = new List<Entry>();

			public float Yaw;

			public float Length;

			public List<Said> Warnings = new List<Said>();
		}

		internal class HintLine
		{
			public string Name;

			public int Have;

			public int Need;

			public Sprite Icon;

			public ItemData Item;
		}

		internal class LevelJob
		{
			public string Key;

			public string Title;

			public string World;

			public bool Interrupted;

			public List<Vector3> Points;

			public List<Vector3> Checks;

			public int Next;

			public int Done;

			public int Skipped;

			public int Pass = 1;

			public bool Running;

			public bool Finished;

			public float Worst;

			public Said State;

			public Action OnDone;

			public Vector3 Anchor;

			public float Yaw;

			public float Target;

			public Vector2 Lo;

			public Vector2 Hi;

			public string Status => State?.English ?? "";

			public string Shown => State?.Shown ?? "";
		}

		internal class PlanInfo
		{
			public string Key;

			public string Title;

			public bool IsBlueprint;

			public List<Order> Orders = new List<Order>();

			public Vector3 Centre;

			public float Distance;

			public string Shown
			{
				get
				{
					if (!IsBlueprint)
					{
						return Translations.T("buildorders_planned_by", Who(Key));
					}
					return ShownTitle(Title);
				}
			}
		}

		internal class Entry
		{
			public string Prefab;

			public Vector3 Local;

			public Quaternion Rot;

			public bool Ground;
		}

		private class Placement
		{
			public string Title;

			public string File;

			public string ReplaceKey;

			public List<Entry> Entries;

			public float Yaw;

			public float OffsetY;

			public readonly List<KeyValuePair<Entry, GameObject>> Ghosts = new List<KeyValuePair<Entry, GameObject>>();

			public readonly List<Material> Materials = new List<Material>();

			public int Spawned;

			public Vector3 LastAnchor = new Vector3(float.NaN, 0f, 0f);

			public float LastYaw = float.NaN;

			public float LastOffset = float.NaN;

			public Vector3 Anchor;

			public bool HaveAnchor;

			public List<Foot> Feet;

			public List<Vector3> LevelSpots = new List<Vector3>();

			public int Strokes;

			public float Cut;

			public float Fill;

			public GameObject Pad;
		}

		private class BlueprintFile
		{
			public string Path;

			public string Name;

			public int Pieces;

			public Vector3 Size;

			public List<KeyValuePair<string, int>> Materials = new List<KeyValuePair<string, int>>();

			public bool Placed;

			public string SharedBy;

			public Texture2D Picture;

			public string Error;
		}

		internal class SharedBlueprint
		{
			public string Path;

			public string Name;

			public string From;

			public int Pieces;

			public List<KeyValuePair<string, int>> Materials = new List<KeyValuePair<string, int>>();

			public Texture2D Picture;
		}

		private class Shape
		{
			public string Material = "";

			public bool Supports;

			public List<Vector3> Feet = new List<Vector3>();

			public float Top;

			public float Bottom;

			public bool IsPost;

			public Vector3 Min;

			public Vector3 Max;
		}

		internal class Foot
		{
			public Vector3 Local;

			public string Material;
		}

		internal class Stab
		{
			public float Support;

			public float Max;

			public float Min;

			public List<string> From = new List<string>();

			public bool Collapses => Support < Min;

			public float Value
			{
				get
				{
					if (!(Support >= Max))
					{
						return Mathf.Clamp01((Support - Min) / Mathf.Max(0.01f, Max * 0.5f - Min));
					}
					return -1f;
				}
			}

			public int Percent => Mathf.RoundToInt(Mathf.Clamp01(Support / Max) * 100f);
		}

		private class Node
		{
			public Order Order;

			public Bounds Box;

			public Vector3 Com;

			public Vector3 Pos;

			public float Max;

			public float Min;

			public float HLoss;

			public float VLoss;

			public float Support;

			public bool Supports;

			public bool Grounded;

			public bool Broken;

			public List<Node> From = new List<Node>();

			public List<Obb> Cols;

			public List<Obb> Reach;

			public readonly List<KeyValuePair<Node, Obb>> Near = new List<KeyValuePair<Node, Obb>>();

			public readonly List<Real> Real = new List<Real>();
		}

		internal struct Obb
		{
			public Vector3 C;

			public Vector3 H;

			public Quaternion R;

			public Bounds Aabb()
			{
				//IL_0001: 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_0020: Unknown result type (might be due to invalid IL or missing references)
				//IL_0025: Unknown result type (might be due to invalid IL or missing references)
				//IL_0027: 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_0046: Unknown result type (might be due to invalid IL or missing references)
				//IL_004b: 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_0067: Unknown result type (might be due to invalid IL or missing references)
				//IL_006c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0071: Unknown result type (might be due to invalid IL or missing references)
				//IL_0074: Unknown result type (might be due to invalid IL or missing references)
				//IL_007f: 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_0097: 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_00ae: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d1: 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_00e8: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
				Vector3 val = R * new Vector3(H.x, 0f, 0f);
				Vector3 val2 = R * new Vector3(0f, H.y, 0f);
				Vector3 val3 = R * new Vector3(0f, 0f, H.z);
				Vector3 val4 = default(Vector3);
				((Vector3)(ref val4))..ctor(Mathf.Abs(val.x) + Mathf.Abs(val2.x) + Mathf.Abs(val3.x), Mathf.Abs(val.y) + Mathf.Abs(val2.y) + Mathf.Abs(val3.y), Mathf.Abs(val.z) + Mathf.Abs(val2.z) + Mathf.Abs(val3.z));
				return new Bounds(C, val4 * 2f);
			}

			public Vector3 Closest(Vector3 p)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_000b: 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_0012: 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_001c: 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_0041: Unknown result type (might be due to invalid IL or missing references)
				//IL_0063: Unknown result type (might be due to invalid IL or missing references)
				//IL_008b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0091: 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_0097: Unknown result type (might be due to invalid IL or missing references)
				//IL_009c: Unknown result type (might be due to invalid IL or missing references)
				Vector3 val = Quaternion.Inverse(R) * (p - C);
				((Vector3)(ref val))..ctor(Mathf.Clamp(val.x, 0f - H.x, H.x), Mathf.Clamp(val.y, 0f - H.y, H.y), Mathf.Clamp(val.z, 0f - H.z, H.z));
				return C + R * val;
			}

			public static bool Overlap(Obb a, Obb b)
			{
				//IL_0020: Unknown result type (might be due to invalid IL or missing references)
				//IL_0025: Unknown result type (might be due to invalid IL or missing references)
				//IL_002a: 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_003c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0041: Unknown result type (might be due to invalid IL or missing references)
				//IL_0046: Unknown result type (might be due to invalid IL or missing references)
				//IL_004b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0058: Unknown result type (might be due to invalid IL or missing references)
				//IL_005d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0062: Unknown result type (might be due to invalid IL or missing references)
				//IL_0067: Unknown result type (might be due to invalid IL or missing references)
				//IL_0081: 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_008b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0090: Unknown result type (might be due to invalid IL or missing references)
				//IL_009d: 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_00a7: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
				//IL_00be: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c3: 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_00da: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
				//IL_0114: Unknown result type (might be due to invalid IL or missing references)
				//IL_013b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0147: Unknown result type (might be due to invalid IL or missing references)
				//IL_014c: Unknown result type (might be due to invalid IL or missing references)
				Vector3[] A = (Vector3[])(object)new Vector3[3]
				{
					a.R * Vector3.right,
					a.R * Vector3.up,
					a.R * Vector3.forward
				};
				Vector3[] B = (Vector3[])(object)new Vector3[3]
				{
					b.R * Vector3.right,
					b.R * Vector3.up,
					b.R * Vector3.forward
				};
				Vector3 t = b.C - a.C;
				for (int i = 0; i < 3; i++)
				{
					if (Sep(A[i]) || Sep(B[i]))
					{
						return false;
					}
				}
				for (int j = 0; j < 3; j++)
				{
					for (int k = 0; k < 3; k++)
					{
						if (Sep(Vector3.Cross(A[j], B[k])))
						{
							return false;
						}
					}
				}
				return true;
				bool Sep(Vector3 axis)
				{
					//IL_0027: Unknown result type (might be due to invalid IL or missing references)
					//IL_002c: Unknown result type (might be due to invalid IL or missing references)
					//IL_004f: Unknown result type (might be due to invalid IL or missing references)
					//IL_0054: Unknown result type (might be due to invalid IL or missing references)
					//IL_0078: Unknown result type (might be due to invalid IL or missing references)
					//IL_007d: Unknown result type (might be due to invalid IL or missing references)
					//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
					//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
					//IL_00ca: 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_00f3: Unknown result type (might be due to invalid IL or missing references)
					//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
					//IL_0107: Unknown result type (might be due to invalid IL or missing references)
					//IL_010c: Unknown result type (might be due to invalid IL or missing references)
					if (((Vector3)(ref axis)).sqrMagnitude < 1E-08f)
					{
						return false;
					}
					float num = a.H.x * Mathf.Abs(Vector3.Dot(A[0], axis)) + a.H.y * Mathf.Abs(Vector3.Dot(A[1], axis)) + a.H.z * Mathf.Abs(Vector3.Dot(A[2], axis));
					float num2 = b.H.x * Mathf.Abs(Vector3.Dot(B[0], axis)) + b.H.y * Mathf.Abs(Vector3.Dot(B[1], axis)) + b.H.z * Mathf.Abs(Vector3.Dot(B[2], axis));
					return Mathf.Abs(Vector3.Dot(t, axis)) > num + num2 + 0.0001f;
				}
			}
		}

		private struct Real
		{
			public Vector3 Com;

			public Vector3 Pos;

			public Vector3 Point;

			public float Support;
		}

		private ConfigEntry<KeyCode> _fetchKey;

		private const string TakeKey = "DHack.BuildFromChests.Take";

		private const string CountKey = "DHack.BuildFromChests.Count";

		internal bool FetchTopUp;

		internal readonly List<FetchLine> FetchLines = new List<FetchLine>();

		internal bool FetchAvailable;

		internal string FetchPieceName = "";

		private float _fetchAt;

		private readonly Dictionary<string, GameObject> _ghosts = new Dictionary<string, GameObject>();

		private readonly HashSet<string> _badPrefabs = new HashSet<string>();

		private ZNetScene _badPrefabsOf;

		private static readonly Color PlannedColor = new Color(0.35f, 0.8f, 1f);

		private static readonly Color AimedColor = new Color(1f, 0.85f, 0.35f);

		private Shader _ghostShader;

		private bool _shaderSearched;

		private static readonly string[] ShaderPreference = new string[9] { "Legacy Shaders/Transparent/Diffuse", "Legacy Shaders/Transparent/VertexLit", "Legacy Shaders/Particles/Alpha Blended", "Particles/Standard Unlit", "Custom/AlphaParticle", "Mobile/Particles/Alpha Blended", "Sprites/Default", "Unlit/Transparent", "Hidden/Internal-Colored" };

		private const int MaxSpawnsPerPass = 10;

		private readonly Dictionary<string, List<Material>> _ghostMaterials = new Dictionary<string, List<Material>>();

		private readonly Dictionary<string, List<Collider>> _ghostColliders = new Dictionary<string, List<Collider>>();

		private bool _collidersOn;

		private const string Rpc = "DHack_BuildOrders";

		private const string PackedRpc = "DHack_BuildOrders_Z";

		private readonly Dictionary<string, Order> _orders = new Dictionary<string, Order>();

		private readonly Dictionary<string, int> _removed = new Dictionary<string, int>();

		private const int RemovedDays = 60;

		private string _loadedWorld;

		private string _loadedWorldName;

		private ZNet _worldOf;

		private ZRoutedRpc _registeredOn;

		private bool _announcePending;

		private bool _saveDue;

		private float _saveAt;

		private readonly Queue<string> _outbox = new Queue<string>();

		private const int OutboxCharsPerFrame = 8192;

		private List<Need> _needs = new List<Need>();

		private float _nextNeeds;

		private const string HudPrefix = "BuildOrders.";

		private readonly Dictionary<string, HudPiece> _hudPieces = new Dictionary<string, HudPiece>();

		private float _hudAt;

		private RectTransform _holdFill;

		private float _holdWidth;

		public const int PlanningApiVersion = 1;

		public const int MaximumApiPieces = 256;

		public const int MaximumShellPieces = 2048;

		private const string AddonPlanPrefix = "Blueprint: Addon ";

		private ConfigEntry<KeyCode> _blueprintKey;

		private bool _dumpStarted;

		private static readonly string[] RuleFlags = new string[16]
		{
			"m_groundPiece", "m_waterPiece", "m_noInWater", "m_notOnWood", "m_notOnTiltingSurface", "m_inCeilingOnly", "m_notOnFloor", "m_onlyInTeleportArea", "m_allowedInDungeons", "m_clipEverything",
			"m_clipGround", "m_noClipping", "m_mustBeAboveConnected", "m_vegetationGroundOnly", "m_cultivatedGroundOnly", "m_isUpgrade"
		};

		internal const string BridgeToolPrefab = "piece_bo_bridge";

		internal const string BridgeTitle = "Bridge";

		private static GameObject _bridgeHolder;

		private static GameObject _bridgeTool;

		private static FieldRef<Player, GameObject> _placementGhost;

		private static bool _placementGhostLooked;

		private PieceTable _bridgeTable;

		private static readonly MethodInfo UpdateKnownRecipes = AccessTools.Method(typeof(Player), "UpdateKnownRecipesList", (Type[])null, (Type[])null);

		private float _nextBridgeKnownCheck;

		private Vector3? _bridgeStart;

		private Vector3 _bridgeEnd;

		private float _bridgeAt;

		private BridgeDesign _bridgeDesign;

		private bool _bridgeEndFixed;

		private bool _bridgeDirty;

		private readonly List<KeyValuePair<string, GameObject>> _bridgeGhosts = new List<KeyValuePair<string, GameObject>>();

		private readonly List<Material> _bridgeMaterials = new List<Material>();

		private static HashSet<string> _bridgeTitles = new HashSet<string>();

		private static float _bridgeTitlesAt = -99f;

		private ConfigEntry<int> _bridgeWidth;

		private ConfigEntry<BridgeMaterial> _bridgeMaterial;

		private ConfigEntry<BridgeSides> _bridgeSides;

		private ConfigEntry<bool> _bridgeRoof;

		private ConfigEntry<bool> _bridgeTorches;

		private ConfigEntry<BridgeSupports> _bridgeSupports;

		private ConfigEntry<BridgeShape> _bridgeShape;

		private ConfigEntry<BridgeEnds> _bridgeEnds;

		internal static bool BridgeOptionsOpen;

		private BridgeOptions _bridgeOpts;

		private const float BridgeW = 520f;

		private const float BridgePad = 24f;

		private RectTransform _bridgeWin;

		private string _bridgeShown = "";

		private float _bridgeCheckAt;

		private Action _bridgePending;

		public const string Guid = "com.quad.buildorders";

		public const string OldGuid = "com.dhack.buildorders";

		public const string Name = "BuildOrders";

		public const string Version = "1.14.2";

		internal static Plugin Instance;

		internal static ServerSettings Synced;

		private ConfigEntry<bool> _enabled;

		private ConfigEntry<bool> _showGhosts;

		private ConfigEntry<bool> _alwaysShowPanel;

		private ConfigEntry<bool> _buildByHand;

		private ConfigEntry<float> _buildReach;

		private ConfigEntry<float> _buildAllRadius;

		private ConfigEntry<int> _maxGhosts;

		private ConfigEntry<KeyCode> _stabilityKey;

		private ConfigEntry<bool> _stabilityInPlan;

		private ConfigEntry<float> _ghostOpacity;

		private ConfigEntry<string> _shaderOverride;

		private ConfigEntry<float> _viewDistance;

		private ConfigEntry<float> _snapDistance;

		private ConfigEntry<KeyCode> _planKey;

		private ConfigEntry<KeyCode> _selectKey;

		private ConfigEntry<KeyCode> _removeKey;

		private ConfigEntry<KeyCode> _toggleGhostsKey;

		private ConfigEntry<bool> _planToggle;

		private ConfigEntry<bool> _swimBuild;

		private ConfigEntry<float> _panelX;

		private ConfigEntry<float> _panelY;

		private Harmony _harmony;

		private int _awakeFrame;

		internal static ManualLogSource Log;

		private float _nextGhostUpdate;

		private float _nextCompletion;

		private float _lastOpacity = -1f;

		private bool _keysChecked;

		private bool _keysWatched;

		private readonly List<string> _keyNotes = new List<string>();

		private float _nextRecords;

		private bool _uiFailed;

		private float _uiPausedUntil;

		private readonly Dictionary<string, KeyValuePair<GameObject, Bounds>> _shapes = new Dictionary<string, KeyValuePair<GameObject, Bounds>>();

		private const string ForceKey = "DHack.BuildFromChests.ForceContext";

		private float _hintAt;

		private string _hintFor;

		internal bool HintAffordable;

		internal readonly List<HintLine> PlanLines = new List<HintLine>();

		internal string PlanTitle = "";

		internal int PlanLeft;

		internal int HoldCount;

		internal int HoldAll;

		internal Sprite HintPieceIcon;

		internal readonly List<HintLine> HintLines = new List<HintLine>();

		internal bool HintKnown;

		private float _promptStabilityAt;

		private const float HoldSeconds = 0.6f;

		private float _holdStart = -1f;

		private string _holdOrderId;

		private bool _holdFired;

		private bool _building;

		internal float HoldProgress;

		private int _completionCursor;

		private readonly Collider[] _hits = (Collider[])(object)new Collider[32];

		private int _pieceMask = -1;

		private bool _planMode;

		private const string HelperCountKey = "DHack.BuildOrders.Count";

		private const string HelperNextKey = "DHack.BuildOrders.Next";

		private const string HelperPlaceKey = "DHack.BuildOrders.Place";

		private const string HelperBlockersKey = "DHack.BuildOrders.Blockers";

		private Func<Vector3, float, int> _helperCount;

		private Func<Vector3, float, int, string[]> _helperNext;

		private Func<string, bool> _helperPlace;

		private Func<Vector3, float, string[]> _helperBlockers;

		private const string LevelPiece = "mud_road_v2";

		private const float TerrainLimit = 8f;

		private const float LevelMargin = 1f;

		private const int MaxPasses = 4;

		private const float FlatEnough = 0.06f;

		private readonly Dictionary<string, LevelJob> _levelJobs = new Dictionary<string, LevelJob>();

		private float _levelRadius = -1f;

		private bool _levelSquare;

		private GameObject _levelPrefab;

		private const float LevelBlend = 3f;

		private const string PaintPiece = "path_v2";

		private JArray _pendingLevels = new JArray();

		private GameObject _paintPrefab;

		private static readonly Color PadColor = new Color(0.85f, 0.65f, 0.35f);

		private const int PicWidth = 320;

		private const int PicHeight = 180;

		private static readonly Vector3 PhotoSpot = new Vector3(0f, 4000f, 0f);

		private readonly Queue<string> _pictureQueue = new Queue<string>();

		private readonly Dictionary<string, float> _pictureTried = new Dictionary<string, float>();

		private bool _photographing;

		internal const string BlueprintPrefix = "Blueprint: ";

		private const string PlannedByTitle = "Planned by ";

		internal const int MaxPieces = 5000;

		private HashSet<string> _buildable;

		private Placement _placing;

		private static readonly Color PreviewColor = new Color(0.45f, 1f, 0.55f);

		internal static bool PlansWindowOpen;

		private int _plansTab;

		private string _confirmKey;

		private float _confirmUntil;

		private int _confirmBuilt;

		private float _removeRadius = 20f;

		private string _plansToast = "";

		private float _plansToastUntil;

		private const float PlansW = 880f;

		private const float PlansH = 680f;

		private const float PlansPad = 30f;

		private const float PlansBodyTop = 142f;

		private const float PlansBottom = 72f;

		private RectTransform _plansWin;

		private RectTransform _plansList;

		private string _plansShown = "";

		private bool _plansScrollTop;

		private float _plansCheckAt;

		private Action _plansPending;

		private readonly List<Action> _plansLive = new List<Action>();

		private List<BlueprintFile> _library = new List<BlueprintFile>();

		private float _libraryAt = -99f;

		private readonly Dictionary<string, Texture2D> _pictures = new Dictionary<string, Texture2D>();

		private static readonly MethodInfo LoadImageMethod = typeof(ImageConversion).GetMethod("LoadImage", new Type[2]
		{
			typeof(Texture2D),
			typeof(byte[])
		});

		private static readonly Dictionary<string, ItemData> ItemsByName = new Dictionary<string, ItemData>();

		private static ObjectDB _itemsFrom;

		private const string ClaudeToolsGuid = "com.quad.claudetools";

		private BaseUnityPlugin _claudeTools;

		private float _nextClaudeCheck;

		private const string CodePrefix = "BO1:";

		private const int MaxShareBytes = 2097152;

		private List<SharedBlueprint> _inbox = new List<SharedBlueprint>();

		private float _inboxAt = -99f;

		internal const string SupportIdPrefix = "s-";

		private const float GroundBand = 0.6f;

		private Dictionary<string, Shape> _pieceShapes;

		private static FieldRef<TerrainComp, bool> TcInit;

		private static FieldRef<TerrainComp, int> TcWidth;

		private static FieldRef<TerrainComp, bool[]> TcModH;

		private static FieldRef<TerrainComp, float[]> TcLevel;

		private static FieldRef<TerrainComp, float[]> TcSmooth;

		private static FieldRef<TerrainComp, bool[]> TcModP;

		private static FieldRef<TerrainComp, Color[]> TcPaint;

		private static FieldRef<TerrainComp, Heightmap> TcHmap;

		private static FieldRef<TerrainComp, ZNetView> TcView;

		private static MethodInfo TcSave;

		private static bool? _terrainAccess;

		private const float PieceMargin = 2f;

		private readonly Dictionary<string, string> _recordPlans = new Dictionary<string, string>();

		private readonly Dictionary<string, List<KeyValuePair<Obb, bool>>> _colliderShapes = new Dictionary<string, List<KeyValuePair<Obb, bool>>>();

		private readonly Dictionary<string, Stab> _stability = new Dictionary<string, Stab>();

		private readonly Dictionary<string, float[]> _materials = new Dictionary<string, float[]>();

		private bool _stabilityDirty = true;

		private bool _stabilityShown;

		private float _nextStability;

		private static readonly MethodInfo MaterialProps = AccessTools.Method(typeof(WearNTear), "GetMaterialProperties", (Type[])null, (Type[])null);

		private static readonly MethodInfo ComOf = AccessTools.Method(typeof(WearNTear), "GetCOM", (Type[])null, (Type[])null);

		private static readonly MethodInfo SupportOf = AccessTools.Method(typeof(WearNTear), "GetSupport", (Type[])null, (Type[])null);

		private readonly Collider[] _near = (Collider[])(object)new Collider[48];

		private bool _stabilityToggle;

		private static Func<string, int, int> ChestTake => AppDomain.CurrentDomain.GetData("DHack.BuildFromChests.Take") as Func<string, int, int>;

		private static Func<string, int> ChestCount => AppDomain.CurrentDomain.GetData("DHack.BuildFromChests.Count") as Func<string, int>;

		private static int Today => (int)(DateTime.UtcNow.Ticks / 864000000000L);

		internal IEnumerable<Order> AllOrders => _orders.Values;

		internal bool WorldKnown
		{
			get
			{
				if ((Object)(object)ZNet.instance != (Object)null && (Object)(object)ZNet.instance == (Object)(object)_worldOf)
				{
					return _loadedWorld != null;
				}
				return false;
			}
		}

		private string HoldText
		{
			get
			{
				if (HoldCount < HoldAll)
				{
					if (HoldCount <= 0)
					{
						return Translations.T("buildorders_hold_none");
					}
					return Translations.T("buildorders_hold_some", HoldCount, HoldAll);
				}
				return Translations.T("buildorders_hold_all", HoldAll, _buildAllRadius.Value.ToString("0"));
			}
		}

		private bool ApiToolBusy
		{
			get
			{
				if (_placing == null && !PlansWindowOpen && !_bridgeStart.HasValue)
				{
					return BridgeOptionsOpen;
				}
				return true;
			}
		}

		private static string BlueprintDir => Path.Combine(Paths.BepInExRootPath, "blueprints");

		internal static bool BridgeDrawing
		{
			get
			{
				if ((Object)(object)Instance != (Object)null)
				{
					return Instance._bridgeStart.HasValue;
				}
				return false;
			}
		}

		internal bool BuildWhileSwimming
		{
			get
			{
				if (_enabled.Value)
				{
					return _swimBuild.Value;
				}
				return false;
			}
		}

		internal Order Aimed { get; private set; }

		internal bool PlanKeyHeld
		{
			get
			{
				if (_enabled.Value)
				{
					return _planMode;
				}
				return false;
			}
		}

		private Said PlanHintSaid => new Said(_planToggle.Value ? "buildorders_hint_press" : "buildorders_hint_hold", _planKey.Value);

		private string PlanHint => PlanHintSaid.Shown;

		internal LevelJob ActiveLevelJob => _levelJobs.Values.FirstOrDefault((LevelJob j) => j.Running);

		private static string PendingLevelDir => Path.Combine(BlueprintDir, "_levelling");

		private string PendingLevelFile => Path.Combine(PendingLevelDir, Safe(_loadedWorld ?? "world") + ".json");

		internal static bool Placing
		{
			get
			{
				if ((Object)(object)Instance != (Object)null)
				{
					return Instance._placing != null;
				}
				return false;
			}
		}

		private bool Toasting => Time.unscaledTime < _plansToastUntil;

		private static string ImportsFile => Path.Combine(BlueprintDir, "_imports.json");

		internal bool ClaudeToolsInstalled => (Object)(object)_claudeTools != (Object)null;

		private static string InboxDir => Path.Combine(BlueprintDir, "_inbox");

		private static string PlanRecordDir => Path.Combine(BlueprintDir, "_plans");

		private static string TerrainDir => Path.Combine(BlueprintDir, "_terrain");

		private string WorldPrefix => Safe((_loadedWorld ?? "world") + "__");

		private void BindFetch()
		{
			_fetchKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Keys", "FetchKey", (KeyCode)121, "With the hammer out and a piece selected: press this to take exactly what it needs out of the chests around you (topping you up to one piece's worth, or another piece's worth when you have enough) and put it in your inventory (needs BuildFromChests).");
		}

		private void UpdateFetch(Player player)
		{
			//IL_02b0: Unknown result type (might be due to invalid IL or missing references)
			FetchAvailable = false;
			if (!_enabled.Value || !((Character)player).InPlaceMode() || PlanKeyHeld || InventoryGui.IsVisible() || TypingOrMenuOpen())
			{
				return;
			}
			Func<string, int> chestCount = ChestCount;
			if (chestCount == null)
			{
				return;
			}
			Piece selectedPiece = player.GetSelectedPiece();
			if ((Object)(object)selectedPiece == (Object)null || selectedPiece.m_resources == null || selectedPiece.m_repairPiece || selectedPiece.m_removePiece)
			{
				return;
			}
			if (Time.unscaledTime - _fetchAt >= 0.4f)
			{
				_fetchAt = Time.unscaledTime;
				FetchPieceName = Localization.instance.Localize(selectedPiece.m_name);
				FetchLines.Clear();
				Inventory inventory = ((Humanoid)player).GetInventory();
				Requirement[] resources = selectedPiece.m_resources;
				foreach (Requirement val in resources)
				{
					if (!((Object)(object)val.m_resItem == (Object)null) && val.GetAmount(1) > 0)
					{
						string item = val.m_resItem.m_itemData.m_shared.m_name;
						FetchLines.Add(new FetchLine
						{
							Item = item,
							Name = Localization.instance.Localize(item),
							Icon = val.m_resItem.m_itemData.GetIcon(),
							Prefab = ((Component)val.m_resItem).gameObject,
							Need = val.GetAmount(1),
							InInventory = (from val2 in inventory.GetAllItems()
								where val2.m_shared.m_name == item
								select val2).Sum((ItemData val2) => val2.m_stack),
							InChests = chestCount(item)
						});
					}
				}
				FetchTopUp = FetchLines.Any((FetchLine l) => l.InInventory < l.Need);
				foreach (FetchLine fetchLine in FetchLines)
				{
					fetchLine.Take = Mathf.Min(fetchLine.InChests, FetchTopUp ? Mathf.Max(0, fetchLine.Need - fetchLine.InInventory) : fetchLine.Need);
				}
			}
			FetchAvailable = FetchLines.Any((FetchLine l) => l.Short);
			if (FetchAvailable && Input.GetKeyDown(_fetchKey.Value))
			{
				Fetch(player);
			}
		}

		private void Fetch(Player player)
		{
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			Func<string, int, int> chestTake = ChestTake;
			if (chestTake == null)
			{
				return;
			}
			Inventory inventory = ((Humanoid)player).GetInventory();
			List<string> list = new List<string>();
			bool flag = false;
			foreach (FetchLine item in FetchLines.Where((FetchLine l) => l.Short).ToList())
			{
				int take = item.Take;
				if (!inventory.CanAddItem(item.Prefab, take))
				{
					flag = true;
					continue;
				}
				int num = chestTake(item.Item, take);
				if (num > 0)
				{
					if (!inventory.AddItem(item.Prefab, num))
					{
						GameObject val = Object.Instantiate<GameObject>(item.Prefab, ((Component)player).transform.position + ((Component)player).transform.forward + Vector3.up, Quaternion.identity);
						val.GetComponent<ItemDrop>().SetStack(num);
					}
					list.Add($"{num} {item.Name}");
				}
			}
			_fetchAt = 0f;
			if (list.Count > 0)
			{
				((Character)player).Message((MessageType)1, Translations.T("buildorders_took", string.Join(", ", list.ToArray())) + (flag ? ("  " + Translations.T("buildorders_took_no_room")) : ""), 0, (Sprite)null, false);
			}
			else
			{
				((Character)player).Message((MessageType)2, Translations.T(flag ? "buildorders_no_room" : "buildorders_nothing_to_take"), 0, (Sprite)null, false);
			}
		}

		private Shader GhostShader()
		{
			if (_shaderSearched)
			{
				return _ghostShader;
			}
			_shaderSearched = true;
			Shader[] source = Resources.FindObjectsOfTypeAll<Shader>();
			string[] words = new string[9] { "transparent", "alpha", "particle", "sprite", "unlit", "ghost", "fade", "blend", "hologram" };
			List<string> list = (from n in (from s in source
					select ((Object)s).name into n
					where words.Any((string w) => n.IndexOf(w, StringComparison.OrdinalIgnoreCase) >= 0)
					select n).Distinct()
				orderby n
				select n).ToList();
			((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("Possible ghost shaders loaded in this game ({0}): {1}", list.Count, string.Join(", ", list.ToArray())));
			List<string> list2 = new List<string>();
			if (!string.IsNullOrWhiteSpace(_shaderOverride.Value))
			{
				list2.Add(_shaderOverride.Value.Trim());
			}
			list2.AddRange(ShaderPreference);
			foreach (string name in list2)
			{
				Shader val = ((IEnumerable<Shader>)source).FirstOrDefault((Func<Shader, bool>)((Shader x) => ((Object)x).name == name)) ?? Shader.Find(name);
				if ((Object)(object)val != (Object)null && val.isSupported)
				{
					_ghostShader = val;
					break;
				}
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)(((Object)(object)_ghostShader != (Object)null) ? ("Ghosts will use the shader '" + ((Object)_ghostShader).name + "'") : "No transparent shader found: ghosts will fall back to the game's own (solid) material."));
			return _ghostShader;
		}

		private void UpdateGhosts(Player player)
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: 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_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			if (!_showGhosts.Value)
			{
				DestroyAllGhosts();
				return;
			}
			float num = _viewDistance.Value * _viewDistance.Value;
			Vector3 here = ((Component)player).transform.position;
			foreach (string item in _ghosts.Keys.Where((string id) => !_orders.ContainsKey(id)).ToList())
			{
				DestroyGhost(item);
			}
			int num2 = 0;
			foreach (Order item2 in _orders.Values.OrderBy(delegate(Order o)
			{
				//IL_0001: 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)
				//IL_000c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0011: Unknown result type (might be due to invalid IL or missing references)
				Vector3 val2 = o.Pos - here;
				return ((Vector3)(ref val2)).sqrMagnitude;
			}))
			{
				Vector3 val = item2.Pos - here;
				bool flag = ((Vector3)(ref val)).sqrMagnitude <= num;
				bool flag2 = _ghosts.ContainsKey(item2.Id);
				if (flag && !flag2 && _ghosts.Count < _maxGhosts.Value && num2 < 10)
				{
					SpawnGhost(item2);
					num2++;
				}
				else if (!flag && flag2)
				{
					DestroyGhost(item2.Id);
				}
			}
		}

		private void SpawnGhost(Order o)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			List<Material> list = new List<Material>();
			GameObject val = MakeGhostObject(o.Prefab, o.Pos, o.Rot, list);
			if (!((Object)(object)val == (Object)null))
			{
				((Object)val).name = o.Prefab + "_order";
				_ghostMaterials[o.Id] = list;
				_ghosts[o.Id] = val;
				RegisterColliders(o.Id, val);
				Tint(val, aimed: false, o.Id);
			}
		}

		internal GameObject MakeGhostObject(string prefabName, Vector3 pos, Quaternion rot, List<Material> materials)
		{
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_badPrefabsOf != (Object)(object)ZNetScene.instance)
			{
				_badPrefabs.Clear();
				_badPrefabsOf = ZNetScene.instance;
			}
			if (_badPrefabs.Contains(prefabName))
			{
				return null;
			}
			GameObject prefab = ZNetScene.instance.GetPrefab(prefabName);
			if ((Object)(object)prefab == (Object)null)
			{
				_badPrefabs.Add(prefabName);
				return null;
			}
			GameObject val = null;
			TerrainModifier componentInChildren = prefab.GetComponentInChildren<TerrainModifier>();
			bool enabled = (Object)(object)componentInChildren != (Object)null && ((Behaviour)componentInChildren).enabled;
			try
			{
				if ((Object)(object)componentInChildren != (Object)null)
				{
					((Behaviour)componentInChildren).enabled = false;
				}
				TerrainOp.m_forceDisableTerrainOps = true;
				ZNetView.m_forceDisableInit = true;
				val = Object.Instantiate<GameObject>(prefab, pos, rot);
				ItemDrop component = val.GetComponent<ItemDrop>();
				if (component != null)
				{
					component.MakePiece(false);
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not make a ghost of " + prefabName + ": " + ex.Message));
				_badPrefabs.Add(prefabName);
			}
			finally
			{
				ZNetView.m_forceDisableInit = false;
				TerrainOp.m_forceDisableTerrainOps = false;
				if ((Object)(object)componentInChildren != (Object)null)
				{
					((Behaviour)componentInChildren).enabled = enabled;
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			Strip(val);
			MakeTranslucent(val, materials);
			return val;
		}

		internal static void TintWith(GameObject go, Color c)
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: 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_0099: Unknown result type (might be due to invalid IL or missing references)
			Renderer[] componentsInChildren = go.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val in componentsInChildren)
			{
				Material[] sharedMaterials = val.sharedMaterials;
				foreach (Material val2 in sharedMaterials)
				{
					if (!((Object)(object)val2 == (Object)null))
					{
						if (val2.HasProperty("_Color"))
						{
							val2.SetColor("_Color", c);
						}
						if (val2.HasProperty("_TintColor"))
						{
							val2.SetColor("_TintColor", c);
						}
						if (val2.HasProperty("_EmissionColor"))
						{
							val2.SetColor("_EmissionColor", new Color(c.r, c.g, c.b) * 0.4f);
						}
					}
				}
			}
		}

		private static void Strip(GameObject go)
		{
			Joint[] componentsInChildren = go.GetComponentsInChildren<Joint>();
			foreach (Joint val in componentsInChildren)
			{
				Object.Destroy((Object)(object)val);
			}
			Rigidbody[] componentsInChildren2 = go.GetComponentsInChildren<Rigidbody>();
			foreach (Rigidbody val2 in componentsInChildren2)
			{
				Object.Destroy((Object)(object)val2);
			}
			ParticleSystemForceField[] componentsInChildren3 = go.GetComponentsInChildren<ParticleSystemForceField>();
			foreach (ParticleSystemForceField val3 in componentsInChildren3)
			{
				Object.Destroy((Object)(object)val3);
			}
			Demister[] componentsInChildren4 = go.GetComponentsInChildren<Demister>();
			foreach (Demister val4 in componentsInChildren4)
			{
				Object.Destroy((Object)(object)val4);
			}
			Collider[] componentsInChildren5 = go.GetComponentsInChildren<Collider>();
			foreach (Collider val5 in componentsInChildren5)
			{
				val5.enabled = false;
			}
			TerrainModifier[] componentsInChildren6 = go.GetComponentsInChildren<TerrainModifier>();
			foreach (TerrainModifier val6 in componentsInChildren6)
			{
				Object.Destroy((Object)(object)val6);
			}
			GuidePoint[] componentsInChildren7 = go.GetComponentsInChildren<GuidePoint>();
			foreach (GuidePoint val7 in componentsInChildren7)
			{
				Object.Destroy((Object)(object)val7);
			}
			LightLod[] componentsInChildren8 = go.GetComponentsInChildren<LightLod>();
			foreach (LightLod val8 in componentsInChildren8)
			{
				Object.Destroy((Object)(object)val8);
			}
			LightFlicker[] componentsInChildren9 = go.GetComponentsInChildren<LightFlicker>();
			foreach (LightFlicker val9 in componentsInChildren9)
			{
				Object.Destroy((Object)(object)val9);
			}
			Light[] componentsInChildren10 = go.GetComponentsInChildren<Light>();
			foreach (Light val10 in componentsInChildren10)
			{
				Object.Destroy((Object)(object)val10);
			}
			WispSpawner[] componentsInChildren11 = go.GetComponentsInChildren<WispSpawner>();
			foreach (WispSpawner val11 in componentsInChildren11)
			{
				Object.Destroy((Object)(object)val11);
			}
			AudioSource[] componentsInChildren12 = go.GetComponentsInChildren<AudioSource>();
			foreach (AudioSource val12 in componentsInChildren12)
			{
				((Behaviour)val12).enabled = false;
			}
			ZSFX[] componentsInChildren13 = go.GetComponentsInChildren<ZSFX>();
			foreach (ZSFX val13 in componentsInChildren13)
			{
				((Behaviour)val13).enabled = false;
			}
			Windmill[] componentsInChildren14 = go.GetComponentsInChildren<Windmill>();
			foreach (Windmill val14 in componentsInChildren14)
			{
				((Behaviour)val14).enabled = false;
			}
			ParticleSystem[] componentsInChildren15 = go.GetComponentsInChildren<ParticleSystem>();
			foreach (ParticleSystem val15 in componentsInChildren15)
			{
				((Component)val15).gameObject.SetActive(false);
			}
			int layer = LayerMask.NameToLayer("ghost");
			Transform[] componentsInChildren16 = go.GetComponentsInChildren<Transform>();
			foreach (Transform val16 in componentsInChildren16)
			{
				((Component)val16).gameObject.layer = layer;
			}
			Transform val17 = go.transform.Find("_GhostOnly");
			if ((Object)(object)val17 != (Object)null)
			{
				((Component)val17).gameObject.SetActive(true);
			}
		}

		private void MakeTranslucent(GameObject go, List<Material> created)
		{
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Expected O, but got Unknown
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Expected O, but got Unknown
			Shader val = GhostShader();
			Renderer[] componentsInChildren = go.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val2 in componentsInChildren)
			{
				val2.shadowCastingMode = (ShadowCastingMode)0;
				val2.receiveShadows = false;
				Material[] sharedMaterials = val2.sharedMaterials;
				Material[] array = (Material[])(object)new Material[sharedMaterials.Length];
				for (int j = 0; j < sharedMaterials.Length; j++)
				{
					if ((Object)(object)sharedMaterials[j] == (Object)null)
					{
						continue;
					}
					if ((Object)(object)val != (Object)null)
					{
						Material val3 = new Material(val)
						{
							renderQueue = 3000 + j
						};
						Texture val4 = (sharedMaterials[j].HasProperty("_MainTex") ? sharedMaterials[j].mainTexture : null);
						if ((Object)(object)val4 != (Object)null)
						{
							val3.mainTexture = val4;
						}
						array[j] = val3;
					}
					else
					{
						Material val5 = new Material(sharedMaterials[j]);
						if (val5.HasProperty("_ValueNoise"))
						{
							val5.SetFloat("_ValueNoise", 0f);
						}
						if (val5.HasProperty("_TriplanarLocalPos"))
						{
							val5.SetFloat("_TriplanarLocalPos", 1f);
						}
						array[j] = val5;
					}
					created.Add(array[j]);
				}
				val2.sharedMaterials = array;
			}
		}

		private void Tint(GameObject go, bool aimed, string id = null)
		{
			//IL_0025: 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_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: 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_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			float num = Mathf.Clamp(_ghostOpacity.Value, 0.03f, 1f);
			Color val = (aimed ? AimedColor : PlannedColor);
			val.a = (aimed ? Mathf.Min(1f, num * 2f + 0.1f) : num);
			if (!aimed && _stabilityShown && id != null && _stability.TryGetValue(id, out var value))
			{
				val = StabilityColor(value);
				val.a = Mathf.Min(1f, num * 1.6f + 0.08f);
			}
			Renderer[] componentsInChildren = go.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val2 in componentsInChildren)
			{
				Material[] sharedMaterials = val2.sharedMaterials;
				foreach (Material val3 in sharedMaterials)
				{
					if (!((Object)(object)val3 == (Object)null))
					{
						if (val3.HasProperty("_Color"))
						{
							val3.SetColor("_Color", val);
						}
						if (val3.HasProperty("_TintColor"))
						{
							val3.SetColor("_TintColor", val);
						}
						if (val3.HasProperty("_EmissionColor"))
						{
							val3.SetColor("_EmissionColor", new Color(val.r, val.g, val.b) * 0.4f);
						}
					}
				}
			}
		}

		private void SetHighlight(Order o, bool on)
		{
			if (_ghosts.TryGetValue(o.Id, out var value) && (Object)(object)value != (Object)null)
			{
				Tint(value, on, o.Id);
			}
		}

		private void RetintAll()
		{
			foreach (KeyValuePair<string, GameObject> ghost in _ghosts)
			{
				if ((Object)(object)ghost.Value != (Object)null)
				{
					Tint(ghost.Value, Aimed != null && Aimed.Id == ghost.Key, ghost.Key);
				}
			}
		}

		private void DestroyGhost(string id)
		{
			if (_ghosts.TryGetValue(id, out var value) && (Object)(object)value != (Object)null)
			{
				Object.Destroy((Object)(object)value);
			}
			_ghosts.Remove(id);
			_ghostColliders.Remove(id);
			FreeMaterials(id);
		}

		private void DestroyAllGhosts()
		{
			foreach (GameObject value in _ghosts.Values)
			{
				if ((Object)(object)value != (Object)null)
				{
					Object.Destroy((Object)(object)value);
				}
			}
			_ghosts.Clear();
			_ghostColliders.Clear();
			foreach (string item in _ghostMaterials.Keys.ToList())
			{
				FreeMaterials(item);
			}
		}

		private void RegisterColliders(string id, GameObject ghost)
		{
			List<Collider> list = new List<Collider>(ghost.GetComponentsInChildren<Collider>(true));
			_ghostColliders[id] = list;
			ApplyColliders(list, _collidersOn);
		}

		private static void ApplyColliders(List<Collider> list, bool on)
		{
			int layer = LayerMask.NameToLayer(on ? "piece_nonsolid" : "ghost");
			foreach (Collider item in list)
			{
				if (!((Object)(object)item == (Object)null))
				{
					item.enabled = on;
					((Component)item).gameObject.layer = layer;
				}
			}
		}

		internal void SetGhostColliders(bool on)
		{
			if (on == _collidersOn)
			{
				return;
			}
			_collidersOn = on;
			foreach (List<Collider> value in _ghostColliders.Values)
			{
				ApplyColliders(value, on);
			}
		}

		private void FreeMaterials(string id)
		{
			if (!_ghostMaterials.TryGetValue(id, out var value))
			{
				return;
			}
			foreach (Material item in value)
			{
				if ((Object)(object)item != (Object)null)
				{
					Object.Destroy((Object)(object)item);
				}
			}
			_ghostMaterials.Remove(id);
		}

		internal void SnapToOrder(GameObject placementGhost)
		{
			//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_0087: 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_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			if (!_enabled.Value || (Object)(object)placementGhost == (Object)null || !placementGhost.activeSelf || PlanKeyHeld)
			{
				return;
			}
			string text = Plain(((Object)placementGhost).name);
			Vector3 position = placementGhost.transform.position;
			float num = _snapDistance.Value * _snapDistance.Value;
			Order order = null;
			foreach (Order value in _orders.Values)
			{
				if (!(value.Prefab != text))
				{
					Vector3 val = value.Pos - position;
					float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude;
					if (sqrMagnitude <= num)
					{
						num = sqrMagnitude;
						order = value;
					}
				}
			}
			if (order != null)
			{
				placementGhost.transform.SetPositionAndRotation(order.Pos, order.Rot);
			}
		}

		private void NoteRemoved(string id, int day = -1)
		{
			if (!string.IsNullOrEmpty(id))
			{
				int today = Today;
				if (day < 0 || day > today)
				{
					day = today;
				}
				_removed[id] = (_removed.TryGetValue(id, out var value) ? Math.Min(value, day) : day);
			}
		}

		private void NoteRemovedLine(string line)
		{
			string[] array = line.Split(new char[1] { '|' });
			if (array.Length >= 2)
			{
				NoteRemoved(array[1], (array.Length > 2 && int.TryParse(array[2], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result)) ? result : (-1));
			}
		}

		private void ForgetOldRemovals()
		{
			int oldest = Today - 60;
			foreach (string item in (from kv in _removed
				where kv.Value < oldest
				select kv.Key).ToList())
			{
				_removed.Remove(item);
			}
		}

		internal bool Plan(Player player, Piece piece, Vector3 pos, Quaternion rot)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: 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)
			string prefab = Plain(((Object)((Component)piece).gameObject).name);
			if (_orders.Values.Any(delegate(Order o)
			{
				//IL_0014: 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_0024: Unknown result type (might be due to invalid IL or missing references)
				//IL_0034: Unknown result type (might be due to invalid IL or missing references)
				//IL_003a: Unknown result type (might be due to invalid IL or missing references)
				if (o.Prefab == prefab)
				{
					Vector3 val = o.Pos - pos;
					if (((Vector3)(ref val)).sqrMagnitude < 0.02f)
					{
						return Quaternion.Angle(o.Rot, rot) < 5f;
					}
				}
				return false;
			}))
			{
				return false;
			}
			Order order = new Order
			{
				Id = Guid_(),
				Prefab = prefab,
				Pos = pos,
				Rot = rot,
				By = player.GetPlayerName()
			};
			_orders[order.Id] = order;
			_stabilityDirty = true;
			Save();
			ShareAdded(order);
			((Character)player).Message((MessageType)1, Translations.T("buildorders_planned", PieceName(prefab), _orders.Count), 0, (Sprite)null, false);
			return true;
		}

		internal void RemoveOrder(string id, bool broadcast, bool save = true)
		{
			if (_orders.Remove(id) || !_removed.ContainsKey(id))
			{
				_stabilityDirty = true;
				NoteRemoved(id);
				DestroyGhost(id);
				if (save)
				{
					Save();
				}
				if (broadcast)
				{
					ShareRemoved(id);
				}
			}
		}

		internal void SaveOrders()
		{
			Save();
		}

		private static string Guid_()
		{
			return System.Guid.NewGuid().ToString("N").Substring(0, 10);
		}

		private static string F(float v)
		{
			return v.ToString("0.###", CultureInfo.InvariantCulture);
		}

		private static string Encode(Order o)
		{
			return string.Join("|", o.Id, o.Prefab, F(o.Pos.x), F(o.Pos.y), F(o.Pos.z), F(o.Rot.x), F(o.Rot.y), F(o.Rot.z), F(o.Rot.w), o.By ?? "");
		}

		private static Order Decode(string line)
		{
			//IL_0061: 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_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			string[] f = line.Split(new char[1] { '|' });
			if (f.Length < 10)
			{
				return null;
			}
			try
			{
				return new Order
				{
					Id = f[0],
					Prefab = f[1],
					Pos = new Vector3(P(2), P(3), P(4)),
					Rot = new Quaternion(P(5), P(6), P(7), P(8)),
					By = f[9]
				};
			}
			catch (Exception)
			{
				return null;
			}
			float P(int i)
			{
				return float.Parse(f[i], CultureInfo.InvariantCulture);
			}
		}

		private void MergeOrder(Order o)
		{
			if (o != null && !_removed.ContainsKey(o.Id) && !_orders.ContainsKey(o.Id))
			{
				_orders[o.Id] = o;
			}
		}

		private static string Safe(string s)
		{
			return new string(s.Select((char c) => (!char.IsLetterOrDigit(c) && c != '-' && c != '_') ? '_' : c).ToArray());
		}

		private static string NamePath(string world)
		{
			char[] invalidFileNameChars = Path.GetInvalidFileNameChars();
			foreach (char oldChar in invalidFileNameChars)
			{
				world = world.Replace(oldChar, '_');
			}
			return Path.Combine(Paths.ConfigPath, "BuildOrders", world + ".txt");
		}

		private string SavePath()
		{
			return NamePath(_loadedWorld ?? "world");
		}

		private void EnsureWorldLoaded()
		{
			if ((Object)(object)ZNet.instance == (Object)null || (Object)(object)ZNet.instance == (Object)(object)_worldOf || (Object)(object)Player.m_localPlayer == (Object)null || ZNet.World == null)
			{
				return;
			}
			_worldOf = ZNet.instance;
			string text = ZNet.World.m_uid.ToString(CultureInfo.InvariantCulture);
			if (text == _loadedWorld)
			{
				return;
			}
			FlushSave();
			_loadedWorld = text;
			_loadedWorldName = ZNet.World.m_name ?? "";
			DropPlacing();
			ForgetWorld();
			DestroyAllGhosts();
			_orders.Clear();
			_removed.Clear();
			AdoptNamedFiles();
			LoadPendingLevels();
			try
			{
				string path = SavePath();
				if (!File.Exists(path))
				{
					return;
				}
				string[] array = File.ReadAllLines(path);
				foreach (string text2 in array)
				{
					if (text2.StartsWith("T|"))
					{
						NoteRemovedLine(text2);
					}
					else
					{
						MergeOrder(Decode(text2));
					}
				}
				ForgetOldRemovals();
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not read saved build orders: " + ex.Message));
			}
		}

		private void AdoptNamedFiles()
		{
			if (_loadedWorldName.Length == 0)
			{
				return;
			}
			try
			{
				string text = NamePath(_loadedWorldName);
				string text2 = SavePath();
				if (!File.Exists(text2) && File.Exists(text))
				{
					File.Move(text, text2);
					((BaseUnityPlugin)this).Logger.LogInfo((object)("Build orders of '" + _loadedWorldName + "' now kept as " + Path.GetFileName(text2)));
				}
				string text3 = Safe(_loadedWorldName + "__");
				string text4 = Safe(_loadedWorld + "__");
				string[] array = new string[2] { PlanRecordDir, TerrainDir };
				foreach (string text5 in array)
				{
					if (!Directory.Exists(text5) || text3 == text4)
					{
						continue;
					}
					string[] files = Directory.GetFiles(text5, text3 + "*.json");
					foreach (string text6 in files)
					{
						string text7 = Path.Combine(text5, text4 + Path.GetFileName(text6).Substring(text3.Length));
						if (!File.Exists(text7))
						{
							File.Move(text6, text7);
						}
					}
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not take over this world's older files: " + ex.Message));
			}
		}

		private void Save()
		{
			if (!_saveDue)
			{
				_saveDue = true;
				_saveAt = Time.unscaledTime + 2f;
			}
		}

		private void UpdateSave()
		{
			if (_saveDue && Time.unscaledTime >= _saveAt)
			{
				FlushSave();
			}
		}

		private void FlushSave()
		{
			if (!_saveDue)
			{
				return;
			}
			_saveDue = false;
			try
			{
				ForgetOldRemovals();
				string path = SavePath();
				Directory.CreateDirectory(Path.GetDirectoryName(path));
				IEnumerable<string> source = _orders.Values.Select(Encode).Concat(_removed.Select((KeyValuePair<string, int> kv) => "T|" + kv.Key + "|" + kv.Value.ToString(CultureInfo.InvariantCulture)));
				File.WriteAllLines(path, source.ToArray());
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not save build orders: " + ex.Message));
			}
		}

		private void UpdateNetwork()
		{
			ZRoutedRpc instance = ZRoutedRpc.instance;
			if (instance == null)
			{
				_registeredOn = null;
				_outbox.Clear();
			}
			else if (Time.frameCount > _awakeFrame + 2)
			{
				if (instance != _registeredOn)
				{
					_registeredOn = instance;
					UnregisterRpc();
					instance.Register<string>("DHack_BuildOrders", (Action<long, string>)OnMessage);
					instance.Register<ZPackage>("DHack_BuildOrders_Z", (Action<long, ZPackage>)OnPacked);
					_announcePending = true;
					_outbox.Clear();
				}
				FlushOutbox();
				if (_announcePending && (Object)(object)Player.m_localPlayer != (Object)null && WorldKnown)
				{
					_announcePending = false;
					Send("Q2", 0L);
				}
			}
		}

		private static void UnregisterRpc()
		{
			if (ZRoutedRpc.instance != null)
			{
				IDictionary dictionary = AccessTools.Field(typeof(ZRoutedRpc), "m_functions").GetValue(ZRoutedRpc.instance) as IDictionary;
				dictionary?.Remove(StringExtensionMethods.GetStableHashCode("DHack_BuildOrders"));
				dictionary?.Remove(StringExtensionMethods.GetStableHashCode("DHack_BuildOrders_Z"));
			}
		}

		private void Send(string message, long target = 0L)
		{
			if (ZRoutedRpc.instance == null || (Object)(object)Player.m_localPlayer == (Object)null)
			{
				return;
			}
			try
			{
				ZRoutedRpc.instance.InvokeRoutedRPC(target, "DHack_BuildOrders", new object[1] { message });
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not share build orders: " + ex.Message));
			}
		}

		private void ShareAdded(Order o)
		{
			_outbox.Enqueue(Encode(o));
		}

		private void ShareRemoved(string id)
		{
			_outbox.Enqueue("T|" + id);
		}

		private void FlushOutbox(bool all = false)
		{
			while (_outbox.Count > 0 && ZRoutedRpc.instance != null && (Object)(object)Player.m_localPlayer != (Object)null)
			{
				string text = _outbox.Dequeue();
				if (_outbox.Count == 0)
				{
					Send(text.StartsWith("T|") ? ("R|" + text.Substring(2)) : ("A|" + text), 0L);
				}
				else
				{
					StringBuilder stringBuilder = new StringBuilder("S\n").Append(text);
					while (_outbox.Count > 0 && stringBuilder.Length + 1 + _outbox.Peek().Length <= 8192)
					{
						stringBuilder.Append('\n').Append(_outbox.Dequeue());
					}
					Send(stringBuilder.ToString(), 0L);
				}
				if (!all)
				{
					break;
				}
			}
		}

		private void OnMessage(long sender, string message)
		{
			if (sender == ZDOMan.GetSessionID() || string.IsNullOrEmpty(message) || (!WorldKnown && message[0] != 'B'))
			{
				return;
			}
			try
			{
				switch (message[0])
				{
				case 'A':
					MergeOrder(Decode(message.Substring(2)));
					Save();
					break;
				case 'R':
				{
					string text2 = message.Substring(2);
					NoteRemoved(text2);
					if (_orders.Remove(text2))
					{
						DestroyGhost(text2);
					}
					Save();
					break;
				}
				case 'Q':
					if (message == "Q2")
					{
						SendPacked(BuildState(withDays: true), sender);
					}
					else
					{
						Send(BuildState(withDays: false), sender);
					}
					SendPlanRecords(sender);
					break;
				case 'P':
					OnPlanRecord(message.Substring(2));
					break;
				case 'B':
					OnSharedBlueprint(message.Substring(2));
					break;
				case 'S':
				{
					string[] array = message.Substring(1).Split(new char[1] { '\n' });
					foreach (string text in array)
					{
						if (text.StartsWith("T|"))
						{
							NoteRemovedLine(text);
						}
						else if (text.Length > 0)
						{
							MergeOrder(Decode(text));
						}
					}
					foreach (string key in _removed.Keys)
					{
						if (_orders.Remove(key))
						{
							DestroyGhost(key);
						}
					}
					Save();
					break;
				}
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Bad build-order message: " + ex.Message));
			}
		}

		private string BuildState(bool withDays)
		{
			ForgetOldRemovals();
			StringBuilder stringBuilder = new StringBuilder("S");
			foreach (Order value in _orders.Values)
			{
				stringBuilder.Append('\n').Append(Encode(value));
			}
			foreach (KeyValuePair<string, int> item in _removed)
			{
				stringBuilder.Append("\nT|").Append(item.Key);
				if (withDays)
				{
					stringBuilder.Append('|').Append(item.Value.ToString(CultureInfo.InvariantCulture));
				}
			}
			return stringBuilder.ToString();
		}

		private void SendPacked(string message, long target)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Expected O, but got Unknown
			if (ZRoutedRpc.instance == null)
			{
				return;
			}
			try
			{
				ZPackage val = new ZPackage();
				val.Write(Utils.Compress(Encoding.UTF8.GetBytes(message)));
				ZRoutedRpc.instance.InvokeRoutedRPC(target, "DHack_BuildOrders_Z", new object[1] { val });
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not share build orders: " + ex.Message));
			}
		}

		private void OnPacked(long sender, ZPackage pkg)
		{
			string message;
			try
			{
				message = Encoding.UTF8.GetString(Utils.Decompress(pkg.ReadByteArray()));
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Bad build-order message: " + ex.Message));
				return;
			}
			OnMessage(sender, message);
		}

		private void RefreshNeeds()
		{
			if (Time.unscaledTime < _nextNeeds)
			{
				return;
			}
			_nextNeeds = Time.unscaledTime + 0.5f;
			Dictionary<string, Need> dictionary = new Dictionary<string, Need>();
			foreach (Order value2 in _orders.Values)
			{
				GameObject val = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab(value2.Prefab) : null);
				Piece val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<Piece>() : null);
				if ((Object)(object)val2 == (Object)null)
				{
					continue;
				}
				Requirement[] resources = val2.m_resources;
				foreach (Requirement val3 in resources)
				{
					if (!((Object)(object)val3.m_resItem == (Object)null) && val3.m_amount > 0)
					{
						string name = val3.m_resItem.m_itemData.m_shared.m_name;
						if (!dictionary.TryGetValue(name, out var value))
						{
							Need obj = new Need
							{
								Item = name,
								Name = Localization.instance.Localize(name),
								Data = val3.m_resItem.m_itemData
							};
							value = obj;
							dictionary[name] = obj;
						}
						value.Amount += val3.m_amount;
					}
				}
			}
			_needs = dictionary.Values.OrderByDescending((Need n) => n.Amount).ToList();
		}

		private void TickHud()
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_holdFill != (Object)null)
			{
				_holdFill.offsetMax = new Vector2(2f + (_holdWidth - 4f) * Mathf.Clamp01(HoldProgress), -2f);
			}
			if (Time.unscaledTime < _hudAt)
			{
				return;
			}
			_hudAt = Time.unscaledTime + 0.1f;
			HashSet<string> wanted = new HashSet<string>();
			Player localPlayer = Player.m_localPlayer;
			if (_enabled.Value && (Object)(object)localPlayer != (Object)null && (Object)(object)GameUi.HudRoot != (Object)null && !Menu.IsVisible() && GameUi.Ready())
			{
				float top = 70f;
				if (!PlansWindowOpen)
				{
					if (_placing != null)
					{
						top = ShowBanner(wanted, "placing", top, PlacementBannerLines());
					}
					else if (ActiveLevelJob != null)
					{
						top = ShowBanner(wanted, "level", top, LevelBannerLines());
					}
					if (_bridgeStart.HasValue && !BridgeOptionsOpen)
					{
						top = ShowBanner(wanted, "bridge", top, BridgeBannerLines());
					}
				}
				bool flag = ((Character)localPlayer).InPlaceMode();
				if (!PlansWindowOpen && !BridgeOptionsOpen && !InventoryGui.IsVisible() && (flag || _alwaysShowPanel.Value || Aimed != null))
				{
					if (PlanKeyHeld && flag)
					{
						top = ShowBanner(wanted, "plan", top, new Line[1]
						{
							new Line(Translations.T("buildorders_banner_plan") + (_planToggle.Value ? ("   " + Translations.T("buildorders_banner_plan_leave", _planKey.Value)) : ""), 18f, GameUi.Warm)
						});
					}
					if (_orders.Count > 0 && (flag || _alwaysShowPanel.Value))
					{
						RefreshNeeds();
						ShowNeeds(wanted, localPlayer);
					}
					if (Aimed != null)
					{
						if (flag)
						{
							ShowAimCard(wanted);
						}
						else
						{
							ShowBuildPrompt(wanted);
						}
					}
					if (flag && FetchAvailable)
					{
						ShowFetchHint(wanted);
					}
				}
			}
			foreach (string item in _hudPieces.Keys.Where((string k) => !wanted.Contains(k)).ToList())
			{
				HideHud(item);
			}
		}

		private void ShowHud(HashSet<string> wanted, string name, string signature, Func<Transform, RectTransform> build)
		{
			wanted.Add(name);
			if (_hudPieces.TryGetValue(name, out var value) && (Object)(object)value.Root != (Object)null && value.Shown == signature)
			{
				return;
			}
			HideHud(name);
			Transform hudRoot = GameUi.HudRoot;
			foreach (Transform item in (from Transform t in (IEnumerable)hudRoot
				where ((Object)t).name == "BuildOrders." + name
				select t).ToList())
			{
				Object.Destroy((Object)(object)((Component)item).gameObject);
			}
			RectTransform val = build(hudRoot);
			((Object)val).name = "BuildOrders." + name;
			_hudPieces[name] = new HudPiece
			{
				Root = val,
				Shown = signature
			};
		}

		private void HideHud(string name)
		{
			if (_hudPieces.TryGetValue(name, out var value) && (Object)(object)value.Root != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)value.Root).gameObject);
			}
			_hudPieces.Remove(name);
			if (name == "prompt")
			{
				_holdFill = null;
			}
		}

		private void HideAllHud()
		{
			foreach (string item in _hudPieces.Keys.ToList())
			{
				HideHud(item);
			}
			Transform hudRoot = GameUi.HudRoot;
			if (!((Object)(object)hudRoot != (Object)null))
			{
				return;
			}
			foreach (Transform item2 in (from Transform t in (IEnumerable)hudRoot
				where ((Object)t).name.StartsWith("BuildOrders.")
				select t).ToList())
			{
				Object.Destroy((Object)(object)((Component)item2).gameObject);
			}
		}

		private static RectTransform TextCard(Transform parent, Vector2 anchor, Vector2 pos, IList<Line> lines)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: 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_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			RectTransform val = GameUi.Box(parent, Vector2.zero, new Vector2(100f, 100f));
			Vector2 anchorMin = (val.anchorMax = anchor);
			val.anchorMin = anchorMin;
			val.pivot = new Vector2(0.5f, 1f);
			val.anchoredPosition = pos;
			float num = 10f;
			float num2 = 200f;
			List<TMP_Text> list = new List<TMP_Text>();
			foreach (Line line in lines)
			{
				TMP_Text val3 = GameUi.Line((Transform)(object)val, line.Text, new Vector2(0f, 0f - num), 1100f, line.Size, line.Color, (TMP_FontAsset)null, (TextAlignmentOptions)258, (Vector2?)new Vector2(0.5f, 1f));
				num2 = Mathf.Max(num2, GameUi.Width(val3, line.Text));
				list.Add(val3);
				num += line.Size * 1.35f + 2f;
			}
			float num3 = Mathf.Min(1100f, num2 + 48f);
			foreach (TMP_Text item in list)
			{
				((RectTransform)item.transform).sizeDelta = new Vector2(num3 - 24f, ((RectTransform)item.transform).sizeDelta.y);
			}
			val.sizeDelta = new Vector2(num3, num + 8f);
			return val;
		}

		private float ShowBanner(HashSet<string> wanted, string name, float top, IList<Line> lines)
		{
			string signature = top + "|" + string.Join("|", lines.Select((Line l) => l.Text).ToArray());
			ShowHud(wanted, name, signature, (Transform hud) => TextCard(hud, new Vector2(0.5f, 1f), new Vector2(0f, 0f - top), lines));
			return top + 10f + lines.Sum((Line l) => l.Size * 1.35f + 2f) + 8f + 6f;
		}

		private static string Key(string key)
		{
			return "[<color=yellow><b>" + key + "</b></color>]";
		}

		private void ShowNeeds(HashSet<string> wanted, Player player)
		{
			Inventory inv = ((Humanoid)player).GetInventory();
			int shown = Mathf.Min(_needs.Count, 10);
			List<Need> list = _needs.Take(shown).ToList();
			int[] have = list.Select((Need n) => inv.CountItems(n.Item, -1, true)).ToArray();
			string signature = $"{_panelX.Value},{_panelY.Value}|{_orders.Count}|{_needs.Count}|{PlanHint}|" + string.Join("|", list.Select((Need n, int i) => n.Item + "," + n.Amount + "," + have[i]).ToArray());
			ShowHud(wanted, "needs", signature, delegate(Transform hud)
			{
				//IL_0067: Unknown result type (might be due to invalid IL or missing references)
				//IL_0072: Unknown result type (might be due to invalid IL or missing references)
				//IL_0097: 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_00e4: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f3: 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_017b: Unknown result type (might be due to invalid IL or missing references)
				//IL_018a: Unknown result type (might be due to invalid IL or missing references)
				//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
				//IL_0146: 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_02d6: Unknown result type (might be due to invalid IL or missing references)
				//IL_02e5: Unknown result type (might be due to invalid IL or missing references)
				//IL_028c: Unknown result type (might be due to invalid IL or missing references)
				//IL_029b: Unknown result type (might be due to invalid IL or missing references)
				//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
				//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
				//IL_020d: Unknown result type (might be due to invalid IL or missing references)
				float num = 42f + (float)shown * 26f + ((_needs.Count > shown) ? 22f : 0f) + 22f + 12f;
				RectTransform val = GameUi.Box(hud, new Vector2(_panelX.Value, 0f - _panelY.Value), new Vector2(280f, num));
				GameUi.Line((Transform)(object)val, Translations.T("buildorders_needs_title"), new Vector2(12f, -10f), 160f, 20f, GameUi.Warm, GameUi.Norse, (TextAlignmentOptions)257);
				GameUi.Line((Transform)(object)val, Pieces(_orders.Count), new Vector2(-12f, -10f), 110f, 15f, GameUi.Dim, (TMP_FontAsset)null, (TextAlignmentOptions)260, (Vector2?)new Vector2(1f, 1f));
				float num2 = 42f;
				for (int i = 0; i < list.Count; i++)
				{
					Need need = list[i];
					if (need.Data != null)
					{
						GameUi.Icon((Transform)(object)val, new Vector2(12f, 0f - num2), new Vector2(22f, 22f), need.Data.GetIcon());
					}
					GameUi.Line((Transform)(object)val, need.Name, new Vector2(40f, 0f - num2), 144f, 16f, GameUi.Text, null, (TextAlignmentOptions)257);
					GameUi.Line((Transform)(object)val, $"{have[i]} / {need.Amount}", new Vector2(-12f, 0f - num2), 84f, 16f, (have[i] >= need.Amount) ? GameUi.Good : GameUi.Warn, (TMP_FontAsset)null, (TextAlignmentOptions)260, (Vector2?)new Vector2(1f, 1f));
					num2 += 26f;
				}
				if (_needs.Count > shown)
				{
					GameUi.Line((Transform)(object)val, Translations.T("buildorders_needs_more", _needs.Count - shown), new Vector2(12f, 0f - num2), 256f, 15f, GameUi.Dim, null, (TextAlignmentOptions)257);
					num2 += 22f;
				}
				GameUi.Line((Transform)(object)val, PlanHint, new Vector2(12f, 0f - num2 - 2f), 256f, 15f, GameUi.Dim, null, (TextAlignmentOptions)257);
				return val;
			});
		}

		private void ShowAimCard(HashSet<string> wanted)
		{
			//IL_0040: 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_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: 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_00fa: Unknown result type (might be due to invalid IL or missing references)
			Order aimed = Aimed;
			Line[] lines = new Line[2]
			{
				new Line(PieceName(aimed.Prefab) + "   <color=#bdb7a9>" + PlannedBy(aimed.By) + "</color>", 19f, GameUi.Warm),
				new Line(Key(((object)_selectKey.Value/*cast due to .constrained prefix*/).ToString()) + " " + Translations.T("buildorders_aim_select") + "    " + Key(((object)_removeKey.Value/*cast due to .constrained prefix*/).ToString()) + " " + Translations.T("buildorders_aim_remove") + "    " + Translations.T("buildorders_aim_shift"), 16f, GameUi.Text)
			};
			ShowHud(wanted, "aim", aimed.Id + "|" + lines[0].Text + "|" + lines[1].Text, (Transform hud) => TextCard(hud, new Vector2(0.5f, 0.5f), new Vector2(0f, -90f), lines));
		}

		private static string PlannedBy(string by)
		{
			if (!(by ?? "").StartsWith("Blueprint: "))
			{
				return Translations.T("buildorders_aim_planned_by", Who(by));
			}
			return Translations.T("buildorders_aim_planned_by_blueprint", ShownTitle(by.Substring("Blueprint: ".Length)));
		}

		internal static string Pieces(int n)
		{
			return Translations.T((n == 1) ? "buildorders_piece_one" : "buildorders_pieces", n);
		}

		private void ShowBuildPrompt(HashSet<string> wanted)
		{
			Order o = Aimed;
			int pn = ((PlanLeft > 1) ? PlanLines.Count : 0);
			Stab stab = StabilityOf(o.Id);
			bool holding = HoldProgress > 0f;
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append(o.Id).Append('|').Append(o.By)
				.Append('|')
				.Append(HintKnown)
				.Append(HintAffordable)
				.Append(holding)
				.Append('|')
				.Append(HoldText)
				.Append('|');
			foreach (HintLine hintLine in HintLines)
			{
				stringBuilder.Append(hintLine.Name).Append(',').Append(hintLine.Have)
					.Append(',')
					.Append(hintLine.Need)
					.Append(';');
			}
			if (pn > 0)
			{
				stringBuilder.Append('|').Append(PlanTitle).Append(PlanLeft);
				foreach (HintLine planLine in PlanLines)
				{
					stringBuilder.Append(planLine.Name).Append(',').Append(planLine.Have)
						.Append(',')
						.Append(planLine.Need)
						.Append(';');
				}
			}
			if (stab != null)
			{
				stringBuilder.Append('|').Append(stab.Percent).Append(stab.Collapses)
					.Append(stab.Support >= stab.Max);
			}
			ShowHud(wanted, "prompt", stringBuilder.ToString(), (Transform hud) => BuildPrompt(hud, o, pn, stab, holding));
		}

		private RectTransform BuildPrompt(Transform hud, Order o, int pn, Stab stab, bool holding)
		{
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: 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_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: 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_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_0304: Unknown result type (might be due to invalid IL or missing references)
			//IL_0315: Unknown result type (might be due to invalid IL or missing references)
			//IL_034b: Unknown result type (might be due to invalid IL or missing references)
			//IL_035a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0367: Unknown result type (might be due to invalid IL or missing references)
			//IL_0372: Unknown result type (might be due to invalid IL or missing references)
			//IL_028e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0299: Unknown result type (might be due to invalid IL or missing references)
			//IL_021a: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_025c: Unknown result type (might be due to invalid IL or missing references)
			//IL_058d: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_03bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_044d: Unknown result type (might be due to invalid IL or missing references)
			//IL_05ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_040a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0403: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0601: Unknown result type (might be due to invalid IL or missing references)
			//IL_060b: Unknown result type (might be due to invalid IL or missing references)
			//IL_05b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_065d: Unknown result type (might be due to invalid IL or missing references)
			float cellSpace = GameUi.CellSpace;
			int count = HintLines.Count;
			float num = HoldText.Sum((char c) => (c < '⺀') ? 7.2f : 14f);
			float num2 = Mathf.Max(new float[4]
			{
				440f,
				(float)count * cellSpace + 32f,
				(float)pn * 96f + 32f,
				Mathf.Min(1000f, num + 32f + 16f)
			});
			RectTransform val = GameUi.Box(hud, Vector2.zero, new Vector2(num2, 100f));
			Vector2 val2 = default(Vector2);
			((Vector2)(ref val2))..ctor(0.5f, 0.5f);
			val.anchorMax = val2;
			val.anchorMin = val2;
			val.pivot = new Vector2(0.5f, 1f);
			val.anchoredPosition = new Vector2(0f, -80f);
			GameUi.Icon((Transform)(object)val, new Vector2(16f, -14f), new Vector2(46f, 46f), HintPieceIcon);
			GameUi.Line((Transform)(object)val, PieceName(o.Prefab), new Vector2(72f, -16f), num2 - 32f - 56f, 22f, GameUi.Warm, null, (TextAlignmentOptions)257);
			GameUi.Line((Transform)(object)val, PlannedBy(o.By), new Vector2(72f, -44f), num2 - 32f - 56f, 16f, GameUi.Dim, null, (TextAlignmentOptions)257);
			float num3 = 74f;
			if (count > 0)
			{
				float num4 = (num2 - (float)count * cellSpace) / 2f + (cellSpace - 64f) / 2f;
				for (int num5 = 0; num5 < count; num5++)
				{
					HintLine hintLine = HintLines[num5];
					bool flag = hintLine.Have >= hintLine.Need;
					if (hintLine.Item != null)
					{
						InventoryElement val3 = GameUi.Cell((Transform)(object)val, new Vector2(num4 + (float)num5 * cellSpace, 0f - num3), hintLine.Item, $"{hintLine.Have}/{hintLine.Need}", selected: false, null);
						if (!flag)
						{
							((Graphic)val3.m_amount).color = GameUi.Warn;
						}
					}
					GameUi.Line((Transform)(object)val, hintLine.Name, new Vector2(num4 + (float)num5 * cellSpace - (cellSpace - 64f) / 2f, 0f - num3 - 66f), cellSpace, 13f, GameUi.Dim, null, (TextAlignmentOptions)258);
				}
				num3 += 90f;
			}
			if (pn > 0)
			{
				GameUi.Line((Transform)(object)val, Translations.T("buildorders_whole_plan", PlanTitle, PlanLeft), new Vector2(16f, 0f - num3), num2 - 32f, 16f, GameUi.Text, null, (TextAlignmentOptions)258);
				num3 += 26f;
				RectTransform val4 = GameUi.Rect((Transform)(object)val, "Plan", new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(0f, 0f - num3), new Vector2(num2, 28f));
				float num6 = 0f;
				foreach (HintLine planLine in PlanLines)
				{
					num6 += ((planLine.Item != null) ? GameUi.Chip((Transform)(object)val4, new Vector2(num6, 0f), planLine.Item, $"{planLine.Have}/{planLine.Need}", 26f, 15f, (planLine.Have >= planLine.Need) ? GameUi.Good : GameUi.Warn) : 0f);
				}
				val4.anchoredPosition = new Vector2((num2 - (num6 - 12f)) / 2f, 0f - num3);
				num3 += 36f;
			}
			if (stab != null)
			{
				string text = ((stab.Support >= stab.Max) ? Translations.T("buildorders_stab_solid") : (stab.Collapses ? Translations.T("buildorders_stab_falls") : Translations.T("buildorders_stab_support", stab.Percent)));
				GameUi.Line((Transform)(object)val, text, new Vector2(16f, 0f - num3), num2 - 32f, 16f, stab.Collapses ? GameUi.Warn : StabilityColor(stab), null, (TextAlignmentOptions)258);
				num3 += 26f;
			}
			string text2 = ((HintKnown && HintAffordable) ? (Localization.instance.Localize(Key("$KEY_Use")) + " " + Translations.T("buildorders_build_it")) : (HintKnown ? Translations.T("buildorders_missing") : Translations.T("buildorders_not_unlocked_this")));
			GameUi.Line((Transform)(object)val, text2, new Vector2(16f, 0f - num3), num2 - 32f, 20f, (HintKnown && HintAffordable) ? GameUi.Text : GameUi.Warn, null, (TextAlignmentOptions)258);
			num3 += 32f;
			_holdWidth = num2 - 32f;
			RectTransform val5 = GameUi.Bar((Transform)(object)val, new Vector2(16f, 0f - num3), new Vector2(_holdWidth, 22f), 0f, GameUi.Gold, holding ? Translations.T("buildorders_keep_holding") : HoldText, 14f);
			ref RectTransform holdFill = ref _holdFill;
			Transform obj = ((Transform)val5).Find("Fill");
			holdFill = (RectTransform)(object)((obj is RectTransform) ? obj : null);
			num3 += 38f;
			val.sizeDelta = new Vector2(num2, num3);
			return val;
		}

		private void ShowFetchHint(HashSet<string> wanted)
		{
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			List<FetchLine> lines = FetchLines.Where((FetchLine l) => l.Short).ToList();
			if (lines.Count == 0 || !FetchTopUp)
			{
				return;
			}
			string head = Key(((object)_fetchKey.Value/*cast due to .constrained prefix*/).ToString()) + " " + Translations.T(FetchTopUp ? "buildorders_fetch_topup" : "buildorders_fetch_another", FetchPieceName);
			string signature = head + "|" + string.Join("|", lines.Select((FetchLine l) => l.Item + "," + l.InInventory + "," + l.Take).ToArray());
			ShowHud(wanted, "fetch", signature, delegate(Transform hud)
			{
				//IL_0007: 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_0034: Unknown result type (might be due to invalid IL or missing references)
				//IL_003b: Unknown result type (might be due to invalid IL or missing references)
				//IL_004d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0062: Unknown result type (might be due to invalid IL or missing references)
				//IL_007d: 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_00a1: 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_00f4: Unknown result type (might be due to invalid IL or missing references)
				//IL_0235: Unknown result type (might be due to invalid IL or missing references)
				//IL_01e1: 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_017e: Unknown result type (might be due to invalid IL or missing references)
				//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
				float cellSpace = GameUi.CellSpace;
				RectTransform val = GameUi.Box(hud, Vector2.zero, new Vector2(100f, 100f));
				Vector2 val2 = default(Vector2);
				((Vector2)(ref val2))..ctor(0.5f, 0f);
				val.anchorMax = val2;
				val.anchorMin = val2;
				val.pivot = new Vector2(0.5f, 0f);
				val.anchoredPosition = new Vector2(0f, 250f);
				TMP_Text val3 = GameUi.Line((Transform)(object)val, head, new Vector2(0f, -14f), 1000f, 18f, GameUi.Text, (TMP_FontAsset)null, (TextAlignmentOptions)258, (Vector2?)new Vector2(0.5f, 1f));
				float num = Mathf.Max((float)lines.Count * cellSpace + 28f, GameUi.Width(val3, head) + 48f);
				((RectTransform)val3.transform).sizeDelta = new Vector2(num - 24f, 26f);
				float num2 = (num - (float)lines.Count * cellSpace) / 2f + (cellSpace - 64f) / 2f;
				float num3 = 46f;
				for (int i = 0; i < lines.Count; i++)
				{
					FetchLine fetchLine = lines[i];
					ItemData val4 = ((!((Object)(object)fetchLine.Prefab != (Object)null)) ? null : fetchLine.Prefab.GetComponent<ItemDrop>()?.m_itemData);
					if (val4 != null)
					{
						InventoryElement val5 = GameUi.Cell((Transform)(object)val, new Vector2(num2 + (float)i * cellSpace, 0f - num3), val4, fetchLine.InInventory.ToString(), selected: false, null);
						((Graphic)val5.m_amount).color = GameUi.Warn;
					}
					GameUi.Line((Transform)(object)val, $"+{fetchLine.Take}", new Vector2(num2 + (float)i * cellSpace - (cellSpace - 64f) / 2f, 0f - num3 - 66f), cellSpace, 15f, GameUi.Good, null, (TextAlignmentOptions)258);
				}
				val.sizeDelta = new Vector2(num, num3 + 64f + 26f + 14f);
				return val;
			});
		}

		private static bool IsAddonGhostPlan(string key)
		{
			return key?.StartsWith("Blueprint: Addon ", StringComparison.Ordinal) ?? false;
		}

		public bool TryCreateGhostPlan(Player player, string title, string[] prefabs, Vector3[] positions, Quaternion[] rotations, out string planKey, out string error)
		{
			return TryCreateAddonPlan(player, title, prefabs, positions, rotations, 256, out planKey, out error);
		}

		public bool TryCreateBuildingShell(Player player, string title, string[] prefabs, Vector3[] positions, Quaternion[] rotations, out string planKey, out string error)
		{
			return TryCreateAddonPlan(player, title, prefabs, positions, rotations, 2048, out planKey, out error);
		}

		private bool TryCreateAddonPlan(Player player, string title, string[] prefabs, Vector3[] positions, Quaternion[] rotations, int maximum, out string planKey, out string error)
		{
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_0441: Unknown result type (might be due to invalid IL or missing references)
			//IL_0446: Unknown result type (might be due to invalid IL or missing references)
			//IL_0458: Unknown result type (might be due to invalid IL or missing references)
			//IL_045d: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d7: 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_01f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_020d: Unknown result type (might be due to invalid IL or missing references)
			//IL_025b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0265: Unknown result type (might be due to invalid IL or missing references)
			//IL_026f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0279: Unknown result type (might be due to invalid IL or missing references)
			//IL_0283: Unknown result type (might be due to invalid IL or missing references)
			//IL_0288: Unknown result type (might be due to invalid IL or missing references)
			//IL_0316: Unknown result type (might be due to invalid IL or missing references)
			//IL_0326: Unknown result type (might be due to invalid IL or missing references)
			planKey = null;
			if (!ApiReady(player, out error))
			{
				return false;
			}
			if (ApiToolBusy)
			{
				error = "Finish or cancel the current blueprint/bridge placement first.";
				return false;
			}
			if (string.IsNullOrWhiteSpace(title) || title.Length > 80 || title.IndexOfAny(new char[3] { '|', '\r', '\n' }) >= 0)
			{
				error = "Invalid plan title.";
				return false;
			}
			if (prefabs == null || positions == null || rotations == null || prefabs.Length < 1 || prefabs.Length > maximum || positions.Length != prefabs.Length || rotations.Length != prefabs.Length)
			{
				error = $"Expected 1–{maximum} matching prefab, position, and rotation entries.";
				return false;
			}
			Quaternion[] turns = (Quaternion[])(object)new Quaternion[rotations.Length];
			HashSet<string> hashSet = Buildable();
			int num = 0;
			while (num < prefabs.Length)
			{
				string text = prefabs[num];
				Vector3 val = positions[num];
				Quaternion val2 = rotations[num];
				if (!string.IsNullOrEmpty(text) && text.Length <= 128 && text.IndexOfAny(new char[3] { '|', '\r', '\n' }) < 0 && ApiFinite(val.x) && ApiFinite(val.y) && ApiFinite(val.z))
				{
					Vector3 val3 = val - ((Component)player).transform.position;
					if (!(((Vector3)(ref val3)).sqrMagnitude > 6400f))
					{
						double num2 = (double)val2.x * (double)val2.x + (double)val2.y * (double)val2.y + (double)val2.z * (double)val2.z + (double)val2.w * (double)val2.w;
						if (!ApiFinite(val2.x) || !ApiFinite(val2.y) || !ApiFinite(val2.z) || !ApiFinite(val2.w) || num2 < 0.0001 || num2 > 10000.0)
						{
							error = "Invalid plan rotation.";
							return false;
						}
						float num3 = (float)(1.0 / Math.Sqrt(num2));
						turns[num] = new Quaternion(val2.x * num3, val2.y * num3, val2.z * num3, val2.w * num3);
						GameObject prefab = ZNetScene.instance.GetPrefab(text);
						Piece val4 = (((Object)(object)prefab != (Object)null) ? prefab.GetComponent<Piece>() : null);
						if ((Object)(object)val4 == (Object)null || text == "piece_bo_bridge" || !hashSet.Contains(text) || (Object)(object)prefab.GetComponentInChildren<TerrainOp>(true) != (Object)null || (Object)(object)prefab.GetComponentInChildren<TerrainModifier>(true) != (Object)null)
						{
							error = "The plan contains an unavailable or non-building piece.";
							return false;
						}
						if (!player.IsRecipeKnown(val4.m_name))
						{
							error = "Unlock the selected building piece first.";
							return false;
						}
						if (!PrivateArea.CheckAccess(val, 0f, false, false) || Location.IsInsideNoBuildLocation(val))
						{
							error = "The plan includes protected ground.";
							return false;
						}
						num++;
						continue;
					}
				}
				error = "Invalid or out-of-reach plan pose.";
				return false;
			}
			string text2 = "Blueprint: Addon " + title.Trim() + " [" + System.Guid.NewGuid().ToString("N") + "]";
			List<Order> list = new List<Order>();
			int i;
			for (i = 0; i < prefabs.Length; i++)
			{
				if (!_orders.Values.Any(delegate(Order o)
				{
					//IL_001b: Unknown result type (might be due to invalid IL or missing references)
					//IL_002c: Unknown result type (might be due to invalid IL or missing references)
					//IL_0031: Unknown result type (might be due to invalid IL or missing references)
					//IL_0036: Unknown result type (might be due to invalid IL or missing references)
					//IL_0046: 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)
					if (o.Prefab == prefabs[i])
					{
						Vector3 val5 = o.Pos - positions[i];
						if (((Vector3)(ref val5)).sqrMagnitude < 0.01f)
						{
							return Quaternion.Angle(o.Rot, turns[i]) < 5f;
						}
					}
					return false;
				}) && !list.Any(delegate(Order o)
				{
					//IL_001b: Unknown