Decompiled source of SafeHarbor v1.0.1

SafeHarbor.dll

Decompiled 3 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Net;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using System.Threading;
using BepInEx;
using BepInEx.Configuration;
using Jotunn;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("SafeHarbor")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: AssemblyInformationalVersion("1.0.1")]
[assembly: AssemblyProduct("SafeHarbor")]
[assembly: AssemblyTitle("SafeHarbor")]
[assembly: AssemblyVersion("1.0.1.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 SafeHarbor
{
	public class BerthLamp : MonoBehaviour
	{
		public int Berth;

		public Vector3 BaseLocalPosition;

		public static readonly Color OpenColor = new Color(0.25f, 1f, 0.35f);

		public static readonly Color ClosedColor = new Color(1f, 0.18f, 0.12f);

		private Light m_light;

		private Renderer[] m_tintRenderers;

		private void Awake()
		{
			m_light = ((Component)this).GetComponentInChildren<Light>(true);
			Renderer[] componentsInChildren = ((Component)this).GetComponentsInChildren<Renderer>(true);
			List<Renderer> list = new List<Renderer>();
			foreach (Renderer val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null))
				{
					string text = ((Object)((Component)val).gameObject).name.ToLowerInvariant();
					Material sharedMaterial = val.sharedMaterial;
					if (((Object)(object)sharedMaterial != (Object)null && sharedMaterial.HasProperty("_EmissionColor")) || text.Contains("lantern") || text.Contains("glass") || text.Contains("flame") || text.Contains("light") || text.Contains("lamp") || text.Contains("bulb"))
					{
						list.Add(val);
					}
				}
			}
			if (list.Count == 0)
			{
				list.AddRange(componentsInChildren);
			}
			m_tintRenderers = list.ToArray();
		}

		public void SetOpen(bool open)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			Color val = (open ? OpenColor : ClosedColor);
			if ((Object)(object)m_light != (Object)null)
			{
				((Behaviour)m_light).enabled = true;
				m_light.color = val;
			}
			if (m_tintRenderers == null)
			{
				return;
			}
			for (int i = 0; i < m_tintRenderers.Length; i++)
			{
				Renderer val2 = m_tintRenderers[i];
				if ((Object)(object)val2 == (Object)null)
				{
					continue;
				}
				Material material = val2.material;
				if (!((Object)(object)material == (Object)null))
				{
					if (material.HasProperty("_Color"))
					{
						material.color = val;
					}
					if (material.HasProperty("_EmissionColor"))
					{
						material.EnableKeyword("_EMISSION");
						material.SetColor("_EmissionColor", val * 1.5f);
					}
				}
			}
		}
	}
	public class BlueprintPiece
	{
		public string Name;

		public Vector3 Position;

		public Quaternion Rotation = Quaternion.identity;

		public Vector3 Scale = Vector3.one;
	}
	public class DockBlueprint
	{
		public string Name = "safeDock";

		public string Creator = "";

		public string Description = "";

		public string Category = "InfinityHammer";

		public Vector3 Coordinates;

		public Vector3 EulerRotation;

		public readonly List<Vector3> SnapPoints = new List<Vector3>();

		public readonly List<BlueprintPiece> Pieces = new List<BlueprintPiece>();

		public static DockBlueprint Load(string path)
		{
			//IL_0244: Unknown result type (might be due to invalid IL or missing references)
			//IL_029f: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0303: Unknown result type (might be due to invalid IL or missing references)
			//IL_0207: Unknown result type (might be due to invalid IL or missing references)
			//IL_020c: Unknown result type (might be due to invalid IL or missing references)
			//IL_021a: Unknown result type (might be due to invalid IL or missing references)
			//IL_021f: Unknown result type (might be due to invalid IL or missing references)
			if (string.IsNullOrEmpty(path) || !File.Exists(path))
			{
				return null;
			}
			string[] array;
			try
			{
				array = File.ReadAllLines(path);
			}
			catch
			{
				return null;
			}
			DockBlueprint dockBlueprint = new DockBlueprint();
			CultureInfo invariantCulture = CultureInfo.InvariantCulture;
			bool flag = false;
			bool flag2 = false;
			for (int i = 0; i < array.Length; i++)
			{
				string text = array[i];
				if (text == null)
				{
					continue;
				}
				text = text.Trim();
				if (text.Length == 0)
				{
					continue;
				}
				if (text[0] == '#')
				{
					flag = false;
					flag2 = false;
					string text2 = text.Substring(1);
					int num = text2.IndexOf(':');
					string text3 = ((num >= 0) ? text2.Substring(0, num) : text2);
					string text4 = ((num >= 0) ? text2.Substring(num + 1) : "");
					switch (text3)
					{
					case "Name":
						dockBlueprint.Name = text4;
						break;
					case "Creator":
						dockBlueprint.Creator = text4;
						break;
					case "Description":
						dockBlueprint.Description = text4;
						break;
					case "Category":
						dockBlueprint.Category = text4;
						break;
					case "Coordinates":
						dockBlueprint.Coordinates = ParseVec(text4, invariantCulture);
						break;
					case "Rotation":
						dockBlueprint.EulerRotation = ParseVec(text4, invariantCulture);
						break;
					case "SnapPoints":
						flag = true;
						break;
					case "Pieces":
						flag2 = true;
						break;
					}
				}
				else if (flag)
				{
					dockBlueprint.SnapPoints.Add(ParseVec(text, invariantCulture));
				}
				else if (flag2)
				{
					string[] array2 = text.Split(';');
					if (array2.Length >= 13)
					{
						BlueprintPiece item = new BlueprintPiece
						{
							Name = array2[0],
							Position = new Vector3(ParseF(array2[2], invariantCulture), ParseF(array2[3], invariantCulture), ParseF(array2[4], invariantCulture)),
							Rotation = new Quaternion(ParseF(array2[5], invariantCulture), ParseF(array2[6], invariantCulture), ParseF(array2[7], invariantCulture), ParseF(array2[8], invariantCulture)),
							Scale = new Vector3(ParseF(array2[10], invariantCulture), ParseF(array2[11], invariantCulture), ParseF(array2[12], invariantCulture))
						};
						dockBlueprint.Pieces.Add(item);
					}
				}
			}
			if (dockBlueprint.Pieces.Count <= 0)
			{
				return null;
			}
			return dockBlueprint;
		}

		private static Vector3 ParseVec(string text, CultureInfo ci)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			if (string.IsNullOrEmpty(text))
			{
				return Vector3.zero;
			}
			string[] array = text.Split(',');
			if (array.Length < 3)
			{
				return Vector3.zero;
			}
			return new Vector3(ParseF(array[0], ci), ParseF(array[1], ci), ParseF(array[2], ci));
		}

		private static float ParseF(string text, CultureInfo ci)
		{
			if (!float.TryParse(text, NumberStyles.Float, ci, out var result))
			{
				return 0f;
			}
			return result;
		}
	}
	[Serializable]
	public class PieceTune
	{
		public string Name = "";

		public float X;

		public float Y;

		public float Z;

		public float Yaw;

		public float Scale = 1f;
	}
	[Serializable]
	public class DockTuning
	{
		public float GlobalX;

		public float GlobalY;

		public float GlobalZ;

		public float GlobalYaw;

		public float GlobalScale = 1f;

		public float BerthX;

		public float BerthY;

		public float BerthZ;

		public float BerthYaw;

		public float LampX;

		public float LampY = 0.5f;

		public float LampZ = -6f;

		public float LampScale = 1f;

		public string DeckMaterial = "";

		public List<PieceTune> Pieces = new List<PieceTune>();
	}
	internal static class SafeHarborAppearance
	{
		public static void Apply(GameObject prefab, float deckWidth, float deckLength, bool addPilings, float pilingLength, int berths, float berthSpacing, GameObject lampPrefab, float lampScale, Vector3 lampOffset, bool statusLights)
		{
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fd: 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_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: 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_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: 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_0227: Unknown result type (might be due to invalid IL or missing references)
			//IL_0243: Unknown result type (might be due to invalid IL or missing references)
			//IL_029e: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_02df: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0358: Unknown result type (might be due to invalid IL or missing references)
			//IL_037a: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ed: Unknown result type (might be due to invalid IL or missing references)
			Mesh val = null;
			Material val2 = null;
			MeshFilter[] componentsInChildren = prefab.GetComponentsInChildren<MeshFilter>(true);
			foreach (MeshFilter val3 in componentsInChildren)
			{
				if (!((Object)(object)val3.sharedMesh == (Object)null))
				{
					MeshRenderer component = ((Component)val3).GetComponent<MeshRenderer>();
					if (!((Object)(object)component == (Object)null) && !((Object)(object)((Renderer)component).sharedMaterial == (Object)null))
					{
						val = val3.sharedMesh;
						val2 = ((Renderer)component).sharedMaterial;
						break;
					}
				}
			}
			MeshRenderer[] componentsInChildren2 = prefab.GetComponentsInChildren<MeshRenderer>(true);
			for (int i = 0; i < componentsInChildren2.Length; i++)
			{
				((Renderer)componentsInChildren2[i]).enabled = false;
			}
			Collider[] componentsInChildren3 = prefab.GetComponentsInChildren<Collider>(true);
			for (int i = 0; i < componentsInChildren3.Length; i++)
			{
				componentsInChildren3[i].enabled = false;
			}
			float num = 0.3f;
			if ((Object)(object)val != (Object)null)
			{
				Bounds bounds = val.bounds;
				num = Mathf.Max(0.1f, ((Bounds)(ref bounds)).size.y);
				float num2 = Mathf.Max(0.01f, ((Bounds)(ref bounds)).size.x);
				float num3 = Mathf.Max(0.01f, ((Bounds)(ref bounds)).size.z);
				GameObject val4 = new GameObject("SafeHarborDeck");
				val4.transform.SetParent(prefab.transform, false);
				val4.transform.localScale = new Vector3(deckWidth / num2, 1f, deckLength / num3);
				val4.transform.localPosition = new Vector3(0f, 0f - ((Bounds)(ref bounds)).max.y, 0f);
				val4.AddComponent<MeshFilter>().sharedMesh = val;
				((Renderer)val4.AddComponent<MeshRenderer>()).sharedMaterial = val2;
			}
			else
			{
				Logger.LogWarning((object)"Safe Harbor: base dock piece had no usable mesh; falling back to a plain platform.");
				GameObject val5 = GameObject.CreatePrimitive((PrimitiveType)3);
				((Object)val5).name = "SafeHarborDeck";
				Object.Destroy((Object)(object)val5.GetComponent<Collider>());
				val5.transform.SetParent(prefab.transform, false);
				val5.transform.localScale = new Vector3(deckWidth, 0.4f, deckLength);
				val5.transform.localPosition = new Vector3(0f, -0.2f, 0f);
				if ((Object)(object)val2 != (Object)null)
				{
					((Renderer)val5.GetComponent<MeshRenderer>()).sharedMaterial = val2;
				}
			}
			BoxCollider obj = prefab.AddComponent<BoxCollider>();
			obj.size = new Vector3(deckWidth, num, deckLength);
			obj.center = new Vector3(0f, (0f - num) * 0.5f, 0f);
			if (addPilings && (Object)(object)val2 != (Object)null)
			{
				float num4 = deckWidth * 0.5f - 0.6f;
				float num5 = deckLength * 0.5f - 0.6f;
				float num6 = Mathf.Max(1f, pilingLength);
				Vector3[] array = (Vector3[])(object)new Vector3[4]
				{
					new Vector3(0f - num4, 0f, 0f - num5),
					new Vector3(num4, 0f, 0f - num5),
					new Vector3(0f - num4, 0f, num5),
					new Vector3(num4, 0f, num5)
				};
				for (int j = 0; j < array.Length; j++)
				{
					GameObject obj2 = GameObject.CreatePrimitive((PrimitiveType)2);
					((Object)obj2).name = "SafeHarborPiling" + j;
					Object.Destroy((Object)(object)obj2.GetComponent<Collider>());
					obj2.transform.SetParent(prefab.transform, false);
					obj2.transform.localPosition = new Vector3(array[j].x, (0f - num6) * 0.5f, array[j].z);
					obj2.transform.localScale = new Vector3(0.5f, num6 * 0.5f, 0.5f);
					((Renderer)obj2.GetComponent<MeshRenderer>()).sharedMaterial = val2;
				}
			}
			if (statusLights && berths > 0)
			{
				float num7 = (0f - deckLength) * 0.5f + 1f;
				for (int k = 0; k < berths; k++)
				{
					float num8 = ((float)k - (float)(berths - 1) * 0.5f) * berthSpacing;
					CreateLamp(prefab.transform, lampPrefab, val2, k, new Vector3(num8, 0f, num7), lampScale, lampOffset);
				}
			}
		}

		public static void ApplyBlueprint(GameObject prefab, DockBlueprint blueprint, Vector3 center, DockTuning tuning, GameObject lampPrefab, bool statusLights, out Vector3 berthLocal, out float deckLength)
		{
			//IL_005e: 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_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: 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)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: 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_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: 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)
			MeshRenderer[] componentsInChildren = prefab.GetComponentsInChildren<MeshRenderer>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				((Renderer)componentsInChildren[i]).enabled = false;
			}
			Collider[] componentsInChildren2 = prefab.GetComponentsInChildren<Collider>(true);
			for (int i = 0; i < componentsInChildren2.Length; i++)
			{
				componentsInChildren2[i].enabled = false;
			}
			Quaternion val = Quaternion.Euler(0f, tuning.GlobalYaw, 0f);
			Vector3 val2 = default(Vector3);
			((Vector3)(ref val2))..ctor(tuning.GlobalX, tuning.GlobalY, tuning.GlobalZ);
			float num = ((tuning.GlobalScale <= 0f) ? 1f : tuning.GlobalScale);
			Material val3 = null;
			for (int j = 0; j < blueprint.Pieces.Count; j++)
			{
				BlueprintPiece blueprintPiece = blueprint.Pieces[j];
				GameObject val4 = SafeHarborPlugin.FindVanillaPrefab(blueprintPiece.Name);
				if ((Object)(object)val4 == (Object)null)
				{
					continue;
				}
				GameObject val5 = Object.Instantiate<GameObject>(val4, prefab.transform, false);
				((Object)val5).name = "SH_BP_" + j;
				StripForDecoration(val5, keepColliders: true);
				if ((Object)(object)val3 == (Object)null)
				{
					MeshRenderer componentInChildren = val5.GetComponentInChildren<MeshRenderer>(true);
					if ((Object)(object)componentInChildren != (Object)null)
					{
						val3 = ((Renderer)componentInChildren).sharedMaterial;
					}
				}
				ApplyPieceTransform(val5.transform, blueprintPiece, j, tuning, center, val, val2, num);
			}
			deckLength = (TryGetBlueprintBounds(prefab.transform, out var bounds) ? Mathf.Max(((Bounds)(ref bounds)).size.x, ((Bounds)(ref bounds)).size.z) : 18f);
			berthLocal = val2 + val * (num * new Vector3(tuning.BerthX, tuning.BerthY, tuning.BerthZ));
			if (statusLights)
			{
				Vector3 lampOffset = val * (num * new Vector3(tuning.LampX, tuning.LampY, tuning.LampZ));
				CreateLamp(prefab.transform, lampPrefab, val3, 0, berthLocal, tuning.LampScale, lampOffset);
			}
		}

		public static void ApplyPieceTransform(Transform child, BlueprintPiece piece, int index, DockTuning tuning, Vector3 center, Quaternion globalRot, Vector3 globalOffset, float globalScale)
		{
			//IL_000b: 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_0033: 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_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: 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_00bf: 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_00c4: 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_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			float num = piece.Position.x - center.x;
			float num2 = piece.Position.y - center.y;
			float num3 = piece.Position.z - center.z;
			float num4 = 0f;
			float num5 = 1f;
			if (tuning != null && tuning.Pieces != null && index < tuning.Pieces.Count)
			{
				PieceTune pieceTune = tuning.Pieces[index];
				num = pieceTune.X;
				num2 = pieceTune.Y;
				num3 = pieceTune.Z;
				num4 = pieceTune.Yaw;
				num5 = pieceTune.Scale;
			}
			child.localPosition = globalOffset + globalRot * (globalScale * new Vector3(num, num2, num3));
			Vector3 eulerAngles = ((Quaternion)(ref piece.Rotation)).eulerAngles;
			child.localRotation = globalRot * Quaternion.Euler(eulerAngles.x, eulerAngles.y + num4, eulerAngles.z);
			child.localScale = Vector3.Scale(piece.Scale, Vector3.one * (globalScale * num5));
		}

		private static void CreateLamp(Transform parent, GameObject lampPrefab, Material fallbackMaterial, int berth, Vector3 baseLocalPosition, float lampScale, Vector3 lampOffset)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: 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_0137: 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_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: 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_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			float num = Mathf.Clamp(lampScale, 0.1f, 3f);
			GameObject val = new GameObject("SafeHarborLamp" + berth);
			val.SetActive(false);
			GameObject val2;
			if ((Object)(object)lampPrefab != (Object)null)
			{
				val2 = Object.Instantiate<GameObject>(lampPrefab, val.transform, false);
				((Object)val2).name = "Lantern";
				StripForDecoration(val2, keepColliders: false);
			}
			else
			{
				val2 = CreateFallbackLamp(fallbackMaterial);
				val2.transform.SetParent(val.transform, false);
			}
			Light val3 = val.GetComponentInChildren<Light>(true);
			if ((Object)(object)val3 == (Object)null)
			{
				val3 = val.AddComponent<Light>();
				val3.type = (LightType)2;
			}
			((Behaviour)val3).enabled = true;
			val3.range = Mathf.Clamp(val3.range, 6f, 10f);
			val3.intensity = Mathf.Clamp(val3.intensity, 0.8f, 1.4f);
			if (TryGetLocalBounds(val.transform, out var bounds))
			{
				Transform transform = val2.transform;
				transform.localPosition -= new Vector3(0f, ((Bounds)(ref bounds)).min.y, 0f);
			}
			val.transform.SetParent(parent, false);
			val.transform.localPosition = baseLocalPosition + lampOffset;
			val.transform.localRotation = Quaternion.identity;
			val.transform.localScale = Vector3.one * num;
			BerthLamp berthLamp = val.AddComponent<BerthLamp>();
			berthLamp.Berth = berth;
			berthLamp.BaseLocalPosition = baseLocalPosition;
			val.SetActive(true);
		}

		private static GameObject CreateFallbackLamp(Material material)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_004f: 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_00d0: 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_00e9: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("FallbackLantern");
			GameObject val2 = GameObject.CreatePrimitive((PrimitiveType)2);
			((Object)val2).name = "LampPost";
			Object.Destroy((Object)(object)val2.GetComponent<Collider>());
			val2.transform.SetParent(val.transform, false);
			val2.transform.localPosition = new Vector3(0f, 0.9f, 0f);
			val2.transform.localScale = new Vector3(0.16f, 0.9f, 0.16f);
			if ((Object)(object)material != (Object)null)
			{
				((Renderer)val2.GetComponent<MeshRenderer>()).sharedMaterial = material;
			}
			GameObject obj = GameObject.CreatePrimitive((PrimitiveType)0);
			((Object)obj).name = "LampBulb";
			Object.Destroy((Object)(object)obj.GetComponent<Collider>());
			obj.transform.SetParent(val.transform, false);
			obj.transform.localPosition = new Vector3(0f, 2f, 0f);
			obj.transform.localScale = Vector3.one * 0.5f;
			return val;
		}

		private static void StripForDecoration(GameObject root, bool keepColliders)
		{
			Component[] componentsInChildren = root.GetComponentsInChildren<Component>(true);
			foreach (Component val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null) && !(val is Transform) && !(val is MeshFilter) && !(val is MeshRenderer) && !(val is SkinnedMeshRenderer) && !(val is Light) && !(val is LODGroup) && (!keepColliders || !(val is Collider)) && !(val is ParticleSystem) && !(val is ParticleSystemRenderer) && !(val is ReflectionProbe))
				{
					Object.DestroyImmediate((Object)(object)val);
				}
			}
		}

		private static bool TryGetLocalBounds(Transform root, out Bounds bounds)
		{
			//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_0010: 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_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: 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_0073: 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_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: 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_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			bounds = new Bounds(Vector3.zero, Vector3.zero);
			Matrix4x4 worldToLocalMatrix = root.worldToLocalMatrix;
			bool flag = false;
			MeshFilter[] componentsInChildren = ((Component)root).GetComponentsInChildren<MeshFilter>(true);
			foreach (MeshFilter val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null) && !((Object)(object)val.sharedMesh == (Object)null))
				{
					Bounds val2 = TransformBounds(worldToLocalMatrix * ((Component)val).transform.localToWorldMatrix, val.sharedMesh.bounds);
					if (!flag)
					{
						bounds = val2;
						flag = true;
					}
					else
					{
						((Bounds)(ref bounds)).Encapsulate(val2);
					}
				}
			}
			SkinnedMeshRenderer[] componentsInChildren2 = ((Component)root).GetComponentsInChildren<SkinnedMeshRenderer>(true);
			foreach (SkinnedMeshRenderer val3 in componentsInChildren2)
			{
				if (!((Object)(object)val3 == (Object)null))
				{
					Bounds val4 = TransformBounds(worldToLocalMatrix * ((Component)val3).transform.localToWorldMatrix, ((Renderer)val3).localBounds);
					if (!flag)
					{
						bounds = val4;
						flag = true;
					}
					else
					{
						((Bounds)(ref bounds)).Encapsulate(val4);
					}
				}
			}
			return flag;
		}

		private static bool TryGetBlueprintBounds(Transform root, out Bounds bounds)
		{
			//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_0010: 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_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: 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)
			//IL_008c: 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_0082: Unknown result type (might be due to invalid IL or missing references)
			bounds = new Bounds(Vector3.zero, Vector3.zero);
			Matrix4x4 worldToLocalMatrix = root.worldToLocalMatrix;
			bool flag = false;
			MeshFilter[] componentsInChildren = ((Component)root).GetComponentsInChildren<MeshFilter>(true);
			foreach (MeshFilter val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null) && !((Object)(object)val.sharedMesh == (Object)null) && UnderBlueprint(((Component)val).transform, root))
				{
					Bounds val2 = TransformBounds(worldToLocalMatrix * ((Component)val).transform.localToWorldMatrix, val.sharedMesh.bounds);
					if (!flag)
					{
						bounds = val2;
						flag = true;
					}
					else
					{
						((Bounds)(ref bounds)).Encapsulate(val2);
					}
				}
			}
			return flag;
		}

		private static bool UnderBlueprint(Transform t, Transform root)
		{
			while ((Object)(object)t != (Object)null && (Object)(object)t.parent != (Object)(object)root)
			{
				t = t.parent;
			}
			if ((Object)(object)t != (Object)null)
			{
				return ((Object)t).name.StartsWith("SH_BP_");
			}
			return false;
		}

		private static Bounds TransformBounds(Matrix4x4 matrix, Bounds local)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: 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_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: 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_0092: 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_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: 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_00dd: 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_00e9: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = ((Matrix4x4)(ref matrix)).MultiplyPoint3x4(((Bounds)(ref local)).center);
			Vector3 extents = ((Bounds)(ref local)).extents;
			Vector3 val2 = ((Matrix4x4)(ref matrix)).MultiplyVector(new Vector3(extents.x, 0f, 0f));
			Vector3 val3 = ((Matrix4x4)(ref matrix)).MultiplyVector(new Vector3(0f, extents.y, 0f));
			Vector3 val4 = ((Matrix4x4)(ref matrix)).MultiplyVector(new Vector3(0f, 0f, extents.z));
			Vector3 val5 = default(Vector3);
			((Vector3)(ref val5))..ctor(Mathf.Abs(val2.x) + Mathf.Abs(val3.x) + Mathf.Abs(val4.x), Mathf.Abs(val2.y) + Mathf.Abs(val3.y) + Mathf.Abs(val4.y), Mathf.Abs(val2.z) + Mathf.Abs(val3.z) + Mathf.Abs(val4.z));
			return new Bounds(val, val5 * 2f);
		}
	}
	[BepInPlugin("com.safeharbor.safeharbor", "Safe Harbor", "1.0.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class SafeHarborPlugin : BaseUnityPlugin
	{
		private class DockVariant
		{
			public string PrefabName;

			public string DisplayName;

			public string Description;

			public float DeckWidth;

			public float DeckLength;

			public int Berths;

			public float BerthSpacing;

			public bool Pilings;

			public float PilingLength;

			public float LampScale;

			public bool UseBlueprint;

			public bool Small;

			public int Wood;

			public int FineWood;

			public int Iron;

			public GameObject Prefab;

			public bool PieceAdded;
		}

		private class BerthChoice
		{
			public ShipDock Dock;

			public int Berth;

			public int DockIndex;

			public float Distance;

			public bool Open;
		}

		public const string PluginGUID = "com.safeharbor.safeharbor";

		public const string PluginName = "Safe Harbor";

		public const string PluginVersion = "1.0.1";

		public const string DockPrefabName = "SafeHarborDock";

		public const string SmallDockPrefabName = "SafeHarborSmallDock";

		private const string LanternPrefabName = "piece_dvergr_lantern_pole";

		private static readonly string[] BasePieceCandidates = new string[6] { "piece_woodfloor2x2", "piece_woodfloor1x1", "piece_stonefloor2x2", "piece_stonefloor4x4", "piece_woodpole", "piece_woodwall" };

		internal static ConfigEntry<bool> Enabled;

		internal static ConfigEntry<bool> AddBuildPiece;

		internal static ConfigEntry<bool> DebugLogging;

		internal static ConfigEntry<bool> ShowHudPrompt;

		internal static ConfigEntry<bool> ShowMessages;

		internal static ConfigEntry<bool> StatusLights;

		internal static ConfigEntry<float> LampScale;

		internal static ConfigEntry<float> LampOffsetX;

		internal static ConfigEntry<float> LampOffsetY;

		internal static ConfigEntry<float> LampOffsetZ;

		internal static ConfigEntry<string> DeckMaterial;

		internal static ConfigEntry<KeyboardShortcut> GuiKey;

		internal static ConfigEntry<bool> UseBlueprint;

		internal static ConfigEntry<string> BlueprintPath;

		internal static ConfigEntry<string> SmallBlueprintPath;

		internal static ConfigEntry<bool> WebTuner;

		internal static ConfigEntry<int> WebPort;

		internal static ConfigEntry<float> DockRange;

		internal static ConfigEntry<float> DockDuration;

		internal static ConfigEntry<float> UndockDuration;

		internal static ConfigEntry<float> LiftHeight;

		internal static ConfigEntry<float> UndockDistance;

		internal static ConfigEntry<float> UndockSpeed;

		internal static ConfigEntry<float> MaxDockSpeed;

		internal static ConfigEntry<KeyboardShortcut> DockKey;

		internal static ConfigEntry<int> BerthCount;

		internal static ConfigEntry<float> BerthSpacing;

		internal static ConfigEntry<float> DeckLength;

		internal static ConfigEntry<bool> AddPilings;

		internal static ConfigEntry<float> PilingLength;

		internal static ConfigEntry<float> Health;

		internal static ConfigEntry<bool> Indestructible;

		internal static ConfigEntry<bool> AddSmallDock;

		internal static ConfigEntry<float> SmallDeckWidth;

		internal static ConfigEntry<float> SmallDeckLength;

		internal static bool PrefabRegistered;

		internal static readonly List<ShipDock> Docks = new List<ShipDock>();

		internal static string CurrentPrompt;

		internal static DockBlueprint Blueprint;

		internal static Vector3 BlueprintCenter;

		internal static DockTuning Tuning = new DockTuning();

		internal static string TuningPath;

		internal static DockBlueprint SmallBlueprint;

		internal static Vector3 SmallCenter;

		internal static DockTuning SmallTuning = new DockTuning();

		internal static string SmallTuningPath;

		private static volatile string s_pendingApply;

		private static volatile int s_pendingApplyTarget;

		private static volatile bool s_pendingSave;

		private static volatile int s_pendingSaveTarget;

		private static SafeHarborWebGui s_web;

		private GUIStyle m_promptStyle;

		private GUIStyle m_menuTitleStyle;

		private GUIStyle m_menuDimStyle;

		private bool m_loggedDiagnostics;

		private bool m_loggedBasePiece;

		private float m_retryTimer;

		private bool m_menuOpen;

		private Ship m_menuShip;

		private readonly List<BerthChoice> m_choices = new List<BerthChoice>();

		private readonly List<DockVariant> m_variants = new List<DockVariant>();

		private bool m_guiOpen;

		private bool m_tuneInit;

		private float m_tuneX;

		private float m_tuneY;

		private float m_tuneZ;

		private float m_tuneScale = 1f;

		private Vector2 m_matScroll;

		private List<string> m_materialNames;

		private Material m_currentDeckMaterial;

		private Rect m_guiRect = new Rect(40f, 140f, 360f, 500f);

		private const int GuiWindowId = 918273645;

		private const string BlueprintFileName = "safeDock.blueprint";

		private static Vector3 LampOffset => new Vector3(LampOffsetX.Value, LampOffsetY.Value, LampOffsetZ.Value);

		private void Awake()
		{
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0393: Unknown result type (might be due to invalid IL or missing references)
			Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Master toggle. When false Safe Harbor does nothing.");
			AddBuildPiece = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "AddBuildPiece", true, "Add the dock pieces to the Hammer build menu. Requires a game restart.");
			DebugLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "DebugLogging", true, "Log docking activity to the BepInEx log. Turn off once everything behaves.");
			ShowHudPrompt = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ShowHudPrompt", true, "Show the persistent 'dock' hint on screen while steering near a dock.");
			ShowMessages = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ShowMessages", true, "Show a message when a ship docks or undocks.");
			StatusLights = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "StatusLights", true, "Show a status lamp per dock (green = open, red = docked). Requires a game restart.");
			LampScale = ((BaseUnityPlugin)this).Config.Bind<float>("General", "LampScale", 1f, "Scale of the status lamps. Requires a game restart.");
			LampScale.Value = Mathf.Clamp(LampScale.Value, 0.1f, 3f);
			LampOffsetX = ((BaseUnityPlugin)this).Config.Bind<float>("General", "LampOffsetX", 0f, "Status lamp X offset (meters) from its default spot. Requires a game restart.");
			LampOffsetY = ((BaseUnityPlugin)this).Config.Bind<float>("General", "LampOffsetY", 0.5f, "Status lamp height (meters) above the deck. Requires a game restart.");
			LampOffsetZ = ((BaseUnityPlugin)this).Config.Bind<float>("General", "LampOffsetZ", 0f, "Status lamp Z offset (meters) from its default spot. Requires a game restart.");
			DeckMaterial = ((BaseUnityPlugin)this).Config.Bind<string>("General", "DeckMaterial", "", "Material name to apply to the dock deck (blank = the base piece's material). Requires a game restart.");
			GuiKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Controls", "GuiKey", new KeyboardShortcut((KeyCode)108, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), "Open the Safe Harbor tuner GUI (lamp position/scale + deck material).");
			UseBlueprint = ((BaseUnityPlugin)this).Config.Bind<bool>("Blueprint", "UseBlueprint", true, "Build the large dock from an Infinity Hammer / PlanBuild blueprint when one is found.");
			BlueprintPath = ((BaseUnityPlugin)this).Config.Bind<string>("Blueprint", "BlueprintPath", "", "Full path to the large dock blueprint. Leave blank to auto-find 'safeDock.blueprint' in the PlanBuild blueprint folders.");
			SmallBlueprintPath = ((BaseUnityPlugin)this).Config.Bind<string>("Blueprint", "SmallBlueprintPath", "", "Full path to the skiff dock blueprint. Leave blank to auto-find 'safeSkiff.blueprint'/'smallDock.blueprint', or to reuse the large dock blueprint.");
			WebTuner = ((BaseUnityPlugin)this).Config.Bind<bool>("Blueprint", "WebTuner", true, "Serve the localhost web tuner for moving the blueprint pieces live.");
			WebPort = ((BaseUnityPlugin)this).Config.Bind<int>("Blueprint", "WebPort", 8781, "Port for the web tuner (http://127.0.0.1:<port>/). 8777-8780 are used by other mods.");
			DockRange = ((BaseUnityPlugin)this).Config.Bind<float>("Docking", "DockRange", 50f, "Max distance (meters) from a dock at which the dock prompt appears.");
			DockDuration = ((BaseUnityPlugin)this).Config.Bind<float>("Docking", "DockDuration", 2.5f, "Seconds the ship takes to ease into the berth and lift onto the cradle.");
			UndockDuration = ((BaseUnityPlugin)this).Config.Bind<float>("Docking", "UndockDuration", 1.5f, "Seconds the ship takes to slide back out of the berth.");
			LiftHeight = ((BaseUnityPlugin)this).Config.Bind<float>("Docking", "LiftHeight", 1.8f, "How far (meters) the ship is raised above the water when docked. 0 = stay at the waterline.");
			UndockDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Docking", "UndockDistance", 20f, "Distance (meters) forward of the berth the ship is released to when undocking. The ship is always pushed clear of the dock platform even if this is smaller.");
			UndockSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Docking", "UndockSpeed", 4f, "Forward push (m/s) given to the ship the moment it is released from the dock. 0 = no push.");
			MaxDockSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Docking", "MaxDockSpeed", 3f, "Ship must be slower than this (m/s) to dock, so you do not slam into the dock. 0 disables the check.");
			DockKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Controls", "DockKey", new KeyboardShortcut((KeyCode)100, (KeyCode[])(object)new KeyCode[1] { (KeyCode)304 }), "Key held while at the rudder to dock/undock. Default: Shift+D.");
			BerthCount = ((BaseUnityPlugin)this).Config.Bind<int>("Dock", "Berths", 1, "How many ships one large dock can hold. 1 is recommended (one boat per dock). Requires a game restart.");
			BerthCount.Value = Mathf.Clamp(BerthCount.Value, 1, 6);
			BerthSpacing = ((BaseUnityPlugin)this).Config.Bind<float>("Dock", "BerthSpacing", 9f, "Distance (meters) between berths across the dock, when Berths > 1. Requires a game restart.");
			DeckLength = ((BaseUnityPlugin)this).Config.Bind<float>("Dock", "DeckLength", 18f, "Length (meters) of the large dock platform. Requires a game restart.");
			AddPilings = ((BaseUnityPlugin)this).Config.Bind<bool>("Dock", "AddPilings", true, "Add support pilings under the dock. Requires a game restart.");
			PilingLength = ((BaseUnityPlugin)this).Config.Bind<float>("Dock", "PilingLength", 20f, "Length (meters) of the support pilings. Longer legs let the dock stand in deeper water. Requires a game restart.");
			Health = ((BaseUnityPlugin)this).Config.Bind<float>("Dock", "Health", 5000f, "Hit points of the dock piece (ignored when Indestructible).");
			Indestructible = ((BaseUnityPlugin)this).Config.Bind<bool>("Dock", "Indestructible", true, "Make the dock immune to all damage so it can never be destroyed.");
			AddSmallDock = ((BaseUnityPlugin)this).Config.Bind<bool>("SmallDock", "Enabled", true, "Also add a smaller dock for karves and rafts. Requires a game restart.");
			SmallDeckWidth = ((BaseUnityPlugin)this).Config.Bind<float>("SmallDock", "DeckWidth", 6f, "Width (meters) of the small dock platform. Requires a game restart.");
			SmallDeckLength = ((BaseUnityPlugin)this).Config.Bind<float>("SmallDock", "DeckLength", 10f, "Length (meters) of the small dock platform. Requires a game restart.");
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Safe Harbor 1.0.1 loading...");
			LoadBlueprintAndTuning();
			BuildVariants();
			if (WebTuner.Value)
			{
				s_web = new SafeHarborWebGui(WebPort.Value, GetWebStateJson, QueueWebApply, QueueWebSave);
				s_web.Start();
			}
			PrefabManager.OnVanillaPrefabsAvailable += OnVanillaPrefabsAvailable;
			PrefabManager.OnPrefabsRegistered += OnPrefabsRegistered;
			PieceManager.OnPiecesRegistered += OnPiecesRegistered;
			TryRegisterDocks();
		}

		private void BuildVariants()
		{
			m_variants.Clear();
			m_variants.Add(new DockVariant
			{
				PrefabName = "SafeHarborDock",
				DisplayName = "Safe Harbor Dock",
				Description = "A sturdy cradle for longships. Steer a ship within range, then press Shift+D at the rudder to dock and lift it out of the water.",
				DeckWidth = Mathf.Max(4f, (float)BerthCount.Value * BerthSpacing.Value),
				DeckLength = DeckLength.Value,
				Berths = BerthCount.Value,
				BerthSpacing = BerthSpacing.Value,
				Pilings = AddPilings.Value,
				PilingLength = PilingLength.Value,
				LampScale = LampScale.Value,
				UseBlueprint = (UseBlueprint.Value && Blueprint != null),
				Wood = 40,
				FineWood = 20,
				Iron = 10
			});
			if (AddSmallDock.Value)
			{
				m_variants.Add(new DockVariant
				{
					PrefabName = "SafeHarborSmallDock",
					DisplayName = "Safe Harbor Skiff Dock",
					Description = "A smaller cradle for karves and rafts. Steer a ship within range, then press Shift+D at the rudder to dock and lift it out of the water.",
					DeckWidth = SmallDeckWidth.Value,
					DeckLength = SmallDeckLength.Value,
					Berths = 1,
					BerthSpacing = 4f,
					Pilings = AddPilings.Value,
					PilingLength = PilingLength.Value,
					LampScale = LampScale.Value,
					UseBlueprint = (SmallBlueprint != null || Blueprint != null),
					Small = true,
					Wood = 20,
					FineWood = 8,
					Iron = 3
				});
			}
		}

		private void OnDestroy()
		{
			PrefabManager.OnVanillaPrefabsAvailable -= OnVanillaPrefabsAvailable;
			PrefabManager.OnPrefabsRegistered -= OnPrefabsRegistered;
			PieceManager.OnPiecesRegistered -= OnPiecesRegistered;
			if (s_web != null)
			{
				s_web.Stop();
				s_web = null;
			}
		}

		private void OnVanillaPrefabsAvailable()
		{
			TryRegisterDocks();
		}

		private void OnPrefabsRegistered()
		{
			TryRegisterDocks();
		}

		private void Update()
		{
			//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)
			UpdateRegistration();
			UpdatePrompt();
			ProcessWebQueue();
			KeyboardShortcut value = GuiKey.Value;
			if (((KeyboardShortcut)(ref value)).IsPressed())
			{
				m_guiOpen = !m_guiOpen;
				if (m_guiOpen)
				{
					InitTune();
				}
			}
			if (m_guiOpen)
			{
				Cursor.lockState = (CursorLockMode)0;
				Cursor.visible = true;
			}
		}

		private void UpdateRegistration()
		{
			if (!PrefabRegistered && Enabled.Value && AddBuildPiece.Value && !((Object)(object)ZNetScene.instance == (Object)null))
			{
				m_retryTimer += Time.deltaTime;
				if (!(m_retryTimer < 2f))
				{
					m_retryTimer = 0f;
					TryRegisterDocks();
				}
			}
		}

		private void TryRegisterDocks()
		{
			//IL_02e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: 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)
			//IL_01ad: 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)
			if (PrefabRegistered || !Enabled.Value || !AddBuildPiece.Value || (Object)(object)ZNetScene.instance == (Object)null || m_variants.Count == 0)
			{
				return;
			}
			try
			{
				GameObject val = FindBasePiecePrefab();
				if ((Object)(object)val == (Object)null)
				{
					if (!m_loggedDiagnostics)
					{
						m_loggedDiagnostics = true;
						LogDiagnostics();
					}
					return;
				}
				if (!m_loggedBasePiece)
				{
					m_loggedBasePiece = true;
					((BaseUnityPlugin)this).Logger.LogInfo((object)("Safe Harbor: using base piece '" + ((Object)val).name + "'. Top: " + DescribeTopPieces(5)));
				}
				GameObject val2 = (StatusLights.Value ? FindVanillaPrefab("piece_dvergr_lantern_pole") : null);
				if (StatusLights.Value && (Object)(object)val2 == (Object)null)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)"Safe Harbor: could not find 'piece_dvergr_lantern_pole'; using simple status lights.");
				}
				bool prefabRegistered = true;
				for (int i = 0; i < m_variants.Count; i++)
				{
					DockVariant dockVariant = m_variants[i];
					if ((Object)(object)dockVariant.Prefab != (Object)null)
					{
						continue;
					}
					GameObject val3 = PrefabManager.Instance.CreateClonedPrefab(dockVariant.PrefabName, val);
					if ((Object)(object)val3 == (Object)null)
					{
						((BaseUnityPlugin)this).Logger.LogWarning((object)("Safe Harbor: failed to clone the base piece for '" + dockVariant.PrefabName + "'."));
						prefabRegistered = false;
						continue;
					}
					StripNestedNetworkObjects(val3);
					ConfigurePiece(val3);
					ShipDock shipDock = val3.AddComponent<ShipDock>();
					if (dockVariant.UseBlueprint)
					{
						DockBlueprint dockBlueprint = (dockVariant.Small ? SmallBlueprint : Blueprint);
						DockTuning tuning = (dockVariant.Small ? SmallTuning : Tuning);
						Vector3 center = (dockVariant.Small ? SmallCenter : BlueprintCenter);
						SafeHarborAppearance.ApplyBlueprint(val3, dockBlueprint, center, tuning, val2, StatusLights.Value, out var _, out var deckLength);
						shipDock.IsBlueprint = true;
						shipDock.IsSmall = dockVariant.Small;
						shipDock.BerthCount = 1;
						shipDock.BerthSpacing = 1f;
						shipDock.DeckLength = deckLength;
						int num = 0;
						Transform[] componentsInChildren = val3.GetComponentsInChildren<Transform>(true);
						for (int j = 0; j < componentsInChildren.Length; j++)
						{
							if ((Object)(object)componentsInChildren[j] != (Object)null && ((Object)componentsInChildren[j]).name.StartsWith("SH_BP_"))
							{
								num++;
							}
						}
						((BaseUnityPlugin)this).Logger.LogInfo((object)("Safe Harbor: blueprint dock '" + dockVariant.PrefabName + "' built with " + num + "/" + (dockBlueprint?.Pieces.Count ?? 0) + " pieces."));
					}
					else
					{
						SafeHarborAppearance.Apply(val3, dockVariant.DeckWidth, dockVariant.DeckLength, dockVariant.Pilings, dockVariant.PilingLength, dockVariant.Berths, dockVariant.BerthSpacing, val2, dockVariant.LampScale, LampOffset, StatusLights.Value);
						ApplyDeckMaterial(val3);
						shipDock.BerthCount = dockVariant.Berths;
						shipDock.BerthSpacing = Mathf.Max(1f, dockVariant.BerthSpacing);
						shipDock.DeckLength = dockVariant.DeckLength;
					}
					PrefabManager.Instance.AddPrefab(val3);
					dockVariant.Prefab = val3;
					int num2 = val3.GetComponentsInChildren<BerthLamp>(true).Length;
					((BaseUnityPlugin)this).Logger.LogInfo((object)("Safe Harbor: registered '" + dockVariant.PrefabName + "' cloned from '" + ((Object)val).name + "' (" + num2 + " lamps)."));
				}
				PrefabRegistered = prefabRegistered;
				TryAddPieces();
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Safe Harbor: failed to register a dock prefab: " + ex));
			}
		}

		private void OnPiecesRegistered()
		{
			TryAddPieces();
		}

		private void TryAddPieces()
		{
			//IL_004a: 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_005b: 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_0072: 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_0085: Expected O, but got Unknown
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Expected O, but got Unknown
			if (!Enabled.Value || !AddBuildPiece.Value)
			{
				return;
			}
			for (int i = 0; i < m_variants.Count; i++)
			{
				DockVariant dockVariant = m_variants[i];
				if (!dockVariant.PieceAdded && !((Object)(object)dockVariant.Prefab == (Object)null))
				{
					try
					{
						PieceConfig val = new PieceConfig
						{
							Name = dockVariant.DisplayName,
							Description = dockVariant.Description,
							PieceTable = "Hammer",
							Category = "Misc",
							Enabled = true
						};
						val.AddRequirement("Wood", dockVariant.Wood, true);
						val.AddRequirement("FineWood", dockVariant.FineWood, true);
						val.AddRequirement("Iron", dockVariant.Iron, true);
						PieceManager.Instance.AddPiece(new CustomPiece(dockVariant.Prefab, false, val));
						dockVariant.PieceAdded = true;
						((BaseUnityPlugin)this).Logger.LogInfo((object)("Safe Harbor: added '" + dockVariant.DisplayName + "' build piece to the Hammer menu."));
					}
					catch (Exception ex)
					{
						((BaseUnityPlugin)this).Logger.LogError((object)("Safe Harbor: failed to add the '" + dockVariant.DisplayName + "' piece: " + ex));
					}
				}
			}
		}

		private static void ConfigurePiece(GameObject prefab)
		{
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: 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_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: 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_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			Piece component = prefab.GetComponent<Piece>();
			if ((Object)(object)component != (Object)null)
			{
				component.m_waterPiece = true;
				component.m_groundPiece = true;
				component.m_groundOnly = false;
				component.m_clipGround = false;
				component.m_noInWater = false;
				component.m_canRotate = true;
				component.m_canBeRemoved = true;
			}
			WearNTear component2 = prefab.GetComponent<WearNTear>();
			if ((Object)(object)component2 != (Object)null)
			{
				component2.m_noSupportWear = true;
				component2.m_noRoofWear = true;
				component2.m_supports = false;
				component2.m_burnable = false;
				component2.m_materialType = (MaterialType)0;
				component2.m_health = Health.Value;
				if (Indestructible.Value)
				{
					component2.m_health = 1000000f;
					DamageModifiers damages = component2.m_damages;
					damages.m_blunt = (DamageModifier)3;
					damages.m_slash = (DamageModifier)3;
					damages.m_pierce = (DamageModifier)3;
					damages.m_chop = (DamageModifier)3;
					damages.m_pickaxe = (DamageModifier)3;
					damages.m_fire = (DamageModifier)3;
					damages.m_frost = (DamageModifier)3;
					damages.m_lightning = (DamageModifier)3;
					damages.m_poison = (DamageModifier)3;
					damages.m_spirit = (DamageModifier)3;
					damages.m_nonPlayer = (DamageModifier)3;
					component2.m_damages = damages;
				}
			}
		}

		private void UpdatePrompt()
		{
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			CurrentPrompt = null;
			if (!Enabled.Value || (Object)(object)Player.m_localPlayer == (Object)null)
			{
				m_menuOpen = false;
				return;
			}
			Ship val = FindSteeredShip();
			if ((Object)(object)val == (Object)null)
			{
				m_menuOpen = false;
				return;
			}
			ShipDockHandler component = ((Component)val).GetComponent<ShipDockHandler>();
			KeyboardShortcut value;
			if ((Object)(object)component != (Object)null && component.IsBusy)
			{
				CurrentPrompt = (component.IsDocking ? "Docking..." : "Undocking...");
				m_menuOpen = false;
			}
			else if ((Object)(object)component != (Object)null && component.IsDocked)
			{
				CurrentPrompt = KeyLabel() + " to undock";
				m_menuOpen = false;
				value = DockKey.Value;
				if (((KeyboardShortcut)(ref value)).IsPressed())
				{
					component.BeginUndock();
				}
			}
			else
			{
				if (m_menuOpen && (Object)(object)m_menuShip == (Object)(object)val)
				{
					return;
				}
				m_menuOpen = false;
				List<BerthChoice> list = GatherChoices(val);
				if (list.Count == 0)
				{
					value = DockKey.Value;
					if (((KeyboardShortcut)(ref value)).IsPressed())
					{
						Message("No docks in range.");
					}
					return;
				}
				int num = 0;
				for (int i = 0; i < list.Count; i++)
				{
					if (list[i].Open)
					{
						num++;
					}
				}
				CurrentPrompt = ((num > 0) ? (KeyLabel() + " to choose dock (" + num + " open)") : "Safe Harbor: all berths occupied");
				value = DockKey.Value;
				if (((KeyboardShortcut)(ref value)).IsPressed())
				{
					m_menuOpen = true;
					m_menuShip = val;
					m_choices.Clear();
					m_choices.AddRange(list);
				}
			}
		}

		private void BeginDockWith(Ship ship, ShipDock dock, int berth)
		{
			m_menuOpen = false;
			if (!((Object)(object)ship == (Object)null) && !((Object)(object)dock == (Object)null) && berth >= 0)
			{
				((Component)ship).gameObject.AddComponent<ShipDockHandler>().BeginDock(ship, dock, berth);
			}
		}

		private static List<BerthChoice> GatherChoices(Ship ship)
		{
			//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)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			List<BerthChoice> list = new List<BerthChoice>();
			Vector3 position = ((Component)ship).transform.position;
			float value = DockRange.Value;
			Dictionary<ShipDock, int> dictionary = new Dictionary<ShipDock, int>();
			for (int i = 0; i < Docks.Count; i++)
			{
				ShipDock shipDock = Docks[i];
				if ((Object)(object)shipDock == (Object)null)
				{
					continue;
				}
				int capacity = shipDock.Capacity;
				for (int j = 0; j < capacity; j++)
				{
					float num = Vector3.Distance(position, shipDock.BerthWorldPosition(j));
					if (!(num > value))
					{
						if (!dictionary.ContainsKey(shipDock))
						{
							dictionary[shipDock] = dictionary.Count + 1;
						}
						list.Add(new BerthChoice
						{
							Dock = shipDock,
							Berth = j,
							DockIndex = dictionary[shipDock],
							Distance = num,
							Open = !shipDock.IsBerthOccupied(j)
						});
					}
				}
			}
			list.Sort((BerthChoice a, BerthChoice b) => (a.Open != b.Open) ? ((!a.Open) ? 1 : (-1)) : a.Distance.CompareTo(b.Distance));
			return list;
		}

		internal static Ship FindSteeredShip()
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || Ship.Instances == null)
			{
				return null;
			}
			long playerID = localPlayer.GetPlayerID();
			List<IMonoUpdater> instances = Ship.Instances;
			for (int i = 0; i < instances.Count; i++)
			{
				IMonoUpdater obj = instances[i];
				Ship val = (Ship)(object)((obj is Ship) ? obj : null);
				if (!((Object)(object)val == (Object)null))
				{
					ShipControlls shipControlls = val.m_shipControlls;
					if (!((Object)(object)shipControlls == (Object)null) && shipControlls.HaveValidUser() && shipControlls.GetUser() == playerID)
					{
						return val;
					}
				}
			}
			return null;
		}

		private static string KeyLabel()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			KeyboardShortcut value = DockKey.Value;
			string text = "";
			foreach (KeyCode modifier in ((KeyboardShortcut)(ref value)).Modifiers)
			{
				text = text + ModifierName(modifier) + "+";
			}
			return text + ((object)((KeyboardShortcut)(ref value)).MainKey/*cast due to .constrained prefix*/).ToString();
		}

		private unsafe static string ModifierName(KeyCode key)
		{
			//IL_0000: 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_0024: Expected I4, but got Unknown
			switch (key - 303)
			{
			case 0:
			case 1:
				return "Shift";
			case 2:
			case 3:
				return "Ctrl";
			case 4:
			case 5:
				return "Alt";
			default:
				return ((object)(*(KeyCode*)(&key))/*cast due to .constrained prefix*/).ToString();
			}
		}

		internal static void Message(string text)
		{
			if (ShowMessages.Value && !((Object)(object)MessageHud.instance == (Object)null))
			{
				MessageHud.instance.ShowMessage((MessageType)1, text, 0, (Sprite)null, false, false);
			}
		}

		internal static void Debug(string text)
		{
			if (DebugLogging.Value)
			{
				Logger.LogInfo((object)("Safe Harbor: " + text));
			}
		}

		private void OnGUI()
		{
			if (Enabled.Value && !((Object)(object)Player.m_localPlayer == (Object)null))
			{
				DrawMenu();
				DrawPrompt();
				DrawTuner();
			}
		}

		private void DrawPrompt()
		{
			//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_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Expected O, but got Unknown
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			if (!m_menuOpen && ShowHudPrompt.Value && !string.IsNullOrEmpty(CurrentPrompt))
			{
				if (m_promptStyle == null)
				{
					m_promptStyle = new GUIStyle(GUI.skin.label)
					{
						alignment = (TextAnchor)4,
						fontSize = 20,
						fontStyle = (FontStyle)1
					};
					m_promptStyle.normal.textColor = Color.white;
				}
				float num = 500f;
				float num2 = 36f;
				Rect val = new Rect(((float)Screen.width - num) * 0.5f, (float)Screen.height * 0.72f, num, num2);
				Color color = GUI.color;
				GUI.color = new Color(0f, 0f, 0f, 0.55f);
				GUI.DrawTexture(val, (Texture)(object)Texture2D.whiteTexture);
				GUI.color = color;
				GUI.Label(val, CurrentPrompt, m_promptStyle);
			}
		}

		private void DrawMenu()
		{
			//IL_0076: 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)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0224: Unknown result type (might be due to invalid IL or missing references)
			//IL_022a: Invalid comparison between Unknown and I4
			//IL_01da: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0241: Unknown result type (might be due to invalid IL or missing references)
			//IL_0247: Invalid comparison between Unknown and I4
			//IL_022e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0235: Invalid comparison between Unknown and I4
			//IL_024e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0255: Invalid comparison between Unknown and I4
			//IL_025c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0263: Invalid comparison between Unknown and I4
			//IL_0267: Unknown result type (might be due to invalid IL or missing references)
			//IL_026e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0271: Expected I4, but got Unknown
			if (!m_menuOpen || (Object)(object)m_menuShip == (Object)null)
			{
				return;
			}
			EnsureMenuStyles();
			float num = 520f;
			float num2 = 32f;
			float num3 = 34f;
			float num4 = 12f;
			float num5 = num3 + (float)m_choices.Count * num2 + num4 * 2f;
			Rect val = default(Rect);
			((Rect)(ref val))..ctor(((float)Screen.width - num) * 0.5f, ((float)Screen.height - num5) * 0.5f, num, num5);
			Color color = GUI.color;
			GUI.color = new Color(0f, 0f, 0f, 0.85f);
			GUI.DrawTexture(val, (Texture)(object)Texture2D.whiteTexture);
			GUI.color = color;
			GUI.Label(new Rect(((Rect)(ref val)).x, ((Rect)(ref val)).y + num4, ((Rect)(ref val)).width, num3), "Select a dock", m_menuTitleStyle);
			float num6 = ((Rect)(ref val)).y + num4 + num3;
			int num7 = 0;
			Rect val2 = default(Rect);
			for (int i = 0; i < m_choices.Count; i++)
			{
				BerthChoice berthChoice = m_choices[i];
				((Rect)(ref val2))..ctor(((Rect)(ref val)).x + num4, num6, num - num4 * 2f, num2 - 2f);
				string text = "Dock " + berthChoice.DockIndex;
				if (berthChoice.Dock.Capacity > 1)
				{
					text = text + "  -  Berth " + (berthChoice.Berth + 1);
				}
				text = text + "   (" + Mathf.RoundToInt(berthChoice.Distance) + " m)";
				if (berthChoice.Open)
				{
					num7++;
					if (GUI.Button(val2, num7 + ".   " + text + "   -   Open"))
					{
						BeginDockWith(m_menuShip, berthChoice.Dock, berthChoice.Berth);
						return;
					}
				}
				else
				{
					GUI.Label(val2, "       " + text + "   -   Docked", m_menuDimStyle);
				}
				num6 += num2;
			}
			Event current = Event.current;
			if (current == null)
			{
				return;
			}
			if ((int)current.type == 4 && (int)current.keyCode == 27)
			{
				m_menuOpen = false;
			}
			else
			{
				if ((int)current.type != 4 || (int)current.keyCode < 49 || (int)current.keyCode > 57)
				{
					return;
				}
				int num8 = current.keyCode - 49;
				int num9 = 0;
				for (int j = 0; j < m_choices.Count; j++)
				{
					if (m_choices[j].Open)
					{
						if (num9 == num8)
						{
							BeginDockWith(m_menuShip, m_choices[j].Dock, m_choices[j].Berth);
							break;
						}
						num9++;
					}
				}
			}
		}

		private void EnsureMenuStyles()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Expected O, but got Unknown
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			if (m_menuTitleStyle == null)
			{
				m_menuTitleStyle = new GUIStyle(GUI.skin.label)
				{
					alignment = (TextAnchor)4,
					fontSize = 20,
					fontStyle = (FontStyle)1
				};
				m_menuTitleStyle.normal.textColor = Color.white;
				m_menuDimStyle = new GUIStyle(GUI.skin.label)
				{
					alignment = (TextAnchor)3,
					fontSize = 16
				};
				m_menuDimStyle.normal.textColor = new Color(0.75f, 0.45f, 0.45f);
			}
		}

		private static void ApplyDeckMaterial(GameObject prefab)
		{
			if (string.IsNullOrEmpty(DeckMaterial.Value))
			{
				return;
			}
			Material val = FindMaterial(DeckMaterial.Value);
			if ((Object)(object)val == (Object)null)
			{
				Logger.LogWarning((object)("Safe Harbor: deck material '" + DeckMaterial.Value + "' not found."));
				return;
			}
			Transform val2 = prefab.transform.Find("SafeHarborDeck");
			if ((Object)(object)val2 != (Object)null)
			{
				MeshRenderer component = ((Component)val2).GetComponent<MeshRenderer>();
				if ((Object)(object)component != (Object)null)
				{
					((Renderer)component).sharedMaterial = val;
				}
			}
		}

		private static Material FindMaterial(string name)
		{
			Material[] array = Resources.FindObjectsOfTypeAll<Material>();
			foreach (Material val in array)
			{
				if ((Object)(object)val != (Object)null && string.Equals(((Object)val).name, name, StringComparison.OrdinalIgnoreCase))
				{
					return val;
				}
			}
			return null;
		}

		private void InitTune()
		{
			if (!m_tuneInit)
			{
				m_tuneInit = true;
				m_tuneX = LampOffsetX.Value;
				m_tuneY = LampOffsetY.Value;
				m_tuneZ = LampOffsetZ.Value;
				m_tuneScale = LampScale.Value;
				m_currentDeckMaterial = (string.IsNullOrEmpty(DeckMaterial.Value) ? null : FindMaterial(DeckMaterial.Value));
			}
			EnsureMaterialNames();
		}

		private void EnsureMaterialNames()
		{
			if (m_materialNames != null)
			{
				return;
			}
			m_materialNames = new List<string>();
			HashSet<string> hashSet = new HashSet<string>();
			Material[] array = Resources.FindObjectsOfTypeAll<Material>();
			foreach (Material val in array)
			{
				if (!((Object)(object)val == (Object)null))
				{
					string name = ((Object)val).name;
					if (!string.IsNullOrEmpty(name) && !name.StartsWith("Hidden", StringComparison.OrdinalIgnoreCase) && !name.StartsWith("Sprites", StringComparison.OrdinalIgnoreCase) && (val.HasProperty("_MainTex") || val.HasProperty("_Color")) && hashSet.Add(name))
					{
						m_materialNames.Add(name);
					}
				}
			}
			m_materialNames.Sort(StringComparer.OrdinalIgnoreCase);
		}

		private void ApplyTune()
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			Vector3 lampOffset = default(Vector3);
			((Vector3)(ref lampOffset))..ctor(m_tuneX, m_tuneY, m_tuneZ);
			for (int i = 0; i < Docks.Count; i++)
			{
				ShipDock shipDock = Docks[i];
				if (!((Object)(object)shipDock == (Object)null))
				{
					if (shipDock.IsBlueprint)
					{
						shipDock.ApplyBlueprintTuning();
					}
					else
					{
						shipDock.ApplyLayout(lampOffset, m_tuneScale, m_currentDeckMaterial, applyMaterial: true);
					}
				}
			}
		}

		private void SaveTune()
		{
			LampOffsetX.Value = m_tuneX;
			LampOffsetY.Value = m_tuneY;
			LampOffsetZ.Value = m_tuneZ;
			LampScale.Value = m_tuneScale;
			Message("Safe Harbor settings saved.");
		}

		private void DrawTuner()
		{
			//IL_0010: 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_0030: Expected O, but got Unknown
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			if (m_guiOpen)
			{
				m_guiRect = GUILayout.Window(918273645, m_guiRect, new WindowFunction(DrawTunerWindow), "Safe Harbor Tuner", Array.Empty<GUILayoutOption>());
			}
		}

		private void DrawTunerWindow(int id)
		{
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.Label("Changes apply live to all placed docks.", Array.Empty<GUILayoutOption>());
			float num = LabeledSlider("Lamp X", m_tuneX, -10f, 10f);
			float num2 = LabeledSlider("Lamp Y", m_tuneY, -10f, 10f);
			float num3 = LabeledSlider("Lamp Z", m_tuneZ, -10f, 10f);
			float num4 = LabeledSlider("Lamp Scale", m_tuneScale, 0.1f, 3f);
			if (num != m_tuneX || num2 != m_tuneY || num3 != m_tuneZ || num4 != m_tuneScale)
			{
				m_tuneX = num;
				m_tuneY = num2;
				m_tuneZ = num3;
				m_tuneScale = num4;
				ApplyTune();
			}
			GUILayout.Space(6f);
			GUILayout.Label("Deck material: " + (((Object)(object)m_currentDeckMaterial != (Object)null) ? ((Object)m_currentDeckMaterial).name : "(base)"), Array.Empty<GUILayoutOption>());
			m_matScroll = GUILayout.BeginScrollView(m_matScroll, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(200f) });
			if (GUILayout.Button("(use base piece material)", Array.Empty<GUILayoutOption>()))
			{
				m_currentDeckMaterial = null;
				DeckMaterial.Value = "";
				ApplyTune();
			}
			for (int i = 0; i < m_materialNames.Count; i++)
			{
				string text = m_materialNames[i];
				if (GUILayout.Button(text, Array.Empty<GUILayoutOption>()))
				{
					m_currentDeckMaterial = FindMaterial(text);
					DeckMaterial.Value = text;
					ApplyTune();
				}
			}
			GUILayout.EndScrollView();
			GUILayout.Space(6f);
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			if (GUILayout.Button("Save defaults", Array.Empty<GUILayoutOption>()))
			{
				SaveTune();
			}
			if (GUILayout.Button("Close", Array.Empty<GUILayoutOption>()))
			{
				m_guiOpen = false;
			}
			GUILayout.EndHorizontal();
			GUI.DragWindow();
		}

		private static float LabeledSlider(string label, float value, float min, float max)
		{
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label(label + ": " + value.ToString("0.00"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(150f) });
			float result = GUILayout.HorizontalSlider(value, min, max, Array.Empty<GUILayoutOption>());
			GUILayout.EndHorizontal();
			return result;
		}

		private void LoadBlueprintAndTuning()
		{
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			string text = ResolveBlueprintPath(small: false);
			Blueprint = DockBlueprint.Load(text);
			if (Blueprint == null)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Safe Harbor: no large dock blueprint found" + (string.IsNullOrEmpty(text) ? "." : (" at '" + text + "'.")) + " Using the built-in model."));
			}
			else
			{
				BlueprintCenter = ComputeCenter(Blueprint);
				TuningPath = Path.Combine(Paths.ConfigPath, "safeharbor_dock.json");
				Tuning = LoadTuning(TuningPath);
				if (Tuning == null)
				{
					Tuning = new DockTuning();
				}
				EnsureTuningPieces(Blueprint, Tuning, BlueprintCenter);
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Safe Harbor: loaded large blueprint '" + Blueprint.Name + "' (" + Blueprint.Pieces.Count + " pieces)."));
			}
			SmallBlueprint = DockBlueprint.Load(ResolveBlueprintPath(small: true));
			if (SmallBlueprint == null)
			{
				SmallBlueprint = Blueprint;
				SmallCenter = BlueprintCenter;
			}
			else
			{
				SmallCenter = ComputeCenter(SmallBlueprint);
			}
			if (SmallBlueprint != null)
			{
				SmallTuningPath = Path.Combine(Paths.ConfigPath, "safeharbor_skiff.json");
				SmallTuning = LoadTuning(SmallTuningPath);
				if (SmallTuning == null)
				{
					SmallTuning = new DockTuning();
				}
				EnsureTuningPieces(SmallBlueprint, SmallTuning, SmallCenter);
				if (SmallBlueprint != Blueprint)
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)("Safe Harbor: loaded skiff blueprint '" + SmallBlueprint.Name + "' (" + SmallBlueprint.Pieces.Count + " pieces)."));
				}
				else
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)"Safe Harbor: no skiff blueprint; the skiff dock reuses the large blueprint (separate tuning).");
				}
			}
		}

		private static List<string> BlueprintDirs()
		{
			List<string> list = new List<string>();
			try
			{
				list.Add(Path.Combine(Paths.ConfigPath, "PlanBuild", "blueprints"));
				list.Add(Path.Combine(Paths.GameRootPath, "BepInEx", "config", "PlanBuild", "blueprints"));
				list.Add(Path.Combine(Paths.ConfigPath, "PlanBuild"));
				list.Add(Path.Combine(Paths.GameRootPath, "BepInEx", "config", "PlanBuild"));
			}
			catch
			{
			}
			return list;
		}

		private static string FindBlueprintFile(string[] names)
		{
			List<string> list = BlueprintDirs();
			for (int i = 0; i < list.Count; i++)
			{
				for (int j = 0; j < names.Length; j++)
				{
					string text = Path.Combine(list[i], names[j]);
					if (File.Exists(text))
					{
						return text;
					}
				}
			}
			return null;
		}

		private static string ResolveBlueprintPath(bool small)
		{
			if (small)
			{
				if (!string.IsNullOrEmpty(SmallBlueprintPath.Value))
				{
					return SmallBlueprintPath.Value;
				}
				return FindBlueprintFile(new string[4] { "safeSkiff.blueprint", "smallDock.blueprint", "safeDockSmall.blueprint", "skiff.blueprint" }) ?? ResolveBlueprintPath(small: false);
			}
			if (!string.IsNullOrEmpty(BlueprintPath.Value))
			{
				return BlueprintPath.Value;
			}
			string text = FindBlueprintFile(new string[1] { "safeDock.blueprint" });
			if (text != null)
			{
				return text;
			}
			List<string> list = BlueprintDirs();
			if (list.Count <= 0)
			{
				return "";
			}
			return Path.Combine(list[0], "safeDock.blueprint");
		}

		private static Vector3 ComputeCenter(DockBlueprint blueprint)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: 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_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: 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)
			if (blueprint == null || blueprint.Pieces.Count == 0)
			{
				return Vector3.zero;
			}
			Vector3 val = blueprint.Pieces[0].Position;
			Vector3 val2 = val;
			for (int i = 1; i < blueprint.Pieces.Count; i++)
			{
				Vector3 position = blueprint.Pieces[i].Position;
				val = Vector3.Min(val, position);
				val2 = Vector3.Max(val2, position);
			}
			return (val + val2) * 0.5f;
		}

		private static void EnsureTuningPieces(DockBlueprint blueprint, DockTuning tuning, Vector3 center)
		{
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			if (blueprint != null && (tuning.Pieces == null || tuning.Pieces.Count != blueprint.Pieces.Count))
			{
				tuning.Pieces = new List<PieceTune>();
				for (int i = 0; i < blueprint.Pieces.Count; i++)
				{
					BlueprintPiece blueprintPiece = blueprint.Pieces[i];
					tuning.Pieces.Add(new PieceTune
					{
						Name = blueprintPiece.Name,
						X = blueprintPiece.Position.x - center.x,
						Y = blueprintPiece.Position.y - center.y,
						Z = blueprintPiece.Position.z - center.z,
						Yaw = 0f,
						Scale = 1f
					});
				}
			}
		}

		private static DockTuning LoadTuning(string path)
		{
			try
			{
				if (!string.IsNullOrEmpty(path) && File.Exists(path))
				{
					return JsonUtility.FromJson<DockTuning>(File.ReadAllText(path));
				}
			}
			catch (Exception ex)
			{
				Logger.LogWarning((object)("Safe Harbor: could not read tuning file: " + ex.Message));
			}
			return null;
		}

		private static void SaveTuning(int target)
		{
			string text = ((target == 1) ? SmallTuningPath : TuningPath);
			DockTuning dockTuning = ((target == 1) ? SmallTuning : Tuning);
			if (string.IsNullOrEmpty(text))
			{
				return;
			}
			try
			{
				File.WriteAllText(text, JsonUtility.ToJson((object)dockTuning, true));
			}
			catch (Exception ex)
			{
				Logger.LogWarning((object)("Safe Harbor: could not save tuning file: " + ex.Message));
			}
		}

		private void ApplyTuningToAll()
		{
			for (int i = 0; i < Docks.Count; i++)
			{
				ShipDock shipDock = Docks[i];
				if ((Object)(object)shipDock != (Object)null)
				{
					shipDock.ApplyBlueprintTuning();
				}
			}
			for (int j = 0; j < m_variants.Count; j++)
			{
				DockVariant dockVariant = m_variants[j];
				if ((Object)(object)dockVariant.Prefab != (Object)null)
				{
					ShipDock component = dockVariant.Prefab.GetComponent<ShipDock>();
					if ((Object)(object)component != (Object)null)
					{
						component.ApplyBlueprintTuning();
					}
				}
			}
		}

		private static string GetWebStateJson(int target)
		{
			try
			{
				return JsonUtility.ToJson((object)((target == 1) ? SmallTuning : Tuning));
			}
			catch
			{
				return "{}";
			}
		}

		private static void QueueWebApply(int target, string json)
		{
			s_pendingApplyTarget = target;
			s_pendingApply = json;
		}

		private static void QueueWebSave(int target)
		{
			s_pendingSaveTarget = target;
			s_pendingSave = true;
		}

		private void ProcessWebQueue()
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			string text = s_pendingApply;
			if (text != null)
			{
				int num = s_pendingApplyTarget;
				s_pendingApply = null;
				DockBlueprint dockBlueprint = ((num == 1) ? SmallBlueprint : Blueprint);
				DockTuning dockTuning = ((num == 1) ? SmallTuning : Tuning);
				Vector3 center = ((num == 1) ? SmallCenter : BlueprintCenter);
				try
				{
					if (dockBlueprint != null)
					{
						JsonUtility.FromJsonOverwrite(text, (object)dockTuning);
						EnsureTuningPieces(dockBlueprint, dockTuning, center);
						ApplyTuningToAll();
					}
				}
				catch (Exception ex)
				{
					Logger.LogWarning((object)("Safe Harbor: bad tuner payload: " + ex.Message));
				}
			}
			if (s_pendingSave)
			{
				s_pendingSave = false;
				SaveTuning(s_pendingSaveTarget);
			}
		}

		private static GameObject FindBasePiecePrefab()
		{
			List<GameObject> list = CollectPiecePrefabs();
			GameObject result = null;
			float num = float.MinValue;
			for (int i = 0; i < list.Count; i++)
			{
				GameObject val = list[i];
				if (!((Object)(object)val == (Object)null))
				{
					float num2 = ScorePiece(val);
					if (num2 > num)
					{
						num = num2;
						result = val;
					}
				}
			}
			return result;
		}

		private static List<GameObject> CollectPiecePrefabs()
		{
			List<GameObject> list = new List<GameObject>();
			HashSet<int> hashSet = new HashSet<int>();
			Piece[] array = Resources.FindObjectsOfTypeAll<Piece>();
			if (array != null)
			{
				Piece[] array2 = array;
				foreach (Piece val in array2)
				{
					if (!((Object)(object)val == (Object)null))
					{
						GameObject gameObject = ((Component)val).gameObject;
						if (!((Object)(object)gameObject == (Object)null) && !IsOwnPrefab(((Object)gameObject).name) && hashSet.Add(((Object)gameObject).GetInstanceID()))
						{
							list.Add(gameObject);
						}
					}
				}
			}
			if ((Object)(object)ObjectDB.instance != (Object)null && ObjectDB.instance.m_items != null)
			{
				foreach (GameObject item in ObjectDB.instance.m_items)
				{
					if ((Object)(object)item == (Object)null)
					{
						continue;
					}
					ItemDrop component = item.GetComponent<ItemDrop>();
					if ((Object)(object)component == (Object)null || component.m_itemData == null || component.m_itemData.m_shared == null)
					{
						continue;
					}
					PieceTable buildPieces = component.m_itemData.m_shared.m_buildPieces;
					if ((Object)(object)buildPieces == (Object)null || buildPieces.m_pieces == null)
					{
						continue;
					}
					foreach (GameObject piece in buildPieces.m_pieces)
					{
						if (!((Object)(object)piece == (Object)null) && !((Object)(object)piece.GetComponent<Piece>() == (Object)null) && !IsOwnPrefab(((Object)piece).name) && hashSet.Add(((Object)piece).GetInstanceID()))
						{
							list.Add(piece);
						}
					}
				}
			}
			return list;
		}

		private static bool IsOwnPrefab(string name)
		{
			if (!string.IsNullOrEmpty(name))
			{
				return name.StartsWith("SafeHarbor", StringComparison.OrdinalIgnoreCase);
			}
			return false;
		}

		private static float ScorePiece(GameObject go)
		{
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0209: Unknown result type (might be due to invalid IL or missing references)
			//IL_0215: Unknown result type (might be due to invalid IL or missing references)
			string text = ((Object)go).name.ToLowerInvariant();
			if ((Object)(object)go.GetComponent<Ship>() != (Object)null)
			{
				return -100000f;
			}
			if (text.Contains("ship") || text.Contains("boat") || text.Contains("raft") || text.Contains("karve") || text.Contains("cart") || text.Contains("wagon") || text.Contains("portal") || text.Contains("armorstand") || text.Contains("throne") || text.Contains("bed") || text.Contains("stair") || text.Contains("roof") || text.Contains("wall") || text.Contains("door") || text.Contains("gate") || text.Contains("window") || text.Contains("lantern") || text.Contains("torch") || text.Contains("ladder"))
			{
				return -100000f;
			}
			if (text.Contains("grausten") || text.Contains("blackmarble") || text.Contains("marble") || text.Contains("stone") || text.Contains("iron") || text.Contains("flametal") || text.Contains("crystal") || text.Contains("metal"))
			{
				return -100000f;
			}
			if (!TryGetPieceFootprint(go, out var bounds))
			{
				return -100000f;
			}
			float num = Mathf.Min(((Bounds)(ref bounds)).size.x, ((Bounds)(ref bounds)).size.z);
			if (num < 1.5f)
			{
				return -100000f;
			}
			if (((Bounds)(ref bounds)).size.y > Mathf.Max(1.2f, num * 0.6f))
			{
				return -100000f;
			}
			float num2 = ((Bounds)(ref bounds)).size.x * ((Bounds)(ref bounds)).size.z;
			if (text.Contains("woodfloor") || text.Contains("wood_floor") || text.Contains("wood floor"))
			{
				num2 += 12000f;
			}
			else if (text.Contains("floor"))
			{
				num2 += 6000f;
			}
			else if (text.Contains("ground"))
			{
				num2 += 2000f;
			}
			else if (text.Contains("platform"))
			{
				num2 += 1000f;
			}
			if (text.Contains("wood"))
			{
				num2 += 4000f;
			}
			if (text.StartsWith("piece_"))
			{
				num2 += 200f;
			}
			return num2;
		}

		private static string DescribeTopPieces(int count)
		{
			List<GameObject> list = CollectPiecePrefabs();
			List<KeyValuePair<string, float>> list2 = new List<KeyValuePair<string, float>>();
			for (int i = 0; i < list.Count; i++)
			{
				if ((Object)(object)list[i] != (Object)null)
				{
					list2.Add(new KeyValuePair<string, float>(((Object)list[i]).name, ScorePiece(list[i])));
				}
			}
			list2.Sort((KeyValuePair<string, float> a, KeyValuePair<string, float> b) => b.Value.CompareTo(a.Value));
			string text = "";
			int num = Mathf.Min(count, list2.Count);
			for (int num2 = 0; num2 < num; num2++)
			{
				if (num2 > 0)
				{
					text += ", ";
				}
				text = text + list2[num2].Key + "(" + Mathf.RoundToInt(list2[num2].Value) + ")";
			}
			return text;
		}

		private static void StripNestedNetworkObjects(GameObject prefab)
		{
			Component[] componentsInChildren = prefab.GetComponentsInChildren<Component>(true);
			foreach (Component val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null) && !(val is Transform) && !((Object)(object)val.gameObject == (Object)(object)prefab) && (val is ZNetView || val is ZSyncTransform))
				{
					Object.Destroy((Object)(object)val);
				}
			}
		}

		private static bool TryGetPieceFootprint(GameObject go, out Bounds bounds)
		{
			//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_0010: 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_0052: 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_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: 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_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: 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)
			bounds = new Bounds(Vector3.zero, Vector3.zero);
			MeshFilter[] componentsInChildren = go.GetComponentsInChildren<MeshFilter>(true);
			bool flag = false;
			Vector3 val3 = default(Vector3);
			Bounds val4 = default(Bounds);
			foreach (MeshFilter val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null) && !((Object)(object)val.sharedMesh == (Object)null))
				{
					Bounds bounds2 = val.sharedMesh.bounds;
					Transform transform = ((Component)val).transform;
					Vector3 val2 = go.transform.InverseTransformPoint(transform.TransformPoint(((Bounds)(ref bounds2)).center));
					Vector3 lossyScale = transform.lossyScale;
					((Vector3)(ref val3))..ctor(Mathf.Abs(lossyScale.x) * ((Bounds)(ref bounds2)).size.x, Mathf.Abs(lossyScale.y) * ((Bounds)(ref bounds2)).size.y, Mathf.Abs(lossyScale.z) * ((Bounds)(ref bounds2)).size.z);
					((Bounds)(ref val4))..ctor(val2, val3);
					if (!flag)
					{
						bounds = val4;
						flag = true;
					}
					else
					{
						((Bounds)(ref bounds)).Encapsulate(val4);
					}
				}
			}
			return flag;
		}

		internal static GameObject FindVanillaPrefab(string name)
		{
			PrefabManager instance = PrefabManager.Instance;
			GameObject val = ((instance != null) ? instance.GetPrefab(name) : null);
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			if ((Object)(object)ZNetScene.instance != (Object)null && ZNetScene.instance.m_prefabs != null)
			{
				foreach (GameObject prefab in ZNetScene.instance.m_prefabs)
				{
					if ((Object)(object)prefab != (Object)null && string.Equals(((Object)prefab).name, name, StringComparison.OrdinalIgnoreCase))
					{
						return prefab;
					}
				}
			}
			if ((Object)(object)ObjectDB.instance != (Object)null && ObjectDB.instance.m_items != null)
			{
				foreach (GameObject item in ObjectDB.instance.m_items)
				{
					if ((Object)(object)item != (Object)null && string.Equals(((Object)item).name, name, StringComparison.OrdinalIgnoreCase))
					{
						return item;
					}
				}
			}
			Piece[] array = Resources.FindObjectsOfTypeAll<Piece>();
			if (array != null)
			{
				Piece[] array2 = array;
				foreach (Piece val2 in array2)
				{
					if ((Object)(object)val2 != (Object)null && string.Equals(((Object)((Component)val2).gameObject).name, name, StringComparison.OrdinalIgnoreCase))
					{
						return ((Component)val2).gameObject;
					}
				}
			}
			return null;
		}

		private static GameObject FindPieceInHammerTable()
		{
			if ((Object)(object)ObjectDB.instance == (Object)null || ObjectDB.instance.m_items == null)
			{
				return null;
			}
			GameObject val = null;
			foreach (GameObject item in ObjectDB.instance.m_items)
			{
				if ((Object)(object)item == (Object)null)
				{
					continue;
				}
				ItemDrop component = item.GetComponent<ItemDrop>();
				if ((Object)(object)component == (Object)null || component.m_itemData == null || component.m_itemData.m_shared == null)
				{
					continue;
				}
				PieceTable buildPieces = component.m_itemData.m_shared.m_buildPieces;
				if ((Object)(object)buildPieces == (Object)null || buildPieces.m_pieces == null)
				{
					continue;
				}
				foreach (GameObject piece in buildPieces.m_pieces)
				{
					if (!((Object)(object)piece == (Object)null) && !((Object)(object)piece.GetComponent<Piece>() == (Object)null))
					{
						if ((Object)(object)val == (Object)null)
						{
							val = piece;
						}
						if (IsCandidateName(((Object)piece).name))
						{
							return piece;
						}
					}
				}
			}
			return val;
		}

		private static GameObject FindPieceViaResources()
		{
			Piece[] array = Resources.FindObjectsOfTypeAll<Piece>();
			if (array == null)
			{
				return null;
			}
			GameObject val = null;
			foreach (Piece val2 in array)
			{
				if (!((Object)(object)val2 == (Object)null))
				{
					GameObject gameObject = ((Component)val2).gameObject;
					if ((Object)(object)val == (Object)null)
					{
						val = gameObject;
					}
					if (IsCandidateName(((Object)gameObject).name))
					{
						return gameObject;
					}
				}
			}
			return val;
		}

		private static bool IsCandidateName(string name)
		{
			if (string.IsNullOrEmpty(name))
			{
				return false;
			}
			string text = name.ToLowerInvariant();
			string[] basePieceCandidates = BasePieceCandidates;
			foreach (string text2 in basePieceCandidates)
			{
				if (text == text2)
				{
					return true;
				}
			}
			return false;
		}

		private static void LogDiagnostics()
		{
			int num = (((Object)(object)ZNetScene.instance != (Object)null && ZNetScene.instance.m_prefabs != null) ? ZNetScene.instance.m_prefabs.Count : (-1));
			int num2 = 0;
			if ((Object)(object)ZNetScene.instance != (Object)null && ZNetScene.instance.m_prefabs != null)
			{
				foreach (GameObject prefab in ZNetScene.instance.m