Decompiled source of CustomShips v0.3.0

CustomShips.dll

Decompiled 2 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security.Permissions;
using BepInEx;
using CustomShips.Helper;
using CustomShips.Pieces;
using CustomShips.ZProperties;
using HarmonyLib;
using Jotunn;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("CustomShips")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("CustomShips")]
[assembly: AssemblyCopyright("Copyright ©  2021")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")]
[assembly: AssemblyFileVersion("0.3.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.3.0.0")]
namespace CustomShips
{
	[BepInPlugin("com.maxsch.valheim.CustomShips", "CustomShips", "0.3.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public class Main : BaseUnityPlugin
	{
		public const string PluginGUID = "com.maxsch.valheim.CustomShips";

		public const string PluginName = "CustomShips";

		public const string PluginVersion = "0.3.0";

		private static AssetBundle assetBundle;

		private static List<CustomPiece> pieces = new List<CustomPiece>();

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

		private static HashSet<int> shipPieceHashes = new HashSet<int>();

		public static CustomPiece customShip;

		private static int shipPrefabHash;

		public static CustomLocalization Localization = LocalizationManager.Instance.GetLocalization();

		private void Awake()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Expected O, but got Unknown
			new Harmony("com.maxsch.valheim.CustomShips").PatchAll();
			Localization.AddJsonFile("English", AssetUtils.LoadTextFromResources("Localization.English.json"));
			assetBundle = AssetUtils.LoadAssetBundleFromResources("customships");
			customShip = new CustomPiece(assetBundle, "MS_CustomShip", false, ShipPartConfig(enabled: false));
			PieceManager.Instance.AddPiece(customShip);
			shipPrefabHash = StringExtensionMethods.GetStableHashCode(((Object)customShip.PiecePrefab).name);
			AddShipPiece("MS_Keel_2m", "RoundLog", 4, "BronzeNails", 2);
			AddShipPiece("MS_Keel_4m", "RoundLog", 8, "BronzeNails", 4);
			AddShipPiece("MS_Keel_Bow_1", "RoundLog", 6, "BronzeNails", 4);
			AddShipPiece("MS_Keel_Bow_2", "RoundLog", 4, "BronzeNails", 2);
			AddShipPiece("MS_Rib_1.0m", "RoundLog", 4, "BronzeNails", 2);
			AddShipPiece("MS_Rib_1.2m", "RoundLog", 4, "BronzeNails", 2);
			AddShipPiece("MS_Rib_1.4m", "RoundLog", 5, "BronzeNails", 2);
			AddShipPiece("MS_Rib_1.6m", "RoundLog", 5, "BronzeNails", 2);
			AddShipPiece("MS_Rib_1.8m", "RoundLog", 6, "BronzeNails", 2);
			AddShipPiece("MS_Rib_2.0m", "RoundLog", 6, "BronzeNails", 2);
			AddShipPiece("MS_Rib_2.2m", "RoundLog", 7, "BronzeNails", 2);
			AddShipPiece("MS_Rib_2.4m", "RoundLog", 7, "BronzeNails", 2);
			AddShipPiece("MS_Rib_2.6m", "RoundLog", 8, "BronzeNails", 2);
			AddShipPiece("MS_Hull_Dynamic", "Wood", 6, "BronzeNails", 2, "Resin", 10);
			AddShipPiece("MS_Rudder_1", "Wood", 12, "BronzeNails", 8);
			AddShipPiece("MS_Crate_1", "FineWood", 8, "BronzeNails", 6);
			AddShipPiece("MS_Barrel_1", "FineWood", 8, "BronzeNails", 6);
			AddShipPiece("MS_Ladder_1", "Wood", 4, "BronzeNails", 2);
			AddShipPiece("MS_Shield_Round_1_Style_1", "FineWood", 6, "BronzeNails", 4);
			AddShipPiece("MS_Shield_Round_1_Style_2", "FineWood", 6, "BronzeNails", 4);
			AddShipPiece("MS_Shield_Round_1_Style_3", "FineWood", 6, "BronzeNails", 4);
			AddShipPiece("MS_Shield_Round_1_Style_4", "FineWood", 6, "BronzeNails", 4);
			AddShipPiece("MS_Sail_2_White", "FineWood", 20, "LeatherScraps", 12, "Resin", 8);
			AddShipPiece("MS_Sail_2_Red_1", "FineWood", 20, "LeatherScraps", 12, "Resin", 8, "Raspberry", 4);
			AddShipPiece("MS_Sail_2_Hide_1", "FineWood", 20, "DeerHide", 12, "Resin", 8);
			AddShipPiece("MS_Sail_1_White", "FineWood", 30, "LeatherScraps", 20, "Resin", 12);
			AddShipPiece("MS_Sail_1_Red_1", "FineWood", 30, "LeatherScraps", 20, "Resin", 12, "Raspberry", 8);
			AddShipPiece("MS_Sail_1_Hide_1", "FineWood", 30, "DeerHide", 20, "Resin", 12);
			PieceManager.OnPiecesRegistered += OnPiecesRegistered;
		}

		private void OnPiecesRegistered()
		{
			PieceManager.OnPiecesRegistered -= OnPiecesRegistered;
			((MonoBehaviour)this).StartCoroutine(RenderSprites());
		}

		private static IEnumerator RenderSprites()
		{
			yield return null;
			foreach (CustomPiece piece in pieces)
			{
				piece.Piece.m_icon = RenderManager.Instance.Render(new RenderRequest(piece.PiecePrefab)
				{
					Width = 64,
					Height = 64,
					Rotation = RenderManager.IsometricRotation * Quaternion.Euler(0f, -90f, 0f)
				});
			}
		}

		private void AddShipPiece(string pieceName, string ingredient1 = "", int amount1 = 0, string ingredient2 = "", int amount2 = 0, string ingredient3 = "", int amount3 = 0, string ingredient4 = "", int amount4 = 0)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Expected O, but got Unknown
			PieceConfig val = ShipPartConfig(enabled: true, ingredient1, amount1, ingredient2, amount2, ingredient3, amount3, ingredient4, amount4);
			CustomPiece val2 = new CustomPiece(assetBundle, pieceName, true, val);
			PieceManager.Instance.AddPiece(val2);
			DynamicHull dynamicHull = default(DynamicHull);
			if (val2.PiecePrefab.TryGetComponent<DynamicHull>(ref dynamicHull))
			{
				dynamicHull.UpdateCurve(2f, 2f, 2f, 2f);
				dynamicHull.RegenerateMesh(2f, 2f, 0.9f, 0f, 0f);
			}
			pieces.Add(val2);
			shipPieceNames.Add(pieceName);
			shipPieceHashes.Add(StringExtensionMethods.GetStableHashCode(pieceName));
		}

		public static bool IsShipPiece(GameObject piece)
		{
			return shipPieceNames.Contains(Utils.GetPrefabName(piece));
		}

		public static bool IsShipPiece(ZDO zdo)
		{
			return shipPieceHashes.Contains(zdo.GetPrefab());
		}

		public static bool IsCustomShip(GameObject piece)
		{
			return StringExtensionMethods.GetStableHashCode(Utils.GetPrefabName(piece)) == shipPrefabHash;
		}

		public static bool IsCustomShip(ZDO zdo)
		{
			return zdo.GetPrefab() == shipPrefabHash;
		}

		private PieceConfig ShipPartConfig(bool enabled, string ingredient1 = "", int amount1 = 0, string ingredient2 = "", int amount2 = 0, string ingredient3 = "", int amount3 = 0, string ingredient4 = "", int amount4 = 0)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Expected O, but got Unknown
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Expected O, but got Unknown
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Expected O, but got Unknown
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Expected O, but got Unknown
			PieceConfig val = new PieceConfig();
			val.PieceTable = PieceTables.Hammer;
			val.CraftingStation = CraftingStations.Workbench;
			val.Category = "Ship";
			val.Enabled = enabled;
			val.AddRequirement(new RequirementConfig(ingredient1, amount1, 0, true));
			val.AddRequirement(new RequirementConfig(ingredient2, amount2, 0, true));
			val.AddRequirement(new RequirementConfig(ingredient3, amount3, 0, true));
			val.AddRequirement(new RequirementConfig(ingredient4, amount4, 0, true));
			if (val.Requirements.Length == 0)
			{
				val.AddRequirement(new RequirementConfig("Wood", 3, 0, true));
			}
			return val;
		}
	}
}
namespace CustomShips.ZProperties
{
	public class ZBool : ZProperty<bool>
	{
		public ZBool(string key, bool defaultValue, ZNetView zNetView)
			: base(key, defaultValue, zNetView)
		{
		}

