Decompiled source of HarborChain v1.0.0

plugins/HarborChain.dll

Decompiled 5 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: UnverifiableCode]
[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 HarborChain
{
	internal sealed class ChainNet : MonoBehaviour
	{
		private enum Detail
		{
			Simulated,
			Held,
			Hidden
		}

		public static readonly List<ChainNet> All = new List<ChainNet>();

		private const float Slack = 0.008f;

		private const float StepTime = 1f / 30f;

		private const int Iterations = 3;

		private const float BarrierThickness = 0.8f;

		private const int MaxRows = 32;

		private const int MaxNodes = 1100;

		private ChainTower m_master;

		private ChainTower m_partner;

		private Vector3 m_portA;

		private Vector3 m_portB;

		private float m_width;

		private float m_water;

		private int m_columns;

		private int m_rows;

		private float[] m_ground;

		private float[] m_bottom;

		private float[] m_top;

		private float[] m_low;

		private Vector3[] m_rest;

		private Vector3[] m_pos;

		private Vector3[] m_prev;

		private Vector3[] m_held;

		private bool[] m_pinned;

		private float[] m_restHorizontal;

		private Quaternion[] m_vertical;

		private Quaternion[] m_horizontal;

		private Transform[] m_bones;

		private SkinnedMeshRenderer m_renderer;

		private Mesh m_mesh;

		private SkinnedMeshRenderer m_farRenderer;

		private Mesh m_farMesh;

		private int m_farStep = -1;

		private Rigidbody m_body;

		private BoxCollider[] m_boxes;

		private BoxCollider[] m_hitboxes;

		private BoxCollider[] m_climbBoxes;

		private bool m_climbable;

		private float[] m_segmentTop;

		private float[] m_segmentLeft;

		private float[] m_segmentRight;

		private float m_drop;

		private NetBarrier m_barrier;

		private float m_height;

		private float m_blockedUntil;

		private float m_simClock;

		private float m_time;

		private Detail m_detail;

		private bool m_posed;

		private static readonly int s_vehicleMask = LayerMask.GetMask(new string[1] { "vehicle" });

		private const float LinksWithin = 45f;

		private const float FarWidth = 0.09f;

		private const float FarWidthPerMetre = 0.0016f;

		private const float FarStep = 1.25f;

		private const float ClimbReach = 3f;

		public static long CostTicks;

		public static long CostFrames;

		public float ShownHeight => m_height;

		public bool Blocked { get; private set; }

		public ChainTower Master => m_master;

		public ChainTower Partner => m_partner;

		public float Span => m_width;

		public int Columns => m_columns;

		public int Rows => m_rows;

		public int Links { get; private set; }

		public int Segments => m_boxes.Length;

		public float Travel { get; private set; }

		public string DetailName => m_detail.ToString();

		public float BarrierTop
		{
			get
			{
				BarrierTops(out var lowest, out var _);
				return lowest;
			}
		}

		public float WaterLevel => m_water;

		public static ChainNet Create(ChainTower master, ChainTower partner)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			GameObject val = new GameObject("HarborChain_Net");
			ChainNet chainNet = val.AddComponent<ChainNet>();
			if (chainNet.Setup(master, partner))
			{
				return chainNet;
			}
			Object.Destroy((Object)(object)val);
			return null;
		}

		public bool Fits(ChainTower master, ChainTower partner)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: 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_004d: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)master == (Object)(object)m_master && (Object)(object)partner == (Object)(object)m_partner)
			{
				Vector3 val = master.Port - m_portA;
				if (((Vector3)(ref val)).sqrMagnitude < 0.01f)
				{
					val = partner.Port - m_portB;
					return ((Vector3)(ref val)).sqrMagnitude < 0.01f;
				}
			}
			return false;
		}

		private bool Setup(ChainTower master, ChainTower partner)
		{
			//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_001c: 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_0027: 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_0037: 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_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_0074: 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_007a: 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_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: 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_03d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03da: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_040e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0413: Unknown result type (might be due to invalid IL or missing references)
			//IL_0414: Unknown result type (might be due to invalid IL or missing references)
			//IL_0416: Unknown result type (might be due to invalid IL or missing references)
			//IL_041b: Unknown result type (might be due to invalid IL or missing references)
			//IL_041d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0476: Unknown result type (might be due to invalid IL or missing references)
			//IL_048f: Unknown result type (might be due to invalid IL or missing references)
			m_master = master;
			m_partner = partner;
			m_portA = master.Port;
			m_portB = partner.Port;
			Vector3 val = m_portB - m_portA;
			val.y = 0f;
			m_width = ((Vector3)(ref val)).magnitude;
			if (m_width < 1f)
			{
				return false;
			}
			val /= m_width;
			((Component)this).transform.SetPositionAndRotation(m_portA, Quaternion.LookRotation(Vector3.Cross(val, Vector3.up), Vector3.up));
			m_water = (((Object)(object)ZoneSystem.instance != (Object)null) ? ZoneSystem.instance.m_waterLevel : 30f);
			float meshSpacing = Settings.MeshSpacing;
			int num = Mathf.Clamp(Mathf.RoundToInt(m_width / meshSpacing), 2, 64);
			m_columns = num + 1;
			m_ground = new float[m_columns];
			m_bottom = new float[m_columns];
			m_top = new float[m_columns];
			m_low = new float[m_columns];
			float num2 = Mathf.Min(1.5f, m_width * 0.035f);
			float num3 = m_water + Settings.RaisedClearance;
			float num4 = 0f;
			for (int i = 0; i < m_columns; i++)
			{
				float num5 = (float)i / (float)num;
				float num6 = Ground(m_portA + val * (m_width * num5));
				float num7 = Mathf.Lerp(m_portA.y, m_portB.y, num5);
				float num8 = ((i == 0) ? m_portA.y : ((i == num) ? m_portB.y : Mathf.Max(num7 - num2 * 4f * num5 * (1f - num5), Mathf.Min(num7, num3))));
				num8 = Mathf.Max(num8, num6 + 0.3f);
				float num9 = Mathf.Min(num8 - 0.3f, num6 + 0.1f);
				float num10 = ((i == 0 || i == num) ? num8 : Mathf.Min(num8, num9 + 0.25f));
				m_ground[i] = num6 - m_portA.y;
				m_top[i] = num8 - m_portA.y;
				m_bottom[i] = num9 - m_portA.y;
				m_low[i] = num10 - m_portA.y;
				num4 = Mathf.Max(num4, num8 - num9);
				Travel = Mathf.Max(Travel, num8 - num10);
			}
			int num11 = Mathf.Max(2, Mathf.Min(32, 1100 / m_columns - 1));
			m_rows = Mathf.Clamp(Mathf.CeilToInt(num4 / meshSpacing - 0.25f), 2, num11) + 1;
			int num12 = m_columns * m_rows;
			m_rest = (Vector3[])(object)new Vector3[num12];
			m_pos = (Vector3[])(object)new Vector3[num12];
			m_prev = (Vector3[])(object)new Vector3[num12];
			m_held = (Vector3[])(object)new Vector3[num12];
			m_pinned = new bool[num12];
			m_vertical = (Quaternion[])(object)new Quaternion[num12];
			m_horizontal = (Quaternion[])(object)new Quaternion[num12];
			m_restHorizontal = new float[num12];
			int num13 = m_rows - 1;
			for (int j = 0; j < m_columns; j++)
			{
				float num14 = m_width * (float)j / (float)num;
				for (int k = 0; k < m_rows; k++)
				{
					int num15 = j * m_rows + k;
					m_rest[num15] = new Vector3(num14, Mathf.Lerp(m_bottom[j], m_top[j], (float)k / (float)num13), 0f);
					m_pinned[num15] = k == 0 || k == num13 || j == 0 || j == num;
					m_vertical[num15] = (m_horizontal[num15] = Quaternion.identity);
				}
			}
			for (int l = 0; l + 1 < m_columns; l++)
			{
				for (int m = 0; m < m_rows; m++)
				{
					m_restHorizontal[l * m_rows + m] = Vector3.Distance(m_rest[l * m_rows + m], m_rest[(l + 1) * m_rows + m]) * 1.008f;
				}
			}
			BuildMesh();
			BuildBarrier(val);
			m_height = m_master.Height();
			if (m_height > 0f && ShipInTheWay(0f, m_height))
			{
				m_height = 0f;
			}
			HeldPose(m_pos);
			Array.Copy(m_pos, m_prev, num12);
			WriteBones();
			PlaceBarrier(teleport: true);
			All.Add(this);
			HarborChainPlugin.Log.LogInfo((object)$"net {m_master.Id:X} -> {m_partner.Id:X}: span {m_width:F1} m, {m_columns}x{m_rows} nodes, {Links} links, {m_mesh.vertexCount} vertices, height {m_height:F2}, top chain {m_portA.y + Min(m_top):F1}..{m_portA.y + Max(m_top):F1}, bottom {m_portA.y + Min(m_bottom):F1}..{m_portA.y + Max(m_bottom):F1}, the winch moves it {Travel:F1} m, barrier sinks {m_drop:F1} m");
			return true;
		}

		private static float Ground(Vector3 at)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			return ZoneSystem.instance.GetGroundHeight(at);
		}

		private void OnDestroy()
		{
			All.Remove(this);
			if ((Object)(object)m_mesh != (Object)null)
			{
				Object.Destroy((Object)(object)m_mesh);
			}
			if ((Object)(object)m_farMesh != (Object)null)
			{
				Object.Destroy((Object)(object)m_farMesh);
			}
		}

		private void BuildMesh()
		{
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Expected O, but got Unknown
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: Expected O, but got Unknown
			//IL_0237: 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_0065: Unknown result type (might be due to invalid IL or missing references)
			int num = m_rest.Length;
			m_bones = (Transform[])(object)new Transform[num * 2];
			for (int i = 0; i < num * 2; i++)
			{
				Transform transform = new GameObject(((i < num) ? "v" : "h") + i % num).transform;
				transform.SetParent(((Component)this).transform, false);
				transform.localPosition = m_rest[i % num];
				m_bones[i] = transform;
			}
			m_mesh = NetMesh.Build(m_rest, m_columns, m_rows, out var links);
			Links = links;
			GameObject val = new GameObject("links");
			val.layer = LayerMask.NameToLayer("piece");
			val.transform.SetParent(((Component)this).transform, false);
			m_renderer = val.AddComponent<SkinnedMeshRenderer>();
			m_renderer.sharedMesh = m_mesh;
			m_renderer.bones = m_bones;
			m_renderer.rootBone = ((Component)this).transform;
			((Renderer)m_renderer).sharedMaterial = Materials.Chain;
			m_renderer.updateWhenOffscreen = false;
			float num2 = Mathf.Min(Min(m_ground), Min(m_bottom)) - 2f;
			float num3 = Max(m_top) + 1.5f;
			((Renderer)m_renderer).localBounds = new Bounds(new Vector3(m_width * 0.5f, (num2 + num3) * 0.5f, 0f), new Vector3(m_width + 2f, num3 - num2, 6f));
			GameObject val2 = new GameObject("links_far");
			val2.layer = val.layer;
			val2.transform.SetParent(((Component)this).transform, false);
			m_farRenderer = val2.AddComponent<SkinnedMeshRenderer>();
			m_farRenderer.bones = m_bones;
			m_farRenderer.rootBone = ((Component)this).transform;
			((Renderer)m_farRenderer).sharedMaterial = Materials.Chain;
			m_farRenderer.updateWhenOffscreen = false;
			((Renderer)m_farRenderer).localBounds = ((Renderer)m_renderer).localBounds;
			((Renderer)m_farRenderer).enabled = false;
		}

		private void BuildBarrier(Vector3 along)
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Expected O, but got Unknown
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ca: Expected O, but got Unknown
			//IL_0207: Unknown result type (might be due to invalid IL or missing references)
			//IL_0231: Unknown result type (might be due to invalid IL or missing references)
			//IL_024b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0252: Expected O, but got Unknown
			//IL_0289: Unknown result type (might be due to invalid IL or missing references)
			//IL_0298: Unknown result type (might be due to invalid IL or missing references)
			//IL_029f: Expected O, but got Unknown
			//IL_02d7: Unknown result type (might be due to invalid IL or missing references)
			int num = m_columns - 1;
			m_boxes = (BoxCollider[])(object)new BoxCollider[num];
			m_hitboxes = (BoxCollider[])(object)new BoxCollider[num];
			m_climbBoxes = (BoxCollider[])(object)new BoxCollider[num];
			m_segmentTop = new float[num];
			m_segmentLeft = new float[num];
			m_segmentRight = new float[num];
			GameObject val = new GameObject("barrier");
			val.layer = LayerMask.NameToLayer("blocker");
			val.transform.SetParent(((Component)this).transform, false);
			m_body = val.AddComponent<Rigidbody>();
			m_body.isKinematic = true;
			m_body.useGravity = false;
			m_body.collisionDetectionMode = (CollisionDetectionMode)3;
			int layer = LayerMask.NameToLayer("blocker");
			int layer2 = LayerMask.NameToLayer("hitbox");
			int layer3 = LayerMask.NameToLayer("static_solid");
			m_drop = 0f;
			for (int i = 0; i < num; i++)
			{
				float num2 = m_width * (float)i / (float)num;
				float num3 = m_width * (float)(i + 1) / (float)num;
				float num4 = Mathf.Min(Ground(m_portA + along * ((num2 + num3) * 0.5f)) - m_portA.y, Mathf.Min(m_ground[i], m_ground[i + 1]));
				float num5 = Mathf.Min(m_top[i], m_top[i + 1]);
				float num6 = num4 - 1.5f;
				m_segmentTop[i] = num5;
				m_segmentLeft[i] = num2;
				m_segmentRight[i] = num3;
				m_drop = Mathf.Max(m_drop, num5 - (num4 - 0.6f));
				GameObject val2 = new GameObject("box" + i);
				val2.layer = layer;
				val2.transform.SetParent(val.transform, false);
				val2.transform.localPosition = new Vector3((num2 + num3) * 0.5f, (num5 + num6) * 0.5f, 0f);
				BoxCollider val3 = val2.AddComponent<BoxCollider>();
				val3.size = new Vector3(num3 - num2 + 0.1f, num5 - num6, 0.8f);
				m_boxes[i] = val3;
				GameObject val4 = new GameObject("hitbox");
				val4.layer = layer2;
				val4.transform.SetParent(val2.transform, false);
				m_hitboxes[i] = val4.AddComponent<BoxCollider>();
				m_hitboxes[i].size = val3.size;
				GameObject val5 = new GameObject("climb");
				val5.layer = layer3;
				val5.transform.SetParent(val2.transform, false);
				m_climbBoxes[i] = val5.AddComponent<BoxCollider>();
				m_climbBoxes[i].size = val3.size;
				((Collider)m_climbBoxes[i]).enabled = false;
			}
			m_drop = Mathf.Max(0f, m_drop);
			m_barrier = val.AddComponent<NetBarrier>();
			m_barrier.Net = this;
		}

		private Vector3 BarrierOffset()
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			return new Vector3(0f, (0f - (1f - m_height)) * m_drop, 0f);
		}

		private void PlaceBarrier(bool teleport)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = ((Component)this).transform.TransformPoint(BarrierOffset());
			if (teleport || !((Component)m_body).gameObject.activeInHierarchy)
			{
				((Component)m_body).transform.position = val;
				m_body.position = val;
			}
			else
			{
				m_body.MovePosition(val);
			}
		}

		private void FixedUpdate()
		{
			if ((Object)(object)m_master == (Object)null || (Object)(object)m_partner == (Object)null)
			{
				return;
			}
			float num = m_master.Height();
			float fixedDeltaTime = Time.fixedDeltaTime;
			Blocked = false;
			if (num > m_height + 0.0001f)
			{
				float num2 = Mathf.MoveTowards(m_height, num, fixedDeltaTime * 2f / m_master.Duration(raising: true));
				if (Time.time < m_blockedUntil || ShipInTheWay(m_height, num2))
				{
					if (Time.time >= m_blockedUntil)
					{
						m_blockedUntil = Time.time + 1f;
					}
					Blocked = true;
				}
				else
				{
					m_height = num2;
				}
			}
			else if (num < m_height - 0.0001f)
			{
				m_height = Mathf.MoveTowards(m_height, num, fixedDeltaTime * 2f / m_master.Duration(raising: false));
			}
			else
			{
				m_height = num;
			}
			PlaceBarrier(teleport: false);
		}

		private bool ShipInTheWay(float from, float to)
		{
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			float num = m_water - m_portA.y;
			Vector3 val2 = default(Vector3);
			for (int i = 0; i < m_boxes.Length; i++)
			{
				float num2 = m_segmentTop[i] - (1f - from) * m_drop;
				float num3 = m_segmentTop[i] - (1f - to) * m_drop;
				if (!(num3 < num - 3f))
				{
					Vector3 val = ((Component)this).transform.TransformPoint(new Vector3((m_segmentLeft[i] + m_segmentRight[i]) * 0.5f, (num3 + num2) * 0.5f, 0f));
					((Vector3)(ref val2))..ctor((m_segmentRight[i] - m_segmentLeft[i]) * 0.5f, Mathf.Max(0.05f, (num3 - num2) * 0.5f + 0.1f), 0.5f);
					if (Physics.CheckBox(val, val2, ((Component)this).transform.rotation, s_vehicleMask, (QueryTriggerInteraction)1))
					{
						return true;
					}
				}
			}
			return false;
		}

		private void Update()
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)m_master == (Object)null || (Object)(object)m_partner == (Object)null)
			{
				return;
			}
			Camera mainCamera = Utils.GetMainCamera();
			float num = (((Object)(object)mainCamera != (Object)null) ? DistanceToSpan(((Component)mainCamera).transform.position) : float.MaxValue);
			Detail detail = ((num > Settings.DrawDistance) ? Detail.Hidden : ((num > Settings.SimulationDistance) ? Detail.Held : Detail.Simulated));
			if (detail != m_detail)
			{
				if (detail == Detail.Simulated)
				{
					Array.Copy(m_pos, m_prev, m_pos.Length);
				}
				m_detail = detail;
				m_posed = false;
			}
			bool flag = detail != Detail.Hidden && num > 45f;
			if (flag)
			{
				UpdateFarMesh(num);
			}
			((Renderer)m_renderer).enabled = detail != Detail.Hidden && !flag;
			((Renderer)m_farRenderer).enabled = flag;
			UpdateClimbable();
		}

		private void UpdateFarMesh(float distance)
		{
			int num = Mathf.CeilToInt(Mathf.Log(Mathf.Max(0.09f, distance * 0.0016f) / 0.09f, 1.25f) - 0.001f);
			if (num != m_farStep)
			{
				m_farStep = num;
				if ((Object)(object)m_farMesh != (Object)null)
				{
					Object.Destroy((Object)(object)m_farMesh);
				}
				m_farMesh = NetMesh.BuildFar(m_rest, m_columns, m_rows, 0.09f * Mathf.Pow(1.25f, (float)num));
				m_farRenderer.sharedMesh = m_farMesh;
			}
		}

		private void UpdateClimbable()
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: 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)
			Player localPlayer = Player.m_localPlayer;
			bool flag = false;
			if ((Object)(object)localPlayer != (Object)null && m_height > 0.02f)
			{
				Vector3 val = ((Component)this).transform.InverseTransformPoint(((Component)localPlayer).transform.position);
				flag = Mathf.Abs(val.z) < 3f && val.x > -3f && val.x < m_width + 3f;
			}
			if (flag != m_climbable)
			{
				m_climbable = flag;
				BoxCollider[] climbBoxes = m_climbBoxes;
				for (int i = 0; i < climbBoxes.Length; i++)
				{
					((Collider)climbBoxes[i]).enabled = flag;
				}
			}
		}

		private void LateUpdate()
		{
			if (!((Object)(object)m_master == (Object)null) && !((Object)(object)m_partner == (Object)null))
			{
				long timestamp = Stopwatch.GetTimestamp();
				UpdateLooks();
				CostTicks += Stopwatch.GetTimestamp() - timestamp;
				CostFrames++;
			}
		}

		private void UpdateLooks()
		{
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: 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_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: 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_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			float num = Mathf.Min(Time.deltaTime, 0.1f);
			m_time += num;
			switch (m_detail)
			{
			case Detail.Hidden:
				break;
			case Detail.Held:
			{
				HeldPose(m_held);
				float num3 = 0f;
				float num4 = 1f - Mathf.Exp((0f - num) * 3f);
				for (int i = 0; i < m_pos.Length; i++)
				{
					Vector3 val = Vector3.Lerp(m_pos[i], m_held[i], num4);
					float num5 = num3;
					Vector3 val2 = val - m_pos[i];
					num3 = Mathf.Max(num5, ((Vector3)(ref val2)).sqrMagnitude);
					m_pos[i] = val;
					m_prev[i] = val;
				}
				if (num3 > 1E-06f || !m_posed)
				{
					WriteBones();
					m_posed = num3 <= 1E-06f;
				}
				break;
			}
			default:
			{
				m_simClock += num;
				int num2 = 0;
				while (m_simClock >= 1f / 30f && num2 < 3)
				{
					m_simClock -= 1f / 30f;
					Step(1f / 30f);
					num2++;
				}
				if (m_simClock > 1f / 30f)
				{
					m_simClock = 0f;
				}
				if (num2 > 0)
				{
					WriteBones();
				}
				break;
			}
			}
		}

		private float TopNow(int i)
		{
			return Mathf.Lerp(m_low[i], m_top[i], m_height);
		}

		private float BottomNow(int i)
		{
			return m_bottom[i];
		}

		private void HeldPose(Vector3[] into)
		{
			//IL_005b: 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)
			int num = m_rows - 1;
			for (int i = 0; i < m_columns; i++)
			{
				float num2 = TopNow(i);
				float num3 = BottomNow(i);
				for (int j = 0; j < m_rows; j++)
				{
					into[i * m_rows + j] = new Vector3(m_rest[i * m_rows + j].x, Mathf.Lerp(num3, num2, (float)j / (float)num), 0f);
				}
			}
		}

		private void Step(float dt)
		{
			//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_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: 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_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: 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_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			int num = m_rows - 1;
			int num2 = m_columns - 1;
			float num3 = m_water - m_portA.y;
			float num4 = dt * dt;
			for (int i = 1; i < num2; i++)
			{
				int num5 = i * m_rows + num;
				m_pos[num5] = new Vector3(m_rest[num5].x, TopNow(i), 0f);
			}
			for (int j = 0; j < m_pos.Length; j++)
			{
				if (!m_pinned[j])
				{
					Vector3 val = m_pos[j];
					bool num6 = val.y < num3;
					float num7 = (num6 ? 0.88f : 0.95f);
					float num8 = (num6 ? (-8.5347f) : (-9.81f));
					float num9 = (num6 ? (0.12f * Mathf.Sin(m_time * 0.5f + val.x * 0.3f)) : 0f);
					Vector3 val2 = (val - m_prev[j]) * num7;
					m_prev[j] = val;
					m_pos[j] = val + val2 + new Vector3(0f, num8, num9) * num4;
				}
			}
			for (int k = 0; k < 3; k++)
			{
				for (int l = 0; l < m_columns; l++)
				{
					float length = Mathf.Max(0.01f, TopNow(l) - BottomNow(l)) / (float)num * 1.008f;
					for (int m = 0; m < num; m++)
					{
						Constrain(l * m_rows + m, l * m_rows + m + 1, length);
					}
				}
				for (int n = 0; n + 1 < m_columns; n++)
				{
					for (int num10 = 1; num10 < num; num10++)
					{
						Constrain(n * m_rows + num10, (n + 1) * m_rows + num10, m_restHorizontal[n * m_rows + num10]);
					}
				}
				for (int num11 = 1; num11 + 1 < m_columns; num11++)
				{
					float num12 = m_ground[num11] + 0.08f;
					for (int num13 = 1; num13 < num; num13++)
					{
						int num14 = num11 * m_rows + num13;
						if (m_pos[num14].y < num12)
						{
							m_pos[num14].y = num12;
						}
					}
				}
			}
		}

		private void Constrain(int a, int b, float length)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: 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)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: 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_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = m_pos[b] - m_pos[a];
			float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude;
			if (sqrMagnitude <= length * length)
			{
				return;
			}
			bool flag = m_pinned[a];
			bool flag2 = m_pinned[b];
			if (!(flag && flag2))
			{
				float num = Mathf.Sqrt(sqrMagnitude);
				Vector3 val2 = val * ((num - length) / num);
				if (flag)
				{
					ref Vector3 reference = ref m_pos[b];
					reference -= val2;
					return;
				}
				if (flag2)
				{
					ref Vector3 reference2 = ref m_pos[a];
					reference2 += val2;
					return;
				}
				val2 *= 0.5f;
				ref Vector3 reference3 = ref m_pos[a];
				reference3 += val2;
				ref Vector3 reference4 = ref m_pos[b];
				reference4 -= val2;
			}
		}

		private void WriteBones()
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: 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_0094: 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_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: 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_012a: 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_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: 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_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			int num = m_rows - 1;
			int num2 = m_columns - 1;
			int num3 = m_pos.Length;
			for (int i = 0; i < m_columns; i++)
			{
				for (int j = 0; j < m_rows; j++)
				{
					int num4 = i * m_rows + j;
					Vector3 val = m_pos[i * m_rows + Mathf.Min(j + 1, num)] - m_pos[i * m_rows + Mathf.Max(j - 1, 0)];
					if (((Vector3)(ref val)).sqrMagnitude > 1E-08f)
					{
						((Vector3)(ref val)).Normalize();
						Vector3 val2 = Vector3.forward - val * val.z;
						if (((Vector3)(ref val2)).sqrMagnitude > 0.0001f)
						{
							m_vertical[num4] = Quaternion.LookRotation(val2, val);
						}
					}
					Vector3 val3 = m_pos[Mathf.Min(i + 1, num2) * m_rows + j] - m_pos[Mathf.Max(i - 1, 0) * m_rows + j];
					if (((Vector3)(ref val3)).sqrMagnitude > 1E-08f)
					{
						((Vector3)(ref val3)).Normalize();
						Vector3 val4 = Vector3.up - val3 * val3.y;
						if (((Vector3)(ref val4)).sqrMagnitude > 0.0001f)
						{
							m_horizontal[num4] = Quaternion.LookRotation(Vector3.Cross(val3, val4), val4);
						}
					}
					m_bones[num4].SetLocalPositionAndRotation(m_pos[num4], m_vertical[num4]);
					m_bones[num3 + num4].SetLocalPositionAndRotation(m_pos[num4], m_horizontal[num4]);
				}
			}
		}

		public void TakeHit(HitData hit)
		{
			if (Settings.Invulnerable)
			{
				return;
			}
			float damageToTowers = Settings.DamageToTowers;
			if (damageToTowers <= 0f)
			{
				return;
			}
			ChainTower[] array = new ChainTower[2] { m_master, m_partner };
			foreach (ChainTower chainTower in array)
			{
				if (!((Object)(object)chainTower == (Object)null) && !((Object)(object)chainTower.Wear == (Object)null) && chainTower.Valid)
				{
					HitData val = hit.Clone();
					((DamageTypes)(ref val.m_damage)).Modify(damageToTowers);
					chainTower.Wear.Damage(val);
				}
			}
		}

		public float DistanceToSpan(Vector3 point)
		{
			//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_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: 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_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_0039: 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_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			Vector3 portA = m_portA;
			Vector3 val = m_portB - portA;
			float num = Mathf.Clamp01(Vector3.Dot(point - portA, val) / Mathf.Max(0.0001f, ((Vector3)(ref val)).sqrMagnitude));
			return Vector3.Distance(point, portA + val * num);
		}

		public void BarrierTops(out float lowest, out float highest)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			float y = BarrierOffset().y;
			lowest = m_portA.y + Min(m_segmentTop) + y;
			highest = m_portA.y + Max(m_segmentTop) + y;
		}

		public Vector3 NodeWorld(int column, int row)
		{
			//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)
			return ((Component)this).transform.TransformPoint(m_pos[column * m_rows + row]);
		}

		public void Sway(out float largest, out float middle)
		{
			largest = 0f;
			for (int i = 0; i < m_pos.Length; i++)
			{
				if (!m_pinned[i])
				{
					largest = Mathf.Max(largest, Mathf.Abs(m_pos[i].z));
				}
			}
			middle = m_pos[m_columns / 2 * m_rows + m_rows / 2].z;
		}

		public float LargestTwist()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			float num = 0f;
			for (int i = 0; i < m_horizontal.Length; i++)
			{
				num = Mathf.Max(num, Vector3.Angle(m_horizontal[i] * Vector3.up, Vector3.up));
			}
			return num;
		}

		private static float Min(float[] values)
		{
			float num = float.MaxValue;
			foreach (float num2 in values)
			{
				num = Mathf.Min(num, num2);
			}
			return num;
		}

		private static float Max(float[] values)
		{
			float num = float.MinValue;
			foreach (float num2 in values)
			{
				num = Mathf.Max(num, num2);
			}
			return num;
		}
	}
	internal sealed class ChainTower : MonoBehaviour, Hoverable, Interactable, IPlaced
	{
		public static readonly int IdKey = StringExtensionMethods.GetStableHashCode("HarborChain_id");

		public static readonly int PartnerKey = StringExtensionMethods.GetStableHashCode("HarborChain_partner");

		public static readonly int PartnerPosKey = StringExtensionMethods.GetStableHashCode("HarborChain_partnerPos");

		public static readonly int TargetKey = StringExtensionMethods.GetStableHashCode("HarborChain_target");

		public static readonly int FromKey = StringExtensionMethods.GetStableHashCode("HarborChain_from");

		public static readonly int SinceKey = StringExtensionMethods.GetStableHashCode("HarborChain_since");

		public static readonly int SecondsKey = StringExtensionMethods.GetStableHashCode("HarborChain_seconds");

		public static readonly int TravelKey = StringExtensionMethods.GetStableHashCode("HarborChain_travel");

		private const string WinchRpc = "HarborChain_Winch";

		private const string UnlinkRpc = "HarborChain_Unlink";

		public const int Toggle = 0;

		public const int Raise = 1;

		public const int Lower = 2;

		private const float DrumCircumference = 2.261947f;

		private const float UsualTravel = 7f;

		private const float ShortestRun = 2f;

		public static readonly List<ChainTower> All = new List<ChainTower>();

		private ZNetView m_nview;

		private WearNTear m_wear;

		private Transform m_drum;

		private ChainNet m_net;

		private float m_checkTimer;

		private float m_partnerMissingFor;

		private LineRenderer m_preview;

		public static bool SuppressLinking;

		private bool m_turning;

		private float m_lastHeight = -1f;

		private float m_lastTurned = -10f;

		private float m_lastStarted = -10f;

		private GameObject m_turningLoop;

		private ChainTower m_lastHolder;

		private static readonly Dictionary<AudioClip, float> s_quietStarts = new Dictionary<AudioClip, float>();

		private static readonly MethodInfo s_getData = typeof(AudioClip).GetMethod("GetData", new Type[2]
		{
			typeof(float[]),
			typeof(int)
		});

		public static string PreviewText = "";

		public static bool PreviewLinks;

		public ZNetView NView => m_nview;

		public WearNTear Wear => m_wear;

		public ChainNet Net => m_net;

		public bool Valid
		{
			get
			{
				if ((Object)(object)m_nview != (Object)null)
				{
					return m_nview.IsValid();
				}
				return false;
			}
		}

		public long Id
		{
			get
			{
				if (!Valid)
				{
					return 0L;
				}
				return m_nview.GetZDO().GetLong(IdKey, 0L);
			}
		}

		public long PartnerId
		{
			get
			{
				if (!Valid)
				{
					return 0L;
				}
				return m_nview.GetZDO().GetLong(PartnerKey, 0L);
			}
		}

		public bool Wood { get; private set; }

		public Vector3 Port => ((Component)this).transform.TransformPoint(TowerModel.Port(Wood ? TowerModel.Style.Wood : TowerModel.Style.Stone));

		public float Target
		{
			get
			{
				if (!Valid)
				{
					return 0f;
				}
				return m_nview.GetZDO().GetFloat(TargetKey, 0f);
			}
		}

		public float Travel
		{
			get
			{
				if (!KnownTravel(out var travel))
				{
					return 7f;
				}
				return travel;
			}
		}

		private string Name
		{
			get
			{
				Piece component = ((Component)this).GetComponent<Piece>();
				if (component == null || string.IsNullOrEmpty(component.m_name))
				{
					return "Chain tower";
				}
				return component.m_name;
			}
		}

		private void Awake()
		{
			m_nview = ((Component)this).GetComponent<ZNetView>();
			m_wear = ((Component)this).GetComponent<WearNTear>();
			m_drum = ((Component)this).transform.Find("model/drum");
			int stableHashCode = StringExtensionMethods.GetStableHashCode(Utils.GetPrefabName(((Component)this).gameObject));
			Wood = TowerPiece.IsWood(stableHashCode);
			if (!((Object)(object)m_nview == (Object)null) && m_nview.GetZDO() != null)
			{
				All.Add(this);
				m_nview.Unregister("HarborChain_Winch");
				m_nview.Unregister("HarborChain_Unlink");
				m_nview.Register<int>("HarborChain_Winch", (Action<long, int>)RPC_Winch);
				m_nview.Register<long>("HarborChain_Unlink", (Action<long, long>)RPC_Unlink);
				if ((Object)(object)m_wear != (Object)null)
				{
					WearNTear wear = m_wear;
					wear.m_onDestroyed = (Action)Delegate.Combine(wear.m_onDestroyed, new Action(OnDestroyedByDamage));
				}
				if (m_nview.IsOwner() && Id == 0L)
				{
					m_nview.GetZDO().Set(IdKey, NewId());
				}
				m_checkTimer = Random.Range(0f, 0.3f);
			}
		}

		private void OnDisable()
		{
			if ((Object)(object)m_nview == (Object)null || m_nview.GetZDO() == null)
			{
				PreviewText = "";
				if ((Object)(object)m_preview != (Object)null)
				{
					((Component)m_preview).gameObject.SetActive(false);
				}
			}
		}

		private void OnDestroy()
		{
			All.Remove(this);
			DestroyNet();
			if ((Object)(object)m_wear != (Object)null)
			{
				WearNTear wear = m_wear;
				wear.m_onDestroyed = (Action)Delegate.Remove(wear.m_onDestroyed, new Action(OnDestroyedByDamage));
			}
			if ((Object)(object)m_nview != (Object)null && m_nview.GetZDO() != null)
			{
				m_nview.Unregister("HarborChain_Winch");
				m_nview.Unregister("HarborChain_Unlink");
			}
			if ((Object)(object)m_preview != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)m_preview).gameObject);
			}
		}

		private static long NewId()
		{
			long num;
			for (num = 0L; num == 0L; num = ((long)Random.Range(int.MinValue, int.MaxValue) << 32) ^ (uint)Random.Range(int.MinValue, int.MaxValue))
			{
			}
			return num;
		}

		public void OnPlaced()
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: 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 (!Valid)
			{
				return;
			}
			if (Id == 0L)
			{
				m_nview.GetZDO().Set(IdKey, NewId());
			}
			if (SuppressLinking)
			{
				return;
			}
			float span;
			string why;
			ChainTower chainTower = FindPartner(Port, ((Component)this).transform.forward, this, Wood, out span, out why);
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)chainTower == (Object)null)
			{
				if (why.Length > 0 && localPlayer != null)
				{
					((Character)localPlayer).Message((MessageType)2, why, 0, (Sprite)null, false);
				}
				HarborChainPlugin.Log.LogInfo((object)string.Format("tower {0:X} placed at {1}, not linked: {2}", Id, ((Component)this).transform.position, (why.Length > 0) ? why : "no free tower near"));
				return;
			}
			ZDO zDO = m_nview.GetZDO();
			zDO.Set(PartnerKey, chainTower.Id);
			zDO.Set(PartnerPosKey, ((Component)chainTower).transform.position);
			zDO.Set(TargetKey, 0f);
			zDO.Set(FromKey, 0f);
			zDO.Set(SinceKey, ZNet.instance.GetTime().Ticks);
			HarborChainPlugin.Log.LogInfo((object)$"tower {Id:X} placed at {((Component)this).transform.position}, linked to {chainTower.Id:X} at {((Component)chainTower).transform.position}: span {span:F1} m");
			m_checkTimer = 0f;
		}

		public static ChainTower FindPartner(Vector3 port, Vector3 forward, ChainTower self, bool wood, out float span, out string why)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			ChainTower rejected;
			return FindPartner(port, forward, self, wood, out span, out why, out rejected);
		}

		public static ChainTower FindPartner(Vector3 port, Vector3 forward, ChainTower self, bool wood, out float span, out string why, out ChainTower rejected)
		{
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: 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_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			ChainTower chainTower = null;
			rejected = null;
			span = 0f;
			float facingTolerance = Settings.FacingTolerance;
			float minSpan = Settings.MinSpan;
			why = "";
			float num = float.MaxValue;
			Vector3 val2 = default(Vector3);
			foreach (ChainTower item in All)
			{
				if ((Object)(object)item == (Object)(object)self || !item.Valid || item.IsLinked())
				{
					continue;
				}
				Vector3 val = item.Port - port;
				((Vector3)(ref val2))..ctor(val.x, 0f, val.z);
				float magnitude = ((Vector3)(ref val2)).magnitude;
				float num2 = Mathf.Min(Settings.MaxSpan(wood), Settings.MaxSpan(item.Wood));
				if (magnitude > num2 * 1.5f || magnitude < 0.5f)
				{
					continue;
				}
				Vector3 forward2 = ((Component)item).transform.forward;
				string text = null;
				if (magnitude > num2)
				{
					text = $"Too far: {magnitude:F0} m (at most {num2:F0})";
				}
				else if (magnitude < minSpan)
				{
					text = $"Too close: {magnitude:F0} m (at least {minSpan:F0})";
				}
				else if (Vector3.Angle(new Vector3(forward.x, 0f, forward.z), val2) > facingTolerance || Vector3.Angle(new Vector3(forward2.x, 0f, forward2.z), -val2) > facingTolerance)
				{
					text = "The towers must face each other";
				}
				if (text != null)
				{
					if (magnitude < num)
					{
						num = magnitude;
						why = text;
						rejected = item;
					}
				}
				else if (!((Object)(object)chainTower != (Object)null) || !(magnitude >= span))
				{
					chainTower = item;
					span = magnitude;
				}
			}
			if ((Object)(object)chainTower != (Object)null)
			{
				why = "";
				rejected = null;
			}
			return chainTower;
		}

		public bool IsLinked()
		{
			if (PartnerId != 0L)
			{
				return true;
			}
			return (Object)(object)Master() != (Object)null;
		}

		public ChainTower Partner()
		{
			long partnerId = PartnerId;
			if (partnerId == 0L)
			{
				return null;
			}
			foreach (ChainTower item in All)
			{
				if ((Object)(object)item != (Object)(object)this && item.Valid && item.Id == partnerId)
				{
					return item;
				}
			}
			return null;
		}

		public ChainTower Master()
		{
			long id = Id;
			if (id == 0L)
			{
				return null;
			}
			foreach (ChainTower item in All)
			{
				if ((Object)(object)item != (Object)(object)this && item.Valid && item.PartnerId == id)
				{
					return item;
				}
			}
			return null;
		}

		public ChainTower StateHolder()
		{
			if (PartnerId == 0L)
			{
				return Master();
			}
			return this;
		}

		public float Height()
		{
			if (!Valid)
			{
				return 0f;
			}
			ZDO zDO = m_nview.GetZDO();
			float num = zDO.GetFloat(TargetKey, 0f);
			float num2 = zDO.GetFloat(FromKey, 0f);
			if (Mathf.Approximately(num, num2))
			{
				return num;
			}
			double num3 = (double)(ZNet.instance.GetTime().Ticks - zDO.GetLong(SinceKey, 0L)) / 10000000.0;
			return Mathf.MoveTowards(num2, num, (float)(num3 / (double)Duration(num > num2)));
		}

		public bool Moving()
		{
			if (!Valid)
			{
				return false;
			}
			if ((Object)(object)m_net != (Object)null && Mathf.Abs(m_net.ShownHeight - Height()) > 0.0001f)
			{
				return true;
			}
			ZDO zDO = m_nview.GetZDO();
			float num = zDO.GetFloat(TargetKey, 0f);
			float num2 = zDO.GetFloat(FromKey, 0f);
			if (Mathf.Approximately(num, num2))
			{
				return false;
			}
			return (double)(ZNet.instance.GetTime().Ticks - zDO.GetLong(SinceKey, 0L)) / 10000000.0 < (double)(Duration(num > num2) * Mathf.Abs(num - num2)) + 0.5;
		}

		public float Duration(bool raising)
		{
			if (Valid)
			{
				ZDO zDO = m_nview.GetZDO();
				float num = zDO.GetFloat(SecondsKey, 0f);
				if (num > 0f && zDO.GetFloat(TargetKey, 0f) > 0.5f == raising)
				{
					return num;
				}
			}
			return RunSeconds(raising);
		}

		private float RunSeconds(bool raising)
		{
			float num = Mathf.Max(0.05f, raising ? Settings.RaiseSpeed : Settings.LowerSpeed);
			return Mathf.Max(2f, Travel / num);
		}

		private bool KnownTravel(out float travel)
		{
			travel = (((Object)(object)m_net != (Object)null) ? m_net.Travel : (Valid ? m_nview.GetZDO().GetFloat(TravelKey, 0f) : 0f));
			return travel > 0f;
		}

		public bool Command(int order)
		{
			ChainTower chainTower = StateHolder();
			if ((Object)(object)chainTower == (Object)null || !chainTower.Valid)
			{
				return false;
			}
			chainTower.m_nview.InvokeRPC("HarborChain_Winch", new object[1] { order });
			return true;
		}

		private void RPC_Winch(long sender, int order)
		{
			if (Valid && m_nview.IsOwner() && PartnerId != 0L)
			{
				float num = (((Object)(object)m_net != (Object)null) ? m_net.ShownHeight : Height());
				float travel = order switch
				{
					1 => 1f, 
					2 => 0f, 
					_ => (Target > 0.5f) ? 0f : 1f, 
				};
				float num2 = travel;
				float num3 = (KnownTravel(out travel) ? RunSeconds(num2 > 0.5f) : 0f);
				ZDO zDO = m_nview.GetZDO();
				zDO.Set(FromKey, num);
				zDO.Set(TargetKey, num2);
				zDO.Set(SinceKey, ZNet.instance.GetTime().Ticks);
				zDO.Set(SecondsKey, num3);
				HarborChainPlugin.Log.LogInfo((object)string.Format("winch on {0:X}: {1} from {2:F2}, {3} (asked by {4})", Id, (num2 > 0.5f) ? "raising" : "lowering", num, (num3 > 0f) ? $"a whole run {num3:F1} s for {Travel:F1} m" : "the travel not known here: each client times it", sender));
			}
		}

		private void RPC_Unlink(long sender, long partner)
		{
			if (Valid && m_nview.IsOwner() && PartnerId == partner)
			{
				Unlink("the other tower is gone");
			}
		}

		private void Unlink(string why)
		{
			HarborChainPlugin.Log.LogInfo((object)$"tower {Id:X} unlinked from {PartnerId:X}: {why}");
			m_nview.GetZDO().Set(PartnerKey, 0L);
			DestroyNet();
		}

		private void OnDestroyedByDamage()
		{
			ChainTower chainTower = Master();
			if ((Object)(object)chainTower != (Object)null && chainTower.Valid)
			{
				if (chainTower.m_nview.IsOwner())
				{
					chainTower.Unlink("the other tower was destroyed");
				}
				else
				{
					chainTower.m_nview.InvokeRPC("HarborChain_Unlink", new object[1] { Id });
				}
			}
			DestroyNet();
		}

		private void Update()
		{
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)m_nview == (Object)null || m_nview.GetZDO() == null)
			{
				if (Player.IsPlacementGhost(((Component)this).gameObject))
				{
					UpdatePreview();
				}
			}
			else if (m_nview.IsValid())
			{
				m_checkTimer -= Time.deltaTime;
				if (m_checkTimer <= 0f)
				{
					m_checkTimer = 0.5f;
					CheckLink();
				}
				ChainTower chainTower = (((Object)(object)m_net != (Object)null) ? this : StateHolder());
				float num = ((!((Object)(object)chainTower != (Object)null)) ? 0f : (((Object)(object)chainTower.m_net != (Object)null) ? chainTower.m_net.ShownHeight : chainTower.Height()));
				float num2 = (((Object)(object)chainTower != (Object)null) ? (chainTower.Travel / 2.261947f) : 0f);
				if ((Object)(object)m_drum != (Object)null)
				{
					m_drum.localRotation = Quaternion.Euler((0f - num) * num2 * 360f, 0f, 0f);
				}
				if ((Object)(object)chainTower != (Object)null && (Object)(object)chainTower == (Object)(object)m_lastHolder && m_lastHeight >= 0f && Mathf.Abs(num - m_lastHeight) > 1E-05f && chainTower.Moving())
				{
					m_lastTurned = Time.time;
				}
				m_lastHeight = num;
				m_lastHolder = chainTower;
				UpdateSound((Object)(object)chainTower != (Object)null && Time.time - m_lastTurned < 1f);
			}
		}

		private void UpdateSound(bool turning)
		{
			//IL_0052: 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_0057: 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_0081: Unknown result type (might be due to invalid IL or missing references)
			if (turning == m_turning)
			{
				return;
			}
			m_turning = turning;
			if ((Object)(object)m_turningLoop != (Object)null)
			{
				Object.Destroy((Object)(object)m_turningLoop);
			}
			m_turningLoop = null;
			Vector3 at = (((Object)(object)m_drum != (Object)null) ? m_drum.position : ((Component)this).transform.position);
			if (!(Time.timeSinceLevelLoad < 5f) && turning)
			{
				if (Time.time - m_lastStarted > 3f)
				{
					Sound("sfx_frozenking_chainflurry_chain", at, 0.5f);
				}
				m_lastStarted = Time.time;
				m_turningLoop = Sound("sfx_deepnorth_gate_close_loop", at, 0.45f, keep: true);
			}
		}

		private GameObject Sound(string prefab, Vector3 at, float volume, bool keep = false)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab(prefab) : null);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			ZNetView.m_forceDisableInit = true;
			GameObject val2;
			try
			{
				val2 = Object.Instantiate<GameObject>(val, at, Quaternion.identity, ((Component)this).transform);
			}
			finally
			{
				ZNetView.m_forceDisableInit = false;
			}
			ZSFX[] componentsInChildren = val2.GetComponentsInChildren<ZSFX>();
			foreach (ZSFX obj in componentsInChildren)
			{
				obj.SetVolumeModifier(volume);
				obj.m_minDelay = (obj.m_maxDelay = 0f);
				obj.m_fadeInDuration = Mathf.Min(obj.m_fadeInDuration, 0.05f);
				obj.m_playOnAwake = false;
				obj.Play();
				AudioSource component = ((Component)obj).GetComponent<AudioSource>();
				if ((Object)(object)component != (Object)null && (Object)(object)component.clip != (Object)null && component.isPlaying)
				{
					component.time = QuietStart(component.clip);
				}
			}
			TimedDestruction component2 = val2.GetComponent<TimedDestruction>();
			float num = (((Object)(object)component2 != (Object)null) ? component2.m_timeout : 10f);
			if ((Object)(object)component2 != (Object)null)
			{
				Object.Destroy((Object)(object)component2);
			}
			if (!keep)
			{
				Object.Destroy((Object)(object)val2, num);
			}
			return val2;
		}

		internal static float QuietStart(AudioClip clip)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Invalid comparison between Unknown and I4
			if (s_quietStarts.TryGetValue(clip, out var value))
			{
				return value;
			}
			value = 0f;
			try
			{
				if ((int)clip.loadType != 2 && clip.samples > 0)
				{
					float[] array = new float[clip.samples * clip.channels];
					if (s_getData != null && (bool)s_getData.Invoke(clip, new object[2] { array, 0 }))
					{
						float peak = 0f;
						float[] array2 = array;
						foreach (float num in array2)
						{
							peak = Mathf.Max(peak, Mathf.Abs(num));
						}
						int num2 = ((peak > 0f) ? Array.FindIndex(array, (float v) => Mathf.Abs(v) >= peak * 0.1f) : (-1));
						if (num2 > 0)
						{
							value = Mathf.Min((float)num2 / (float)(clip.frequency * clip.channels), clip.length / 3f);
						}
					}
				}
			}
			catch (Exception ex)
			{
				HarborChainPlugin.Log.LogDebug((object)(((Object)clip).name + ": samples not read (" + ex.Message + ")"));
			}
			s_quietStarts[clip] = value;
			HarborChainPlugin.Log.LogInfo((object)$"sound {((Object)clip).name}: {clip.length:F1} s, quiet for its first {value:F2} s");
			return value;
		}

		private void CheckLink()
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			if (PartnerId == 0L)
			{
				DestroyNet();
				return;
			}
			ChainTower chainTower = Partner();
			if ((Object)(object)chainTower == (Object)null)
			{
				DestroyNet();
				Vector3 vec = m_nview.GetZDO().GetVec3(PartnerPosKey, ((Component)this).transform.position);
				if ((Object)(object)ZNet.instance != (Object)null && ZNetScene.InActiveArea(vec, ZNet.instance.GetReferencePosition()) && (Object)(object)ZoneSystem.instance != (Object)null && ZoneSystem.instance.IsZoneLoaded(vec) && !TowerExists(vec, PartnerId))
				{
					m_partnerMissingFor += 0.5f;
				}
				else
				{
					m_partnerMissingFor = 0f;
				}
				if (m_partnerMissingFor > 15f && m_nview.IsOwner())
				{
					Unlink("the other tower is not there any more");
				}
				return;
			}
			m_partnerMissingFor = 0f;
			if ((Object)(object)m_net == (Object)null)
			{
				m_net = ChainNet.Create(this, chainTower);
			}
			else if (!m_net.Fits(this, chainTower))
			{
				DestroyNet();
				m_net = ChainNet.Create(this, chainTower);
			}
			if ((Object)(object)m_net != (Object)null && m_nview.IsOwner() && Mathf.Abs(m_nview.GetZDO().GetFloat(TravelKey, 0f) - m_net.Travel) > 0.05f)
			{
				m_nview.GetZDO().Set(TravelKey, m_net.Travel);
			}
		}

		private static bool TowerExists(Vector3 where, long id)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			if (ZDOMan.instance == null)
			{
				return true;
			}
			List<ZDO> list = ZDOMan.instance.m_objectsBySector[ZoneSystem.SectorToIndex(ZoneSystem.GetZone(where)).Sector];
			if (list == null)
			{
				return false;
			}
			foreach (ZDO item in list)
			{
				if (item != null && TowerPiece.IsTower(item.GetPrefab()) && item.GetLong(IdKey, 0L) == id)
				{
					return true;
				}
			}
			return false;
		}

		public void DestroyNet()
		{
			if ((Object)(object)m_net != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)m_net).gameObject);
			}
			m_net = null;
		}

		private void UpdatePreview()
		{
			//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_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Expected O, but got Unknown
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: 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_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
			Vector3 port = Port;
			float span;
			string why;
			ChainTower rejected;
			ChainTower chainTower = FindPartner(port, ((Component)this).transform.forward, null, Wood, out span, out why, out rejected);
			ChainTower chainTower2 = chainTower ?? rejected;
			if ((Object)(object)chainTower2 == (Object)null)
			{
				if ((Object)(object)m_preview != (Object)null)
				{
					((Component)m_preview).gameObject.SetActive(false);
				}
				PreviewText = "";
				return;
			}
			bool flag = (Object)(object)chainTower != (Object)null;
			if ((Object)(object)m_preview == (Object)null)
			{
				GameObject val = new GameObject("HarborChain_SpanPreview");
				m_preview = val.AddComponent<LineRenderer>();
				((Renderer)m_preview).sharedMaterial = Materials.Preview;
				m_preview.positionCount = 16;
				m_preview.widthMultiplier = 0.12f;
				m_preview.useWorldSpace = true;
				((Renderer)m_preview).shadowCastingMode = (ShadowCastingMode)0;
				((Renderer)m_preview).receiveShadows = false;
			}
			((Component)m_preview).gameObject.SetActive(true);
			Color val2 = (flag ? new Color(0.3f, 1f, 0.35f, 0.9f) : new Color(1f, 0.3f, 0.25f, 0.9f));
			m_preview.startColor = val2;
			m_preview.endColor = val2;
			Vector3 val3 = port;
			Vector3 port2 = chainTower2.Port;
			float num = Mathf.Min(1.5f, Vector3.Distance(val3, port2) * 0.04f);
			for (int i = 0; i < 16; i++)
			{
				float num2 = (float)i / 15f;
				m_preview.SetPosition(i, Vector3.Lerp(val3, port2, num2) + Vector3.down * (num * 4f * num2 * (1f - num2)));
			}
			PreviewLinks = flag;
			PreviewText = (flag ? $"Links across {span:F0} m" : why);
		}

		public string GetHoverName()
		{
			return Name;
		}

		public float GetHoverOffset()
		{
			return 0f;
		}

		public string GetHoverText()
		{
			if (!Valid)
			{
				return "";
			}
			ChainTower chainTower = StateHolder();
			if ((Object)(object)chainTower == (Object)null)
			{
				return Localization.instance.Localize(Name + " (not linked)");
			}
			float num = (((Object)(object)chainTower.m_net != (Object)null) ? chainTower.m_net.ShownHeight : chainTower.Height());
			float target = chainTower.Target;
			bool flag = target > 0.5f;
			string text;
			if ((Object)(object)chainTower.m_net != (Object)null && chainTower.m_net.Blocked)
			{
				text = "a ship is in the way";
			}
			else if (Mathf.Approximately(num, target))
			{
				text = (flag ? "raised" : "lowered");
			}
			else
			{
				int num2 = Mathf.CeilToInt(Mathf.Abs(target - num) * chainTower.Duration(target > num));
				text = string.Format("{0}, {1} s", flag ? "raising" : "lowering", num2);
			}
			string text2 = (flag ? "Lower the net" : "Raise the net");
			return Localization.instance.Localize(Name + " (" + text + ")\n[<color=yellow><b>$KEY_Use</b></color>] " + text2);
		}

		public bool Interact(Humanoid user, bool hold, bool alt)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			if (hold || !Valid)
			{
				return false;
			}
			if (!PrivateArea.CheckAccess(((Component)this).transform.position, 0f, true, false))
			{
				return true;
			}
			if ((Object)(object)StateHolder() == (Object)null)
			{
				((Character)user).Message((MessageType)2, "Not linked", 0, (Sprite)null, false);
				return true;
			}
			Command(0);
			return true;
		}

		public bool UseItem(Humanoid user, ItemData item)
		{
			return false;
		}
	}
	internal static class Materials
	{
		private static readonly Dictionary<string, Material> s_found = new Dictionary<string, Material>();

		private static Material s_chain;

		private static Material s_preview;

		public static Material Stone => OfPiece("stone_pillar", "stone_mat") ?? First("stone_mat", "stone");

		public static Material Wood => OfPiece("wood_beam", "woodwall") ?? First("woodwall", "woodpole", "wood");

		public static Material DarkWood => OfPiece("darkwood_beam", "DarkWood_mat") ?? First("DarkWood_mat", "woodwall");

		public static Material Iron => OfPiece("woodiron_pole", "Ironbeam_mat") ?? First("Ironbeam_mat", "metalwall", "iron");

		public static Material Chain
		{
			get
			{
				//IL_0025: Unknown result type (might be due to invalid IL or missing references)
				//IL_002a: Unknown result type (might be due to invalid IL or missing references)
				//IL_003a: Expected O, but got Unknown
				if ((Object)(object)s_chain != (Object)null)
				{
					return s_chain;
				}
				Material iron = Iron;
				if ((Object)(object)iron == (Object)null)
				{
					return null;
				}
				s_chain = new Material(iron)
				{
					name = "HarborChain_chain"
				};
				s_chain.EnableKeyword("_MOVEABLEOBJECT_ON");
				if (s_chain.HasProperty("_TriplanarLocalPos"))
				{
					s_chain.SetFloat("_TriplanarLocalPos", 1f);
				}
				if (s_chain.HasProperty("_ValueNoise"))
				{
					s_chain.SetFloat("_ValueNoise", 0f);
				}
				return s_chain;
			}
		}

		public static Material Preview
		{
			get
			{
				//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_0074: Expected O, but got Unknown
				if ((Object)(object)s_preview != (Object)null)
				{
					return s_preview;
				}
				Shader val = Shader.Find("Sprites/Default") ?? Shader.Find("Legacy Shaders/Particles/Alpha Blended");
				if ((Object)(object)val == (Object)null)
				{
					Material val2 = Find("item_particle");
					val = (((Object)(object)val2 != (Object)null) ? val2.shader : null);
				}
				if ((Object)(object)val == (Object)null)
				{
					return null;
				}
				s_preview = new Material(val)
				{
					name = "HarborChain_preview"
				};
				return s_preview;
			}
		}

		public static Material Find(string name)
		{
			if (s_found.TryGetValue(name, out var value) && (Object)(object)value != (Object)null)
			{
				return value;
			}
			Material[] array = Resources.FindObjectsOfTypeAll<Material>();
			foreach (Material val in array)
			{
				if (!((Object)(object)val == (Object)null) && !(((Object)val).name != name))
				{
					s_found[name] = val;
					return val;
				}
			}
			return null;
		}

		public static Material First(params string[] names)
		{
			for (int i = 0; i < names.Length; i++)
			{
				Material val = Find(names[i]);
				if ((Object)(object)val != (Object)null)
				{
					return val;
				}
			}
			return null;
		}

		public static Material OfPiece(string prefab, string material)
		{
			string key = prefab + "/" + material;
			if (s_found.TryGetValue(key, out var value) && (Object)(object)value != (Object)null)
			{
				return value;
			}
			GameObject val = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab(prefab) : null);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			Renderer[] componentsInChildren = val.GetComponentsInChildren<Renderer>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Material[] sharedMaterials = componentsInChildren[i].sharedMaterials;
				foreach (Material val2 in sharedMaterials)
				{
					if ((Object)(object)val2 != (Object)null && ((Object)val2).name == material)
					{
						s_found[key] = val2;
						return val2;
					}
				}
			}
			return null;
		}

		public static void Unload()
		{
			s_chain = null;
			s_preview = null;
			s_found.Clear();
		}
	}
	internal sealed class MeshBuilder
	{
		public readonly List<Vector3> Vertices = new List<Vector3>();

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

		public readonly List<Vector2> Uvs = new List<Vector2>();

		public readonly List<int> Triangles = new List<int>();

		public float UvPerMetre = 0.5f;

		public int Count => Vertices.Count;

		public int Vertex(Vector3 position, Vector3 normal, Vector2 uv)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			Vertices.Add(position);
			Normals.Add(normal);
			Uvs.Add(uv);
			return Vertices.Count - 1;
		}

		public void Triangle(int a, int b, int c)
		{
			Triangles.Add(a);
			Triangles.Add(b);
			Triangles.Add(c);
		}

		public void Quad(Vector3 a, Vector3 b, Vector3 c, Vector3 d, Vector2 uvOffset = default(Vector2))
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: 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_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: 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_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_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: 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_0065: 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_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: 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_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = Vector3.Cross(b - a, d - a);
			Vector3 normalized = ((Vector3)(ref val)).normalized;
			float num = Vector3.Distance(a, b) * UvPerMetre;
			float num2 = Vector3.Distance(a, d) * UvPerMetre;
			int num3 = Vertex(a, normalized, uvOffset);
			Vertex(b, normalized, uvOffset + new Vector2(num, 0f));
			Vertex(c, normalized, uvOffset + new Vector2(num, num2));
			Vertex(d, normalized, uvOffset + new Vector2(0f, num2));
			Triangle(num3, num3 + 1, num3 + 2);
			Triangle(num3, num3 + 2, num3 + 3);
		}

		public void Box(Vector3 center, Vector3 size, Quaternion rotation, Vector2 uvOffset = default(Vector2))
		{
			//IL_0002: 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_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: 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_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: 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_00c0: 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_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_019b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0214: Unknown result type (might be due to invalid IL or missing references)
			//IL_022a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0240: Unknown result type (might be due to invalid IL or missing references)
			//IL_0256: Unknown result type (might be due to invalid IL or missing references)
			//IL_025b: Unknown result type (might be due to invalid IL or missing references)
			Vector3 h = size * 0.5f;
			Quad(P(-1f, -1f, 1f), P(1f, -1f, 1f), P(1f, 1f, 1f), P(-1f, 1f, 1f), uvOffset);
			Quad(P(1f, -1f, -1f), P(-1f, -1f, -1f), P(-1f, 1f, -1f), P(1f, 1f, -1f), uvOffset);
			Quad(P(1f, -1f, 1f), P(1f, -1f, -1f), P(1f, 1f, -1f), P(1f, 1f, 1f), uvOffset);
			Quad(P(-1f, -1f, -1f), P(-1f, -1f, 1f), P(-1f, 1f, 1f), P(-1f, 1f, -1f), uvOffset);
			Quad(P(-1f, 1f, 1f), P(1f, 1f, 1f), P(1f, 1f, -1f), P(-1f, 1f, -1f), uvOffset);
			Quad(P(-1f, -1f, -1f), P(1f, -1f, -1f), P(1f, -1f, 1f), P(-1f, -1f, 1f), uvOffset);
			Vector3 P(float x, float y, float z)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0007: Unknown result type (might be due to invalid IL or missing references)
				//IL_0033: Unknown result type (might be due to invalid IL or missing references)
				//IL_0038: Unknown result type (might be due to invalid IL or missing references)
				//IL_003d: Unknown result type (might be due to invalid IL or missing references)
				return center + rotation * new Vector3(x * h.x, y * h.y, z * h.z);
			}
		}

		public void Box(Vector3 center, Vector3 size)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: 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_000a: 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)
			Box(center, size, Quaternion.identity);
		}

		public void Cylinder(Vector3 a, Vector3 b, float radius, int sides, bool caps = true)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//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_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0046: 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_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: 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_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: 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_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: 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_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: 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)
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: 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_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01da: Unknown result type (might be due to invalid IL or missing references)
			//IL_01df: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0203: Unknown result type (might be due to invalid IL or missing references)
			//IL_022b: Unknown result type (might be due to invalid IL or missing references)
			//IL_025d: Unknown result type (might be due to invalid IL or missing references)
			//IL_025f: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = b - a;
			Vector3 normalized = ((Vector3)(ref val)).normalized;
			val = Vector3.Cross(normalized, (Mathf.Abs(normalized.y) < 0.9f) ? Vector3.up : Vector3.right);
			Vector3 normalized2 = ((Vector3)(ref val)).normalized;
			Vector3 val2 = Vector3.Cross(normalized, normalized2);
			float num = Vector3.Distance(a, b) * UvPerMetre;
			float num2 = (float)Math.PI * 2f * radius * UvPerMetre;
			int count = Count;
			for (int i = 0; i <= sides; i++)
			{
				float num3 = (float)i * 2f * (float)Math.PI / (float)sides;
				Vector3 val3 = normalized2 * Mathf.Cos(num3) + val2 * Mathf.Sin(num3);
				Vertex(a + val3 * radius, val3, new Vector2(num2 * (float)i / (float)sides, 0f));
				Vertex(b + val3 * radius, val3, new Vector2(num2 * (float)i / (float)sides, num));
			}
			for (int j = 0; j < sides; j++)
			{
				int num4 = count + j * 2;
				Triangle(num4, num4 + 3, num4 + 1);
				Triangle(num4, num4 + 2, num4 + 3);
			}
			if (!caps)
			{
				return;
			}
			(Vector3, Vector3)[] array = new(Vector3, Vector3)[2]
			{
				(a, -normalized),
				(b, normalized)
			};
			for (int k = 0; k < array.Length; k++)
			{
				(Vector3, Vector3) tuple = array[k];
				Vector3 item = tuple.Item1;
				Vector3 item2 = tuple.Item2;
				int a2 = Vertex(item, item2, new Vector2(0.5f, 0.5f));
				int count2 = Count;
				for (int l = 0; l < sides; l++)
				{
					float num5 = (float)l * 2f * (float)Math.PI / (float)sides;
					Vector3 val4 = normalized2 * Mathf.Cos(num5) + val2 * Mathf.Sin(num5);
					Vertex(item + val4 * radius, item2, new Vector2(0.5f + 0.5f * Mathf.Cos(num5), 0.5f + 0.5f * Mathf.Sin(num5)));
				}
				for (int m = 0; m < sides; m++)
				{
					int num6 = count2 + m;
					int num7 = count2 + (m + 1) % sides;
					if (item2 == normalized)
					{
						Triangle(a2, num6, num7);
					}
					else
					{
						Triangle(a2, num7, num6);
					}
				}
			}
		}

		public int Link(Vector3 center, Vector3 along, Vector3 across, float length, float width, float wire, int pathPoints, int wireSides)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//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_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: 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_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00d9: 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_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = Vector3.Cross(along, across);
			Vector3 normalized = ((Vector3)(ref val)).normalized;
			float num = (width - wire) * 0.5f;
			float num2 = Mathf.Max(0f, (length - wire) * 0.5f - num);
			int count = Count;
			for (int i = 0; i < pathPoints; i++)
			{
				float num3 = ((float)i + 0.5f) * 2f * (float)Math.PI / (float)pathPoints;
				float num4 = Mathf.Cos(num3);
				float num5 = Mathf.Sin(num3);
				Vector3 val2 = along * (num4 * num + Mathf.Sign(num4) * num2) + across * (num5 * num);
				val = along * num4 + across * num5;
				Vector3 normalized2 = ((Vector3)(ref val)).normalized;
				for (int j = 0; j < wireSides; j++)
				{
					float num6 = (float)j * 2f * (float)Math.PI / (float)wireSides;
					Vector3 val3 = normalized2 * Mathf.Cos(num6) + normalized * Mathf.Sin(num6);
					Vertex(center + val2 + val3 * (wire * 0.5f), val3, new Vector2((float)i / (float)pathPoints, (float)j / (float)wireSides));
				}
			}
			for (int k = 0; k < pathPoints; k++)
			{
				int num7 = (k + 1) % pathPoints;
				for (int l = 0; l < wireSides; l++)
				{
					int num8 = (l + 1) % wireSides;
					int a = count + k * wireSides + l;
					int b = count + num7 * wireSides + l;
					int num9 = count + num7 * wireSides + num8;
					int c = count + k * wireSides + num8;
					Triangle(a, b, num9);
					Triangle(a, num9, c);
				}
			}
			return count;
		}

		public Mesh ToMesh(string name)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Expected O, but got Unknown
			Mesh val = new Mesh
			{
				name = name
			};
			if (Vertices.Count > 65000)
			{
				val.indexFormat = (IndexFormat)1;
			}
			val.SetVertices(Vertices);
			val.SetNormals(Normals);
			val.SetUVs(0, Uvs);
			val.SetTriangles(Triangles, 0);
			val.RecalculateBounds();
			val.RecalculateTangents();
			return val;
		}
	}
	internal sealed class NetBarrier : StaticTarget, IDestructible
	{
		public ChainNet Net;

		private void Awake()
		{
			base.m_primaryTarget = false;
			base.m_randomTarget = true;
		}

		public void Damage(HitData hit)
		{
			if ((Object)(object)Net != (Object)null)
			{
				Net.TakeHit(hit);
			}
		}

		public DestructibleType GetDestructibleType()
		{
			return (DestructibleType)1;
		}
	}
	internal static class NetMesh
	{
		private const float NetPitch = 0.26f;

		private const float HeavyPitch = 0.38f;

		public static Mesh Build(Vector3[] rest, int columns, int rows, out int links)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: 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_015e: Unknown result type (might be due to invalid IL or missing references)
			MeshBuilder meshBuilder = new MeshBuilder
			{
				UvPerMetre = 1f
			};
			List<BoneWeight> list = new List<BoneWeight>();
			links = 0;
			int num = 0;
			for (int i = 0; i < columns; i++)
			{
				for (int j = 0; j + 1 < rows; j++)
				{
					num += Mathf.RoundToInt(Vector3.Distance(rest[i * rows + j], rest[i * rows + j + 1]) / 0.26f);
				}
			}
			bool coarse = num > 1600;
			int num2 = rest.Length;
			for (int k = 0; k < columns; k++)
			{
				for (int l = 0; l + 1 < rows; l++)
				{
					links += Segment(meshBuilder, list, rest, k * rows + l, k * rows + l + 1, 0, heavy: false, coarse);
				}
			}
			for (int m = 0; m < rows; m++)
			{
				for (int n = 0; n + 1 < columns; n++)
				{
					links += Segment(meshBuilder, list, rest, n * rows + m, (n + 1) * rows + m, num2, m == 0 || m == rows - 1, coarse);
				}
			}
			Mesh val = meshBuilder.ToMesh("HarborChain_net");
			val.boneWeights = list.ToArray();
			Matrix4x4[] array = (Matrix4x4[])(object)new Matrix4x4[num2 * 2];
			for (int num3 = 0; num3 < num2; num3++)
			{
				array[num3] = (array[num2 + num3] = Matrix4x4.Translate(-rest[num3]));
			}
			val.bindposes = array;
			return val;
		}

		public static Mesh BuildFar(Vector3[] rest, int columns, int rows, float width)
		{
			//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_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			MeshBuilder meshBuilder = new MeshBuilder
			{
				UvPerMetre = 1f
			};
			List<BoneWeight> list = new List<BoneWeight>();
			int num = rest.Length;
			for (int i = 0; i < columns; i++)
			{
				for (int j = 0; j + 1 < rows; j++)
				{
					Bar(meshBuilder, list, rest, i * rows + j, i * rows + j + 1, 0, width);
				}
			}
			for (int k = 0; k < rows; k++)
			{
				for (int l = 0; l + 1 < columns; l++)
				{
					Bar(meshBuilder, list, rest, l * rows + k, (l + 1) * rows + k, num, (k == 0 || k == rows - 1) ? (width * 1.6f) : width);
				}
			}
			Mesh val = meshBuilder.ToMesh("HarborChain_netfar");
			val.boneWeights = list.ToArray();
			Matrix4x4[] array = (Matrix4x4[])(object)new Matrix4x4[num * 2];
			for (int m = 0; m < num; m++)
			{
				array[m] = (array[num + m] = Matrix4x4.Translate(-rest[m]));
			}
			val.bindposes = array;
			return val;
		}

		private static void Bar(MeshBuilder builder, List<BoneWeight> weights, Vector3[] rest, int a, int b, int boneSet, float width)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//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_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_004d: 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_008c: 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_00ba: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = rest[a];
			Vector3 val2 = rest[b];
			if (!(Vector3.Distance(val, val2) < 0.05f))
			{
				int count = builder.Count;
				builder.Cylinder(val, val2, width * 0.5f, 4, caps: false);
				for (int i = count; i < builder.Count; i++)
				{
					bool flag = (i - count) % 2 == 0;
					BoneWeight item = default(BoneWeight);
					((BoneWeight)(ref item)).boneIndex0 = boneSet + (flag ? a : b);
					((BoneWeight)(ref item)).weight0 = 1f;
					weights.Add(item);
					builder.Uvs[i] = new Vector2(0.4f + builder.Uvs[i].x * 0.08f, 0.4f + builder.Uvs[i].y * 0.08f);
				}
			}
		}

		private static int Segment(MeshBuilder builder, List<BoneWeight> weights, Vector3[] rest, int a, int b, int boneSet, bool heavy, bool coarse)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//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_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: