Decompiled source of FehuBarge v420.101.12

FehuBarge.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security.Cryptography;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("FehuBarge")]
[assembly: AssemblyProduct("FehuBarge")]
[assembly: AssemblyFileVersion("420.101.12.0")]
[assembly: AssemblyInformationalVersion("420.101.12")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("420.101.12.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace FehuBarge
{
	internal static class BargeAxisRewrite
	{
		internal static bool TryRewrite(IEnumerable<CodeInstruction> instructions, MethodInfo forward, MethodInfo right, MethodInfo forwardHelper, MethodInfo rightHelper, int expectedForward, int expectedRight, out List<CodeInstruction> output, out string reason)
		{
			List<CodeInstruction> source = (output = instructions.ToList());
			if (!Compatible(forward, forwardHelper) || !Compatible(right, rightHelper))
			{
				reason = "getter/helper stack signature differs";
				return false;
			}
			int num = source.Count((CodeInstruction i) => CodeInstructionExtensions.Calls(i, forward));
			int num2 = source.Count((CodeInstruction i) => CodeInstructionExtensions.Calls(i, right));
			if (num != expectedForward || num2 != expectedRight || source.Any((CodeInstruction i) => (object.Equals(i.operand, forward) || object.Equals(i.operand, right)) && i.opcode != OpCodes.Call && i.opcode != OpCodes.Callvirt))
			{
				reason = "getter contract mismatch (forward=" + num + ", right=" + num2 + ")";
				return false;
			}
			output = ((IEnumerable<CodeInstruction>)source).Select((Func<CodeInstruction, CodeInstruction>)((CodeInstruction i) => new CodeInstruction(i))).ToList();
			foreach (CodeInstruction item in output)
			{
				if (object.Equals(item.operand, forward))
				{
					item.opcode = OpCodes.Call;
					item.operand = forwardHelper;
				}
				else if (object.Equals(item.operand, right))
				{
					item.opcode = OpCodes.Call;
					item.operand = rightHelper;
				}
			}
			reason = "validated forward=" + num + " right=" + num2;
			return true;
		}

		private static bool Compatible(MethodInfo getter, MethodInfo helper)
		{
			if (getter == null || helper == null || getter.IsStatic || !helper.IsStatic || getter.GetParameters().Length != 0)
			{
				return false;
			}
			ParameterInfo[] parameters = helper.GetParameters();
			if (parameters.Length == 1 && parameters[0].ParameterType == getter.DeclaringType)
			{
				return getter.ReturnType == helper.ReturnType;
			}
			return false;
		}
	}
	internal static class BargeBeamMaterials
	{
		private static readonly Dictionary<Material, Material> MobileCopies = new Dictionary<Material, Material>();

		internal static Material MobileWood(Material source)
		{
			//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_0039: Expected O, but got Unknown
			if ((Object)(object)source == (Object)null)
			{
				return null;
			}
			if (MobileCopies.TryGetValue(source, out var value))
			{
				return value;
			}
			Material val = new Material(source)
			{
				name = "FehuBargeBeamMobile_" + ((Object)source).name
			};
			Configure(val);
			MobileCopies[source] = val;
			MobileCopies[val] = val;
			return val;
		}

		internal static void Configure(Material material)
		{
			Set(material, "_MoveableObject", 1f);
			Set(material, "_RippleDistance", 0f);
			Set(material, "_ValueNoise", 0f);
			Set(material, "_ValueNoiseVertex", 0f);
		}

		private static void Set(Material material, string property, float value)
		{
			if ((Object)(object)material != (Object)null && material.HasProperty(property))
			{
				material.SetFloat(property, value);
			}
		}
	}
	internal static class BargeBeamMeshes
	{
		private static readonly Dictionary<string, Mesh> Meshes = new Dictionary<string, Mesh>(StringComparer.Ordinal);

		private static Dictionary<string, HatchMeshData> data;

		internal static void Apply(Transform visual, string memberName)
		{
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Expected O, but got Unknown
			//IL_015b: 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_0202: Unknown result type (might be due to invalid IL or missing references)
			//IL_0258: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b9: Unknown result type (might be due to invalid IL or missing references)
			MeshFilter[] componentsInChildren = ((Component)visual).GetComponentsInChildren<MeshFilter>(true);
			if (componentsInChildren.Length != 1)
			{
				throw new InvalidDataException("Expected one native perimeter beam mesh: " + memberName);
			}
			if (!Meshes.TryGetValue(memberName, out var value))
			{
				if (data == null)
				{
					data = new Dictionary<string, HatchMeshData>(StringComparer.Ordinal);
					string[] array = new string[2] { "A", "B" };
					foreach (string text in array)
					{
						foreach (KeyValuePair<string, HatchMeshData> item in HatchVisualData.Read(typeof(BargeBeamMeshes).Assembly.GetManifestResourceStream("FehuBarge.BeamVisual" + text + ".bin") ?? throw new InvalidDataException("Missing prepared perimeter beam resource.")))
						{
							data.Add(item.Key, item.Value);
						}
					}
				}
				if (!data.TryGetValue(memberName, out var value2))
				{
					throw new InvalidDataException("Missing prepared perimeter beam: " + memberName);
				}
				value = new Mesh
				{
					name = "FehuStableBeam_" + memberName
				};
				List<Vector3> list = new List<Vector3>();
				float[][] positions = value2.Positions;
				foreach (float[] array2 in positions)
				{
					list.Add(new Vector3(array2[0], array2[1], array2[2]));
				}
				value.SetVertices(list);
				if (value2.Normals.Length != 0)
				{
					List<Vector3> list2 = new List<Vector3>();
					positions = value2.Normals;
					foreach (float[] array3 in positions)
					{
						list2.Add(new Vector3(array3[0], array3[1], array3[2]));
					}
					value.SetNormals(list2);
				}
				if (value2.Tangents.Length != 0)
				{
					List<Vector4> list3 = new List<Vector4>();
					positions = value2.Tangents;
					foreach (float[] array4 in positions)
					{
						list3.Add(new Vector4(array4[0], array4[1], array4[2], array4[3]));
					}
					value.SetTangents(list3);
				}
				if (value2.Colors.Length != 0)
				{
					List<Color> list4 = new List<Color>();
					positions = value2.Colors;
					foreach (float[] array5 in positions)
					{
						list4.Add(new Color(array5[0], array5[1], array5[2], array5[3]));
					}
					value.SetColors(list4);
				}
				for (int j = 0; j < 8; j++)
				{
					if (value2.UV[j].Length != 0)
					{
						List<Vector4> list5 = new List<Vector4>();
						positions = value2.UV[j];
						foreach (float[] array6 in positions)
						{
							list5.Add(new Vector4(array6[0], array6[1], array6[2], array6[3]));
						}
						value.SetUVs(j, list5);
					}
				}
				value.subMeshCount = value2.Submeshes.Length;
				for (int k = 0; k < value2.Submeshes.Length; k++)
				{
					value.SetTriangles(value2.Submeshes[k], k, false);
				}
				value.RecalculateBounds();
				Meshes.Add(memberName, value);
			}
			componentsInChildren[0].sharedMesh = value;
		}
	}
	[HarmonyPatch(typeof(Player), "AttachStart")]
	internal static class BargeHelmAttachPatch
	{
		private static void Prefix(Transform attachPoint, ref GameObject colliderRoot, bool onShip)
		{
			if (onShip && !((Object)(object)colliderRoot != (Object)null) && !((Object)(object)attachPoint == (Object)null) && !(((Object)attachPoint).name != "HelmAttachPoint"))
			{
				Ship componentInParent = ((Component)attachPoint).GetComponentInParent<Ship>();
				if (!((Object)(object)componentInParent == (Object)null) && ((Object)((Component)componentInParent).gameObject).name.StartsWith("FehuBarge") && !((Object)(object)((Component)componentInParent).transform.Find("Integration/HelmAttachPoint") != (Object)(object)attachPoint))
				{
					colliderRoot = ((Component)componentInParent).gameObject;
					Debug.Log((object)"[FehuBarge] Helm native attachment: ship collisions ignored until AttachStop; bow-facing seat unchanged");
				}
			}
		}
	}
	internal struct HoldVector
	{
		internal double X;

		internal double Y;

		internal double Z;

		internal double Length => Math.Sqrt(X * X + Y * Y + Z * Z);

		internal HoldVector(double x, double y, double z)
		{
			X = x;
			Y = y;
			Z = z;
		}

		public static HoldVector operator +(HoldVector a, HoldVector b)
		{
			return new HoldVector(a.X + b.X, a.Y + b.Y, a.Z + b.Z);
		}

		public static HoldVector operator -(HoldVector a, HoldVector b)
		{
			return new HoldVector(a.X - b.X, a.Y - b.Y, a.Z - b.Z);
		}

		public static HoldVector operator *(HoldVector a, double b)
		{
			return new HoldVector(a.X * b, a.Y * b, a.Z * b);
		}

		internal HoldVector Limited(double max)
		{
			if (!(Length > max))
			{
				return this;
			}
			return this * (max / Length);
		}
	}
	internal sealed class BargeHoldController
	{
		internal const double TransitionSeconds = 2.5;

		internal const double MaximumAcceleration = 0.65;

		internal const double MaximumJerk = 0.35;

		internal const double MaximumAngularAcceleration = 0.15;

		internal const double MaximumAngularJerk = 0.45;

		private double blend;

		internal HoldVector Acceleration { get; private set; }

		internal HoldVector AngularAcceleration { get; private set; }

		internal bool IsActive
		{
			get
			{
				if (!(blend > 0.0) && !(Acceleration.Length > 0.0))
				{
					return AngularAcceleration.Length > 0.0;
				}
				return true;
			}
		}

		internal void Reset()
		{
			blend = 0.0;
			Acceleration = default(HoldVector);
			AngularAcceleration = default(HoldVector);
		}

		internal void Step(double dt, bool enabled, HoldVector displacement, HoldVector velocity, HoldVector tiltError, HoldVector angularVelocity, double headingError)
		{
			if (!(dt <= 0.0) && !double.IsNaN(dt) && !double.IsInfinity(dt))
			{
				blend = Math.Max(0.0, Math.Min(1.0, blend + (double)(enabled ? 1 : (-1)) * dt / 2.5));
				double num = blend * blend * (3.0 - 2.0 * blend);
				HoldVector to = new HoldVector(-0.16 * displacement.X - 0.8 * velocity.X, 0.0, -0.16 * displacement.Z - 0.8 * velocity.Z).Limited(0.65) * num;
				HoldVector holdVector = new HoldVector(tiltError.X, 0.0, tiltError.Z).Limited(0.342);
				headingError = Math.Atan2(Math.Sin(headingError), Math.Cos(headingError));
				HoldVector to2 = new HoldVector(0.3 * holdVector.X - 1.1 * angularVelocity.X, 0.4 * headingError - 1.0 * angularVelocity.Y, 0.3 * holdVector.Z - 1.1 * angularVelocity.Z).Limited(0.15) * num;
				Acceleration = MoveTowards(Acceleration, to, 0.35 * dt);
				AngularAcceleration = MoveTowards(AngularAcceleration, to2, 0.45 * dt);
			}
		}

		private static HoldVector MoveTowards(HoldVector from, HoldVector to, double step)
		{
			HoldVector holdVector = to - from;
			if (!(holdVector.Length <= step))
			{
				return from + holdVector.Limited(step);
			}
			return to;
		}
	}
	[HarmonyPatch(typeof(Ship), "CustomFixedUpdate")]
	internal static class BargeHoldWaterUpdatePatch
	{
		[HarmonyAfter(new string[] { "com.custom.shipbuildmod" })]
		[HarmonyPriority(0)]
		private static void Postfix(Ship __instance, float fixedDeltaTime)
		{
			((Component)__instance).GetComponent<FehuBargeHold>()?.ApplyForces(fixedDeltaTime);
		}
	}
	[HarmonyPatch(typeof(Ship), "UpdateControlls")]
	internal static class BargeHoldNativeControlsPatch
	{
		private static void Prefix(Ship __instance, ref Speed ___m_speed, ref float ___m_rudderValue, ref float ___m_rudder, ref bool ___m_forwardPressed, ref bool ___m_backwardPressed)
		{
			FehuBargeHold component = ((Component)__instance).GetComponent<FehuBargeHold>();
			if (!((Object)(object)component == (Object)null) && component.BlocksControls)
			{
				___m_speed = (Speed)0;
				___m_rudderValue = 0f;
				___m_rudder = 0f;
				___m_forwardPressed = false;
				___m_backwardPressed = false;
			}
		}
	}
	[HarmonyPatch(typeof(Ship), "ApplyControlls")]
	internal static class BargeHoldInputPatch
	{
		private static bool Prefix(Ship __instance)
		{
			FehuBargeHold component = ((Component)__instance).GetComponent<FehuBargeHold>();
			if (!((Object)(object)component == (Object)null))
			{
				return !component.BlocksControls;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(ShipControlls), "Interact")]
	internal static class BargeHoldHelmInteractionPatch
	{
		private static bool Prefix(ShipControlls __instance, Humanoid character, bool repeat, bool alt, ref bool __result)
		{
			FehuBargeHold fehuBargeHold = (((Object)(object)__instance.m_ship != (Object)null) ? ((Component)__instance.m_ship).GetComponent<FehuBargeHold>() : null);
			if ((Object)(object)fehuBargeHold == (Object)null || !FehuBargeHold.ToggleModifier || alt)
			{
				return true;
			}
			__result = !repeat && fehuBargeHold.RequestToggle((Player)(object)((character is Player) ? character : null));
			return false;
		}
	}
	[HarmonyPatch(typeof(ShipControlls), "GetHoverText")]
	internal static class BargeHoldHelmPromptPatch
	{
		private static void Postfix(ShipControlls __instance, ref string __result)
		{
			FehuBargeHold fehuBargeHold = (((Object)(object)__instance.m_ship != (Object)null) ? ((Component)__instance.m_ship).GetComponent<FehuBargeHold>() : null);
			if ((Object)(object)fehuBargeHold != (Object)null)
			{
				__result += Localization.instance.Localize(fehuBargeHold.Prompt);
			}
		}
	}
	[HarmonyPatch(typeof(Ship), "UpdateControlls")]
	internal static class BargeMotorFuelGate
	{
		[HarmonyPriority(0)]
		private static void Prefix(Ship __instance, float dt, ref Speed ___m_speed, ref float ___m_backwardForce, ref float ___m_stearForce)
		{
			if (!((Object)(object)((Component)__instance).GetComponent<FehuBargeBuildSurface>() == (Object)null))
			{
				FehuBargeMotor componentInChildren = ((Component)__instance).GetComponentInChildren<FehuBargeMotor>(true);
				if ((Object)(object)componentInChildren == (Object)null)
				{
					___m_speed = (Speed)0;
				}
				else
				{
					componentInChildren.PrepareFuel(dt, ref ___m_speed, ref ___m_backwardForce, ref ___m_stearForce);
				}
			}
		}
	}
	[HarmonyPatch(typeof(Ship), "CustomFixedUpdate")]
	internal static class BargeMotorFuelStep
	{
		[HarmonyPriority(0)]
		[HarmonyAfter(new string[] { "com.custom.shipbuildmod" })]
		private static void Postfix(Ship __instance, float fixedDeltaTime, ref float ___m_backwardForce, ref float ___m_stearForce)
		{
			FehuBargeMotor componentInChildren = ((Component)__instance).GetComponentInChildren<FehuBargeMotor>(true);
			if (!((Object)(object)componentInChildren == (Object)null))
			{
				componentInChildren.RestoreNativeFuelForces(ref ___m_backwardForce, ref ___m_stearForce);
				componentInChildren.ApplyMotorForces(fixedDeltaTime);
			}
		}

		private static void Finalizer(Ship __instance, ref float ___m_backwardForce, ref float ___m_stearForce)
		{
			((Component)__instance).GetComponentInChildren<FehuBargeMotor>(true)?.RestoreNativeFuelForces(ref ___m_backwardForce, ref ___m_stearForce);
		}
	}
	internal static class BargeOpenDeckVariant
	{
		internal const float HullRimTop = 1.975f;

		internal static void Install(GameObject barge)
		{
			Transform obj = barge.transform.Find("Visual");
			if ((Object)(object)obj == (Object)null)
			{
				throw new InvalidDataException("Open-deck visual root is missing.");
			}
			int num = 0;
			MeshFilter[] componentsInChildren = ((Component)obj).GetComponentsInChildren<MeshFilter>(true);
			foreach (MeshFilter val in componentsInChildren)
			{
				if ((Object)(object)val.sharedMesh != (Object)null && ((Object)val.sharedMesh).name == "DoubleSidedMesh_0_DeckHatch")
				{
					val.sharedMesh = HatchMeshCut.PreparedMesh("DoubleSidedMesh_0", openDeck: true);
					num++;
				}
			}
			if (num != 1)
			{
				throw new InvalidDataException("Expected one cleaned main mesh, found " + num);
			}
			Debug.Log((object)"[FehuBarge] Open deck inherits clean perimeter, 26 native beams and 52 endpoint snaps.");
		}

		internal static void TrimRailingColliders(GameObject barge)
		{
			//IL_0079: 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_0092: 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_00d9: 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_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			string[] array = new string[4] { "PortCollider", "StarboardCollider", "BowWall", "SternWall" };
			foreach (string text in array)
			{
				Transform val = barge.transform.Find("Physics/" + text);
				BoxCollider val2 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<BoxCollider>() : null);
				if ((Object)(object)val2 == (Object)null)
				{
					throw new InvalidDataException("Boundary collider missing: " + text);
				}
				float num = val.localPosition.y + val2.center.y - val2.size.y * 0.5f;
				if (num >= 1.975f)
				{
					throw new InvalidDataException("Unexpected hull-rim geometry: " + text);
				}
				Vector3 size = val2.size;
				size.y = 1.975f - num;
				val2.size = size;
				Vector3 center = val2.center;
				center.y = (num + 1.975f) * 0.5f - val.localPosition.y;
				val2.center = center;
			}
		}
	}
	[HarmonyPatch(typeof(Ship), "CustomFixedUpdate")]
	internal static class BargeSpawnBodyPatch
	{
		[HarmonyPriority(0)]
		[HarmonyAfter(new string[] { "com.custom.shipbuildmod" })]
		private static void Prefix(Ship __instance)
		{
			((Component)__instance).GetComponent<FehuBargeRailings>()?.InitializeBodyInertia();
		}

		private static void Postfix(Ship __instance, float fixedDeltaTime)
		{
			((Component)__instance).GetComponent<FehuBargeRailings>()?.SampleSpawnMotion(fixedDeltaTime);
		}
	}
	[HarmonyPatch]
	internal static class BargeRailingSupportPatch
	{
		private static MethodBase TargetMethod()
		{
			return AccessTools.Method(Type.GetType("ShipBuildingMod.WearNTearHelper, BuildOnShip"), "IsDirectlyOnShip", (Type[])null, (Type[])null);
		}

		private static bool Prepare()
		{
			return TargetMethod() != null;
		}

		private static void Postfix(WearNTear wnt, object container, ref bool __result)
		{
			if (__result)
			{
				return;
			}
			Component val = (Component)((container is Component) ? container : null);
			if (val != null)
			{
				FehuBargeRailings component = val.GetComponent<FehuBargeRailings>();
				if ((Object)(object)component != (Object)null && component.TouchesRailing(wnt))
				{
					__result = true;
				}
			}
		}
	}
	[HarmonyPatch]
	internal static class BargeRailingGridPatch
	{
		private static MethodBase TargetMethod()
		{
			return AccessTools.Method(Type.GetType("ShipBuildingMod.ShipPiecesContainer, BuildOnShip"), "CreateDeckSnapPoints", (Type[])null, (Type[])null);
		}

		private static bool Prepare()
		{
			return TargetMethod() != null;
		}

		private static void Postfix(Component __instance)
		{
			__instance.GetComponent<FehuBargeRailings>()?.AppendToBuildOnShip(__instance);
		}
	}
	[HarmonyPatch]
	internal static class BargeRailingSupportCachePatch
	{
		private static readonly FieldRef<WearNTear, float> Support = AccessTools.FieldRefAccess<WearNTear, float>("m_support");

		private static MethodBase TargetMethod()
		{
			return AccessTools.Method(Type.GetType("ShipBuildingMod.WearNTearHelper, BuildOnShip"), "SetSupport", (Type[])null, (Type[])null);
		}

		private static bool Prepare()
		{
			return TargetMethod() != null;
		}

		private static void Postfix(WearNTear wnt, float support)
		{
			if ((Object)(object)wnt == (Object)null || (Object)(object)((Component)wnt).GetComponent<Ship>() != (Object)null)
			{
				return;
			}
			Ship componentInParent = ((Component)wnt).GetComponentInParent<Ship>();
			if (!((Object)(object)componentInParent == (Object)null) && !((Object)(object)((Component)componentInParent).GetComponent<FehuBargeRailings>() == (Object)null))
			{
				ZNetView component = ((Component)wnt).GetComponent<ZNetView>();
				if (!((Object)(object)component == (Object)null) && component.IsValid() && component.IsOwner())
				{
					Support.Invoke(wnt) = support;
				}
			}
		}
	}
	[HarmonyPatch(typeof(Piece), "GetSnapPoints", new Type[] { typeof(List<Transform>) })]
	internal static class BargeRailingNativePointsPatch
	{
		private static bool Prefix(Piece __instance, List<Transform> points)
		{
			if ((Object)(object)((Component)__instance).GetComponent<FehuBargeRailings>() == (Object)null)
			{
				return true;
			}
			for (int i = 0; i < ((Component)__instance).transform.childCount; i++)
			{
				Transform child = ((Component)__instance).transform.GetChild(i);
				if (((Component)child).CompareTag("snappoint"))
				{
					return !points.Contains(child);
				}
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(Piece), "GetSnapPoints", new Type[]
	{
		typeof(Vector3),
		typeof(float),
		typeof(List<Transform>),
		typeof(List<Piece>)
	})]
	internal static class BargeRailingDuplicatePointsPatch
	{
		[HarmonyPriority(0)]
		[HarmonyAfter(new string[] { "com.custom.shipbuildmod" })]
		private static void Postfix(List<Transform> points, List<Piece> pieces)
		{
			HashSet<Transform> hashSet = new HashSet<Transform>();
			int num = 0;
			for (int i = 0; i < points.Count; i++)
			{
				Transform val = points[i];
				if (!((Object)(object)val != (Object)null) || !((Object)val).name.StartsWith("FehuRailSnap_", StringComparison.Ordinal) || !((Object)(object)val.parent != (Object)null) || !((Object)(object)((Component)val.parent).GetComponent<FehuBargeRailings>() != (Object)null) || hashSet.Add(val))
				{
					points[num++] = val;
				}
			}
			if (num < points.Count)
			{
				points.RemoveRange(num, points.Count - num);
			}
			HashSet<Piece> hashSet2 = new HashSet<Piece>();
			num = 0;
			for (int j = 0; j < pieces.Count; j++)
			{
				Piece val2 = pieces[j];
				if (!((Object)(object)val2 != (Object)null) || !((Object)(object)((Component)val2).GetComponent<FehuBargeRailings>() != (Object)null) || hashSet2.Add(val2))
				{
					pieces[num++] = val2;
				}
			}
			if (num < pieces.Count)
			{
				pieces.RemoveRange(num, pieces.Count - num);
			}
		}
	}
	[HarmonyPatch]
	internal static class BargeShipAxesPatch
	{
		private static readonly Dictionary<string, int[]> Expected = new Dictionary<string, int[]>
		{
			{
				"CustomFixedUpdate",
				new int[2] { 3, 4 }
			},
			{
				"GetSailForce",
				new int[2] { 1, 0 }
			},
			{
				"GetWindAngleFactor",
				new int[2] { 1, 0 }
			},
			{
				"FixTilt",
				new int[2] { 3, 3 }
			},
			{
				"UpdateSail",
				new int[2] { 3, 0 }
			},
			{
				"GetSpeed",
				new int[2] { 1, 0 }
			},
			{
				"GetShipYawAngle",
				new int[2] { 1, 0 }
			},
			{
				"OnDrawGizmosSelected",
				new int[2] { 1, 0 }
			}
		};

		private static bool Prepare()
		{
			foreach (string key in Expected.Keys)
			{
				MethodInfo methodInfo = AccessTools.Method(typeof(Ship), key, (Type[])null, (Type[])null);
				ParameterInfo[] array = methodInfo?.GetParameters();
				int num;
				switch (key)
				{
				default:
					num = 0;
					break;
				case "CustomFixedUpdate":
				case "UpdateSail":
					num = 1;
					break;
				case "GetSailForce":
					num = 2;
					break;
				}
				int num2 = num;
				Type? typeFromHandle;
				switch (key)
				{
				default:
					typeFromHandle = typeof(void);
					break;
				case "GetWindAngleFactor":
				case "GetSpeed":
				case "GetShipYawAngle":
					typeFromHandle = typeof(float);
					break;
				case "GetSailForce":
					typeFromHandle = typeof(Vector3);
					break;
				}
				Type type = typeFromHandle;
				if (methodInfo == null || methodInfo.IsStatic || methodInfo.ReturnType != type || array.Length != num2 || array.Any((ParameterInfo p) => p.ParameterType != typeof(float)))
				{
					Debug.LogWarning((object)("[FehuBarge] Ship axis patches skipped: native signature contract differs at " + key));
					return false;
				}
			}
			return true;
		}

		private static IEnumerable<MethodBase> TargetMethods()
		{
			return ((IEnumerable<string>)Expected.Keys).Select((Func<string, MethodBase>)((string name) => AccessTools.Method(typeof(Ship), name, (Type[])null, (Type[])null)));
		}

		[HarmonyPriority(0)]
		[HarmonyAfter(new string[] { "com.custom.shipbuildmod" })]
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase original)
		{
			MethodInfo forward = AccessTools.PropertyGetter(typeof(Transform), "forward");
			MethodInfo right = AccessTools.PropertyGetter(typeof(Transform), "right");
			MethodInfo forwardHelper = AccessTools.Method(typeof(BargeShipAxesPatch), "Forward", (Type[])null, (Type[])null);
			MethodInfo rightHelper = AccessTools.Method(typeof(BargeShipAxesPatch), "Right", (Type[])null, (Type[])null);
			if (!Expected.TryGetValue(original.Name, out var value))
			{
				return instructions;
			}
			if (!BargeAxisRewrite.TryRewrite(instructions, forward, right, forwardHelper, rightHelper, value[0], value[1], out var output, out var reason))
			{
				Debug.LogWarning((object)("[FehuBarge] Ship axis patch skipped entirely for " + original.Name + ": " + reason + ". Original IL retained."));
				return output;
			}
			Debug.Log((object)("[FehuBarge] Native Ship axis patch " + original.Name + ": " + reason));
			return output;
		}

		internal static void LogPatchOwners()
		{
			foreach (string key in Expected.Keys)
			{
				MethodInfo methodInfo = AccessTools.Method(typeof(Ship), key, (Type[])null, (Type[])null);
				Patches val = ((methodInfo == null) ? null : Harmony.GetPatchInfo((MethodBase)methodInfo));
				if (val != null)
				{
					Debug.Log((object)("[FehuBarge] Ship patch owners " + key + ": " + string.Join(", ", val.Owners)));
				}
			}
		}

		internal static Vector3 Forward(Transform point)
		{
			//IL_001f: 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)
			Ship componentInParent = ((Component)point).GetComponentInParent<Ship>();
			if (!((Object)(object)componentInParent != (Object)null) || !((Object)(object)((Component)componentInParent).GetComponent<FehuBargeBuildSurface>() != (Object)null))
			{
				return point.forward;
			}
			return ((Component)componentInParent).transform.right;
		}

		internal static Vector3 Right(Transform point)
		{
			//IL_001f: 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_0030: Unknown result type (might be due to invalid IL or missing references)
			Ship componentInParent = ((Component)point).GetComponentInParent<Ship>();
			if (!((Object)(object)componentInParent != (Object)null) || !((Object)(object)((Component)componentInParent).GetComponent<FehuBargeBuildSurface>() != (Object)null))
			{
				return point.right;
			}
			return -((Component)componentInParent).transform.forward;
		}
	}
	[HarmonyPatch(typeof(Ship), "GetSailForce")]
	internal static class BargeWindPatch
	{
		private static bool Prefix(Ship __instance, ref Vector3 __result, ref Vector3 ___m_sailForce, ref Vector3 ___m_windChangeVelocity)
		{
			//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_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_002c: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)((Component)__instance).GetComponent<FehuBargeBuildSurface>() == (Object)null)
			{
				return true;
			}
			___m_sailForce = Vector3.zero;
			___m_windChangeVelocity = Vector3.zero;
			__result = Vector3.zero;
			return false;
		}
	}
	[HarmonyPatch(typeof(Ship), "UpdateSailSize")]
	internal static class BargeSailVisualPatch
	{
		private static bool Prefix(Ship __instance)
		{
			return (Object)(object)((Component)__instance).GetComponent<FehuBargeBuildSurface>() == (Object)null;
		}
	}
	[HarmonyPatch(typeof(ShipEffects), "FadeSound")]
	internal static class BargeInactiveAudioPatch
	{
		private static bool Prefix(AudioSource source)
		{
			if ((Object)(object)source == (Object)null || (Object)(object)((Component)source).GetComponentInParent<FehuBargeBuildSurface>() == (Object)null)
			{
				return true;
			}
			if (((Behaviour)source).enabled)
			{
				return ((Component)source).gameObject.activeInHierarchy;
			}
			return false;
		}
	}
	internal static class BlackResinIcon
	{
		internal static Sprite Create(Sprite original)
		{
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Expected O, but got Unknown
			//IL_0083: 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_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0288: Unknown result type (might be due to invalid IL or missing references)
			//IL_028d: 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: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a8: Expected O, but got Unknown
			//IL_02cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ef: 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_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: 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_020d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0212: 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_021b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0222: Unknown result type (might be due to invalid IL or missing references)
			//IL_0240: Unknown result type (might be due to invalid IL or missing references)
			//IL_0247: Unknown result type (might be due to invalid IL or missing references)
			//IL_024c: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)original == (Object)null || (Object)(object)original.texture == (Object)null)
			{
				throw new InvalidOperationException("Resin icon texture is unavailable.");
			}
			Texture2D texture = original.texture;
			RenderTexture active = RenderTexture.active;
			RenderTexture temporary = RenderTexture.GetTemporary(((Texture)texture).width, ((Texture)texture).height, 0, (RenderTextureFormat)0, (RenderTextureReadWrite)2);
			Texture2D val = null;
			Texture2D val2 = null;
			try
			{
				Graphics.Blit((Texture)(object)texture, temporary);
				RenderTexture.active = temporary;
				val = new Texture2D(((Texture)texture).width, ((Texture)texture).height, (TextureFormat)4, false);
				val.ReadPixels(new Rect(0f, 0f, (float)((Texture)texture).width, (float)((Texture)texture).height), 0, 0);
				val.Apply(false, false);
				Rect rect = original.rect;
				int num = Mathf.RoundToInt(((Rect)(ref rect)).width);
				rect = original.rect;
				int num2 = Mathf.RoundToInt(((Rect)(ref rect)).height);
				Color[] array = (Color[])(object)new Color[num * num2];
				Vector2[] vertices = original.vertices;
				Vector2[] uv = original.uv;
				ushort[] triangles = original.triangles;
				for (int i = 0; i < num2; i++)
				{
					for (int j = 0; j < num; j++)
					{
						Vector2 val3 = (new Vector2((float)j + 0.5f, (float)i + 0.5f) - original.pivot) / original.pixelsPerUnit;
						for (int k = 0; k < triangles.Length; k += 3)
						{
							ushort num3 = triangles[k];
							ushort num4 = triangles[k + 1];
							ushort num5 = triangles[k + 2];
							if (BlackResinVisualMath.TryUv(val3.x, val3.y, vertices[num3].x, vertices[num3].y, vertices[num4].x, vertices[num4].y, vertices[num5].x, vertices[num5].y, uv[num3].x, uv[num3].y, uv[num4].x, uv[num4].y, uv[num5].x, uv[num5].y, out var u, out var v))
							{
								Color pixelBilinear = val.GetPixelBilinear(u, v);
								float num6 = BlackResinVisualMath.Charcoal(pixelBilinear.r, pixelBilinear.g, pixelBilinear.b);
								array[i * num + j] = new Color(num6, num6, num6, pixelBilinear.a);
								break;
							}
						}
					}
				}
				val2 = new Texture2D(num, num2, (TextureFormat)4, false)
				{
					name = "FehuBlackResinIconTexture",
					filterMode = (FilterMode)1,
					wrapMode = (TextureWrapMode)1
				};
				val2.SetPixels(array);
				val2.Apply(false, true);
				Sprite obj = Sprite.Create(val2, new Rect(0f, 0f, (float)num, (float)num2), new Vector2(original.pivot.x / (float)num, original.pivot.y / (float)num2), original.pixelsPerUnit, 0u, (SpriteMeshType)0);
				((Object)obj).name = "FehuBlackResinIcon";
				return obj;
			}
			catch
			{
				if ((Object)(object)val2 != (Object)null)
				{
					Object.Destroy((Object)(object)val2);
				}
				throw;
			}
			finally
			{
				RenderTexture.active = active;
				RenderTexture.ReleaseTemporary(temporary);
				if ((Object)(object)val != (Object)null)
				{
					Object.Destroy((Object)(object)val);
				}
			}
		}
	}
	internal static class BlackResinVisualMath
	{
		internal static float Charcoal(float r, float g, float b)
		{
			return 0.025f + 0.16f * Math.Max(0f, Math.Min(1f, 0.2126f * r + 0.7152f * g + 0.0722f * b));
		}

		internal static bool TryUv(float x, float y, float ax, float ay, float bx, float by, float cx, float cy, float au, float av, float bu, float bv, float cu, float cv, out float u, out float v)
		{
			u = (v = 0f);
			float num = (by - cy) * (ax - cx) + (cx - bx) * (ay - cy);
			if (Math.Abs(num) < 1E-12f)
			{
				return false;
			}
			float num2 = ((by - cy) * (x - cx) + (cx - bx) * (y - cy)) / num;
			float num3 = ((cy - ay) * (x - cx) + (ax - cx) * (y - cy)) / num;
			float num4 = 1f - num2 - num3;
			if (num2 < -1E-05f || num3 < -1E-05f || num4 < -1E-05f)
			{
				return false;
			}
			u = num2 * au + num3 * bu + num4 * cu;
			v = num2 * av + num3 * bv + num4 * cv;
			return true;
		}
	}
	internal static class DriverSeatLayout
	{
		internal const float DeckY = 1.86f;

		internal const float X = -8.1f;

		internal const float BarrelZ = 0.83f;

		internal const float BarrelDiameter = 0.46f;

		internal const float BarrelHeight = 0.62f;

		internal const float BoardThickness = 0.08f;

		internal const float BoardDepth = 0.48f;

		internal const float BoardWidth = 2.12f;

		internal const float AttachY = 1.96f;
	}
	public sealed class FehuBargeBuildSurface : MonoBehaviour
	{
		[SerializeField]
		private bool _enabled;

		[SerializeField]
		private float _deckY;

		internal float DeckY => _deckY;

		public void Configure(bool enabled, float deckY)
		{
			_enabled = enabled;
			_deckY = deckY;
		}

		private IEnumerator Start()
		{
			if (!_enabled)
			{
				yield break;
			}
			if ((Object)(object)((Component)this).transform.Find("Integration/BuildRoot") == (Object)null)
			{
				Debug.LogError((object)"[FehuBarge] Building integration unavailable: Integration/BuildRoot is missing.");
				yield break;
			}
			Type containerType = Type.GetType("ShipBuildingMod.ShipPiecesContainer, BuildOnShip");
			if (containerType == null)
			{
				Debug.Log((object)"[FehuBarge] BuildOnShip detected: false");
				yield break;
			}
			Debug.Log((object)"[FehuBarge] BuildOnShip detected: true");
			yield return null;
			Component val = ((Component)this).GetComponent(containerType) ?? ((Component)this).gameObject.AddComponent(containerType);
			ConfigureBuildOnShipSnapGrid(containerType, val);
			containerType.GetMethod("CreateDeckSnapPoints")?.Invoke(val, null);
			containerType.GetField("DeckY")?.SetValue(val, _deckY);
			Debug.Log((object)"[FehuBarge] BuildOnShip deck integration active.");
		}

		private void ConfigureBuildOnShipSnapGrid(Type containerType, Component container)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Expected O, but got Unknown
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			Transform val = ((Component)this).transform.Find("_DeckSnapGrid");
			if ((Object)(object)val == (Object)null)
			{
				GameObject val2 = new GameObject("_DeckSnapGrid");
				val2.transform.SetParent(((Component)this).transform, false);
				val = val2.transform;
			}
			for (int num = val.childCount - 1; num >= 0; num--)
			{
				Transform child = val.GetChild(num);
				child.SetParent((Transform)null, false);
				Object.Destroy((Object)(object)((Component)child).gameObject);
			}
			IList list = containerType.GetField("DeckSnapPoints")?.GetValue(container) as IList;
			list?.Clear();
			for (float num2 = -8f; num2 <= 8f; num2 += 1f)
			{
				for (float num3 = -3f; num3 <= 3f; num3 += 1f)
				{
					if (!HatchGeometry.InOpening(num2, num3))
					{
						GameObject val3 = new GameObject("snappoint");
						val3.transform.SetParent(val, false);
						val3.transform.localPosition = new Vector3(num2, _deckY, num3);
						try
						{
							val3.tag = "snappoint";
						}
						catch (UnityException)
						{
						}
						list?.Add(val3.transform);
					}
				}
			}
		}
	}
	internal static class FehuBargeDriverSeat
	{
		internal static void Install(GameObject barge)
		{
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Expected O, but got Unknown
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_020d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Expected O, but got Unknown
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: 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_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_0268: Unknown result type (might be due to invalid IL or missing references)
			//IL_026d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0278: Unknown result type (might be due to invalid IL or missing references)
			//IL_0288: Unknown result type (might be due to invalid IL or missing references)
			//IL_0294: Expected O, but got Unknown
			//IL_02dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_030b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0332: Unknown result type (might be due to invalid IL or missing references)
			//IL_034b: Unknown result type (might be due to invalid IL or missing references)
			Transform val = barge.transform.Find("Integration");
			GameObject prefab = PrefabManager.Instance.GetPrefab("barrell");
			if ((Object)(object)val == (Object)null || (Object)(object)prefab == (Object)null)
			{
				throw new InvalidOperationException("Native barrell prefab or barge Integration root is missing.");
			}
			Container componentInChildren = barge.GetComponentInChildren<Container>(true);
			if ((Object)(object)componentInChildren == (Object)null || barge.GetComponentsInChildren<Container>(true).Length != 1)
			{
				throw new InvalidOperationException("Driver station requires exactly one existing native cargo Container.");
			}
			GameObject val2 = new GameObject("OperatorSeat");
			val2.layer = LayerMask.NameToLayer("piece");
			val2.transform.SetParent(val, false);
			((Component)componentInChildren).transform.SetParent(val2.transform, false);
			((Component)componentInChildren).transform.localPosition = new Vector3(-8.1f, 2.17f, 0f);
			componentInChildren.m_name = "Barrel Storage";
			for (int i = -1; i <= 1; i += 2)
			{
				GameObject val3 = new GameObject((i < 0) ? "PortStorageBarrel" : "StarboardStorageBarrel");
				val3.layer = val2.layer;
				val3.transform.SetParent(val2.transform, false);
				val3.transform.localPosition = new Vector3(-8.1f, 1.86f, (float)i * 0.83f);
				FitVisual(CopyVisual(prefab.transform, val3.transform, root: true), new Vector3(0.46f, 0.62f, 0.46f));
				BoxCollider obj = val3.AddComponent<BoxCollider>();
				obj.center = Vector3.up * 0.31f;
				obj.size = new Vector3(0.46f, 0.62f, 0.46f);
				val3.AddComponent<FehuBargeBarrelHandle>().Configure(componentInChildren);
			}
			GameObject obj2 = GameObject.CreatePrimitive((PrimitiveType)3);
			((Object)obj2).name = "WoodenSeatBoard";
			obj2.layer = val2.layer;
			obj2.transform.SetParent(val2.transform, false);
			obj2.transform.localPosition = new Vector3(-8.1f, 2.52f, 0f);
			obj2.transform.localScale = new Vector3(0.48f, 0.08f, 2.12f);
			Object.DestroyImmediate((Object)(object)obj2.GetComponent<Collider>());
			GameObject prefab2 = PrefabManager.Instance.GetPrefab("wood_floor");
			object obj3;
			if (!((Object)(object)prefab2 != (Object)null))
			{
				obj3 = null;
			}
			else
			{
				MeshRenderer componentInChildren2 = prefab2.GetComponentInChildren<MeshRenderer>(true);
				obj3 = ((componentInChildren2 != null) ? ((Renderer)componentInChildren2).sharedMaterial : null);
			}
			if ((Object)obj3 == (Object)null)
			{
				throw new InvalidOperationException("Native wooden seat material is missing.");
			}
			Material sharedMaterial = new Material((Material)obj3)
			{
				name = "FehuBargeBrownSeatWood",
				color = new Color(0.75f, 0.55f, 0.35f)
			};
			((Renderer)obj2.GetComponent<MeshRenderer>()).sharedMaterial = sharedMaterial;
			MeshFilter component = obj2.GetComponent<MeshFilter>();
			Mesh val4 = Object.Instantiate<Mesh>(component.sharedMesh);
			Color[] array = (Color[])(object)new Color[val4.vertexCount];
			for (int j = 0; j < array.Length; j++)
			{
				array[j] = new Color(0.5568628f, 0.40392157f, 22f / 85f);
			}
			val4.colors = array;
			component.sharedMesh = val4;
			Transform transform = new GameObject("AttachReference").transform;
			transform.SetParent(val2.transform, false);
			transform.localPosition = new Vector3(-8.1f, 1.96f, 0f);
			transform.localRotation = Quaternion.Euler(0f, 90f, 0f);
			Transform val5 = val.Find("HelmAttachPoint");
			if ((Object)(object)val5 == (Object)null)
			{
				throw new InvalidOperationException("Native helm attach point is missing.");
			}
			PositionHelm(barge.GetComponent<Ship>(), val5);
			if (val2.GetComponentsInChildren<Rigidbody>(true).Length != 0 || val2.GetComponentsInChildren<ZNetView>(true).Length != 0)
			{
				throw new InvalidOperationException("Driver barrels must be visual/interaction children of the existing ship network body.");
			}
			Debug.Log((object)("[FehuBarge] Driver support installed: 2 native wooden barrell visuals, fixed wooden board, one retained " + componentInChildren.m_width + "x" + componentInChildren.m_height + " cargo/fuel inventory; no additional Rigidbody, ZNetView, Container or save keys."));
		}

		internal static void PositionHelm(Ship ship, Transform helm)
		{
			//IL_0033: 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_0054: Unknown result type (might be due to invalid IL or missing references)
			Transform val = (((Object)(object)ship != (Object)null) ? ((Component)ship).transform.Find("Integration/OperatorSeat/AttachReference") : null);
			if ((Object)(object)val == (Object)null)
			{
				throw new InvalidOperationException("Prepared operator seat reference is missing.");
			}
			helm.position = val.position;
			helm.rotation = Quaternion.LookRotation(BargeShipAxesPatch.Forward(((Component)ship).transform), ((Component)ship).transform.up);
		}

		internal static Transform CopyVisual(Transform source, Transform parent, bool root)
		{
			//IL_0006: 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_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: 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_0067: 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_00d6: Unknown result type (might be due to invalid IL or missing references)
			Transform transform = new GameObject(((Object)source).name).transform;
			((Component)transform).gameObject.layer = ((Component)parent).gameObject.layer;
			transform.SetParent(parent, false);
			transform.localPosition = (root ? Vector3.zero : source.localPosition);
			transform.localRotation = (root ? Quaternion.identity : source.localRotation);
			transform.localScale = (root ? Vector3.one : source.localScale);
			MeshFilter component = ((Component)source).GetComponent<MeshFilter>();
			MeshRenderer component2 = ((Component)source).GetComponent<MeshRenderer>();
			if ((Object)(object)component != (Object)null && (Object)(object)component.sharedMesh != (Object)null && (Object)(object)component2 != (Object)null && ((Renderer)component2).enabled)
			{
				((Component)transform).gameObject.AddComponent<MeshFilter>().sharedMesh = component.sharedMesh;
				MeshRenderer obj = ((Component)transform).gameObject.AddComponent<MeshRenderer>();
				((Renderer)obj).sharedMaterials = ((Renderer)component2).sharedMaterials;
				((Renderer)obj).shadowCastingMode = ((Renderer)component2).shadowCastingMode;
				((Renderer)obj).receiveShadows = ((Renderer)component2).receiveShadows;
			}
			for (int i = 0; i < source.childCount; i++)
			{
				if (((Component)source.GetChild(i)).gameObject.activeSelf)
				{
					CopyVisual(source.GetChild(i), transform, root: false);
				}
			}
			return transform;
		}

		private static void FitVisual(Transform visual, Vector3 size)
		{
			//IL_0004: 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_002c: 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_003b: 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_0045: 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_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: 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_0130: 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_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: 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_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: 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_0061: 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_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: 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_008a: 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)
			bool flag = false;
			Bounds val = default(Bounds);
			MeshFilter[] componentsInChildren = ((Component)visual).GetComponentsInChildren<MeshFilter>(true);
			foreach (MeshFilter val2 in componentsInChildren)
			{
				Bounds bounds = val2.sharedMesh.bounds;
				Matrix4x4 val3 = visual.worldToLocalMatrix * ((Component)val2).transform.localToWorldMatrix;
				for (int j = -1; j <= 1; j += 2)
				{
					for (int k = -1; k <= 1; k += 2)
					{
						for (int l = -1; l <= 1; l += 2)
						{
							Vector3 val4 = ((Matrix4x4)(ref val3)).MultiplyPoint3x4(((Bounds)(ref bounds)).center + Vector3.Scale(((Bounds)(ref bounds)).extents, new Vector3((float)j, (float)k, (float)l)));
							if (!flag)
							{
								((Bounds)(ref val))..ctor(val4, Vector3.zero);
								flag = true;
							}
							else
							{
								((Bounds)(ref val)).Encapsulate(val4);
							}
						}
					}
				}
			}
			if (!flag || ((Bounds)(ref val)).size.x <= 0f || ((Bounds)(ref val)).size.y <= 0f || ((Bounds)(ref val)).size.z <= 0f)
			{
				throw new InvalidOperationException("Native barrel mesh bounds are invalid.");
			}
			Vector3 val5 = default(Vector3);
			((Vector3)(ref val5))..ctor(size.x / ((Bounds)(ref val)).size.x, size.y / ((Bounds)(ref val)).size.y, size.z / ((Bounds)(ref val)).size.z);
			visual.localScale = val5;
			visual.localPosition = -Vector3.Scale(new Vector3(((Bounds)(ref val)).center.x, ((Bounds)(ref val)).min.y, ((Bounds)(ref val)).center.z), val5);
		}
	}
	public sealed class FehuBargeBarrelHandle : MonoBehaviour, Hoverable, Interactable
	{
		[SerializeField]
		private Container _cargo;

		internal void Configure(Container cargo)
		{
			_cargo = cargo;
		}

		public string GetHoverName()
		{
			return "Barrel Storage";
		}

		public string GetHoverText()
		{
			if (!((Object)(object)_cargo != (Object)null) || _cargo.GetInventory() == null)
			{
				return "Barrel Storage (initializing)";
			}
			return _cargo.GetHoverText();
		}

		public float GetHoverOffset()
		{
			return 0.4f;
		}

		public bool Interact(Humanoid user, bool hold, bool alt)
		{
			if ((Object)(object)_cargo != (Object)null && _cargo.GetInventory() != null)
			{
				return _cargo.Interact(user, hold, alt);
			}
			return false;
		}

		public bool UseItem(Humanoid user, ItemData item)
		{
			if ((Object)(object)_cargo != (Object)null)
			{
				return _cargo.UseItem(user, item);
			}
			return false;
		}
	}
	internal sealed class FehuBargeFuel
	{
		private static readonly MethodInfo LoadInventory = AccessTools.Method(typeof(Container), "Load", (Type[])null, (Type[])null);

		private static readonly MethodInfo CheckAccess = AccessTools.Method(typeof(Container), "CheckAccess", (Type[])null, (Type[])null);

		private readonly ZNetView view;

		private readonly Container cargo;

		private ZDO State => view.GetZDO();

		internal string Selected => "FehuBlackResin";

		private double Remaining
		{
			get
			{
				if (State.GetString("fehu_motor_burning", "none") != "FehuBlackResin")
				{
					return 0.0;
				}
				double num = ReadCredit();
				if (!FuelBudget.Finite(num) || !(num >= 0.0) || !(num <= 60.0))
				{
					return 0.0;
				}
				return num;
			}
		}

		internal FehuBargeFuel(ZNetView view, Ship ship)
		{
			this.view = view;
			cargo = ((Component)ship).GetComponentInChildren<Container>(true);
			MigrateState();
		}

		private static double Seconds(string prefab)
		{
			return FuelBudget.Seconds(prefab);
		}

		private double ReadCredit()
		{
			long num = State.GetLong("fehu_motor_seconds_exact", long.MinValue);
			if (num != long.MinValue)
			{
				return BitConverter.Int64BitsToDouble(num);
			}
			return State.GetFloat("fehu_motor_seconds", 0f);
		}

		internal void MigrateState()
		{
			if ((Object)(object)view == (Object)null || !view.IsValid() || !view.IsOwner())
			{
				return;
			}
			if (State.GetString("fehu_motor_fuel", "") != Selected)
			{
				State.Set("fehu_motor_fuel", Selected);
			}
			string text = State.GetString("fehu_motor_burning", "none");
			double num = ReadCredit();
			if (text == Selected && FuelBudget.Finite(num) && num >= 0.0 && num <= 60.0)
			{
				if (State.GetLong("fehu_motor_seconds_exact", long.MinValue) == long.MinValue)
				{
					State.Set("fehu_motor_seconds_exact", BitConverter.DoubleToInt64Bits(num));
				}
				if (State.GetFloat("fehu_motor_seconds", 0f) != (float)num)
				{
					State.Set("fehu_motor_seconds", (float)num);
				}
				return;
			}
			if (State.GetLong("fehu_motor_seconds_exact", long.MinValue) != 0L)
			{
				State.Set("fehu_motor_seconds_exact", 0L);
			}
			if (State.GetFloat("fehu_motor_seconds", 0f) != 0f)
			{
				State.Set("fehu_motor_seconds", 0f);
			}
			if (text != "none")
			{
				State.Set("fehu_motor_burning", "none");
			}
		}

		private ItemData Find(string prefab)
		{
			if ((Object)(object)cargo == (Object)null)
			{
				return null;
			}
			foreach (ItemData allItem in cargo.GetInventory().GetAllItems())
			{
				if ((Object)(object)allItem.m_dropPrefab != (Object)null && ((Object)allItem.m_dropPrefab).name == prefab)
				{
					return allItem;
				}
			}
			return null;
		}

		internal bool Open(Humanoid user)
		{
			if ((Object)(object)cargo != (Object)null)
			{
				return cargo.Interact(user, false, false);
			}
			return false;
		}

		internal bool Select(Humanoid user, ItemData item)
		{
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			object obj;
			if (item == null)
			{
				obj = null;
			}
			else
			{
				GameObject dropPrefab = item.m_dropPrefab;
				obj = ((dropPrefab != null) ? ((Object)dropPrefab).name : null);
			}
			string text = (string)obj;
			if (!view.IsValid() || Seconds(text) <= 0.0 || (Object)(object)cargo == (Object)null || !user.GetInventory().ContainsItem(item))
			{
				return false;
			}
			Player val = (Player)(object)((user is Player) ? user : null);
			if ((Object)(object)val == (Object)null || cargo.IsInUse() || !PrivateArea.CheckAccess(((Component)cargo).transform.position, 0f, false, false) || !(bool)CheckAccess.Invoke(cargo, new object[1] { val.GetPlayerID() }))
			{
				return false;
			}
			if (!view.IsOwner() || !cargo.IsOwner())
			{
				((Character)user).Message((MessageType)2, "Load Black Resin in cargo, then use Black Resin on the engine.", 0, (Sprite)null, false);
				return Open(user);
			}
			LoadInventory.Invoke(cargo, null);
			ItemData val2 = item.Clone();
			val2.m_stack = 1;
			if (!cargo.GetInventory().AddItem(val2))
			{
				return false;
			}
			user.GetInventory().RemoveItem(item, 1);
			State.Set("fehu_motor_fuel", text);
			return true;
		}

		internal float Burn(float dt)
		{
			if (!view.IsValid() || !view.IsOwner() || (Object)(object)cargo == (Object)null || !cargo.IsOwner())
			{
				return 0f;
			}
			MigrateState();
			FuelStep fuelStep = FuelBudget.Consume(Remaining, dt, TakeUnit, delegate(string fuel)
			{
				State.Set("fehu_motor_burning", fuel);
			});
			State.Set("fehu_motor_seconds_exact", BitConverter.DoubleToInt64Bits(fuelStep.Remaining));
			State.Set("fehu_motor_seconds", (float)fuelStep.Remaining);
			return fuelStep.Fraction;
		}

		private string TakeUnit()
		{
			LoadInventory.Invoke(cargo, null);
			ItemData val = Find(Selected);
			if (val == null)
			{
				return null;
			}
			cargo.GetInventory().RemoveItem(val, 1);
			return Selected;
		}

		internal string Status()
		{
			if (!view.IsValid())
			{
				return "Fuel initializing";
			}
			MigrateState();
			int num = 0;
			if ((Object)(object)cargo != (Object)null && cargo.GetInventory() != null)
			{
				foreach (ItemData allItem in cargo.GetInventory().GetAllItems())
				{
					if ((Object)(object)allItem.m_dropPrefab != (Object)null && ((Object)allItem.m_dropPrefab).name == Selected)
					{
						num += allItem.m_stack;
					}
				}
			}
			double remaining = Remaining;
			double seconds = remaining + (double)num * 60.0;
			return "Fuel: Black Resin x" + num + " (60s per item)\nRemaining motor time: " + FuelBudget.DisplaySeconds(seconds) + "s | active Black Resin: " + remaining.ToString("0.0") + "s\nShift + E: fuel/cargo storage\nUse Black Resin on engine to load one unit";
		}
	}
	public sealed class FehuBargeHatch : MonoBehaviour
	{
		private const string OpenKey = "fehu_deck_hatch_open";

		private const string RequestRpc = "FehuHatchToggle";

		private const string ResultRpc = "FehuHatchResult";

		private const float OpenAngle = -105f;

		private ZNetView view;

		private Ship ship;

		private Transform hinge;

		private BoxCollider lidCollider;

		private BoxCollider nativeFloat;

		private float angle;

		private bool registered;

		private readonly Dictionary<Collider, bool> ignored = new Dictionary<Collider, bool>();

		internal bool IsOpen
		{
			get
			{
				if ((Object)(object)view != (Object)null && view.IsValid())
				{
					return view.GetZDO().GetBool("fehu_deck_hatch_open", false);
				}
				return false;
			}
		}

		internal string HoverText => Localization.instance.Localize("Deck Hatch\n[<color=yellow><b>$KEY_Use</b></color>] " + (IsOpen ? "Close hatch" : "Open hatch"));

		internal static void Install(GameObject barge, GameObject visual)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Expected O, but got Unknown
			//IL_0057: 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_00ac: 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_00de: 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_011d: 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_015c: 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_019b: 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_01da: Unknown result type (might be due to invalid IL or missing references)
			HatchMeshCut.CutVisual(visual);
			HatchMeshCut.CutColliders(barge.transform.Find("Physics"));
			GameObject val = new GameObject("DeckHatch");
			val.transform.SetParent(barge.transform.Find("Integration"), false);
			val.transform.localPosition = new Vector3(-6.95f, 0f, 0f);
			val.layer = barge.layer;
			val.AddComponent<FehuBargeHatch>();
			Material sharedMaterial = ((Renderer)visual.GetComponentInChildren<MeshRenderer>()).sharedMaterial;
			Transform transform = new GameObject("Hinge").transform;
			transform.SetParent(val.transform, false);
			transform.localPosition = new Vector3(0.65f, 1.7f, 0f);
			Cube(transform, "Lid", new Vector3(-0.65f, 0.08f, 0f), new Vector3(1.3f, 0.16f, 1.3f), sharedMaterial, val.layer);
			Cube(val.transform, "PortFrame", new Vector3(0f, 1.885f, 0.69f), new Vector3(1.46f, 0.06f, 0.08f), sharedMaterial, val.layer);
			Cube(val.transform, "StarboardFrame", new Vector3(0f, 1.885f, -0.69f), new Vector3(1.46f, 0.06f, 0.08f), sharedMaterial, val.layer);
			Cube(val.transform, "BowFrame", new Vector3(0.69f, 1.885f, 0f), new Vector3(0.08f, 0.06f, 1.3f), sharedMaterial, val.layer);
			Cube(val.transform, "SternFrame", new Vector3(-0.69f, 1.885f, 0f), new Vector3(0.08f, 0.06f, 1.3f), sharedMaterial, val.layer);
			Debug.Log((object)"[FehuBarge] Deck hatch installed: 1.3m opening, 1.4m bowward of motor; no floor beneath passage");
		}

		private static void Cube(Transform parent, string name, Vector3 position, Vector3 size, Material material, int layer)
		{
			//IL_0029: 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_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)
			GameObject val = GameObject.CreatePrimitive((PrimitiveType)3);
			((Object)val).name = name;
			val.layer = layer;
			val.transform.SetParent(parent, false);
			val.transform.localPosition = position;
			val.transform.localScale = size;
			((Renderer)val.GetComponent<MeshRenderer>()).sharedMaterial = material;
			MeshFilter component = val.GetComponent<MeshFilter>();
			Mesh val2 = Object.Instantiate<Mesh>(component.sharedMesh);
			Color[] array = (Color[])(object)new Color[val2.vertexCount];
			for (int i = 0; i < array.Length; i++)
			{
				array[i] = new Color(0.5568628f, 0.40392157f, 22f / 85f);
			}
			val2.colors = array;
			component.sharedMesh = val2;
			val.AddComponent<FehuBargeHatchHandle>();
		}

		private void Start()
		{
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			view = ((Component)this).GetComponentInParent<ZNetView>();
			ship = ((Component)this).GetComponentInParent<Ship>();
			hinge = ((Component)this).transform.Find("Hinge");
			Transform obj = ((Component)this).transform.Find("Hinge/Lid");
			lidCollider = ((obj != null) ? ((Component)obj).GetComponent<BoxCollider>() : null);
			if (!((Object)(object)view == (Object)null) && view.IsValid() && !((Object)(object)ship == (Object)null) && !((Object)(object)hinge == (Object)null) && !((Object)(object)lidCollider == (Object)null))
			{
				ref BoxCollider reference = ref nativeFloat;
				object? obj2 = AccessTools.Field(typeof(Ship), "m_floatCollider")?.GetValue(ship);
				reference = (BoxCollider)((obj2 is BoxCollider) ? obj2 : null);
				view.Register<long>("FehuHatchToggle", (Action<long, long>)RPC_Toggle);
				view.Register<bool, bool>("FehuHatchResult", (Action<long, bool, bool>)RPC_Result);
				registered = true;
				angle = (IsOpen ? (-105f) : 0f);
				hinge.localRotation = Quaternion.Euler(0f, 0f, angle);
				((Collider)lidCollider).enabled = !IsOpen;
				Debug.Log((object)("[FehuBarge] Deck hatch ready; multiplayer state restored; native float collider unchanged, trigger=" + ((Object)(object)nativeFloat != (Object)null && ((Collider)nativeFloat).isTrigger)));
			}
		}

		internal bool Interact(Humanoid user, bool repeat)
		{
			Player val = (Player)(object)((user is Player) ? user : null);
			if (repeat || !registered || (Object)(object)val == (Object)null || ((Character)val).IsDead() || !InRange(val))
			{
				return false;
			}
			view.InvokeRPC("FehuHatchToggle", new object[1] { val.GetPlayerID() });
			return true;
		}

		private bool InRange(Player player)
		{
			//IL_0006: 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)
			return Vector3.Distance(((Component)player).transform.position, ((Component)this).transform.TransformPoint(new Vector3(0f, 1.86f, 0f))) < 4f;
		}

		private void RPC_Toggle(long sender, long playerId)
		{
			if (view.IsValid() && view.IsOwner())
			{
				Player player = Player.GetPlayer(playerId);
				bool flag = (Object)(object)player != (Object)null && ((Character)player).GetOwner() == sender && !((Character)player).IsDead() && InRange(player);
				if (flag && IsOpen && !CanClose())
				{
					flag = false;
				}
				if (flag)
				{
					view.GetZDO().Set("fehu_deck_hatch_open", !IsOpen);
					Debug.Log((object)("[FehuBarge] Deck hatch: " + (IsOpen ? "OPEN" : "CLOSED")));
				}
				view.InvokeRPC(sender, "FehuHatchResult", new object[2] { flag, IsOpen });
			}
		}

		private void RPC_Result(long sender, bool accepted, bool open)
		{
			if (view.IsValid() && sender == view.GetZDO().GetOwner() && !((Object)(object)Player.m_localPlayer == (Object)null))
			{
				((Character)Player.m_localPlayer).Message((MessageType)2, accepted ? ("Deck hatch: " + (open ? "OPEN" : "CLOSED")) : "Deck hatch cannot close while a player is in the opening, or you are too far away.", 0, (Sprite)null, false);
			}
		}

		private bool CanClose()
		{
			//IL_0035: 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_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: 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_0136: 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_0151: 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_007d: 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_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: 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_00dd: 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_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = default(Vector3);
			foreach (Player allPlayer in Player.GetAllPlayers())
			{
				Collider component = ((Component)allPlayer).GetComponent<Collider>();
				if ((Object)(object)component == (Object)null || !component.enabled)
				{
					continue;
				}
				Bounds bounds = component.bounds;
				((Vector3)(ref val))..ctor(float.MaxValue, float.MaxValue, float.MaxValue);
				Vector3 val2 = -val;
				for (int i = 0; i < 2; i++)
				{
					for (int j = 0; j < 2; j++)
					{
						for (int k = 0; k < 2; k++)
						{
							Vector3 val3 = ((Component)this).transform.InverseTransformPoint(new Vector3((i == 0) ? ((Bounds)(ref bounds)).min.x : ((Bounds)(ref bounds)).max.x, (j == 0) ? ((Bounds)(ref bounds)).min.y : ((Bounds)(ref bounds)).max.y, (k == 0) ? ((Bounds)(ref bounds)).min.z : ((Bounds)(ref bounds)).max.z));
							val = Vector3.Min(val, val3);
							val2 = Vector3.Max(val2, val3);
						}
					}
				}
				if (val.x < 0.65f && val2.x > -0.65f && val.z < 0.65f && val2.z > -0.65f && val.y < 1.84f && val2.y > 1.7f)
				{
					return false;
				}
			}
			return true;
		}

		private void Update()
		{
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			if (registered && view.IsValid())
			{
				angle = Mathf.MoveTowards(angle, IsOpen ? (-105f) : 0f, 180f * Time.deltaTime);
				hinge.localRotation = Quaternion.Euler(0f, 0f, angle);
				bool flag = !IsOpen && Mathf.Abs(angle) < 0.01f;
				if (flag && !((Collider)lidCollider).enabled && view.IsOwner() && !CanClose())
				{
					view.GetZDO().Set("fehu_deck_hatch_open", true);
					flag = false;
					Debug.Log((object)"[FehuBarge] Deck hatch closure deferred: player in opening");
				}
				if (!flag)
				{
					((Collider)lidCollider).enabled = false;
				}
				else if (!((Collider)lidCollider).enabled && CanClose())
				{
					((Collider)lidCollider).enabled = true;
				}
				UpdateFloatPassage();
			}
		}

		private void UpdateFloatPassage()
		{
			//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)
			//IL_0065: 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_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)nativeFloat == (Object)null || ((Collider)nativeFloat).isTrigger)
			{
				return;
			}
			HashSet<Collider> hashSet = new HashSet<Collider>();
			foreach (Player allPlayer in Player.GetAllPlayers())
			{
				Collider component = ((Component)allPlayer).GetComponent<Collider>();
				if ((Object)(object)component == (Object)null)
				{
					continue;
				}
				Vector3 val = ((Component)this).transform.InverseTransformPoint(((Component)allPlayer).transform.position);
				if (!(Mathf.Abs(val.x) > 0.65f) && !(Mathf.Abs(val.z) > 0.65f) && !(val.y > 2.1f) && (IsOpen || !(val.y > 1.7f)))
				{
					hashSet.Add(component);
					if (!ignored.ContainsKey(component))
					{
						ignored[component] = Physics.GetIgnoreCollision(component, (Collider)(object)nativeFloat);
						Physics.IgnoreCollision(component, (Collider)(object)nativeFloat, true);
					}
				}
			}
			List<Collider> list = new List<Collider>();
			foreach (KeyValuePair<Collider, bool> item in ignored)
			{
				if (!hashSet.Contains(item.Key))
				{
					RestoreCollision(item.Key, item.Value);
					list.Add(item.Key);
				}
			}
			foreach (Collider item2 in list)
			{
				ignored.Remove(item2);
			}
		}

		private void RestoreCollision(Collider collider, bool previous)
		{
			if (!((Object)(object)collider == (Object)null) && !((Object)(object)nativeFloat == (Object)null))
			{
				Player component = ((Component)collider).GetComponent<Player>();
				if (!((Object)(object)component != (Object)null) || !((Character)component).IsAttachedToShip() || !((Object)(object)component.GetAttachPoint() != (Object)null) || !((Object)(object)((Component)component.GetAttachPoint()).GetComponentInParent<Ship>() == (Object)(object)ship))
				{
					Physics.IgnoreCollision(collider, (Collider)(object)nativeFloat, previous);
				}
			}
		}

		private void OnDestroy()
		{
			foreach (KeyValuePair<Collider, bool> item in ignored)
			{
				RestoreCollision(item.Key, item.Value);
			}
			if (registered && !((Object)(object)view == (Object)null))
			{
				view.Unregister("FehuHatchToggle");
				view.Unregister("FehuHatchResult");
			}
		}
	}
	public sealed class FehuBargeHatchHandle : MonoBehaviour, Interactable, Hoverable
	{
		private FehuBargeHatch Hatch => ((Component)this).GetComponentInParent<FehuBargeHatch>();

		public bool Interact(Humanoid user, bool hold, bool alt)
		{
			if ((Object)(object)Hatch != (Object)null)
			{
				return Hatch.Interact(user, hold);
			}
			return false;
		}

		public bool UseItem(Humanoid user, ItemData item)
		{
			return false;
		}

		public string GetHoverName()
		{
			return "Deck Hatch";
		}

		public string GetHoverText()
		{
			return Hatch?.HoverText ?? "Deck Hatch";
		}

		public float GetHoverOffset()
		{
			return 0f;
		}
	}
	public sealed class FehuBargeHold : MonoBehaviour
	{
		private const string EnabledKey = "fehu_hold_enabled";

		private const string AnchorKey = "fehu_hold_anchor";

		private const string HeadingKey = "fehu_hold_heading";

		private const string RequestRpc = "FehuHoldRequest";

		private const string ResultRpc = "FehuHoldResult";

		private ZNetView view;

		private Rigidbody body;

		private Ship ship;

		private ShipControlls controls;

		private FehuBargeFuel fuel;

		private readonly BargeHoldController controller = new BargeHoldController();

		private bool wasOwner;

		private bool registered;

		internal bool IsHolding
		{
			get
			{
				if ((Object)(object)view != (Object)null && view.IsValid())
				{
					return view.GetZDO().GetBool("fehu_hold_enabled", false);
				}
				return false;
			}
		}

		internal bool BlocksControls
		{
			get
			{
				if (!IsHolding)
				{
					if ((Object)(object)view != (Object)null && view.IsOwner())
					{
						return controller.IsActive;
					}
					return false;
				}
				return true;
			}
		}

		internal static bool ToggleModifier
		{
			get
			{
				if (!Input.GetKey((KeyCode)306))
				{
					return Input.GetKey((KeyCode)305);
				}
				return true;
			}
		}

		internal string Prompt => "\n[<color=yellow><b>Ctrl + $KEY_Use</b></color>] " + (IsHolding ? "Disable Level and Hold Position" : "Level and Hold Position") + "\nLevel and Hold Position: " + (IsHolding ? "ON" : "OFF");

		private void Start()
		{
			view = ((Component)this).GetComponent<ZNetView>();
			body = ((Component)this).GetComponent<Rigidbody>();
			ship = ((Component)this).GetComponent<Ship>();
			controls = ((Component)this).GetComponentInChildren<ShipControlls>(true);
			if (!((Object)(object)view == (Object)null) && view.IsValid() && !((Object)(object)body == (Object)null) && !((Object)(object)ship == (Object)null) && !((Object)(object)controls == (Object)null))
			{
				fuel = new FehuBargeFuel(view, ship);
				view.Register<long>("FehuHoldRequest", (Action<long, long>)RPC_Request);
				view.Register<bool, bool>("FehuHoldResult", (Action<long, bool, bool>)RPC_Result);
				registered = true;
				Debug.Log((object)"[FehuBarge] Level and Hold Position initialized; owner-authoritative ZDO state; vertical buoyancy retained");
			}
		}

		private void OnDestroy()
		{
			if (registered && !((Object)(object)view == (Object)null))
			{
				view.Unregister("FehuHoldRequest");
				view.Unregister("FehuHoldResult");
			}
		}

		internal bool RequestToggle(Player player)
		{
			if (!registered || (Object)(object)player == (Object)null || !CanUse(player))
			{
				return false;
			}
			view.InvokeRPC("FehuHoldRequest", new object[1] { player.GetPlayerID() });
			return true;
		}

		private bool CanUse(Player player)
		{
			//IL_001c: 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)
			if (((Character)player).IsDead() || !ship.IsPlayerInBoat(player) || Vector3.Distance(((Component)player).transform.position, controls.m_attachPoint.position) > controls.m_maxUseRange)
			{
				return false;
			}
			long user = controls.GetUser();
			if (user != 0L && user != player.GetPlayerID())
			{
				return !controls.HaveValidUser();
			}
			return true;
		}

		private void RPC_Request(long sender, long playerId)
		{
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			if (!view.IsValid() || !view.IsOwner())
			{
				return;
			}
			Player player = Player.GetPlayer(playerId);
			bool flag = (Object)(object)player != (Object)null && ((Character)player).GetOwner() == sender && CanUse(player);
			if (flag)
			{
				bool flag2 = !IsHolding;
				ZDO zDO = view.GetZDO();
				if (flag2)
				{
					Vector3 position = body.position;
					position.y = 0f;
					zDO.Set("fehu_hold_anchor", position);
					zDO.Set("fehu_hold_heading", Heading(body.rotation));
					controller.Reset();
					wasOwner = true;
				}
				zDO.Set("fehu_hold_enabled", flag2);
				Debug.Log((object)("[FehuBarge] Level and Hold Position: " + (flag2 ? "ON" : "OFF")));
			}
			view.InvokeRPC(sender, "FehuHoldResult", new object[2] { flag, IsHolding });
		}

		private void RPC_Result(long sender, bool accepted, bool enabled)
		{
			if (view.IsValid() && sender == view.GetZDO().GetOwner() && !((Object)(object)Player.m_localPlayer == (Object)null))
			{
				((Character)Player.m_localPlayer).Message((MessageType)2, accepted ? ("Level and Hold Position: " + (enabled ? "ON" : "OFF")) : "Level and Hold Position: move to the motor or wait for the helm to become available.", 0, (Sprite)null, false);
			}
		}

		internal void ApplyForces(float dt)
		{
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: 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)
			//IL_00a3: 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_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: 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_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: 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: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
			if (!registered || !view.IsValid() || !view.IsOwner())
			{
				wasOwner = false;
				controller.Reset();
				return;
			}
			if (!wasOwner)
			{
				controller.Reset();
				wasOwner = true;
			}
			if (IsHolding || controller.IsActive)
			{
				ZDO zDO = view.GetZDO();
				Vector3 v = body.position - zDO.GetVec3("fehu_hold_anchor", body.position);
				Vector3 linearVelocity = body.linearVelocity;
				Vector3 v2 = Vector3.Cross(body.rotation * Vector3.up, Vector3.up);
				float num = Mathf.DeltaAngle(Heading(body.rotation), zDO.GetFloat("fehu_hold_heading", Heading(body.rotation))) * ((float)Math.PI / 180f);
				controller.Step(dt, IsHolding, From(v), From(linearVelocity), From(v2), From(body.angularVelocity), num);
				float num2 = (((controller.Acceleration.Length > 1E-09 || controller.AngularAcceleration.Length > 1E-09) && FehuBargePlugin.MotorFuelRequiredConfig) ? fuel.Burn(dt) : 1f);
				if (num2 <= 0f)
				{
					controller.Reset();
					return;
				}
				body.AddForce(To(controller.Acceleration) * num2, (ForceMode)5);
				body.AddTorque(To(controller.AngularAcceleration) * num2, (ForceMode)5);
			}
		}

		private static float Heading(Quaternion rotation)
		{
			//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_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: 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)
			Vector3 val = rotation * Vector3.right;
			return Mathf.Atan2(val.x, val.z) * 57.29578f;
		}

		private static HoldVector From(Vector3 v)
		{
			//IL_0000: 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)
			return new HoldVector(v.x, v.y, v.z);
		}

		private static Vector3 To(HoldVector v)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			return new Vector3((float)v.X, (float)v.Y, (float)v.Z);
		}
	}
	public sealed class FehuBargeMotor : MonoBehaviour, Interactable, Hoverable
	{
		private const float BaseMotorThrust = 12000f;

		private const float ReverseSpeedFraction = 0.5f;

		private static readonly FieldInfo RudderValueField = typeof(Ship).GetField("m_rudderValue", BindingFlags.Instance | BindingFlags.NonPublic);

		private static readonly FieldInfo SpeedField = typeof(Ship).GetField("m_speed", BindingFlags.Instance | BindingFlags.NonPublic);

		private FehuBargeFuel _fuel;

		private ZNetView _nview;

		private Rigidbody _body;

		private Ship _ship;

		private ShipControlls _shipControls;

		private Transform _helmAttachPoint;

		private FehuBargeHold _holdMode;

		private bool _motorEnabled;

		private float _power;

		private float _maxSpeed;

		private float _fuelFraction;

		private float _nativeBackward;

		private float _nativeSteering;

		private bool _nativeFuelScaled;

		private bool _wasControlling;

		private bool _ownershipRequested;

		private bool _forwardInputLogged;

		private bool _reverseInputLogged;

		private bool _fixedThrustActive;

		private bool _velocityAfterLogged;

		private float _continuousForwardTime;

		private bool _diagnosticsLogged;

		public void Configure(bool motorEnabled, float power, float maxSpeed, bool fuelRequired)
		{
			_motorEnabled = motorEnabled;
			_power = power;
			_maxSpeed = Mathf.Max(1f, maxSpeed);
		}

		private IEnumerator Start()
		{
			yield return null;
			_nview = ((Component)this).GetComponentInParent<ZNetView>();
			_body = ((Component)this).GetComponentInParent<Rigidbody>();
			_ship = ((Component)this).GetComponentInParent<Ship>();
			_shipControls = (((Object)(object)_ship != (Object)null) ? ((Component)_ship).GetComponentInChildren<ShipControlls>(true) : null);
			_holdMode = (((Object)(object)_ship != (Object)null) ? ((Component)_ship).GetComponent<FehuBargeHold>() : null);
			if ((Object)(object)_nview == (Object)null || (Object)(object)_body == (Object)null || (Object)(object)_ship == (Object)null || (Object)(object)_shipControls == (Object)null)
			{
				Debug.LogError((object)"[FehuBarge] Motor integration unavailable: expected parent Ship, ShipControlls, ZNetView and Rigidbody.");
				((Behaviour)this).enabled = false;
				yield break;
			}
			_fuel = new FehuBargeFuel(_nview, _ship);
			_helmAttachPoint = ((Component)_ship).transform.Find("Integration/HelmAttachPoint");
			if ((Object)(object)_helmAttachPoint == (Object)null)
			{
				Debug.LogError((object)"[FehuBarge] Integration/HelmAttachPoint is missing.");
				((Behaviour)this).enabled = false;
				yield break;
			}
			if ((Object)(object)((Component)_ship).transform.Find("Integration/OperatorSeat/AttachReference") == (Object)null)
			{
				Debug.LogError((object)"[FehuBarge] Operator seat reference is missing.");
				((Behaviour)this).enabled = false;
				yield break;
			}
			FehuBargeDriverSeat.PositionHelm(_ship, _helmAttachPoint);
			((Component)_shipControls).transform.position = _helmAttachPoint.position;
			((Component)_shipControls).transform.rotation = _helmAttachPoint.rotation;
			_shipControls.m_attachPoint = _helmAttachPoint;
			Debug.Log((object)("[FehuBarge] Barrel-supported operator seat helm=" + ((object)_helmAttachPoint.position/*cast due to .constrained prefix*/).ToString() + " facing=" + ((object)_helmAttachPoint.forward/*cast due to .constrained prefix*/).ToString() + " nativePose=" + _shipControls.m_attachAnimation));
			LogHierarchy();
			_motorEnabled = FehuBargePlugin.MotorEnabledConfig;
			_power = Mathf.Max(FehuBargePlugin.MotorPowerConfig, 0.1f);
			_maxSpeed = Mathf.Max(1f, FehuBargePlugin.MotorMaxSpeedConfig);
			Debug.Log((object)"[FehuBarge] Motor component initialized");
			Debug.Log((object)"[FehuBarge] Motor Ship reference: READY");
			Debug.Log((object)"[FehuBarge] Native ShipControlls reference: READY");
			Debug.Log((object)"[FehuBarge] Native ShipControlls station: Integration/HelmAttachPoint");
			Debug.Log((object)"[FehuBarge] Effective physical Ship forward = visible hull bow (+X in legacy root frame)");
			Debug.Log((object)"[FehuBarge] Helm attach = Integration/HelmAttachPoint at barrel seat; MotorMount remains unchanged");
			Debug.Log((object)"[FehuBarge] Motor Rigidbody reference: READY");
			Debug.Log((object)"[FehuBarge] Motor ZNetView reference: READY");
			Debug.Log((object)("[FehuBarge] Motor enabled: " + _motorEnabled.ToString().ToLowerInvariant()));
			Debug.Log((object)("[FehuBarge] Motor power multiplier = " + _power.ToString("0.##")));
			Debug.Log((object)("[FehuBarge] Motor forward speed cap = " + _maxSpeed.ToString("0.##") + " m/s"));
			Debug.Log((object)("[FehuBarge] Motor reverse speed cap = " + (_maxSpeed * 0.5f).ToString("0.##") + " m/s"));
		}

		public void CreateVisual()
		{
			//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_0079: 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_0094: Expected O, but got Unknown
			//IL_0099: 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_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_011b: 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_0152: 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_0189: 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_01b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_020f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0223: Unknown result type (might be due to invalid IL or missing references)
			//IL_0237: Unknown result type (might be due to invalid IL or missing references)
			Material val = null;
			Renderer[] componentsInChildren = ((Component)((Component)this).transform.root).GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val2 in componentsInChildren)
			{
				if ((Object)(object)val2.sharedMaterial != (Object)null && (Object)(object)((Component)val2).gameObject != (Object)(object)((Component)this).gameObject)
				{
					val = val2.sharedMaterial;
					break;
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				Debug.LogError((object)"[FehuBarge] Motor visual unavailable: no compatible FehuBarge renderer material was found.");
				return;
			}
			Material material = new Material(val)
			{
				name = "FehuBargeMotorMetal",
				color = new Color(0.12f, 0.13f, 0.12f)
			};
			Transform transform = new GameObject("MotorAssembly").transform;
			transform.SetParent(((Component)this).transform, false);
			Primitive(transform, "EngineHousing", (PrimitiveType)3, new Vector3(0f, 0.28f, 0f), Vector3.zero, new Vector3(0.85f, 0.45f, 0.65f), material, keepCollider: true);
			Primitive(transform, "MotorExhaust", (PrimitiveType)2, new Vector3(-0.2f, 0.78f, 0f), Vector3.zero, new Vector3(0.14f, 0.32f, 0.14f), material, keepCollider: false);
			Primitive(transform, "ControlLever", (PrimitiveType)2, new Vector3(0.18f, 0.75f, 0.25f), new Vector3(35f, 0f, 0f), new Vector3(0.06f, 0.32f, 0.06f), val, keepCollider: false);
			Primitive(transform, "Shaft", (PrimitiveType)2, new Vector3(-0.45f, -0.28f, 0f), new Vector3(0f, 0f, 90f), new Vector3(0.1f, 0.45f, 0.1f), material, keepCollider: false);
			Primitive(transform, "PropellerHousing", (PrimitiveType)3, new Vector3(-0.68f, -0.38f, 0f), Vector3.zero, new Vector3(0.32f, 0.48f, 0.38f), material, keepCollider: false);
			Primitive(transform, "Propeller", (PrimitiveType)2, new Vector3(-1.04f, -0.57f, 0f), new Vector3(0f, 0f, 90f), new Vector3(0.12f, 0.38f, 0.38f), material, keepCollider: false);
		}

		private static GameObject Primitive(Transform parent, string name, PrimitiveType type, Vector3 position, Vector3 rotation, Vector3 scale, Material material, bool keepCollider)
		{
			//IL_0000: 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_002d: 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)
			GameObject val = GameObject.CreatePrimitive(type);
			((Object)val).name = name;
			val.transform.SetParent(parent, false);
			val.transform.localPosition = position;
			val.transform.localEulerAngles = rotation;
			val.transform.localScale = scale;
			val.GetComponent<Renderer>().sharedMaterial = material;
			if (!keepCollider)
			{
				Object.Destroy((Object)(object)val.GetComponent<Collider>());
			}
			return val;
		}

		public bool Interact(Humanoid user, bool hold, bool alt)
		{
			if (hold || (Object)(object)_nview == (Object)null || !_nview.IsValid())
			{
				return false;
			}
			Player val = (Player)(object)((user is Player) ? user : null);
			if ((Object)(object)val == (Object)null || (Object)(object)_shipControls == (Object)null)
			{
				return false;
			}
			if (!alt && FehuBargeHold.ToggleModifier && (Object)(object)_holdMode != (Object)null)
			{
				return _holdMode.RequestToggle(val);
			}
			if (!_motorEnabled)
			{
				return false;
			}
			if (alt)
			{
				if (_fuel != null)
				{
					return _fuel.Open(user);
				}
				return false;
			}
			if ((Object)(object)val.GetControlledShip() == (Object)(object)_ship)
			{
				_shipControls.OnUseStop(val);
				return true;
			}
			return _shipControls.Interact(user, false, alt);
		}

		public bool UseItem(Humanoid user, ItemData item)
		{
			if (_fuel != null && _nview.IsValid())
			{
				return _fuel.Select(user, item);
			}
			return false;
		}

		public string GetHoverName()
		{
			return "Fehu Barge Motor";
		}

		public string GetHoverText()
		{
			if (!_motorEnabled)
			{
				return Localization.instance.Localize("<color=grey>Fehu Barge Motor (disabled in config)</color>" + _holdMode?.Prompt);
			}
			Player localPlayer = Player.m_localPlayer;
			bool flag = (Object)(object)localPlayer != (Object)null && (Object)(object)localPlayer.GetControlledShip() == (Object)(object)_ship;
			return Localization.instance.Localize("<color=yellow>Fehu Barge Motor</color>\n[<color=yellow><b>$KEY_Use</b></color>] " + (flag ? "Release controls" : "Take controls") + _holdMode?.Prompt + "\n" + (_fuel?.Status() ?? "Fuel initializing") + (FehuBargePlugin.MotorFuelRequiredConfig ? "" : "\nFuel consumption disabled in config"));
		}

		public float GetHoverOffset()
		{
			return 0.5f;
		}

		private void Update()
		{
			if (_motorEnabled && !((Object)(object)_nview == (Object)null) && _nview.IsValid())
			{
				Player localPlayer = Player.m_localPlayer;
				bool flag = (Object)(object)localPlayer != (Object)null && (Object)(object)localPlayer.GetControlledShip() == (Object)(object)_ship;
				if (flag && !_wasControlling)
				{
					_ownershipRequested = false;
					_forwardInputLogged = false;
					_reverseInputLogged = false;
					_fixedThrustActive = false;
					_velocityAfterLogged = false;
					_continuousForwardTime = 0f;
					Debug.Log((object)("[FehuBarge] Controls acquired by " + localPlayer.GetPlayerName()));
					Debug.Log((object)"[FehuBarge] Motor running = true");
					Debug.Log((object)"[FehuBarge] Rigidbody = READY");
					Debug.Log((object)("[FehuBarge] ZNetView owner = " + _nview.IsOwner().ToString().ToLowerInvariant()));
					LogHelmDiagnostics(localPlayer);
				}
				else if (!flag && _wasControlling)
				{
					StopFixedThrustSession();
					Debug.Log((object)"[FehuBarge] Controls released");
				}
				_wasControlling = flag;
				if (flag && !_nview.IsOwner() && !_ownershipRequested)
				{
					_ownershipRequested = true;
					_nview.ClaimOwnership();
					Debug.Log((object)"[FehuBarge] Ownership requested");
				}
			}
		}

		internal void PrepareFuel(float dt, ref Speed speed, ref float backward, ref float steering)
		{
			_fuelFraction = 0f;
			if ((Object)(object)_nview == (Object)null || !_nview.IsValid() || !_nview.IsOwner())
			{
				return;
			}
			if (!_motorEnabled || (Object)(object)_shipControls == (Object)null || _shipControls.GetUser() == 0L || ((Object)(object)_holdMode != (Object)null && _holdMode.BlocksControls))
			{
				speed = (Speed)0;
			}
			else if (speed)
			{
				_fuelFraction = ((!FehuBargePlugin.MotorFuelRequiredConfig) ? 1f : (_fuel?.Burn(dt) ?? 0f));
				if (_fuelFraction <= 0f)
				{
					speed = (Speed)0;
					StopFixedThrustSession();
					return;
				}
				_nativeBackward = backward;
				_nativeSteering = steering;
				_nativeFuelScaled = true;
				backward *= _fuelFraction;
				steering *= _fuelFraction;
			}
		}

		internal void RestoreNativeFuelForces(ref float backward, ref float steering)
		{
			if (_nativeFuelScaled)
			{
				backward = _nativeBackward;
				steering = _nativeSteering;
				_nativeFuelScaled = false;
			}
		}

		internal void ApplyMotorForces(float dt)
		{
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			//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_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_022d: Unknown result type (might be due to invalid IL or missing references)
			//IL_022e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0234: Unknown result type (might be due to invalid IL or missing references)
			//IL_023e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01db: 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)
			if (!_motorEnabled || (Object)(object)_nview == (Object)null || !_nview.IsOwner() || (Object)(object)_body == (Object)null || (Object)(object)_ship == (Object)null)
			{
				return;
			}
			if ((Object)(object)_holdMode != (Object)null && _holdMode.BlocksControls)
			{
				StopFixedThrustSession();
			}
			else
			{
				if (_shipControls.GetUser() == 0L)
				{
					return;
				}
				float num = ReadNativeMotorThrottle();
				if (num != 0f && _fuelFraction <= 0f)
				{
					StopFixedThrustSession();
					return;
				}
				Vector3 right = ((Component)_ship).transform.right;
				right.y = 0f;
				((Vector3)(ref right)).Normalize();
				float num2 = 12000f * _power * _fuelFraction;
				float num3 = _maxSpeed * 0.5f;
				float num4 = Vector3.Dot(_body.linearVelocity, right);
				float num5 = Mathf.Clamp(num4, 0f - num3, _maxSpeed);
				if (num5 != num4)
				{
					Rigidbody body = _body;
					body.linearVelocity += right * (num5 - num4);
					num4 = num5;
				}
				if (num > 0f)
				{
					if (!_fixedThrustActive)
					{
						_fixedThrustActive = true;
						_velocityAfterLogged = false;
						_continuousForwardTime = 0f;
						Debug.Log((object)"[FehuBarge] motor fixed-thrust START");
					}
					float num6 = num4;
					if (num6 < _maxSpeed)
					{
						float num7 = Mathf.Clamp01((_maxSpeed - num6) / Mathf.Max(1f, _maxSpeed * 0.25f));
						_body.AddForce(right * (num2 * num7), (ForceMode)0);
					}
					_continuousForwardTime += dt;
					if (!_velocityAfterLogged && _continuousForwardTime >= 1f)
					{
						_velocityAfterLogged = true;
						Vector3 linearVelocity = _body.line