		protected override bool GetValue()
		{
			return base.NetView.GetZDO().GetBool(base.KeyHash, base.DefaultValue);
		}

		protected override void SetValue(bool value)
		{
			base.NetView.GetZDO().Set(base.KeyHash, value);
		}
	}
	public class ZFloat : ZProperty<float>
	{
		public ZFloat(string key, float defaultValue, ZNetView zNetView)
			: base(key, defaultValue, zNetView)
		{
		}

		protected override float GetValue()
		{
			return base.NetView.GetZDO().GetFloat(base.KeyHash, base.DefaultValue);
		}

		protected override void SetValue(float value)
		{
			base.NetView.GetZDO().Set(base.KeyHash, value);
		}
	}
	public class ZInt : ZProperty<int>
	{
		public ZInt(string key, int defaultValue, ZNetView zNetView)
			: base(key, defaultValue, zNetView)
		{
		}

		protected override int GetValue()
		{
			return base.NetView.GetZDO().GetInt(base.KeyHash, base.DefaultValue);
		}

		protected override void SetValue(int value)
		{
			base.NetView.GetZDO().Set(base.KeyHash, value, false);
		}
	}
	public abstract class ZProperty<T>
	{
		private T editorValue;

		public string Key { get; }

		public T DefaultValue { get; }

		protected ZNetView NetView { get; }

		protected int KeyHash { get; }

		private string RPCName { get; }

		protected ZProperty(string key, T defaultValue, ZNetView netView)
		{
			Key = key;
			RPCName = "RPC_" + key;
			KeyHash = StringExtensionMethods.GetStableHashCode(Key);
			DefaultValue = defaultValue;
			NetView = netView;
			NetView.Register<T>(RPCName, (Action<long, T>)RPCSet);
		}

		public void Set(T value)
		{
			if (Application.isEditor && !Object.op_Implicit((Object)(object)ZNetScene.instance))
			{
				editorValue = value;
				return;
			}
			if (NetView.IsValid() && NetView.IsOwner())
			{
				SetValue(value);
				return;
			}
			NetView.InvokeRPC(RPCName, new object[1] { value });
		}

		public T Get()
		{
			if (Application.isEditor && !Object.op_Implicit((Object)(object)ZNetScene.instance))
			{
				return editorValue;
			}
			return GetValue();
		}

		public void Reset()
		{
			Set(DefaultValue);
		}

		protected abstract T GetValue();

		protected abstract void SetValue(T value);

		private void RPCSet(long sender, T value)
		{
			SetValue(value);
		}
	}
	public class ZQuaternion : ZProperty<Quaternion>
	{
		public ZQuaternion(string key, Quaternion defaultValue, ZNetView zNetView)
			: base(key, defaultValue, zNetView)
		{
		}//IL_0002: Unknown result type (might be due to invalid IL or missing references)


		protected override Quaternion GetValue()
		{
			//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)
			return base.NetView.GetZDO().GetQuaternion(base.KeyHash, base.DefaultValue);
		}

		protected override void SetValue(Quaternion value)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			base.NetView.GetZDO().Set(base.KeyHash, value);
		}
	}
	public class ZVector3 : ZProperty<Vector3>
	{
		public ZVector3(string key, Vector3 defaultValue, ZNetView zNetView)
			: base(key, defaultValue, zNetView)
		{
		}//IL_0002: Unknown result type (might be due to invalid IL or missing references)


		protected override Vector3 GetValue()
		{
			//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)
			return base.NetView.GetZDO().GetVec3(base.KeyHash, base.DefaultValue);
		}

		protected override void SetValue(Vector3 value)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			base.NetView.GetZDO().Set(base.KeyHash, value);
		}
	}
}
namespace CustomShips.Pieces
{
	public class Crate : ShipPart
	{
	}
	public class CustomShip : MonoBehaviour
	{
		public ShipControlls shipControls;

		public Transform partParent;

		public BoxCollider onboardTrigger;

		public ZInt uniqueID;

		[HideInInspector]
		public Ship ship;

		private static List<CustomShip> ships = new List<CustomShip>();

		private List<ShipPart> shipParts = new List<ShipPart>();

		private ZNetView nview;

		private Rigidbody rigidbody;

		private Rudder currentRudder;

		private ZQuaternion localPartRotation;

		private void Awake()
		{
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			nview = ((Component)this).gameObject.GetComponent<ZNetView>();
			if (Application.isEditor || (Object.op_Implicit((Object)(object)nview) && nview.GetZDO() != null))
			{
				ships.Add(this);
				ship = ((Component)this).gameObject.GetComponent<Ship>();
				rigidbody = ((Component)this).gameObject.GetComponent<Rigidbody>();
				uniqueID = new ZInt("MS_UniqueID", 0, nview);
				localPartRotation = new ZQuaternion("MS_LocalPartRotation", Quaternion.identity, nview);
				if (uniqueID.Get() == 0)
				{
					uniqueID.Set(StringExtensionMethods.GetStableHashCode(Guid.NewGuid().ToString()));
				}
				((MonoBehaviour)this).InvokeRepeating("UpdatePieces", 1f, 1f);
			}
		}

		public void AddPart(ShipPart shipPart)
		{
			if (!shipParts.Contains(shipPart))
			{
				shipParts.Add(shipPart);
				((Component)shipPart).transform.SetParent(partParent);
			}
		}

		private void UpdatePieces()
		{
			shipParts.RemoveAll((ShipPart i) => !Object.op_Implicit((Object)(object)i));
			UpdateRudder();
			UpdateSails();
			UpdateCollider();
			UpdateWeight();
		}

		public void UpdateRudder()
		{
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: 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_0083: 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_00a5: Unknown result type (might be due to invalid IL or missing references)
			if (!Application.isEditor && !nview.IsOwner())
			{
				return;
			}
			if (Object.op_Implicit((Object)(object)currentRudder))
			{
				currentRudder.SetShipControls(shipControls);
				return;
			}
			List<Rudder> partsOfType = GetPartsOfType<Rudder>();
			if (partsOfType.Count == 1)
			{
				currentRudder = partsOfType[0];
				Quaternion rotation = partParent.rotation;
				((Component)this).transform.rotation = Quaternion.LookRotation(((Component)currentRudder).transform.forward, ((Component)currentRudder).transform.up);
				partParent.rotation = rotation;
				localPartRotation.Set(partParent.localRotation);
				currentRudder.SetShipControls(shipControls);
			}
		}

		private void UpdateSails()
		{
			float num = GetPartsOfType<Sail>().Sum((Sail sail) => sail.force);
			float sailForceFactor = Mathf.Round(1000f * (Mathf.Log(1f + num * 4f) / 4f)) / 1000f;
			ship.m_sailForceFactor = sailForceFactor;
		}

		public List<T> GetPartsOfType<T>() where T : ShipPart
		{
			return (from part in shipParts
				select part as T into part
				where Object.op_Implicit((Object)(object)part)
				select part).ToList();
		}

		public Vector3 ToLocalPosition(Vector3 global)
		{
			//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)
			return ((Component)this).transform.InverseTransformPoint(global);
		}

		public Vector3 ToLocalPosition(ShipPart part)
		{
			//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)
			return ToLocalPosition(((Component)part).transform.position);
		}

		private void Update()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			if (localPartRotation != null)
			{
				partParent.localRotation = localPartRotation.Get();
			}
		}

		private void OnDestroy()
		{
			if (Application.isEditor)
			{
				return;
			}
			foreach (ShipPart shipPart in shipParts)
			{
				if (Object.op_Implicit((Object)(object)shipPart))
				{
					((Component)shipPart).transform.SetParent((Transform)null);
				}
			}
		}

		private void UpdateCollider()
		{
			//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_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: 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_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: 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_0094: 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_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: 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_00e3: Unknown result type (might be due to invalid IL or missing references)
			float num = 1000f;
			float num2 = -1000f;
			float num3 = 1000f;
			float num4 = -1000f;
			Vector3 val = Vector3.zero;
			int num5 = 0;
			Vector3 val2 = Vector3.zero;
			float num6 = 0f;
			bool flag = false;
			foreach (ShipPart shipPart in shipParts)
			{
				if (Object.op_Implicit((Object)(object)shipPart))
				{
					flag = true;
					Vector3 val3 = ((!(shipPart is Rib rib)) ? ToLocalPosition(shipPart) : ToLocalPosition(rib.EndPosition));
					num = Mathf.Min(num, val3.z);
					num2 = Mathf.Max(num2, val3.z);
					num3 = Mathf.Min(num3, val3.x);
					num4 = Mathf.Max(num4, val3.x);
					val += val3;
					num5++;
					val2 += val3 * shipPart.buoyancy;
					num6 += shipPart.buoyancy;
				}
			}
			if (flag)
			{
				float num7 = Mathf.Abs(num - num2) + 1f;
				float num8 = Mathf.Abs(num3 - num4) + 1f;
				ship.m_floatCollider.size = new Vector3(num8, 0.2f, num7);
				((Component)ship.m_floatCollider).transform.localPosition = val2 / num6;
				rigidbody.centerOfMass = val / (float)num5;
				onboardTrigger.size = new Vector3(6f, 5f, num7 + 1f);
				((Component)onboardTrigger).transform.position = rigidbody.worldCenterOfMass;
				UpdateSteerForce(num7);
			}
		}

		private void UpdateWeight()
		{
			rigidbody.mass = Mathf.Max(100f, shipParts.Sum((ShipPart part) => part.Weight));
		}

		private void UpdateSteerForce(float sizeZ)
		{
			float num = (sizeZ - 4f) / 16f;
			ship.m_stearForce = Mathf.Lerp(0.2f, 1f, num);
			ship.m_stearVelForceFactor = Mathf.Lerp(0.2f, 0.8f, num);
			ship.m_backwardForce = Mathf.Lerp(0.5f, 0.2f, num);
			ship.m_angularDamping = Mathf.Lerp(0.05f, 0.3f, num);
		}

		public static CustomShip FindCustomShip(int uniqueID)
		{
			return ships.FirstOrDefault((CustomShip ship) => Object.op_Implicit((Object)(object)ship) && ship.uniqueID.Get() == uniqueID);
		}
	}
	public class DynamicHull : MonoBehaviour
	{
		public int segments = 2;

		public int splits = 1;

		public float width = 0.2f;

		public float offsetY = -0.1f;

		public Rect uvRect = new Rect(0.54f, 0.04f, 0.08f, 0.1f);

		private AnimationCurve curve = new AnimationCurve();

		private Hull hull;

		private void Awake()
		{
			hull = ((Component)this).GetComponent<Hull>();
			hull.OnChange += delegate
			{
				UpdateCurve();
				if (Object.op_Implicit((Object)(object)hull.leftRib) && Object.op_Implicit((Object)(object)hull.rightRib))
				{
					RegenerateMesh(hull.leftRib.size + 0.1f, hull.rightRib.size + 0.1f, 0.9f, 0f, 0f);
				}
				else if (Object.op_Implicit((Object)(object)hull.leftRib))
				{
					RegenerateMesh(hull.leftRib.size + 0.1f, 0.1f, 0.9f, 0f, 0.4f);
				}
				else if (Object.op_Implicit((Object)(object)hull.rightRib))
				{
					RegenerateMesh(0.1f, hull.rightRib.size + 0.1f, 0.9f, 0.4f, 0f);
				}
			};
		}

		private void UpdateCurve()
		{
			float num = 0f;
			float num2 = (Object.op_Implicit((Object)(object)hull.leftRib) ? hull.leftRib.size : 0.1f);
			float num3 = (Object.op_Implicit((Object)(object)hull.rightRib) ? hull.rightRib.size : 0.1f);
			float num4 = 0f;
			if (Object.op_Implicit((Object)(object)hull.leftRib))
			{
				num = (Object.op_Implicit((Object)(object)hull.leftRib.leftRib) ? hull.leftRib.leftRib.size : ((!Object.op_Implicit((Object)(object)hull.rightRib)) ? 0.1f : (Mathf.Min(hull.leftRib.size, hull.rightRib.size) - Mathf.Clamp(Mathf.Abs(hull.leftRib.size - hull.rightRib.size), 0.1f, 0.6f))));
			}
			else if (Object.op_Implicit((Object)(object)hull.rightRib))
			{
				num = (0f - hull.rightRib.size) * 2f;
			}
			if (Object.op_Implicit((Object)(object)hull.rightRib))
			{
				num4 = (Object.op_Implicit((Object)(object)hull.rightRib.rightRib) ? hull.rightRib.rightRib.size : ((!Object.op_Implicit((Object)(object)hull.leftRib)) ? 0.1f : (Mathf.Min(hull.leftRib.size, hull.rightRib.size) - Mathf.Clamp(Mathf.Abs(hull.leftRib.size - hull.rightRib.size), 0.1f, 0.6f))));
			}
			else if (Object.op_Implicit((Object)(object)hull.leftRib))
			{
				num4 = (0f - hull.leftRib.size) * 2f;
			}
			curve.ClearKeys();
			curve.AddKey(-3f, num);
			curve.AddKey(-1f, num2);
			curve.AddKey(1f, num3);
			curve.AddKey(3f, num4);
		}

		public void UpdateCurve(float preLeft, float left, float right, float preRight)
		{
			curve.ClearKeys();
			curve.AddKey(-3f, preLeft);
			curve.AddKey(-1f, left);
			curve.AddKey(1f, right);
			curve.AddKey(3f, preRight);
		}

		private void MakeTriangle(int index, int[] triangles, int a, int b, int c)
		{
			if (index > triangles.Length - 3)
			{
				Debug.Log((object)("Index " + index + " out of bounds " + triangles.Length));
				return;
			}
			triangles[index] = a;
			triangles[index + 1] = b;
			triangles[index + 2] = c;
		}

		private void MakeFace(ref int index, int[] triangles, int a, int b, int c, int d)
		{
			MakeTriangle(index, triangles, a, c, b);
			MakeTriangle(index + 3, triangles, b, c, d);
			index += 6;
		}

		private int GetTopVertice(int segment, int split)
		{
			return segment * (splits + 2) * 2 + split * 2;
		}

		private int GetBottomVertice(int segment, int split)
		{
			return segment * (splits + 2) * 2 + split * 2 + 1;
		}

		public void RegenerateMesh(float left, float right, float height, float startLeft, float startRight)
		{
			//IL_06d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_06dc: Expected O, but got Unknown
			//IL_02c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0411: 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_0441: Unknown result type (might be due to invalid IL or missing references)
			//IL_0446: Unknown result type (might be due to invalid IL or missing references)
			//IL_046c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0471: Unknown result type (might be due to invalid IL or missing references)
			//IL_0495: Unknown result type (might be due to invalid IL or missing references)
			//IL_049a: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_04eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0513: Unknown result type (might be due to invalid IL or missing references)
			//IL_0518: Unknown result type (might be due to invalid IL or missing references)
			//IL_053e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0543: Unknown result type (might be due to invalid IL or missing references)
			//IL_0559: Unknown result type (might be due to invalid IL or missing references)
			//IL_055e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0589: Unknown result type (might be due to invalid IL or missing references)
			//IL_058e: Unknown result type (might be due to invalid IL or missing references)
			//IL_05b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_05b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_05dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_05e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_05fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0630: Unknown result type (might be due to invalid IL or missing references)
			//IL_0635: Unknown result type (might be due to invalid IL or missing references)
			//IL_065d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0662: Unknown result type (might be due to invalid IL or missing references)
			//IL_0688: Unknown result type (might be due to invalid IL or missing references)
			//IL_068d: Unknown result type (might be due to invalid IL or missing references)
			//IL_06a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_06a8: Unknown result type (might be due to invalid IL or missing references)
			int num = (segments + 1) * (splits + 2);
			int num2 = (segments + 1) * (splits + 2);
			int num3 = (splits + 2) * 4;
			int num4 = (splits + 2) * 4;
			int num5 = (segments + 1) * 4;
			int num6 = (segments + 1) * 4;
			int num7 = num + num2;
			int num8 = num7 + num3 + num4;
			Vector3[] array = (Vector3[])(object)new Vector3[num + num2 + num3 + num4 + num5 + num6];
			int[] triangles = new int[segments * (splits + 1) * 6 * 2 + (splits + 1) * 6 * 2 + segments * 6 * 2];
			Vector2[] array2 = (Vector2[])(object)new Vector2[array.Length];
			int index = 0;
			for (int i = 0; i <= splits; i++)
			{
				MakeFace(ref index, triangles, num7 + i * 2 + 1, num7 + (i + 1) * 2 + 1, num7 + i * 2, num7 + (i + 1) * 2);
			}
			for (int j = 0; j <= splits; j++)
			{
				MakeFace(ref index, triangles, num7 + num3 + j * 2, num7 + num3 + (j + 1) * 2, num7 + num3 + j * 2 + 1, num7 + num3 + (j + 1) * 2 + 1);
			}
			for (int k = 0; k <= segments; k++)
			{
				float num9 = (float)k / (float)segments;
				float num10 = width / 2f;
				float num11 = 0.2f * num9 + 0.6f * Mathf.Pow(num9, 3f) + 0.4f * Mathf.Pow(num9, 10f);
				float num12 = (height - num10) * num11;
				float num13 = Mathf.Lerp(0f, (float)Math.PI / 2f, num12);
				float num14 = Mathf.Sin(num13) * num10;
				float num15 = Mathf.Cos(num13) * num10;
				if (k < segments)
				{
					MakeFace(ref index, triangles, num8 + k * 2, num8 + (k + 1) * 2, num8 + k * 2 + 1, num8 + (k + 1) * 2 + 1);
					MakeFace(ref index, triangles, num8 + num5 + k * 2 + 1, num8 + num5 + (k + 1) * 2 + 1, num8 + num5 + k * 2, num8 + num5 + (k + 1) * 2);
				}
				for (int l = 0; l <= splits + 1; l++)
				{
					float num16 = (float)l / (float)(splits + 1);
					float num17 = startLeft * (1f - num16) + startRight * num16;
					float num18 = 0f - curve.Evaluate(num16 * 2f - 1f) - width / 4f;
					float num19 = Mathf.Max(0f, num12 - num17) + num17;
					float num20 = Mathf.Lerp(-1f, 1f, num16);
					array[GetTopVertice(k, l)] = new Vector3(num18 * num9 + num14, num19 + num15 + offsetY, num20);
					array[GetBottomVertice(k, l)] = new Vector3(num18 * num9 - num14, num19 - num15 + offsetY, num20);
					if (k < segments && l < splits + 1)
					{
						MakeFace(ref index, triangles, GetTopVertice(k, l), GetTopVertice(k, l + 1), GetTopVertice(k + 1, l), GetTopVertice(k + 1, l + 1));
						MakeFace(ref index, triangles, GetBottomVertice(k, l), GetBottomVertice(k + 1, l), GetBottomVertice(k, l + 1), GetBottomVertice(k + 1, l + 1));
					}
					float num21 = Mathf.LerpUnclamped(((Rect)(ref uvRect)).xMin, ((Rect)(ref uvRect)).xMax, (float)l / (float)(splits + 1));
					float num22 = Mathf.LerpUnclamped(((Rect)(ref uvRect)).yMin, ((Rect)(ref uvRect)).yMax, num9);
					array2[GetTopVertice(k, l)] = new Vector2(num21, num22 + ((Rect)(ref uvRect)).height / 10f);
					array2[GetBottomVertice(k, l)] = new Vector2(num21, num22);
					if (k == 0)
					{
						array[num7 + l * 2] = new Vector3(num18 * num9 + num14, num19 + num15 + offsetY, num20);
						array[num7 + l * 2 + 1] = new Vector3(num18 * num9 + num14, num19 - num15 + offsetY, num20);
						array2[num7 + l * 2] = new Vector2(num21, num22 + ((Rect)(ref uvRect)).height / 10f);
						array2[num7 + l * 2 + 1] = new Vector2(num21, num22);
					}
					if (k == segments)
					{
						array[num7 + num3 + l * 2] = new Vector3(num18 * num9 + num14, num19 + num15 + offsetY, num20);
						array[num7 + num3 + l * 2 + 1] = new Vector3(num18 * num9 - num14, num19 - num15 + offsetY, num20);
						array2[num7 + num3 + l * 2] = new Vector2(num21, num22 + ((Rect)(ref uvRect)).height / 10f);
						array2[num7 + num3 + l * 2 + 1] = new Vector2(num21, num22);
					}
					if (l == 0)
					{
						array[num8 + k * 2] = new Vector3(num18 * num9 + num14, num19 + num15 + offsetY, num20);
						array[num8 + k * 2 + 1] = new Vector3(num18 * num9 - num14, num19 - num15 + offsetY, num20);
						array2[num8 + k * 2] = new Vector2(num21 + ((Rect)(ref uvRect)).height / 10f, num22);
						array2[num8 + k * 2 + 1] = new Vector2(num21, num22);
					}
					if (l == splits + 1)
					{
						array[num8 + num5 + k * 2] = new Vector3(num18 * num9 + num14, num19 + num15 + offsetY, num20);
						array[num8 + num5 + k * 2 + 1] = new Vector3(num18 * num9 - num14, num19 - num15 + offsetY, num20);
						array2[num8 + num5 + k * 2] = new Vector2(num21 + ((Rect)(ref uvRect)).height / 10f, num22);
						array2[num8 + num5 + k * 2 + 1] = new Vector2(num21, num22);
					}
				}
			}
			Mesh val = new Mesh();
			val.vertices = array;
			val.triangles = triangles;
			val.uv = array2;
			val.RecalculateNormals();
			((Component)this).GetComponent<MeshFilter>().mesh = val;
			if (!Object.op_Implicit((Object)(object)hull))
			{
				hull = ((Component)this).GetComponent<Hull>();
			}
			Collider mainCollider = hull.mainCollider;
			MeshCollider val2 = (MeshCollider)(object)((mainCollider is MeshCollider) ? mainCollider : null);
			if (val2 != null)
			{
				val2.sharedMesh = GenerateBottomCollider(left + 0.1f, right + 0.1f, 0.1f, 0.2f);
			}
			if (Object.op_Implicit((Object)(object)hull.sideCollider))
			{
				hull.sideCollider.sharedMesh = GenerateSideCollider(left, right, 0f, height, 0.2f);
			}
			if (Object.op_Implicit((Object)(object)hull.watermask))
			{
				hull.watermask.mesh = GenerateWatermask(left, right, height);
			}
		}

		private Mesh GenerateWatermask(float left, float right, float height)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Expected O, but got Unknown
			Vector3[] array = (Vector3[])(object)new Vector3[4];
			int[] triangles = new int[6];
			array[0] = new Vector3(0f, height, -1f);
			array[1] = new Vector3(0f, height, 1f);
			array[2] = new Vector3(0f - left, height, -1f);
			array[3] = new Vector3(0f - right, height, 1f);
			MakeTriangle(0, triangles, 0, 2, 1);
			MakeTriangle(3, triangles, 1, 2, 3);
			Mesh val = new Mesh
			{
				vertices = array,
				triangles = triangles
			};
			val.RecalculateNormals();
			return val;
		}

		private Mesh GenerateBottomCollider(float left, float right, float offset, float colliderWidth)
		{
			//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_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_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_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: 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_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Expected O, but got Unknown
			Vector3[] array = (Vector3[])(object)new Vector3[8];
			int[] triangles = new int[12];
			array[0] = new Vector3(0f, offset + colliderWidth / 2f, -1f);
			array[1] = new Vector3(0f, offset + colliderWidth / 2f, 1f);
			array[2] = new Vector3(0f - left, offset + colliderWidth / 2f, -1f);
			array[3] = new Vector3(0f - right, offset + colliderWidth / 2f, 1f);
			array[4] = new Vector3(0f, offset - colliderWidth / 2f, -1f);
			array[5] = new Vector3(0f, offset - colliderWidth / 2f, 1f);
			array[6] = new Vector3(0f - left, offset - colliderWidth / 2f, -1f);
			array[7] = new Vector3(0f - right, offset - colliderWidth / 2f, 1f);
			MakeTriangle(0, triangles, 0, 2, 1);
			MakeTriangle(3, triangles, 1, 2, 3);
			MakeTriangle(6, triangles, 3, 5, 4);
			MakeTriangle(9, triangles, 4, 5, 6);
			Mesh val = new Mesh
			{
				vertices = array,
				triangles = triangles
			};
			val.RecalculateNormals();
			return val;
		}

		private Mesh GenerateSideCollider(float left, float right, float startHeight, float endHeight, float colliderWidth)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0098: 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_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: 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_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_0128: 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_0134: 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_0142: Expected O, but got Unknown
			Vector3[] array = (Vector3[])(object)new Vector3[8];
			int[] triangles = new int[12];
			array[0] = new Vector3(0f - left + colliderWidth / 2f, startHeight, -1f);
			array[1] = new Vector3(0f - right + colliderWidth / 2f, startHeight, 1f);
			array[2] = new Vector3(0f - left + colliderWidth / 2f, endHeight, -1f);
			array[3] = new Vector3(0f - right + colliderWidth / 2f, endHeight, 1f);
			array[4] = new Vector3(0f - left - colliderWidth / 2f, startHeight, -1f);
			array[5] = new Vector3(0f - right - colliderWidth / 2f, startHeight, 1f);
			array[6] = new Vector3(0f - left - colliderWidth / 2f, endHeight, -1f);
			array[7] = new Vector3(0f - right - colliderWidth / 2f, endHeight, 1f);
			MakeTriangle(0, triangles, 0, 2, 1);
			MakeTriangle(3, triangles, 1, 2, 3);
			MakeTriangle(6, triangles, 3, 5, 4);
			MakeTriangle(9, triangles, 4, 5, 6);
			Mesh val = new Mesh
			{
				vertices = array,
				triangles = triangles
			};
			val.RecalculateNormals();
			return val;
		}
	}
	public class Hull : ShipPart
	{
		public MeshCollider sideCollider;

		public MeshFilter watermask;

		public Rib leftRib;

		public Rib rightRib;

		public Transform outerSnappoint;

		public float height = 0.9f;

		public override float Weight
		{
			get
			{
				if (Object.op_Implicit((Object)(object)leftRib) && Object.op_Implicit((Object)(object)rightRib))
				{
					return weight * (leftRib.size + rightRib.size) / 2f;
				}
				if (Object.op_Implicit((Object)(object)leftRib))
				{
					return weight * leftRib.size;
				}
				if (Object.op_Implicit((Object)(object)rightRib))
				{
					return weight * rightRib.size;
				}
				return weight * 2f;
			}
		}

		public event Action OnChange;

		protected override void Start()
		{
			base.Start();
			((MonoBehaviour)this).InvokeRepeating("UpdateHull", 0f, 3f);
		}

		private void UpdateHull()
		{
			//IL_0006: 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_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0039: 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_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: 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)
			Vector3 position = ((Component)this).transform.position;
			Vector3 forward = ((Component)this).transform.forward;
			Vector3 val = -((Component)this).transform.right;
			Rib rib = Rib.FindRib(position + forward * -1f + val * 0.5f);
			Rib rib2 = Rib.FindRib(position + forward * 1f + val * 0.5f);
			if ((Object)(object)rib != (Object)(object)leftRib || (Object)(object)rib2 != (Object)(object)rightRib)
			{
				if (Object.op_Implicit((Object)(object)leftRib))
				{
					leftRib.OnChange -= this.OnChange;
				}
				if (Object.op_Implicit((Object)(object)rightRib))
				{
					rightRib.OnChange -= this.OnChange;
				}
				leftRib = rib;
				rightRib = rib2;
				if (Object.op_Implicit((Object)(object)leftRib))
				{
					leftRib.OnChange += this.OnChange;
				}
				if (Object.op_Implicit((Object)(object)rightRib))
				{
					rightRib.OnChange += this.OnChange;
				}
				float num = ((Object.op_Implicit((Object)(object)leftRib) && Object.op_Implicit((Object)(object)rightRib)) ? ((leftRib.size + rightRib.size) / 2f) : (Object.op_Implicit((Object)(object)leftRib) ? (leftRib.size / 2f) : ((!Object.op_Implicit((Object)(object)rightRib)) ? 2f : (rightRib.size / 2f))));
				outerSnappoint.localPosition = new Vector3(0f - num, height, 0f);
				this.OnChange?.Invoke();
			}
		}

		private void UpdateCollider()
		{
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: 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_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0207: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val;
			float num;
			float num2;
			if (Object.op_Implicit((Object)(object)leftRib) && Object.op_Implicit((Object)(object)rightRib))
			{
				val = (GetRibCenter(leftRib, 0f) + GetRibCenter(rightRib, 0f)) / 2f;
				num = (leftRib.size + rightRib.size) / 2f;
				num2 = Mathf.Atan((leftRib.size - rightRib.size) / 2f) * 57.29578f;
			}
			else if (Object.op_Implicit((Object)(object)leftRib))
			{
				val = (GetRibCenter(leftRib, 0f) + GetRibCenter(leftRib, 2f)) / 2f;
				num = leftRib.size;
				num2 = Mathf.Atan((leftRib.size - 0f) / 2f) * 57.29578f;
			}
			else if (Object.op_Implicit((Object)(object)rightRib))
			{
				val = (GetRibCenter(rightRib, 0f) + GetRibCenter(rightRib, -2f)) / 2f;
				num = rightRib.size;
				num2 = Mathf.Atan((0f - rightRib.size) / 2f) * 57.29578f;
			}
			else
			{
				val = ((Component)this).transform.position;
				num = 2f;
				num2 = 0f;
			}
			float num3 = Mathf.Atan(num / height) * 57.29578f - 90f;
			((Component)mainCollider).transform.position = val + Vector3.up * 0.35f;
			((Component)mainCollider).transform.localScale = new Vector3(num, 1f, 1f);
			((Component)mainCollider).transform.localRotation = Quaternion.Euler(0f, num2, num3);
		}

		private Vector3 GetRibCenter(Rib rib, float offsetZ)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			return ((Component)rib).transform.TransformPoint((0f - rib.size) / 2f, 0f, offsetZ);
		}
	}
	public class Keel : ShipPart
	{
	}
	public class Rib : ShipPart
	{
		public float size = 2f;

		public Rib leftRib;

		public Rib rightRib;

		private static List<Rib> ribs = new List<Rib>();

		public Vector3 EndPosition => ((Component)this).transform.position - ((Component)this).transform.right * size;

		public override float Weight => weight * size;

		public event Action OnChange;

		protected override void Awake()
		{
			base.Awake();
			ribs.Add(this);
			((MonoBehaviour)this).InvokeRepeating("UpdateRib", 0f, 3f);
		}

		private void OnDestroy()
		{
			ribs.Remove(this);
		}

		private void UpdateRib()
		{
			//IL_0006: 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_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0039: 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_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			Vector3 position = ((Component)this).transform.position;
			Vector3 forward = ((Component)this).transform.forward;
			Vector3 val = -((Component)this).transform.right;
			Rib rib = FindRib(position + forward * -2f + val * 0.5f);
			Rib rib2 = FindRib(position + forward * 2f + val * 0.5f);
			if ((Object)(object)rib != (Object)(object)leftRib || (Object)(object)rib2 != (Object)(object)rightRib)
			{
				leftRib = rib;
				rightRib = rib2;
				this.OnChange?.Invoke();
			}
		}

		public static Rib FindRib(Vector3 position)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			foreach (Rib rib in ribs)
			{
				Vector3 val = -((Component)rib).transform.right;
				Vector3 val2 = ((Component)rib).transform.position + val * 0.5f - position;
				if (((Vector3)(ref val2)).magnitude <= 0.5f)
				{
					return rib;
				}
			}
			return null;
		}
	}
	public class Rudder : ShipPart, Interactable, Hoverable
	{
		public Transform rudder;

		public Transform attachPoint;

		private Rib rightRib;

		protected override void Start()
		{
			base.Start();
			((MonoBehaviour)this).InvokeRepeating("UpdateRudder", 0f, 3f);
		}

		private void Update()
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)base.CustomShip))
			{
				rudder.localRotation = base.CustomShip.ship.m_rudderObject.transform.localRotation;
			}
		}

		private void UpdateRudder()
		{
			//IL_0006: 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_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: 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_008e: Unknown result type (might be due to invalid IL or missing references)
			Rib rib = Rib.FindRib(((Component)this).transform.position + ((Component)this).transform.right * 1f);
			if ((Object)(object)rib != (Object)(object)rightRib)
			{
				rightRib = rib;
				if (Object.op_Implicit((Object)(object)rudder) && Object.op_Implicit((Object)(object)rightRib))
				{
					Vector3 localPosition = ((Component)rudder).transform.localPosition;
					localPosition.x = rightRib.size + 0.2f;
					((Component)rudder).transform.localPosition = localPosition;
				}
			}
		}

		public void SetShipControls(ShipControlls shipControls)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: 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_006f: Unknown result type (might be due to invalid IL or missing references)
			((Component)shipControls).transform.position = ((Component)this).transform.position;
			((Component)shipControls).transform.rotation = ((Component)this).transform.rotation;
			((Component)shipControls.m_attachPoint).transform.position = attachPoint.position;
			((Component)shipControls.m_attachPoint).transform.rotation = attachPoint.rotation;
			shipControls.m_ship.m_stearForceOffset = base.CustomShip.ToLocalPosition((ShipPart)this).z;
		}

		public bool Interact(Humanoid user, bool hold, bool alt)
		{
			if (base.CustomShip.GetPartsOfType<Rudder>().Count > 1)
			{
				((Character)Player.m_localPlayer).Message((MessageType)2, "$MS_CustomShips_MultipleRudder", 0, (Sprite)null);
				return false;
			}
			return base.CustomShip.shipControls.Interact(user, hold, alt);
		}

		public bool UseItem(Humanoid user, ItemData item)
		{
			if (base.CustomShip.GetPartsOfType<Rudder>().Count > 1)
			{
				((Character)Player.m_localPlayer).Message((MessageType)2, "$MS_CustomShips_MultipleRudder", 0, (Sprite)null);
				return false;
			}
			return base.CustomShip.shipControls.UseItem(user, item);
		}

		public string GetHoverText()
		{
			return base.CustomShip.shipControls.GetHoverText();
		}

		public string GetHoverName()
		{
			return base.CustomShip.shipControls.GetHoverName();
		}
	}
	public class Sail : ShipPart
	{
		public float force = 0.03f;

		public Transform mast;

		public Transform sail;

		public Cloth sailCloth;

		private bool sailWasInPosition;

		private void Update()
		{
			//IL_002e: 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)
			if (Object.op_Implicit((Object)(object)base.CustomShip))
			{
				((Component)mast).transform.rotation = base.CustomShip.ship.m_mastObject.transform.rotation;
				((Component)sail).transform.localScale = base.CustomShip.ship.m_sailObject.transform.localScale;
				sailCloth.enabled = base.CustomShip.ship.m_sailCloth.enabled;
				bool flag = base.CustomShip.ship.m_sailWasInPosition;
				if (!sailWasInPosition && flag)
				{
					Utils.RecreateComponent(ref sailCloth);
				}
				sailWasInPosition = flag;
			}
		}
	}
	public abstract class ShipPart : MonoBehaviour
	{
		public float weight = 5f;

		public float buoyancy = 1f;

		private CustomShip customShip;

		private ZNetView nview;

		private ZInt connectedShip;

		public Collider mainCollider;

		protected List<Transform> snapPoints = new List<Transform>();

		private static Collider[] tmpColliders = (Collider[])(object)new Collider[1000];

		public CustomShip CustomShip
		{
			get
			{
				return customShip;
			}
			set
			{
				//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
				//IL_0101: Unknown result type (might be due to invalid IL or missing references)
				//IL_007e: Unknown result type (might be due to invalid IL or missing references)
				//IL_009e: Unknown result type (might be due to invalid IL or missing references)
				customShip = value;
				if (Object.op_Implicit((Object)(object)customShip))
				{
					customShip.AddPart(this);
					connectedShip.Set(customShip.uniqueID.Get());
					if (Application.isEditor)
					{
						Debug.LogWarning((object)"Application running in Editor, skipping setting CustomShip");
					}
					else if (!nview.GetZDO().GetBool("MS_HasRelativePosition", false))
					{
						nview.GetZDO().Set(ZDOVars.s_relPosHash, ((Component)this).transform.localPosition);
						nview.GetZDO().Set(ZDOVars.s_relRotHash, ((Component)this).transform.localRotation);
						nview.GetZDO().Set("MS_HasRelativePosition", true);
					}
					else
					{
						Vector3 localPosition = default(Vector3);
						nview.GetZDO().GetVec3(ZDOVars.s_relPosHash, ref localPosition);
						Quaternion localRotation = default(Quaternion);
						nview.GetZDO().GetQuaternion(ZDOVars.s_relRotHash, ref localRotation);
						((Component)this).transform.localPosition = localPosition;
						((Component)this).transform.localRotation = localRotation;
					}
				}
			}
		}

		public virtual float Weight => weight;

		protected virtual void Awake()
		{
			((Component)this).GetComponent<Piece>().GetSnapPoints(snapPoints);
			nview = ((Component)this).GetComponent<ZNetView>();
			connectedShip = new ZInt("MS_ConnectedShip", 0, nview);
		}

		protected virtual void Start()
		{
			((MonoBehaviour)this).InvokeRepeating("SearchShip", 0f, 3f);
			((MonoBehaviour)this).InvokeRepeating("SetPosition", 0f, 5f);
		}

		private void SearchShip()
		{
			if (Object.op_Implicit((Object)(object)CustomShip))
			{
				return;
			}
			CustomShip = ((Component)((Component)this).transform).GetComponentInParent<CustomShip>();
			if (!Object.op_Implicit((Object)(object)CustomShip))
			{
				CustomShip customShip = CustomShip.FindCustomShip(connectedShip.Get());
				if (Object.op_Implicit((Object)(object)customShip))
				{
					CustomShip = customShip;
				}
			}
		}

		private void SetPosition()
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			if (nview.IsOwner())
			{
				nview.GetZDO().SetPosition(((Component)this).transform.position);
			}
		}

		public void CreateCustomShip()
		{
			//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)
			GameObject val = Object.Instantiate<GameObject>(Main.customShip.PiecePrefab, ((Component)this).transform.position, Quaternion.identity);
			CustomShip = val.GetComponent<CustomShip>();
		}

		public static ShipPart FindNearest(Vector3 position)
		{
			//IL_0000: 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_0061: Unknown result type (might be due to invalid IL or missing references)
			int num = Physics.OverlapSphereNonAlloc(position, 4f, tmpColliders, LayerMask.GetMask(new string[1] { "piece" }));
			float num2 = float.MaxValue;
			ShipPart result = null;
			for (int i = 0; i < num; i++)
			{
				ShipPart componentInParent = ((Component)tmpColliders[i]).GetComponentInParent<ShipPart>();
				if (Object.op_Implicit((Object)(object)componentInParent) && Object.op_Implicit((Object)(object)componentInParent.CustomShip))
				{
					float num3 = Vector3.Distance(((Component)componentInParent).transform.position, position);
					if (num3 < num2)
					{
						num2 = num3;
						result = componentInParent;
					}
				}
			}
			return result;
		}
	}
}
namespace CustomShips.Patches
{
	[HarmonyPatch]
	public static class ZDOManPatch
	{
		private static Dictionary<int, ZDO> ships = new Dictionary<int, ZDO>();

		private static Dictionary<int, List<ZDO>> shipPieces = new Dictionary<int, List<ZDO>>();

		private static Queue<ZDO> newZDOs = new Queue<ZDO>();

		[HarmonyPatch(typeof(ZDOMan), "Load")]
		[HarmonyPostfix]
		public static void Load(ZDOMan __instance)
		{
			foreach (ZDO value in __instance.m_objectsByID.Values)
			{
				RegisterZDO(value);
			}
			foreach (int key in ships.Keys)
			{
				CheckShip(key);
			}
			__instance.m_onZDODestroyed = (Action<ZDO>)Delegate.Combine(__instance.m_onZDODestroyed, new Action<ZDO>(OnZDODestroyed));
		}

		[HarmonyPatch(typeof(ZDOMan), "ShutDown")]
		[HarmonyPostfix]
		public static void OnShutDown()
		{
			ships.Clear();
			shipPieces.Clear();
			newZDOs.Clear();
		}

		[HarmonyPatch(typeof(ZDOMan), "CreateNewZDO", new Type[]
		{
			typeof(ZDOID),
			typeof(Vector3),
			typeof(int)
		})]
		[HarmonyPostfix]
		public static void OnCreateNewZDO(ref ZDO __result)
		{
			if (ZNet.instance.IsServer())
			{
				newZDOs.Enqueue(__result);
			}
		}

		[HarmonyPatch(typeof(ZDOMan), "Update")]
		[HarmonyPostfix]
		public static void ZDOManUpdate()
		{
			while (newZDOs.Count > 0)
			{
				RegisterZDO(newZDOs.Dequeue());
			}
		}

		private static void CheckShip(int targetShip)
		{
			if (!HasAnyPiece(targetShip) && ships.TryGetValue(targetShip, out var value))
			{
				Logger.LogInfo((object)$"Deleting empty ship {value}");
				if (!value.IsOwner())
				{
					value.SetOwner(ZDOMan.GetSessionID());
				}
				ZDOMan.instance.DestroyZDO(value);
			}
		}

		private static bool HasAnyPiece(int targetShip)
		{
			if (shipPieces.TryGetValue(targetShip, out var value))
			{
				return value.Count > 0;
			}
			return false;
		}

		private static void OnZDODestroyed(ZDO zdo)
		{
			if (Main.IsShipPiece(zdo))
			{
				int @int = zdo.GetInt("MS_UniqueID", 0);
				ships.Remove(@int);
			}
			if (Main.IsShipPiece(zdo))
			{
				int int2 = zdo.GetInt("MS_ConnectedShip", 0);
				if (shipPieces.TryGetValue(int2, out var value))
				{
					value.Remove(zdo);
				}
				else
				{
					Logger.LogWarning((object)$"ship {int2} for {zdo} not registered");
				}
				CheckShip(int2);
			}
		}

		private static void RegisterZDO(ZDO zdo)
		{
			if (Main.IsCustomShip(zdo))
			{
				ships.Add(zdo.GetInt("MS_UniqueID", 0), zdo);
			}
			if (Main.IsShipPiece(zdo))
			{
				int @int = zdo.GetInt("MS_ConnectedShip", 0);
				if (shipPieces.TryGetValue(@int, out var value))
				{
					value.Add(zdo);
					return;
				}
				shipPieces[@int] = new List<ZDO> { zdo };
			}
		}
	}
	[HarmonyPatch]
	public class PlacementPatch
	{
		private static CustomShip snapShip;

		[HarmonyPatch(typeof(Player), "SetupPlacementGhost")]
		[HarmonyPostfix]
		public static void SetupPlacementGhostPatch(Player __instance)
		{
			if (Object.op_Implicit((Object)(object)__instance.m_placementGhost))
			{
				DynamicHull[] componentsInChildren = __instance.m_placementGhost.GetComponentsInChildren<DynamicHull>();
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					Object.Destroy((Object)(object)componentsInChildren[i]);
				}
				ShipPart[] componentsInChildren2 = __instance.m_placementGhost.GetComponentsInChildren<ShipPart>();
				for (int i = 0; i < componentsInChildren2.Length; i++)
				{
					Object.Destroy((Object)(object)componentsInChildren2[i]);
				}
				CustomShip[] componentsInChildren3 = __instance.m_placementGhost.GetComponentsInChildren<CustomShip>();
				for (int i = 0; i < componentsInChildren3.Length; i++)
				{
					Object.Destroy((Object)(object)componentsInChildren3[i]);
				}
			}
		}

		[HarmonyPatch(typeof(Player), "PlacePiece")]
		[HarmonyTranspiler]
		public static IEnumerable<CodeInstruction> PlacePieceTranspiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0002: 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_0036: Expected O, but got Unknown
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Expected O, but got Unknown
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Expected O, but got Unknown
			return new CodeMatcher(instructions, (ILGenerator)null).MatchForward(true, (CodeMatch[])(object)new CodeMatch[1]
			{
				new CodeMatch((Func<CodeInstruction, bool>)((CodeInstruction i) => i.IsCall("Object", "Instantiate")), (string)null)
			}).ThrowIfInvalid("Could not find Object.Instantiate call").InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1]
			{
				new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(PlacementPatch), "BeforePlacePiece", (Type[])null, (Type[])null))
			})
				.Advance(1)
				.InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1]
				{
					new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(PlacementPatch), "AfterPlacePiece", (Type[])null, (Type[])null))
				})
				.Instructions();
		}

		private static void BeforePlacePiece()
		{
			Player localPlayer = Player.m_localPlayer;
			if (Main.IsShipPiece(localPlayer.m_placementGhost))
			{
				if (Object.op_Implicit((Object)(object)localPlayer.m_hoveringPiece))
				{
					snapShip = ((Component)localPlayer.m_hoveringPiece).GetComponentInParent<CustomShip>();
				}
				Transform val = default(Transform);
				Transform val2 = default(Transform);
				localPlayer.FindClosestSnapPoints(localPlayer.m_placementGhost.transform, 0.5f, ref val, ref val2, localPlayer.m_tempPieces);
				ShipPart shipPart = default(ShipPart);
				if (Object.op_Implicit((Object)(object)val2) && Object.op_Implicit((Object)(object)val2.parent) && ((Component)val2.parent).TryGetComponent<ShipPart>(ref shipPart))
				{
					snapShip = shipPart.CustomShip;
				}
			}
		}

		private static GameObject AfterPlacePiece(GameObject piece)
		{
			ShipPart shipPart = default(ShipPart);
			if (Object.op_Implicit((Object)(object)piece) && Main.IsShipPiece(piece) && piece.TryGetComponent<ShipPart>(ref shipPart))
			{
				if (Object.op_Implicit((Object)(object)snapShip))
				{
					shipPart.CustomShip = snapShip;
				}
				else
				{
					shipPart.CreateCustomShip();
				}
			}
			snapShip = null;
			return piece;
		}

		[HarmonyPatch(typeof(Player), "UpdatePlacementGhost")]
		[HarmonyTranspiler]
		public static IEnumerable<CodeInstruction> UpdatePlacementGhostRotationTranspiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Expected O, but got Unknown
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bf: Expected O, but got Unknown
			//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e2: Expected O, but got Unknown
			//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f0: Expected O, but got Unknown
			List<CodeInstruction> list = instructions.ToList();
			int num = -1;
			for (int i = 0; i < list.Count; i++)
			{
				if (list[i].opcode == OpCodes.Ldarg_0 && CodeInstructionExtensions.LoadsField(list[i + 1], AccessTools.Field(typeof(Player), "m_placeRotationDegrees"), false) && list[i + 2].opcode == OpCodes.Ldarg_0 && CodeInstructionExtensions.LoadsField(list[i + 3], AccessTools.Field(typeof(Player), "m_placeRotation"), false) && list[i + 4].opcode == OpCodes.Conv_R4 && list[i + 5].opcode == OpCodes.Mul && list[i + 6].opcode == OpCodes.Ldc_R4 && list[i + 7].CallReturns(typeof(Quaternion)))
				{
					if (list[i + 8].opcode == OpCodes.Stloc_S)
					{
						num = i + 8;
						break;
					}
					if (list[i + 8].CallReturns(typeof(Quaternion)) && list[i + 9].opcode == OpCodes.Stloc_S)
					{
						num = i + 9;
						break;
					}
				}
			}
			if (num < 0)
			{
				throw new InvalidOperationException("Could not find rotation calculation");
			}
			object operand;
			return new CodeMatcher((IEnumerable<CodeInstruction>)list, (ILGenerator)null).Advance(num + 1).GetOperand(out operand).Advance(1)
				.InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[4]
				{
					new CodeInstruction(OpCodes.Ldarg_0, (object)null),
					new CodeInstruction(OpCodes.Ldloc_S, operand),
					new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(PlacementPatch), "PieceRotation", (Type[])null, (Type[])null)),
					new CodeInstruction(OpCodes.Stloc_S, operand)
				})
				.Instructions();
		}

		private static Quaternion PieceRotation(Player player, Quaternion rotation)
		{
			//IL_0054: 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_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			GameObject placementGhost = player.m_placementGhost;
			if (Object.op_Implicit((Object)(object)placementGhost) && Main.IsShipPiece(placementGhost))
			{
				Vector3 position = default(Vector3);
				Vector3 val = default(Vector3);
				Piece val2 = default(Piece);
				Heightmap val3 = default(Heightmap);
				Collider val4 = default(Collider);
				player.PieceRayTest(ref position, ref val, ref val2, ref val3, ref val4, false);
				ShipPart shipPart = ShipPart.FindNearest(position);
				if (Object.op_Implicit((Object)(object)shipPart))
				{
					return ((Component)shipPart.CustomShip).transform.rotation * rotation;
				}
				return rotation;
			}
			return rotation;
		}

		[HarmonyPatch(typeof(Player), "PieceRayTest")]
		[HarmonyTranspiler]
		public static IEnumerable<CodeInstruction> AllowShipRigidbodyTranspiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_012b: 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_015b: Expected O, but got Unknown
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Expected O, but got Unknown
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Expected O, but got Unknown
			MethodInfo methodInfo = AccessTools.PropertyGetter(typeof(RaycastHit), "collider");
			MethodInfo methodInfo2 = AccessTools.PropertyGetter(typeof(Collider), "attachedRigidbody");
			MethodInfo methodInfo3 = AccessTools.Method(typeof(Object), "op_Implicit", (Type[])null, (Type[])null);
			List<CodeInstruction> list = instructions.ToList();
			int num = -1;
			for (int i = 0; i < list.Count; i++)
			{
				if (list[i].opcode == OpCodes.Ldloca_S && CodeInstructionExtensions.Calls(list[i + 1], methodInfo) && CodeInstructionExtensions.Calls(list[i + 2], methodInfo2) && CodeInstructionExtensions.Calls(list[i + 3], methodInfo3))
				{
					num = i;
					break;
				}
				if (list[i].opcode == OpCodes.Ldloca_S && CodeInstructionExtensions.Calls(list[i + 1], methodInfo) && list[i + 2].IsCall("ValheimRAFT_Patch", "AttachRigidbodyMovableBase") && CodeInstructionExtensions.Calls(list[i + 3], methodInfo3))
				{
					num = i;
					break;
				}
			}
			if (num < 0)
			{
				throw new InvalidOperationException("Could not find rigidbody load");
			}
			object operand;
			return new CodeMatcher((IEnumerable<CodeInstruction>)list, (ILGenerator)null).Advance(num + 1).GetOperand(out operand).Advance(4)
				.InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[3]
				{
					new CodeInstruction(OpCodes.Ldloca_S, operand),
					new CodeInstruction(OpCodes.Call, (object)methodInfo),
					new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(PlacementPatch), "DenyPieceRay", (Type[])null, (Type[])null))
				})
				.Instructions();
		}

		private static bool DenyPieceRay(bool hasRigidbody, Collider hit)
		{
			if (!Main.IsShipPiece(Player.m_localPlayer.m_placementGhost))
			{
				return hasRigidbody;
			}
			Piece val = (Object.op_Implicit((Object)(object)hit) ? ((Component)hit).GetComponentInParent<Piece>() : null);
			if (Object.op_Implicit((Object)(object)val) && Main.IsShipPiece(((Component)val).gameObject))
			{
				return false;
			}
			return hasRigidbody;
		}
	}
}
namespace CustomShips.Helper
{
	public static class CodeMatcherExtensions
	{
		public static CodeMatcher GetPosition(this CodeMatcher codeMatcher, out int position)
		{
			position = codeMatcher.Pos;
			return codeMatcher;
		}

		public static CodeMatcher AddLabel(this CodeMatcher codeMatcher, out Label label)
		{
			label = default(Label);
			codeMatcher.AddLabels((IEnumerable<Label>)new Label[1] { label });
			return codeMatcher;
		}

		public static CodeMatcher GetOperand(this CodeMatcher codeMatcher, out object operand)
		{
			operand = codeMatcher.Operand;
			return codeMatcher;
		}

		public static bool IsCall(this CodeInstruction i, string declaringType, string name)
		{
			if ((i.opcode == OpCodes.Callvirt || i.opcode == OpCodes.Call) && i.operand is MethodInfo methodInfo && methodInfo.DeclaringType?.Name == declaringType)
			{
				return methodInfo.Name == name;
			}
			return false;
		}

		public static bool CallReturns(this CodeInstruction i, Type returnType)
		{
			if ((i.opcode == OpCodes.Callvirt || i.opcode == OpCodes.Call) && i.operand is MethodInfo methodInfo)
			{
				return methodInfo.ReturnType == returnType;
			}
			return false;
		}
	}
}