Decompiled source of Behold Pirates v0.14.1

BepInEx/plugins/Behold.Pirates/Behold.Pirates.dll

Decompiled a month 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 BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using FishNet;
using FishNet.Connection;
using FishNet.Managing;
using FishNet.Managing.Object;
using FishNet.Object;
using FishNet.Observing;
using FishNet.Transporting;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Unity.Mathematics;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Behold")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Adds hostile pirate fleets to the open ocean in How to Fish.")]
[assembly: AssemblyFileVersion("0.14.1.0")]
[assembly: AssemblyInformationalVersion("0.14.1+6b3c3d8ae249a35490bff0a914e30f9f2d1cff04")]
[assembly: AssemblyProduct("Behold: Pirates")]
[assembly: AssemblyTitle("Behold: Pirates")]
[assembly: AssemblyVersion("0.14.1.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[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 Behold.Pirates
{
	internal sealed class OpenSeaBoundary : MonoBehaviour
	{
		private const int ShorelineSampleCount = 120;

		private const float MinimumScanRadius = 500f;

		private const float ScanRadiusMultiplier = 4f;

		private const float MinimumValidShoreRadius = 1f;

		private const float MinimumValidSampleRatio = 0.5f;

		private static readonly float[] ProbeHeightsAboveWater = new float[3] { 0.25f, 1f, 2f };

		private ConfigEntry<float> _distanceBeyondIsland;

		private Island? _sampledIsland;

		private Vector3 _islandPosition;

		private float _authoredIslandRadius;

		private float[] _shoreRadii = Array.Empty<float>();

		private int _revision;

		public int Revision
		{
			get
			{
				EnsureCurrentIsland();
				return _revision;
			}
		}

		public int SampleCount
		{
			get
			{
				EnsureCurrentIsland();
				return _shoreRadii.Length;
			}
		}

		public float DistanceBeyondIsland => Mathf.Max(0f, _distanceBeyondIsland.Value);

		public void Initialize(ConfigEntry<float> distanceBeyondIsland)
		{
			_distanceBeyondIsland = distanceBeyondIsland;
		}

		private void Update()
		{
			EnsureCurrentIsland();
		}

		public float GetDistanceFromShoreline(Vector3 position)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: 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)
			EnsureCurrentIsland();
			Vector3 offset = position - _islandPosition;
			offset.y = 0f;
			return ((Vector3)(ref offset)).magnitude - GetShoreRadius(offset);
		}

		public bool IsBeyondBoundary(Vector3 position, float distanceBeyondShoreline)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			return GetDistanceFromShoreline(position) > Mathf.Max(0f, distanceBeyondShoreline);
		}

		public Vector3 GetBoundaryPoint(int sampleIndex, float distanceBeyondShoreline)
		{
			//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_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			EnsureCurrentIsland();
			if (_shoreRadii.Length == 0)
			{
				return _islandPosition;
			}
			int num = (sampleIndex % _shoreRadii.Length + _shoreRadii.Length) % _shoreRadii.Length;
			float num2 = MathF.PI * 2f * (float)num / (float)_shoreRadii.Length;
			Vector3 val = default(Vector3);
			((Vector3)(ref val))..ctor(Mathf.Cos(num2), 0f, Mathf.Sin(num2));
			float num3 = _shoreRadii[num] + Mathf.Max(0f, distanceBeyondShoreline);
			return _islandPosition + val * num3;
		}

		private void EnsureCurrentIsland()
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			if (IslandManager.IsLoading || !Object.op_Implicit((Object)(object)Island.CurIsland))
			{
				Clear();
				return;
			}
			Island curIsland = Island.CurIsland;
			if (!((Object)(object)_sampledIsland == (Object)(object)curIsland) || !(HorizontalSqrDistance(_islandPosition, Island.IslandPos) <= 0.01f) || !Mathf.Approximately(_authoredIslandRadius, Island.IslandSize))
			{
				SampleShoreline(curIsland);
			}
		}

		private void SampleShoreline(Island island)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			_sampledIsland = island;
			_islandPosition = Island.IslandPos;
			_authoredIslandRadius = Mathf.Max(1f, Island.IslandSize);
			_shoreRadii = new float[120];
			bool[] array = new bool[120];
			float scanRadius = Mathf.Max(500f, _authoredIslandRadius * 4f);
			float waterHeight = WaterManager.WaterHeight;
			int num = 0;
			Physics.SyncTransforms();
			Vector3 outward = default(Vector3);
			for (int i = 0; i < 120; i++)
			{
				float num2 = MathF.PI * 2f * (float)i / 120f;
				((Vector3)(ref outward))..ctor(Mathf.Cos(num2), 0f, Mathf.Sin(num2));
				float num3 = FindOutermostShoreRadius(outward, scanRadius, waterHeight);
				if (num3 >= 1f)
				{
					array[i] = true;
					num++;
					_shoreRadii[i] = num3;
				}
				else
				{
					_shoreRadii[i] = _authoredIslandRadius;
				}
			}
			if (num < Mathf.CeilToInt(60f))
			{
				for (int j = 0; j < _shoreRadii.Length; j++)
				{
					_shoreRadii[j] = _authoredIslandRadius;
				}
				Plugin.Log.LogWarning((object)($"Only {num}/{120} shoreline directions hit level geometry; " + $"using the authored {_authoredIslandRadius:0.#}m island radius as the open-sea boundary fallback."));
			}
			else
			{
				ReplaceMissingSamples(array);
			}
			_revision++;
		}

		private float FindOutermostShoreRadius(Vector3 outward, float scanRadius, float waterHeight)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: 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_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0071: Unknown result type (might be due to invalid IL or missing references)
			float num = -1f;
			float[] probeHeightsAboveWater = ProbeHeightsAboveWater;
			RaycastHit val2 = default(RaycastHit);
			foreach (float num2 in probeHeightsAboveWater)
			{
				Vector3 val = _islandPosition + outward * scanRadius;
				val.y = waterHeight + num2;
				if (Physics.Raycast(val, -outward, ref val2, scanRadius, LayerMask.op_Implicit(GameInfo.LevelLayer), (QueryTriggerInteraction)1))
				{
					Vector3 val3 = ((RaycastHit)(ref val2)).point - _islandPosition;
					val3.y = 0f;
					float num3 = Vector3.Dot(val3, outward);
					num = Mathf.Max(num, num3);
				}
			}
			return num;
		}

		private void ReplaceMissingSamples(bool[] validDirections)
		{
			for (int i = 0; i < _shoreRadii.Length; i++)
			{
				if (!validDirections[i])
				{
					int num = FindValidNeighbor(i, -1, validDirections);
					int num2 = FindValidNeighbor(i, 1, validDirections);
					if (num != i && num2 != i)
					{
						int num3 = (num2 - num + _shoreRadii.Length) % _shoreRadii.Length;
						int num4 = (i - num + _shoreRadii.Length) % _shoreRadii.Length;
						_shoreRadii[i] = Mathf.Lerp(_shoreRadii[num], _shoreRadii[num2], (float)num4 / (float)num3);
					}
				}
			}
		}

		private int FindValidNeighbor(int startIndex, int step, bool[] validDirections)
		{
			int num = startIndex;
			for (int i = 0; i < _shoreRadii.Length; i++)
			{
				num = (num + step + _shoreRadii.Length) % _shoreRadii.Length;
				if (validDirections[num])
				{
					return num;
				}
			}
			return startIndex;
		}

		private float GetShoreRadius(Vector3 offset)
		{
			//IL_001e: 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)
			if (_shoreRadii.Length == 0 || ((Vector3)(ref offset)).sqrMagnitude <= 0.0001f)
			{
				return _authoredIslandRadius;
			}
			float num = Mathf.Atan2(offset.z, offset.x);
			if (num < 0f)
			{
				num += MathF.PI * 2f;
			}
			float num2 = num * (float)_shoreRadii.Length / (MathF.PI * 2f);
			int num3 = Mathf.FloorToInt(num2) % _shoreRadii.Length;
			int num4 = (num3 + 1) % _shoreRadii.Length;
			return Mathf.Lerp(_shoreRadii[num3], _shoreRadii[num4], num2 - (float)num3);
		}

		private void Clear()
		{
			if (Object.op_Implicit((Object)(object)_sampledIsland) || _shoreRadii.Length != 0)
			{
				_sampledIsland = null;
				_shoreRadii = Array.Empty<float>();
				_authoredIslandRadius = 0f;
				_revision++;
			}
		}

		private static float HorizontalSqrDistance(Vector3 first, Vector3 second)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			float num = first.x - second.x;
			float num2 = first.z - second.z;
			return num * num + num2 * num2;
		}
	}
	internal sealed class OpenSeaBoundaryMarkers : MonoBehaviour
	{
		private const float MarkerSpacing = 10f;

		private const float MarkerDiameter = 0.6f;

		private const string MarkerShaderName = "Universal Render Pipeline/Lit";

		private static readonly int BaseColorId = Shader.PropertyToID("_BaseColor");

		private static readonly Color MarkerColor = Color32.op_Implicit(new Color32(byte.MaxValue, (byte)60, (byte)12, byte.MaxValue));

		private readonly List<Transform> _markers = new List<Transform>();

		private OpenSeaBoundary _openSeaBoundary;

		private GameObject? _markerRoot;

		private Material? _markerMaterial;

		private Mesh? _markerMesh;

		private int _boundaryRevision = -1;

		private float _boundaryOffset = -1f;

		public void Initialize(OpenSeaBoundary openSeaBoundary)
		{
			_openSeaBoundary = openSeaBoundary;
		}

		private void Update()
		{
			if (IslandManager.IsLoading || !Object.op_Implicit((Object)(object)Island.CurIsland))
			{
				ClearMarkers();
				return;
			}
			int revision = _openSeaBoundary.Revision;
			float distanceBeyondIsland = _openSeaBoundary.DistanceBeyondIsland;
			if (!Object.op_Implicit((Object)(object)_markerRoot) || revision != _boundaryRevision || !Mathf.Approximately(distanceBeyondIsland, _boundaryOffset))
			{
				CreateMarkers(revision, distanceBeyondIsland);
			}
			UpdateWaterHeights();
		}

		private void CreateMarkers(int boundaryRevision, float boundaryOffset)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Expected O, but got Unknown
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: 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_00d1: 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_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			ClearMarkers();
			_boundaryRevision = boundaryRevision;
			_boundaryOffset = boundaryOffset;
			_markerRoot = new GameObject("Open Sea Boundary Markers");
			_markerRoot.transform.SetParent(((Component)this).transform, false);
			int sampleCount = _openSeaBoundary.SampleCount;
			if (sampleCount == 0)
			{
				return;
			}
			Vector3[] array = (Vector3[])(object)new Vector3[sampleCount];
			float[] array2 = new float[sampleCount];
			float num = 0f;
			for (int i = 0; i < _openSeaBoundary.SampleCount; i++)
			{
				array[i] = _openSeaBoundary.GetBoundaryPoint(i, boundaryOffset);
			}
			for (int j = 0; j < sampleCount; j++)
			{
				num += (array2[j] = Vector3.Distance(array[j], array[(j + 1) % sampleCount]));
			}
			if (num <= Mathf.Epsilon)
			{
				CreateMarker(0, array[0]);
				return;
			}
			int num2 = Mathf.Max(1, Mathf.RoundToInt(num / 10f));
			float num3 = num / (float)num2;
			int k = 0;
			float num4 = 0f;
			for (int l = 0; l < num2; l++)
			{
				float num5;
				for (num5 = (float)l * num3; k < sampleCount && (array2[k] <= Mathf.Epsilon || num4 + array2[k] < num5); k++)
				{
					num4 += array2[k];
				}
				if (k < sampleCount)
				{
					float num6 = (num5 - num4) / array2[k];
					Vector3 position = Vector3.Lerp(array[k], array[(k + 1) % sampleCount], num6);
					CreateMarker(l, position);
					continue;
				}
				break;
			}
		}

		private void CreateMarker(int index, Vector3 position)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			//IL_0045: 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_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Expected O, but got Unknown
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject($"Open Sea Boundary Point {index + 1}");
			val.layer = LayerMask.NameToLayer("Ignore Raycast");
			val.transform.SetParent(_markerRoot.transform, true);
			val.transform.position = position;
			val.transform.localScale = Vector3.one * 0.6f;
			MeshFilter obj = val.AddComponent<MeshFilter>();
			if (!Object.op_Implicit((Object)(object)_markerMesh))
			{
				_markerMesh = CreateMarkerMesh();
			}
			obj.sharedMesh = _markerMesh;
			MeshRenderer obj2 = val.AddComponent<MeshRenderer>();
			if (!Object.op_Implicit((Object)(object)_markerMaterial))
			{
				Shader val2 = Shader.Find("Universal Render Pipeline/Lit");
				if (!Object.op_Implicit((Object)(object)val2))
				{
					Plugin.Log.LogError((object)"Could not find the Universal Render Pipeline/Lit shader for boundary markers.");
				}
				else
				{
					_markerMaterial = new Material(val2)
					{
						name = "Open Sea Boundary Orange Red",
						color = MarkerColor
					};
					_markerMaterial.SetColor(BaseColorId, MarkerColor);
				}
			}
			((Renderer)obj2).sharedMaterial = _markerMaterial;
			((Renderer)obj2).shadowCastingMode = (ShadowCastingMode)1;
			((Renderer)obj2).receiveShadows = true;
			_markers.Add(val.transform);
		}

		private static Mesh CreateMarkerMesh()
		{
			//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)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: 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_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_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: 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_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cf: Expected O, but got Unknown
			float num = (1f + Mathf.Sqrt(5f)) * 0.5f;
			Vector3[] array = (Vector3[])(object)new Vector3[12]
			{
				new Vector3(-1f, num, 0f),
				new Vector3(1f, num, 0f),
				new Vector3(-1f, 0f - num, 0f),
				new Vector3(1f, 0f - num, 0f),
				new Vector3(0f, -1f, num),
				new Vector3(0f, 1f, num),
				new Vector3(0f, -1f, 0f - num),
				new Vector3(0f, 1f, 0f - num),
				new Vector3(num, 0f, -1f),
				new Vector3(num, 0f, 1f),
				new Vector3(0f - num, 0f, -1f),
				new Vector3(0f - num, 0f, 1f)
			};
			int[] array2 = new int[60]
			{
				0, 11, 5, 0, 5, 1, 0, 1, 7, 0,
				7, 10, 0, 10, 11, 1, 5, 9, 5, 11,
				4, 11, 10, 2, 10, 7, 6, 7, 1, 8,
				3, 9, 4, 3, 4, 2, 3, 2, 6, 3,
				6, 8, 3, 8, 9, 4, 9, 5, 2, 4,
				11, 6, 2, 10, 8, 6, 7, 9, 8, 1
			};
			Vector3[] array3 = (Vector3[])(object)new Vector3[array2.Length];
			int[] array4 = new int[array2.Length];
			for (int i = 0; i < array2.Length; i++)
			{
				array3[i] = ((Vector3)(ref array[array2[i]])).normalized * 0.5f;
				array4[i] = i;
			}
			Mesh val = new Mesh
			{
				name = "Open Sea Boundary Low-Poly Icosahedron",
				vertices = array3,
				triangles = array4
			};
			val.RecalculateNormals();
			val.RecalculateBounds();
			val.UploadMeshData(true);
			return val;
		}

		private void UpdateWaterHeights()
		{
			//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_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			foreach (Transform marker in _markers)
			{
				if (Object.op_Implicit((Object)(object)marker))
				{
					Vector3 position = marker.position;
					position.y = WaterManager.GetWaterHeight(position);
					marker.position = position;
				}
			}
		}

		private void ClearMarkers()
		{
			if (Object.op_Implicit((Object)(object)_markerRoot))
			{
				Object.Destroy((Object)(object)_markerRoot);
			}
			_markerRoot = null;
			_markers.Clear();
			_boundaryRevision = -1;
			_boundaryOffset = -1f;
		}

		private void OnDestroy()
		{
			ClearMarkers();
			if (Object.op_Implicit((Object)(object)_markerMaterial))
			{
				Object.Destroy((Object)(object)_markerMaterial);
			}
			if (Object.op_Implicit((Object)(object)_markerMesh))
			{
				Object.Destroy((Object)(object)_markerMesh);
			}
		}
	}
	internal sealed class OpenSeaConfig
	{
		public ConfigEntry<bool> PiratesEnabled { get; }

		public ConfigEntry<float> DistanceBeyondIsland { get; }

		public ConfigEntry<float> DifficultyMultiplier { get; }

		public ConfigEntry<int> MaximumActiveBoats { get; }

		public ConfigEntry<bool> BoundaryMarkersEnabled { get; }

		public bool StreamModeEnabled => false;

		public int StreamBoatsPerTeam => 3;

		public OpenSeaConfig(ConfigFile config)
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Expected O, but got Unknown
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Expected O, but got Unknown
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Expected O, but got Unknown
			PiratesEnabled = config.Bind<bool>("Pirates", "Enabled", true, "Spawn pirate encounters in the open ocean. The host's setting controls multiplayer encounters.");
			DistanceBeyondIsland = config.Bind<float>("Pirates", "DistanceBeyondIsland", 60f, new ConfigDescription("Horizontal distance in metres beyond the sampled island shoreline before pirates spawn.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 500f), Array.Empty<object>()));
			DifficultyMultiplier = config.Bind<float>("Pirates", "DifficultyMultiplier", 1f, new ConfigDescription("Multiplier applied to the value budget used to equip and reinforce pirate fleets. Lower values make encounters easier; higher values make them harder.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.25f, 3f), Array.Empty<object>()));
			MaximumActiveBoats = config.Bind<int>("Pirates", "MaximumActiveBoats", 8, new ConfigDescription("Maximum number of pirate boats that may be active at once.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 8), Array.Empty<object>()));
			BoundaryMarkersEnabled = config.Bind<bool>("Visuals", "BoundaryMarkersEnabled", true, "Show the orange-red markers around the open-sea encounter boundary.");
		}
	}
	[HarmonyPatch(typeof(GameInfo), "Awake")]
	internal static class ItemFishGameCatalogPatch
	{
		private static void Postfix()
		{
			try
			{
				PirateCollectibleSupport.RegisterPirateItem();
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"Could not register the pirate item: {arg}");
			}
			ItemFishRegistry.ApplyGameCatalog();
		}
	}
	[HarmonyPatch(typeof(NetworkManager), "Awake")]
	internal static class ItemFishNetworkCatalogPatch
	{
		private static void Postfix(NetworkManager __instance)
		{
			ItemFishRegistry.ApplyNetworkManager(__instance);
		}
	}
	[HarmonyPatch(typeof(Item), "GetName")]
	internal static class CustomItemDisplayNamePatch
	{
		private static bool Prefix(Item __instance, ref string __result)
		{
			if (ItemFishRegistry.TryGetDisplayName(__instance, out string displayName))
			{
				__result = displayName;
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch]
	internal static class PirateBoatDrivingInitializationPatch
	{
		private static readonly FieldInfo DrivingField = AccessTools.Field(typeof(Boat), "<IsDrivingLocally>k__BackingField");

		private static readonly FieldInfo WantToDriveField = AccessTools.Field(typeof(Boat), "<WantToDrive>k__BackingField");

		private static IEnumerable<MethodBase> TargetMethods()
		{
			yield return AccessTools.Method(typeof(Boat), "Awake", (Type[])null, (Type[])null);
			yield return AccessTools.Method(typeof(Boat), "OnStartClient", (Type[])null, (Type[])null);
		}

		private static void Prefix(Boat __instance, out (bool Preserve, bool Driving, bool Want) __state)
		{
			__state = (Preserve: Object.op_Implicit((Object)(object)BoatManager.Boat) && (Object)(object)BoatManager.Boat != (Object)(object)__instance, Driving: Boat.IsDrivingLocally, Want: Boat.WantToDrive);
		}

		private static void Finalizer((bool Preserve, bool Driving, bool Want) __state)
		{
			if (__state.Preserve)
			{
				DrivingField.SetValue(null, __state.Driving);
				WantToDriveField.SetValue(null, __state.Want);
			}
		}
	}
	[HarmonyPatch(typeof(Boat), "OnDriverChange")]
	internal static class PirateBoatDriverChangePatch
	{
		private static bool Prefix(Boat __instance)
		{
			return !PirateBoatSupport.IsPirateBoat(__instance);
		}
	}
	[HarmonyPatch(typeof(Boat), "OnStartClient")]
	internal static class PirateBoatClientRegistrationPatch
	{
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			MethodInfo original = AccessTools.Method(typeof(BoatManager), "SetBoat", (Type[])null, (Type[])null);
			MethodInfo replacement = AccessTools.Method(typeof(PirateBoatClientRegistrationPatch), "Register", (Type[])null, (Type[])null);
			foreach (CodeInstruction instruction in instructions)
			{
				if (CodeInstructionExtensions.Calls(instruction, original))
				{
					instruction.operand = replacement;
				}
				yield return instruction;
			}
		}

		private static void Register(Collider[] cols, Boat boat)
		{
			if (!PirateBoatSupport.IsPirateBoat(boat))
			{
				BoatManager.SetBoat(cols, boat);
				return;
			}
			foreach (Collider key in cols)
			{
				BoatManager.ColToBoat[key] = boat;
			}
		}
	}
	[HarmonyPatch(typeof(Boat), "OnStopClient")]
	internal static class PirateBoatClientRemovalPatch
	{
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			MethodInfo original = AccessTools.Method(typeof(BoatManager), "RemoveBoat", (Type[])null, (Type[])null);
			MethodInfo replacement = AccessTools.Method(typeof(PirateBoatClientRemovalPatch), "Remove", (Type[])null, (Type[])null);
			foreach (CodeInstruction instruction in instructions)
			{
				if (CodeInstructionExtensions.Calls(instruction, original))
				{
					yield return CodeInstructionExtensions.MoveLabelsFrom(new CodeInstruction(OpCodes.Ldarg_0, (object)null), instruction);
					instruction.operand = replacement;
				}
				yield return instruction;
			}
		}

		private static void Remove(Boat boat)
		{
			if ((Object)(object)boat == (Object)(object)BoatManager.Boat && !PirateBoatSupport.IsPirateBoat(boat))
			{
				BoatManager.RemoveBoat();
				return;
			}
			List<Collider> list = new List<Collider>();
			foreach (KeyValuePair<Collider, Boat> item in BoatManager.ColToBoat)
			{
				if ((Object)(object)item.Value == (Object)(object)boat)
				{
					list.Add(item.Key);
				}
			}
			foreach (Collider item2 in list)
			{
				BoatManager.ColToBoat.Remove(item2);
			}
		}
	}
	[HarmonyPatch(typeof(BoatTrigger), "FixedUpdate")]
	internal static class PirateBoatCargoTriggerPatch
	{
		private static void Postfix(BoatTrigger __instance)
		{
			Boat boat;
			bool flag = PirateBoatSupport.TryGetPirateBoat(__instance, out boat);
			foreach (RigidbodySync item in __instance.ItemsOnBoat)
			{
				if (Object.op_Implicit((Object)(object)item))
				{
					PirateBoatCargo pirateBoatCargo = ((Component)item).GetComponent<PirateBoatCargo>();
					if (flag && !Object.op_Implicit((Object)(object)pirateBoatCargo))
					{
						pirateBoatCargo = ((Component)item).gameObject.AddComponent<PirateBoatCargo>();
					}
					if (Object.op_Implicit((Object)(object)pirateBoatCargo))
					{
						pirateBoatCargo.Boat = (flag ? boat : null);
						item.SetBoat(true);
					}
				}
			}
		}
	}
	internal sealed class PirateBoatCargo : MonoBehaviour
	{
		public Boat? Boat;

		public static bool UsePlayerBoatCoordinates(RigidbodySync sync)
		{
			PirateBoatCargo component = ((Component)sync).GetComponent<PirateBoatCargo>();
			PirateCreatureLink component2 = ((Component)sync).GetComponent<PirateCreatureLink>();
			if (sync.OnBoat && (!Object.op_Implicit((Object)(object)component) || !Object.op_Implicit((Object)(object)component.Boat)))
			{
				if (Object.op_Implicit((Object)(object)component2))
				{
					return !component2.IsAttached;
				}
				return true;
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(RigidbodySync), "SetBoat")]
	internal static class PirateBoatCargoLeavePatch
	{
		private static void Postfix(RigidbodySync __instance, bool onBoat)
		{
			if (!onBoat)
			{
				PirateBoatCargo component = ((Component)__instance).GetComponent<PirateBoatCargo>();
				if (Object.op_Implicit((Object)(object)component))
				{
					component.Boat = null;
				}
			}
		}
	}
	[HarmonyPatch(typeof(RigidbodySync), "GetSendBoatVisual")]
	internal static class PirateBoatCargoSendFramePatch
	{
		private static bool Prefix(RigidbodySync __instance, ref Transform? __result)
		{
			if (PirateBoatCargo.UsePlayerBoatCoordinates(__instance))
			{
				return true;
			}
			__result = null;
			return false;
		}
	}
	[HarmonyPatch(typeof(RigidbodySync), "SendPosRotToObservers")]
	internal static class PirateBoatCargoPacketPatch
	{
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			MethodInfo original = AccessTools.PropertyGetter(typeof(RigidbodySync), "OnBoat");
			MethodInfo replacement = AccessTools.Method(typeof(PirateBoatCargo), "UsePlayerBoatCoordinates", (Type[])null, (Type[])null);
			foreach (CodeInstruction instruction in instructions)
			{
				if (CodeInstructionExtensions.Calls(instruction, original))
				{
					instruction.opcode = OpCodes.Call;
					instruction.operand = replacement;
				}
				yield return instruction;
			}
		}
	}
	[HarmonyPatch(typeof(Boat), "OnStartClient")]
	internal static class PirateBoatStartClientPatch
	{
		private static void Prefix(Boat __instance, out Boat? __state)
		{
			Boat boat = BoatManager.Boat;
			__state = ((Object.op_Implicit((Object)(object)boat) && (Object)(object)boat != (Object)(object)__instance) ? boat : null);
			if (Object.op_Implicit((Object)(object)__state))
			{
				PirateBoatSupport.IdentifyClientPirate(__instance);
			}
		}

		private static void Postfix(Boat __instance, Boat? __state)
		{
			if (Object.op_Implicit((Object)(object)__state))
			{
				PirateBoatSupport.ConfigureClientPirate(__instance, __state);
			}
		}
	}
	[HarmonyPatch(typeof(Boat), "OnStartServer")]
	internal static class PirateBoatStartServerPatch
	{
		private static void Postfix(Boat __instance)
		{
			PirateBoatSupport.ApplyServerPirateDefaults(__instance);
		}
	}
	[HarmonyPatch(typeof(Boat), "OnSkinChange")]
	internal static class PirateBoatSkinPatch
	{
		private static bool Prefix(Boat __instance, byte next)
		{
			return PirateBoatSupport.ShouldApplyBoatSkin(__instance, next);
		}
	}
	[HarmonyPatch(typeof(Boat), "OnMotorChange")]
	internal static class PirateBoatMotorAchievementScopePatch
	{
		private static void Prefix(Boat __instance, out bool __state)
		{
			__state = PirateBoatSupport.BeginPirateMotorChange(__instance);
		}

		private static void Postfix(bool __state)
		{
			if (__state)
			{
				PirateBoatSupport.EndPirateMotorChange();
			}
		}
	}
	[HarmonyPatch(typeof(AchievementManager), "CheckBoatUpgradeAchievement")]
	internal static class PirateBoatMotorAchievementPatch
	{
		private static bool Prefix()
		{
			return !PirateBoatSupport.IsApplyingPirateMotor;
		}
	}
	[HarmonyPatch(typeof(Boat), "OnStopClient")]
	internal static class PirateBoatStopClientPatch
	{
		private static void Prefix(Boat __instance, out Boat? __state)
		{
			Boat boat = BoatManager.Boat;
			__state = ((Object.op_Implicit((Object)(object)boat) && (Object)(object)boat != (Object)(object)__instance) ? boat : null);
		}

		private static void Postfix(Boat __instance, Boat? __state)
		{
			PirateBoatSupport.UnregisterServerPirate(__instance);
			if (Object.op_Implicit((Object)(object)__state))
			{
				PirateBoatSupport.RestoreMainBoat(__state);
			}
		}
	}
	[HarmonyPatch(typeof(Boat), "ApplyReturnForce")]
	internal static class PirateBoatReturnForcePatch
	{
		private static bool Prefix(Boat __instance)
		{
			return PirateBoatSupport.ShouldApplyAutomaticReturnForce(__instance);
		}
	}
	[HarmonyPatch(typeof(Boat), "ApplyInputForce")]
	internal static class PirateBoatInputForcePatch
	{
		private static bool Prefix(Boat __instance)
		{
			if (!PirateBoatSupport.IsServerPirate(__instance))
			{
				return true;
			}
			PirateBoatController component = ((Component)__instance).GetComponent<PirateBoatController>();
			if (Object.op_Implicit((Object)(object)component))
			{
				component.ApplyNativeInputForce();
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(Boat), "ApplyWaterForce")]
	internal static class PirateBoatWaterForcePatch
	{
		private static bool Prefix(Boat __instance)
		{
			PirateBoatController component = ((Component)__instance).GetComponent<PirateBoatController>();
			if (Object.op_Implicit((Object)(object)component) && component.IsSinking)
			{
				component.ReduceNativeBuoyancy();
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(Boat), "UpdateCollider")]
	internal static class PirateBoatColliderSyncPatch
	{
		private static readonly FieldInfo DynamicCollidersHolderField = AccessTools.Field(typeof(Boat), "_dynamicObjectColsHolder");

		private static readonly FieldInfo ItemCollidersHolderField = AccessTools.Field(typeof(Boat), "_itemColsHolder");

		private static readonly FieldInfo LerpPositionField = AccessTools.Field(typeof(Boat), "_curLerpedPos");

		private static readonly FieldInfo LerpRotationField = AccessTools.Field(typeof(Boat), "_curLerpedRot");

		private static bool Prefix(Boat __instance)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			//IL_009e: 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_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			if (!PirateBoatSupport.IsPirateBoat(__instance))
			{
				return true;
			}
			Transform val = (Transform)DynamicCollidersHolderField.GetValue(__instance);
			if (((NetworkBehaviour)__instance).IsServerInitialized)
			{
				Rigidbody val2 = (Rigidbody)ItemCollidersHolderField.GetValue(__instance);
				val.SetPositionAndRotation(__instance.HiddenPhysicsRig.position, __instance.HiddenPhysicsRig.rotation);
				val2.MovePosition(__instance.HiddenPhysicsRig.position);
				val2.MoveRotation(__instance.HiddenPhysicsRig.rotation);
				if (!val2.isKinematic)
				{
					val2.linearVelocity = Vector3.zero;
					val2.angularVelocity = Vector3.zero;
				}
			}
			else
			{
				val.position = (Vector3)LerpPositionField.GetValue(__instance);
				val.rotation = (Quaternion)LerpRotationField.GetValue(__instance);
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(BoatTrigger), "TellPlayerTheyAreOnBoat")]
	internal static class PirateBoatTriggerPlayerPatch
	{
		private struct RideTransition
		{
			public Boat? PreviousBoat;

			public Boat? PirateBoat;

			public bool Switched;

			public bool Leaving;
		}

		private static readonly FieldInfo LocalPlayerOnBoatField = AccessTools.Field(typeof(BoatTrigger), "_localPlayerOnBoat");

		private static readonly FieldInfo OldLocalPlayerOnBoatField = AccessTools.Field(typeof(BoatTrigger), "_oldLocalPlayerOnBoat");

		private static void Prefix(BoatTrigger __instance, out RideTransition __state)
		{
			__state = default(RideTransition);
			if (!PirateBoatSupport.TryGetPirateBoat(__instance, out Boat boat))
			{
				return;
			}
			bool flag = (bool)LocalPlayerOnBoatField.GetValue(__instance);
			bool flag2 = (bool)OldLocalPlayerOnBoatField.GetValue(__instance);
			if (flag != flag2)
			{
				if (flag)
				{
					PirateBoatSupport.BeginLocalPirateRide(boat);
				}
				__state.PreviousBoat = BoatManager.Boat;
				__state.PirateBoat = boat;
				__state.Switched = true;
				__state.Leaving = !flag;
				PirateBoatSupport.SelectPirateBoatForLocalPlayer(boat);
			}
		}

		private static void Postfix(RideTransition __state)
		{
			if (__state.Switched)
			{
				if (__state.Leaving && Object.op_Implicit((Object)(object)__state.PirateBoat))
				{
					PirateBoatSupport.EndLocalPirateRide(__state.PirateBoat);
				}
				PirateBoatSupport.RestoreBoatSelection(__state.PreviousBoat);
			}
		}
	}
	[HarmonyPatch(typeof(PlayerMovement), "FixedUpdate")]
	internal static class PirateBoatPlayerMovementPatch
	{
		private static void Prefix(PlayerMovement __instance, out Boat? __state)
		{
			__state = null;
			if (Object.op_Implicit((Object)(object)Player.LocalPlayer) && (Object)(object)__instance == (Object)(object)Player.LocalPlayer.Movement)
			{
				PirateBoatSupport.SelectLocalRiddenPirate(out __state);
			}
		}

		private static void Postfix(Boat? __state)
		{
			if (Object.op_Implicit((Object)(object)__state))
			{
				PirateBoatSupport.RestoreBoatSelection(__state);
			}
		}
	}
	[HarmonyPatch(typeof(PlayerMovement), "AddBoatPos")]
	internal static class PirateBoatPlayerCarryPatch
	{
		private static void Prefix(PlayerMovement __instance, out Boat? __state)
		{
			__state = null;
			if (Object.op_Implicit((Object)(object)Player.LocalPlayer) && (Object)(object)__instance == (Object)(object)Player.LocalPlayer.Movement)
			{
				PirateBoatSupport.SelectLocalRiddenPirate(out __state);
			}
		}

		private static void Postfix(Boat? __state)
		{
			if (Object.op_Implicit((Object)(object)__state))
			{
				PirateBoatSupport.RestoreBoatSelection(__state);
			}
		}
	}
	[HarmonyPatch(typeof(Boat), "GiveBoatDeltaToPlayerAndItems")]
	internal static class PirateBoatItemCarryPatch
	{
		private static void Prefix(Boat __instance, out Boat? __state)
		{
			__state = null;
			if (PirateBoatSupport.IsPirateBoat(__instance))
			{
				__state = BoatManager.Boat;
				PirateBoatSupport.SelectPirateBoatForLocalPlayer(__instance);
			}
		}

		private static void Postfix(Boat __instance, Boat? __state)
		{
			if (PirateBoatSupport.IsPirateBoat(__instance))
			{
				PirateBoatSupport.RestoreBoatSelection(__state);
			}
		}
	}
	[HarmonyPatch(typeof(Player), "SendPosRot")]
	internal static class PirateBoatPlayerNetworkPositionPatch
	{
		private static readonly FieldInfo SendTeleportField = AccessTools.Field(typeof(Player), "_sendTeleport");

		private static bool Prefix(Player __instance)
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)Player.LocalPlayer) || (Object)(object)__instance != (Object)(object)Player.LocalPlayer || !PirateBoatSupport.IsLocalRidingPirate)
			{
				return true;
			}
			bool flag = (bool)SendTeleportField.GetValue(__instance);
			if (flag)
			{
				SendTeleportField.SetValue(__instance, false);
			}
			Vector3 localEulerAngles = __instance.CamObject.localEulerAngles;
			Server.Instance.UpdatePlayerPosRot(__instance, __instance.Transform.position, new Vector2(localEulerAngles.x, localEulerAngles.y), false, flag, (Channel)1);
			return false;
		}
	}
	[HarmonyPatch(typeof(Boat), "SetLocalPlayerOnBoat")]
	internal static class PirateBoatInteractionStatePatch
	{
		private static void Postfix(Boat __instance)
		{
			if (PirateBoatSupport.IsPirateBoat(__instance))
			{
				PirateBoatSupport.DisableDrivingInteraction(__instance);
			}
		}
	}
	[HarmonyPatch(typeof(BoatInteractable), "Interact")]
	internal static class PirateBoatDriveInteractionPatch
	{
		private static bool Prefix(BoatInteractable __instance)
		{
			return !PirateBoatSupport.IsPirateBoat(((Component)__instance).GetComponentInParent<Boat>());
		}
	}
	[HarmonyPatch]
	internal static class PirateBoatMeleeTargetPatch
	{
		private static readonly FieldInfo PunchPlayerField = AccessTools.Field(typeof(PlayerPunching), "_player");

		private static readonly FieldInfo PunchRangeField = AccessTools.Field(typeof(PlayerPunching), "_range");

		private static readonly FieldInfo MeleeHolderField = AccessTools.Field(typeof(Item), "_holder");

		private static readonly FieldInfo MeleeRangeField = AccessTools.Field(typeof(Melee), "_range");

		private static IEnumerable<MethodBase> TargetMethods()
		{
			yield return AccessTools.Method(typeof(PlayerPunching), "CheckForPlayersAndLevel", (Type[])null, (Type[])null);
			yield return AccessTools.Method(typeof(Melee), "CheckForPlayersAndLevel", (Type[])null, (Type[])null);
		}

		private static void Postfix(object __instance, ref Transform finalTarget, ref Vector3 finalHitPoint)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Expected O, but got Unknown
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)finalTarget) || !((Component)finalTarget).CompareTag("Boat"))
			{
				return;
			}
			Vector3 val = finalTarget.TransformPoint(finalHitPoint);
			if (PirateBoatSupport.TryGetPirateBoatAtPoint(val, out Boat boat))
			{
				Player val2 = ((__instance is PlayerPunching) ? ((Player)PunchPlayerField.GetValue(__instance)) : ((Player)MeleeHolderField.GetValue(__instance)));
				float maxDistance = ((__instance is PlayerPunching) ? ((float)PunchRangeField.GetValue(__instance)) : ((float)MeleeRangeField.GetValue(__instance)));
				if (Object.op_Implicit((Object)(object)val2) && Object.op_Implicit((Object)(object)val2.CamObject) && PirateBoatSupport.TryGetLivingPirateHit(boat, new Ray(val2.CamObject.position, val2.CamObject.forward), maxDistance, 0f, out var pirateHit))
				{
					finalTarget = ((RaycastHit)(ref pirateHit)).transform;
					finalHitPoint = finalTarget.InverseTransformPoint(((RaycastHit)(ref pirateHit)).point);
				}
				else
				{
					finalTarget = boat.VisualBoat;
					finalHitPoint = finalTarget.InverseTransformPoint(val);
				}
			}
		}
	}
	[HarmonyPatch]
	internal static class PirateBoatMeleeForcePatch
	{
		private static readonly FieldInfo PunchTargetsField = AccessTools.Field(typeof(PlayerPunching), "_curTarget");

		private static readonly FieldInfo MeleeTargetsField = AccessTools.Field(typeof(Melee), "_curTarget");

		private static IEnumerable<MethodBase> TargetMethods()
		{
			yield return AccessTools.Method(typeof(PlayerPunching), "HitTarget", (Type[])null, (Type[])null);
			yield return AccessTools.Method(typeof(Melee), "HitTarget", (Type[])null, (Type[])null);
		}

		private static void Prefix(object __instance, int side, out Boat? __state)
		{
			__state = null;
			Transform[] array = (Transform[])((__instance is PlayerPunching) ? PunchTargetsField : MeleeTargetsField).GetValue(__instance);
			if (side >= 0 && side < array.Length && PirateBoatSupport.TryGetPirateBoat(array[side], out Boat boat))
			{
				__state = BoatManager.Boat;
				PirateBoatSupport.SelectPirateBoatForLocalPlayer(boat);
			}
		}

		private static void Postfix(Boat? __state)
		{
			if (Object.op_Implicit((Object)(object)__state))
			{
				PirateBoatSupport.RestoreBoatSelection(__state);
			}
		}
	}
	[HarmonyPatch(typeof(ProjectileManager), "Hit")]
	internal static class PirateBoatProjectileForcePatch
	{
		private static void Prefix(RaycastHit hit, out Boat? __state)
		{
			__state = null;
			if (PirateBoatSupport.TryGetPirateBoat(((RaycastHit)(ref hit)).transform, out Boat boat))
			{
				__state = BoatManager.Boat;
				PirateBoatSupport.SelectPirateBoatForLocalPlayer(boat);
			}
		}

		private static void Postfix(Boat? __state)
		{
			if (Object.op_Implicit((Object)(object)__state))
			{
				PirateBoatSupport.RestoreBoatSelection(__state);
			}
		}
	}
	[HarmonyPatch(typeof(PlayerInventory), "LocalTrySelectSlot")]
	internal static class PirateCorpseInventorySlotPatch
	{
		private static void Prefix(PlayerInventory __instance)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			Player componentInParent = ((Component)__instance).GetComponentInParent<Player>();
			Item val = (Object.op_Implicit((Object)(object)componentInParent) ? componentInParent.Holding.HeldItem : null);
			if (PirateCollectibleSupport.IsPirateCorpse(val))
			{
				val.Drop(true, default(Vector3), default(Vector3));
			}
		}
	}
	[HarmonyPatch(typeof(PlayerInventory), "ResolveHeldItemReplacement")]
	internal static class PirateCorpseHeldReplacementPatch
	{
		private static bool Prefix(Item item)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			if (!PirateCollectibleSupport.IsPirateCorpse(item))
			{
				return true;
			}
			item.Drop(false, default(Vector3), default(Vector3));
			return false;
		}
	}
	[HarmonyPatch(typeof(PlayerInventory), "ServerTryStoreHeldItem")]
	internal static class PirateCorpseServerStorePatch
	{
		private static bool Prefix(Item item, ref bool __result)
		{
			if (!PirateCollectibleSupport.IsPirateCorpse(item))
			{
				return true;
			}
			__result = false;
			return false;
		}
	}
	[HarmonyPatch(typeof(PlayerInventory), "AddItem")]
	internal static class PirateCorpseInventoryAddPatch
	{
		private static bool Prefix(Item item)
		{
			return !PirateCollectibleSupport.IsPirateCorpse(item);
		}
	}
	[HarmonyPatch(typeof(Item), "PutInInventory")]
	internal static class PirateCorpsePutInInventoryPatch
	{
		private static bool Prefix(Item __instance)
		{
			return !PirateCollectibleSupport.IsPirateCorpse(__instance);
		}
	}
	[HarmonyPatch(typeof(Item), "UpdateLayer")]
	internal static class PirateCorpsePlayerCollisionPatch
	{
		private static readonly FieldInfo DisablePlayerCollisionField = AccessTools.Field(typeof(Item), "_disablePlayerColOnGround");

		private static void Prefix(Item __instance)
		{
			if (PirateCollectibleSupport.IsPirateCorpse(__instance))
			{
				DisablePlayerCollisionField.SetValue(__instance, true);
			}
		}
	}
	[HarmonyPatch(typeof(PlayerHolding), "ScanForInteractable")]
	internal static class PirateCorpseSteeringInteractionPatch
	{
		private static void Prefix(Player ____player, ref Item ____grabbableItem, ref Interactable ____interactable, out Item? __state)
		{
			__state = null;
			if (PirateCollectibleSupport.IsPirateCorpse(____grabbableItem) && !____player.BlockInputs && !Boat.IsDrivingLocally && !Boat.WantToDrive)
			{
				__state = ____grabbableItem;
				____grabbableItem.UnHover();
				____grabbableItem = null;
				if (Object.op_Implicit((Object)(object)____interactable))
				{
					____interactable.UnHover();
					____interactable = null;
				}
			}
		}

		private static void Postfix(ref Item ____grabbableItem, ref Interactable ____interactable, Item? __state)
		{
			if (!Object.op_Implicit((Object)(object)__state))
			{
				return;
			}
			Interactable obj = ____interactable;
			BoatInteractable val = (BoatInteractable)(object)((obj is BoatInteractable) ? obj : null);
			if (val != null)
			{
				Boat componentInParent = ((Component)val).GetComponentInParent<Boat>();
				if (Object.op_Implicit((Object)(object)componentInParent) && (Object)(object)componentInParent == (Object)(object)BoatManager.Boat && !PirateBoatSupport.IsPirateBoat(componentInParent))
				{
					return;
				}
			}
			if (Object.op_Implicit((Object)(object)____interactable))
			{
				____interactable.UnHover();
				____interactable = null;
			}
			____grabbableItem = __state;
			__state.Hover();
		}
	}
	[HarmonyPatch(typeof(ItemManager), "FloatItems")]
	internal static class PirateCorpseWaterClassificationPatch
	{
		private static readonly FieldInfo CreatureReferenceField = AccessTools.Field(typeof(Item), "_creature");

		private static readonly Dictionary<Item, Creature> MaskedCreatures = new Dictionary<Item, Creature>();

		private static void Prefix()
		{
			MaskedCreatures.Clear();
			foreach (Item value in ItemManager.Items.Values)
			{
				if (PirateCollectibleSupport.IsPirateCorpse(value) && !MaskedCreatures.ContainsKey(value))
				{
					Creature creature = value.Creature;
					if (Object.op_Implicit((Object)(object)creature))
					{
						MaskedCreatures.Add(value, creature);
						CreatureReferenceField.SetValue(value, null);
					}
				}
			}
		}

		private static Exception? Finalizer(Exception? __exception)
		{
			foreach (KeyValuePair<Item, Creature> maskedCreature in MaskedCreatures)
			{
				if (Object.op_Implicit((Object)(object)maskedCreature.Key))
				{
					CreatureReferenceField.SetValue(maskedCreature.Key, maskedCreature.Value);
				}
			}
			MaskedCreatures.Clear();
			return __exception;
		}
	}
	[HarmonyPatch(typeof(ProjectileManager), "Hit")]
	[HarmonyPriority(801)]
	internal static class StreamProjectileFriendlyFirePatch
	{
		private const float FriendlyPassThroughDistance = 0.75f;

		private static bool Prefix(Projectile projectile, ref RaycastHit hit)
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			PirateTeam streamProjectileTeam = PirateProjectileSupport.GetStreamProjectileTeam(projectile.Id);
			if (streamProjectileTeam == PirateTeam.None || !Object.op_Implicit((Object)(object)((RaycastHit)(ref hit)).collider))
			{
				return true;
			}
			Boat boat;
			bool flag = PirateBoatSupport.TryGetPirateBoat(((RaycastHit)(ref hit)).transform, out boat);
			if (!flag && ((Component)((RaycastHit)(ref hit)).transform).CompareTag("Boat"))
			{
				flag = PirateBoatSupport.TryGetPirateBoatAtPoint(((RaycastHit)(ref hit)).point, out boat);
			}
			if (!flag || PirateBoatSupport.GetTeam(boat) != streamProjectileTeam)
			{
				return true;
			}
			Vector3 normalized = ((Vector3)(ref projectile.Velocity)).normalized;
			if (((Vector3)(ref normalized)).sqrMagnitude > 0.001f)
			{
				projectile.Position = ((RaycastHit)(ref hit)).point + normalized * 0.75f;
				projectile.PreviousPosition = projectile.Position;
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(ProjectileManager), "Hit")]
	[HarmonyPriority(800)]
	internal static class PirateCrewProjectileOcclusionPatch
	{
		private const float MaximumHullTraversalDistance = 12f;

		private static void Prefix(Projectile projectile, ProjectileType type, ref RaycastHit hit)
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			if (projectile.FromNpc || !Object.op_Implicit((Object)(object)((RaycastHit)(ref hit)).collider))
			{
				return;
			}
			Boat boat;
			Boat val = (PirateBoatSupport.TryGetPirateBoat(((RaycastHit)(ref hit)).transform, out boat) ? boat : null);
			if (!Object.op_Implicit((Object)(object)val) && !((Component)((RaycastHit)(ref hit)).transform).CompareTag("Boat"))
			{
				return;
			}
			Vector3 normalized = ((Vector3)(ref projectile.Velocity)).normalized;
			if (!(((Vector3)(ref normalized)).sqrMagnitude <= 0.001f))
			{
				Ray ray = default(Ray);
				((Ray)(ref ray))..ctor(projectile.Position, normalized);
				float maxDistance = ((RaycastHit)(ref hit)).distance + 12f;
				if (PirateBoatSupport.TryGetLivingPirateHit(val, ray, maxDistance, type.WidthRadius, out var pirateHit))
				{
					hit = pirateHit;
				}
			}
		}
	}
	[HarmonyPatch(typeof(CreatureManager), "AddAliveCreature")]
	internal static class PirateCreatureManagerRegistrationPatch
	{
		private static bool Prefix(Creature creature)
		{
			return !Object.op_Implicit((Object)(object)((Component)creature).GetComponent<PirateCreatureProxy>());
		}
	}
	[HarmonyPatch(typeof(ItemManager), "OnIslandUnloaded")]
	internal static class PirateCreatureIslandCleanupPatch
	{
		private static void Prefix(out List<KeyValuePair<Transform, Item>> __state)
		{
			__state = new List<KeyValuePair<Transform, Item>>();
			foreach (KeyValuePair<Transform, Item> item in ItemManager.Items)
			{
				PirateCreatureLink pirateCreatureLink = (Object.op_Implicit((Object)(object)item.Value) ? ((Component)item.Value).GetComponent<PirateCreatureLink>() : null);
				if (Object.op_Implicit((Object)(object)pirateCreatureLink) && pirateCreatureLink.IsAttached)
				{
					__state.Add(item);
				}
			}
			foreach (KeyValuePair<Transform, Item> item2 in __state)
			{
				ItemManager.Items.Remove(item2.Key);
			}
		}

		private static void Postfix(List<KeyValuePair<Transform, Item>> __state)
		{
			foreach (KeyValuePair<Transform, Item> item in __state)
			{
				if (Object.op_Implicit((Object)(object)item.Key) && Object.op_Implicit((Object)(object)item.Value))
				{
					ItemManager.Items.TryAdd(item.Key, item.Value);
				}
			}
		}
	}
	[HarmonyPatch(typeof(Creature), "OnStartClient")]
	internal static class PirateCollectibleStartClientPatch
	{
		private static void Prefix(Creature __instance, out PirateCrewHealth? __state)
		{
			if (!PirateCollectibleSupport.IsPirateProxy((Item)(object)__instance))
			{
				__state = null;
				return;
			}
			if (__instance._hp.Value <= 0)
			{
				__state = null;
				PirateCollectibleSupport.PrepareRestoredCorpse((Item)(object)__instance, ((NetworkBehaviour)__instance).ObjectId);
				return;
			}
			__state = PirateCollectibleSupport.FindMatchingPirate(__instance);
			if (Object.op_Implicit((Object)(object)__state))
			{
				PirateCollectibleSupport.Prepare(__instance, __state);
			}
			else if (!((NetworkBehaviour)__instance).IsServerInitialized)
			{
				PirateCollectibleSupport.QueuePendingClientBinding(__instance);
			}
		}

		private static void Postfix(Creature __instance, PirateCrewHealth? __state)
		{
			if (Object.op_Implicit((Object)(object)__state))
			{
				PirateCollectibleSupport.BindLivingCreature(__instance, __state);
			}
			else if (PirateCollectibleSupport.IsPirateProxy((Item)(object)__instance) && __instance._hp.Value <= 0)
			{
				PirateCollectibleSupport.FinalizeRestoredCorpse((Item)(object)__instance);
			}
		}
	}
	[HarmonyPatch(typeof(Creature), "ServerChangeHp")]
	internal static class PirateCreatureServerDeathPatch
	{
		private static void Postfix(Creature __instance)
		{
			PirateCreatureLink component = ((Component)__instance).GetComponent<PirateCreatureLink>();
			if (Object.op_Implicit((Object)(object)component))
			{
				component.TryAdoptIfDead();
			}
		}
	}
	[HarmonyPatch(typeof(Creature), "OnHealthChange")]
	internal static class PirateCreatureObservedDeathPatch
	{
		private static void Postfix(Creature __instance)
		{
			PirateCreatureLink component = ((Component)__instance).GetComponent<PirateCreatureLink>();
			if (Object.op_Implicit((Object)(object)component))
			{
				component.TryAdoptIfDead();
			}
		}
	}
	[HarmonyPatch(typeof(Item), "OnCooknessChange")]
	internal static class PirateCollectibleCookVisualPatch
	{
		private static void Postfix(Item __instance, float next)
		{
			if (PirateCollectibleSupport.IsPirateProxy(__instance))
			{
				PirateCollectibleVisual component = ((Component)__instance).GetComponent<PirateCollectibleVisual>();
				if (Object.op_Implicit((Object)(object)component))
				{
					component.ApplyCookness(next);
				}
			}
		}
	}
	[HarmonyPatch(typeof(Item), "OnSyncedHolderChange")]
	internal static class PirateCollectibleHolderWaterTimerPatch
	{
		private static void Postfix(Item __instance, Player next)
		{
			if (Object.op_Implicit((Object)(object)next) && PirateCollectibleSupport.IsPirateProxy(__instance))
			{
				PirateCollectibleVisual component = ((Component)__instance).GetComponent<PirateCollectibleVisual>();
				if (Object.op_Implicit((Object)(object)component))
				{
					component.ResetWaterTimeout();
				}
			}
		}
	}
	[HarmonyPatch(typeof(RigidbodySync), "SetBoat")]
	internal static class PirateCollectibleBoatWaterTimerPatch
	{
		private static void Postfix(RigidbodySync __instance, bool onBoat)
		{
			if (!onBoat)
			{
				return;
			}
			Item component = ((Component)__instance).GetComponent<Item>();
			if (PirateCollectibleSupport.IsPirateProxy(component))
			{
				PirateCollectibleVisual component2 = ((Component)component).GetComponent<PirateCollectibleVisual>();
				if (Object.op_Implicit((Object)(object)component2))
				{
					component2.ResetWaterTimeout();
				}
			}
		}
	}
	[HarmonyPatch(typeof(ItemUI), "ShowSpecificItemInfo", new Type[] { typeof(Item) })]
	internal static class PirateCorpseHeldInfoPatch
	{
		private static bool Prefix(ItemUI __instance, Item __0)
		{
			if (!PirateCollectibleSupport.IsPirateProxy(__0))
			{
				return true;
			}
			__instance.HideSpecificItemInfo();
			return false;
		}
	}
	[HarmonyPatch(typeof(ItemManager), "Get", new Type[] { typeof(Collider) })]
	internal static class PirateCrewColliderItemLookupPatch
	{
		private static void Postfix(Collider col, ref Item? __result)
		{
			if (!Object.op_Implicit((Object)(object)__result) && Object.op_Implicit((Object)(object)col))
			{
				PirateCrewHealth componentInParent = ((Component)col).GetComponentInParent<PirateCrewHealth>();
				if (Object.op_Implicit((Object)(object)componentInParent) && Object.op_Implicit((Object)(object)componentInParent.BoundCreature))
				{
					__result = (Item?)(object)componentInParent.BoundCreature;
				}
			}
		}
	}
	[HarmonyPatch(typeof(ItemManager), "Get", new Type[] { typeof(Transform) })]
	internal static class PirateCrewTransformItemLookupPatch
	{
		private static void Postfix(Transform tran, ref Item? __result)
		{
			if (!Object.op_Implicit((Object)(object)__result) && Object.op_Implicit((Object)(object)tran))
			{
				PirateCrewHealth componentInParent = ((Component)tran).GetComponentInParent<PirateCrewHealth>();
				if (Object.op_Implicit((Object)(object)componentInParent) && Object.op_Implicit((Object)(object)componentInParent.BoundCreature))
				{
					__result = (Item?)(object)componentInParent.BoundCreature;
				}
			}
		}
	}
	[HarmonyPatch(typeof(ProjectileManager), "Hit")]
	internal static class PirateCrewProjectileHitPatch
	{
		private static void Prefix(Projectile projectile, RaycastHit hit)
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			if (projectile.FromNpc && Object.op_Implicit((Object)(object)((RaycastHit)(ref hit)).collider) && !projectile.IsLocal && Object.op_Implicit((Object)(object)Server.Instance) && ((NetworkBehaviour)Server.Instance).IsServerInitialized)
			{
				Player playerFromBodyPart = PlayerManager.GetPlayerFromBodyPart(((RaycastHit)(ref hit)).transform);
				if (Object.op_Implicit((Object)(object)playerFromBodyPart) && !((NetworkBehaviour)playerFromBodyPart).IsDeinitializing)
				{
					Vector3 val = ((Vector3)(ref projectile.Velocity)).normalized * GameInfo.PlayerKillForce;
					Server.Instance.RpcLogic___HitPlayer___2449261505(playerFromBodyPart, projectile.Damage, val, ((RaycastHit)(ref hit)).point, (byte)2, (Player)null);
				}
			}
		}
	}
	[HarmonyPatch(typeof(Creature), "LocalHit")]
	internal static class PirateCreatureDamageScalingPatch
	{
		private static void Prefix(Creature __instance, ref int damage)
		{
			PirateCreatureLink component = ((Component)__instance).GetComponent<PirateCreatureLink>();
			if (Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)component.Pirate))
			{
				damage = component.Pirate.ScalePlayerDamage(damage);
			}
		}
	}
	[HarmonyPatch(typeof(Item), "LocalHit")]
	internal static class PirateCreaturePhysicsHitPatch
	{
		private static bool Prefix(Item __instance)
		{
			PirateCreatureLink component = ((Component)__instance).GetComponent<PirateCreatureLink>();
			if (Object.op_Implicit((Object)(object)component))
			{
				return !component.IsAttached;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(ProjectileManager), "ReceiveAddProjectiles")]
	internal static class PirateProjectileReceivePatch
	{
		private static bool Prefix(ProjectileManager __instance, Player owner, WeaponInfo weaponInfo, uint tick, uint id, Vector3 pos, Vector3[] velocities)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			if (!PirateProjectileSupport.IsPirateProjectile(weaponInfo, isLocal: false, id))
			{
				return true;
			}
			if (((NetworkBehaviour)__instance).IsServerInitialized || velocities == null || velocities.Length == 0)
			{
				return false;
			}
			PirateWeaponVisual.FireClosestTo(pos);
			uint num = (uint)((float)(uint)((float)(InstanceFinder.TimeManager.Tick - tick) * GameInfo.TickMulti) * GameInfo.TickMulti);
			if (velocities.Length == 1)
			{
				bool flag = PirateProjectileSupport.IsStreamProjectile(weaponInfo, isLocal: false, id);
				__instance.AddProjectile(owner, weaponInfo, false, pos, velocities[0], num, id, !flag);
			}
			else
			{
				bool flag2 = PirateProjectileSupport.IsStreamProjectile(weaponInfo, isLocal: false, id);
				__instance.AddProjectiles(owner, weaponInfo, false, pos, velocities, num, id, !flag2);
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(ProjectileManager), "HitWater")]
	internal static class PirateProjectileWaterImpactPatch
	{
		private const int SurfaceSearchIterations = 10;

		private const float MinimumSearchDistance = 1f;

		private const float MaximumSearchDistance = 500f;

		private static bool Prefix(Projectile projectile)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: 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_002d: Unknown result type (might be due to invalid IL or missing references)
			if (!PirateProjectileSupport.IsPirateProjectile(projectile.Id))
			{
				return true;
			}
			Vector3 val = FindWaterCrossing(projectile);
			VFXManager.Play("WaterSplash", val, Vector3.zero);
			AudioManager.PlayRandomClipAt("ItemHitWaterMedium_V", 1, 3, val, true, (AudioDistance)1, 2f, 0.1f);
			return false;
		}

		private static Vector3 FindWaterCrossing(Projectile projectile)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: 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_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: 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_00f7: 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_00cd: 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)
			Vector3 previousPosition = projectile.PreviousPosition;
			Vector3 position = projectile.Position;
			float num = HeightAboveWater(previousPosition);
			float num2 = HeightAboveWater(position);
			if (HasCrossedSurface(num, num2))
			{
				return BisectSurface(previousPosition, position, num);
			}
			Vector3 normalized = ((Vector3)(ref projectile.Velocity)).normalized;
			if (((Vector3)(ref normalized)).sqrMagnitude <= 0.001f || Mathf.Abs(normalized.y) <= 0.001f)
			{
				position.y = WaterManager.GetWaterHeight(position);
				return position;
			}
			Vector3 val = ((num2 >= 0f) ? normalized : (-normalized));
			Vector3 val2 = position;
			float num3 = num2;
			for (float num4 = Mathf.Max(1f, ((Vector3)(ref projectile.Velocity)).magnitude * Time.fixedDeltaTime); num4 <= 500f; num4 *= 2f)
			{
				Vector3 val3 = val2 + val * num4;
				float secondHeight = HeightAboveWater(val3);
				if (HasCrossedSurface(num3, secondHeight))
				{
					return BisectSurface(val2, val3, num3);
				}
			}
			position.y = WaterManager.GetWaterHeight(position);
			return position;
		}

		private static Vector3 BisectSurface(Vector3 start, Vector3 end, float startHeight)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			bool flag = startHeight >= 0f;
			for (int i = 0; i < 10; i++)
			{
				Vector3 val = Vector3.Lerp(start, end, 0.5f);
				if (HeightAboveWater(val) >= 0f == flag)
				{
					start = val;
				}
				else
				{
					end = val;
				}
			}
			Vector3 val2 = Vector3.Lerp(start, end, 0.5f);
			val2.y = WaterManager.GetWaterHeight(val2);
			return val2;
		}

		private static float HeightAboveWater(Vector3 position)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			return position.y - WaterManager.GetWaterHeight(position);
		}

		private static bool HasCrossedSurface(float firstHeight, float secondHeight)
		{
			if (!(firstHeight >= 0f) || !(secondHeight <= 0f))
			{
				if (firstHeight <= 0f)
				{
					return secondHeight >= 0f;
				}
				return false;
			}
			return true;
		}
	}
	internal static class PirateProjectileHitmarkerScope
	{
		[ThreadStatic]
		private static int _depth;

		public static bool IsActive => _depth > 0;

		public static bool Begin(Projectile projectile)
		{
			if (!PirateProjectileSupport.IsPirateProjectile(projectile.Id))
			{
				return false;
			}
			_depth++;
			return true;
		}

		public static void End(bool began)
		{
			if (began && _depth > 0)
			{
				_depth--;
			}
		}
	}
	[HarmonyPatch(typeof(ProjectileManager), "Hit")]
	[HarmonyPriority(802)]
	internal static class PirateProjectileHitAudioScopePatch
	{
		private static void Prefix(Projectile projectile, out bool __state)
		{
			__state = PirateProjectileHitmarkerScope.Begin(projectile);
		}

		private static Exception? Finalizer(Exception? __exception, bool __state)
		{
			PirateProjectileHitmarkerScope.End(__state);
			return __exception;
		}
	}
	[HarmonyPatch(typeof(AudioManager), "PlayGlobalClip", new Type[]
	{
		typeof(string),
		typeof(bool),
		typeof(float),
		typeof(float),
		typeof(bool)
	})]
	internal static class PirateProjectileHitGlobalClipPatch
	{
		private static bool Prefix(string __0)
		{
			if (PirateProjectileHitmarkerScope.IsActive)
			{
				return __0 != "Hitmarker";
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(ProjectileManager), "AddProjectile")]
	internal static class PirateSingleProjectileDamagePatch
	{
		private static void Prefix(WeaponInfo weaponInfo, bool isLocal, uint id, ref bool fromNpc, out int __state)
		{
			__state = int.MinValue;
			if (PirateProjectileSupport.IsPirateProjectile(weaponInfo, isLocal, id))
			{
				bool flag = PirateProjectileSupport.IsStreamProjectile(weaponInfo, isLocal, id);
				fromNpc = !flag;
				__state = weaponInfo.ProjectileDamage;
				if (!flag)
				{
					int num = Math.Max(0, PlayerManager.Players.Count - 1) * 2;
					weaponInfo.ProjectileDamage -= num;
				}
			}
		}

		private static void Postfix(WeaponInfo weaponInfo, int __state)
		{
			if (__state != int.MinValue)
			{
				weaponInfo.ProjectileDamage = __state;
			}
		}
	}
	[HarmonyPatch(typeof(ProjectileManager), "AddProjectiles")]
	internal static class PirateMultipleProjectileNpcPatch
	{
		private static void Prefix(WeaponInfo weaponInfo, bool isLocal, uint id, ref bool canHitOwner)
		{
			if (PirateProjectileSupport.IsPirateProjectile(weaponInfo, isLocal, id))
			{
				canHitOwner = !PirateProjectileSupport.IsStreamProjectile(weaponInfo, isLocal, id);
			}
		}
	}
	[HarmonyPatch(typeof(SaveManager), "SaveServer")]
	internal static class CustomItemSavePatch
	{
		private static void Postfix()
		{
			CustomItemSaveSupport.SaveCurrentServer();
		}
	}
	[HarmonyPatch(typeof(SaveManager), "SavePlayer")]
	internal static class CustomItemPlayerSavePatch
	{
		private static void Prefix(Player player, ref Item heldItem, ref Dictionary<byte, Item> slotToItem)
		{
			Item filteredHeldItem = heldItem;
			Dictionary<byte, Item> filteredSlotToItem = slotToItem;
			CustomItemSaveSupport.CapturePlayer(player, heldItem, slotToItem, ref filteredHeldItem, ref filteredSlotToItem);
			heldItem = filteredHeldItem;
			slotToItem = filteredSlotToItem;
		}
	}
	[HarmonyPatch(typeof(SaveManager), "CanSaveWorldItem")]
	internal static class CustomItemVanillaWorldSavePatch
	{
		private static void Postfix(Item item, ref bool __result)
		{
			if (__result && CustomItemSaveSupport.TryGetSaveKey(item, out string _))
			{
				__result = false;
			}
		}
	}
	[HarmonyPatch(typeof(SaveManager), "SelectServer")]
	internal static class CustomItemServerSelectionPatch
	{
		private static void Postfix()
		{
			CustomItemSaveSupport.SelectServer();
		}
	}
	[HarmonyPatch(typeof(SaveManager), "CreateServer")]
	internal static class CustomItemServerCreationPatch
	{
		private static void Postfix()
		{
			CustomItemSaveSupport.CreateServer();
		}
	}
	[HarmonyPatch(typeof(SaveManager), "DeleteServer")]
	internal static class CustomItemServerDeletionPatch
	{
		private static void Prefix()
		{
			CustomItemSaveSupport.DeleteCurrentServer();
		}
	}
	[HarmonyPatch(typeof(PlayerInventory), "LoadFromSave")]
	internal static class CustomItemPlayerLoadPatch
	{
		private static void Postfix(PlayerInventory __instance)
		{
			CustomItemSaveSupport.RestorePlayer(__instance);
		}
	}
	[HarmonyPatch(typeof(SaveManager), "LoadWorldItemsRoutine")]
	internal static class CustomItemWorldLoadPatch
	{
		private static void Postfix(ServerSaveObject saveToLoad, ref IEnumerator __result)
		{
			__result = CustomItemSaveSupport.AppendWorldRestore(__result, saveToLoad);
		}
	}
	[HarmonyPatch(typeof(RigidbodySync), "InheritFakeVel")]
	internal static class KinematicVelocityNoisePatch
	{
		private static bool Prefix(RigidbodySync __instance)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			RigidbodySyncVelocitySupport.Apply(__instance, __instance.FakeVelocity, __instance.FakeAngularVelocity);
			return false;
		}
	}
	[HarmonyPatch(typeof(RigidbodySync), "ZeroVelocity")]
	internal static class KinematicZeroVelocityNoisePatch
	{
		private static bool Prefix(RigidbodySync __instance)
		{
			//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)
			RigidbodySyncVelocitySupport.Apply(__instance, Vector3.zero, Vector3.zero);
			return false;
		}
	}
	internal static class RigidbodySyncVelocitySupport
	{
		public static void Apply(RigidbodySync sync, Vector3 linear, Vector3 angular)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: 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)
			Apply(((Component)sync).GetComponent<Rigidbody>(), linear, angular);
			Rigidbody[] extraHinges = sync.ExtraHinges;
			for (int i = 0; i < extraHinges.Length; i++)
			{
				Apply(extraHinges[i], linear, angular);
			}
		}

		private static void Apply(Rigidbody body, Vector3 linear, Vector3 angular)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)body) && !body.isKinematic)
			{
				body.linearVelocity = linear;
				body.angularVelocity = angular;
			}
		}
	}
	internal sealed class PirateEncounterController : MonoBehaviour
	{
		private sealed class PirateBoatPlan
		{
			public int MotorIndex;

			public IReadOnlyList<PirateWeaponDefinition> Weapons;

			public int Worth;
		}

		private sealed class PirateFleetPlan
		{
			public readonly List<PirateBoatPlan> Boats = new List<PirateBoatPlan>();

			public int Worth;
		}

		private const float CheckInterval = 1f;

		private const float ReinforcementCooldown = 30f;

		private const float PreferredSingleBoatChance = 0.7f;

		private const float PreferredTwoBoatChance = 0.25f;

		private const float AdditionalPirateChance = 0.5f;

		private const float AdditionalPirateChanceMultiplier = 0.5f;

		private const float HorizonSpawnDistance = 250f;

		private const float MaximumFleetBearingOffsetDegrees = 90f;

		private const float FleetArcSpacingDegrees = 12f;

		private const float FleetArcJitterDegrees = 4f;

		private const float WeaponRangeOrbitMultiplier = 0.25f;

		private const float StreamBattleDistanceBeyondBoundary = 350f;

		private const float StreamFleetSeparation = 82f;

		private const float StreamReinforcementSpawnDistance = 115f;

		private const float StreamBoatSpacing = 14f;

		private const float StreamReinforcementCooldown = 6f;

		private const float UpgradeMotorWeightMultiplier = 0.35f;

		private const float FleetWorthLowerBound = 0.75f;

		private const int WorthPercentPerDistanceBand = 10;

		private const int WorthNormalizationReference = 100;

		private const int NormalizedWorthPerDoubling = 100;

		private const int FallbackMotorWorthPerTier = 100;

		private const int MaximumFleetRerolls = 256;

		private static readonly string[] PirateWeaponSpawnNames = new string[5] { "pistol", "shotgun", "smg", "assaultrifle", "sniperrifle" };

		private static readonly FieldInfo MotorsField = AccessTools.Field(typeof(Boat), "_motors");

		private static readonly FieldInfo MotorPurchasableIndexField = AccessTools.Field(typeof(MotorPurchasable), "_motorIndex");

		private static readonly FieldInfo PurchasableCostField = AccessTools.Field(typeof(Purchasable), "_customCost");

		private static readonly Dictionary<int, int> MotorWorthByIndex = new Dictionary<int, int>();

		private OpenSeaConfig _config;

		private OpenSeaBoundary _openSeaBoundary;

		private Boat? _boatPrefab;

		private readonly List<Weapon> _weapons = new List<Weapon>();

		private readonly Dictionary<Boat, int> _activePirateBoats = new Dictionary<Boat, int>();

		private float _nextCheckTime;

		private float _nextReinforcementTime;

		private int _preferredReinforcementBoatCount;

		private bool _loggedNoWeapons;

		private bool _motorWorthsLoaded;

		private bool _streamBattleSpawned;

		private bool _streamSuspendedForLoading;

		private bool _wasStreamMode;

		private Vector3 _streamBattleCenter;

		private Vector3 _streamBattleAxis = Vector3.forward;

		private float _nextCrimsonReinforcementTime;

		private float _nextAzureReinforcementTime;

		public void Initialize(OpenSeaConfig config, OpenSeaBoundary openSeaBoundary)
		{
			_config = config;
			_openSeaBoundary = openSeaBoundary;
		}

		private void Update()
		{
			if (Time.time < _nextCheckTime)
			{
				return;
			}
			_nextCheckTime = Time.time + 1f;
			if (IslandManager.IsLoading || !Object.op_Implicit((Object)(object)Island.CurIsland))
			{
				_motorWorthsLoaded = false;
				if (_config.StreamModeEnabled)
				{
					_streamBattleSpawned = false;
					ResetStreamReinforcementTimers();
					_streamSuspendedForLoading = true;
				}
			}
			else
			{
				if (!Object.op_Implicit((Object)(object)Server.Instance) || !((NetworkBehaviour)Server.Instance).IsServerInitialized)
				{
					return;
				}
				if (_streamSuspendedForLoading)
				{
					DespawnPirates();
					_streamBattleSpawned = false;
					ResetStreamReinforcementTimers();
					_streamSuspendedForLoading = false;
				}
				if (!_config.PiratesEnabled.Value)
				{
					DespawnPirates();
					_streamBattleSpawned = false;
					ResetStreamReinforcementTimers();
					return;
				}
				if (!_motorWorthsLoaded)
				{
					RefreshMotorWorths();
					_motorWorthsLoaded = true;
				}
				if (_config.StreamModeEnabled)
				{
					if (!_wasStreamMode)
					{
						DespawnPirates();
						_streamBattleSpawned = false;
						ResetStreamReinforcementTimers();
					}
					_wasStreamMode = true;
					UpdateStreamMode();
					return;
				}
				if (_wasStreamMode)
				{
					DespawnPirates();
					_streamBattleSpawned = false;
					ResetStreamReinforcementTimers();
					_wasStreamMode = false;
				}
				float distanceBeyondIsland = _openSeaBoundary.DistanceBeyondIsland;
				float farthestDistanceFromShoreline;
				Player val = FindFarthestPlayerFromIsland(out farthestDistanceFromShoreline);
				RemoveDestroyedPirateBoats();
				if (!Object.op_Implicit((Object)(object)val) || farthestDistanceFromShoreline <= distanceBeyondIsland)
				{
					_preferredReinforcementBoatCount = 0;
					return;
				}
				int openOceanPlayerWorth = GetOpenOceanPlayerWorth(distanceBeyondIsland);
				openOceanPlayerWorth = ApplyDifficultyMultiplier(openOceanPlayerWorth);
				int activePirateWorth = GetActivePirateWorth();
				int num = Mathf.Max(1, openOceanPlayerWorth);
				int num2 = Mathf.Max(0, _config.MaximumActiveBoats.Value - _activePirateBoats.Count);
				if (activePirateWorth < num && num2 > 0 && Time.time >= _nextReinforcementTime)
				{
					if (TrySpawnPirates(val, num - activePirateWorth, openOceanPlayerWorth, num2))
					{
						_nextReinforcementTime = Time.time + 30f;
					}
				}
				else
				{
					_preferredReinforcementBoatCount = 0;
				}
			}
		}

		private bool TrySpawnPirates(Player target, int reinforcementWorth, int playerWorth, int maximumBoatCount)
		{
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			Boat boatPrefab = GetBoatPrefab();
			if (!Object.op_Implicit((Object)(object)boatPrefab))
			{
				Plugin.Log.LogError((object)"Could not find the game's registered boat network prefab for the pirate encounter.");
				return false;
			}
			IReadOnlyList<Weapon> readOnlyList = FindPirateWeapons();
			if (readOnlyList.Count == 0)
			{
				if (!_loggedNoWeapons)
				{
					_loggedNoWeapons = true;
					Plugin.Log.LogError((object)"No pirate weapon resources were available; pirate encounter could not spawn.");
				}
				return false;
			}
			_loggedNoWeapons = false;
			if (_preferredReinforcementBoatCount <= 0)
			{
				_preferredReinforcementBoatCount = Mathf.Min(SelectPreferredReinforcementBoatCount(), maximumBoatCount);
			}
			Vector3 val = target.Transform.position - Island.IslandPos;
			val.y = 0f;
			Vector3 val2 = ((((Vector3)(ref val)).sqrMagnitude > 0.01f) ? ((Vector3)(ref val)).normalized : Vector3.forward);
			PirateFleetPlan pirateFleetPlan = SelectFleetForWorth(boatPrefab, readOnlyList, reinforcementWorth, _preferredReinforcementBoatCount, maximumBoatCount);
			if (pirateFleetPlan == null)
			{
				return false;
			}
			int count = pirateFleetPlan.Boats.Count;
			Vector3 seawardDirection = Quaternion.AngleAxis(Random.Range(-90f, 90f), Vector3.up) * val2;
			float formationAngle = Random.Range(-4f, 4f);
			for (int i = 0; i < count; i++)
			{
				SpawnPirateBoat(target, boatPrefab, pirateFleetPlan.Boats[i], seawardDirection, formationAngle, i, count);
			}
			_preferredReinforcementBoatCount = 0;
			return true;
		}

		private void SpawnPirateBoat(Player target, Boat boatPrefab, PirateBoatPlan plan, Vector3 seawardDirection, float formationAngle, int index, int boatCount)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: 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_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: 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_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			float num = (float)index - (float)(boatCount - 1) * 0.5f;
			Vector3 val = Quaternion.AngleAxis(formationAngle + num * 12f, Vector3.up) * seawardDirection;
			float num2 = 250f + Mathf.Abs(num) * 5f;
			Vector3 val2 = target.Transform.position + val * num2;
			val2.y = SpawnManager.BoatSpawnPos.y;
			Vector3 approachDirection = target.Transform.position - val2;
			approachDirection.y = 0f;
			Quaternion spawnRotation = Quaternion.LookRotation(((Vector3)(ref approachDirection)).normalized, Vector3.up);
			SpawnPirateBoatAt(boatPrefab, plan, val2, spawnRotation, approachDirection, PirateTeam.None, $"Pirate Boat {index + 1}");
		}

		private Boat SpawnPirateBoatAt(Boat boatPrefab, PirateBoatPlan plan, Vector3 spawnPosition, Quaternion spawnRotation, Vector3 approachDirection, PirateTeam team, string name)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: 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_00bf: Unknown result type (might be due to invalid IL or missing references)
			Boat val = Object.Instantiate<Boat>(boatPrefab, spawnPosition, spawnRotation);
			((Object)val).name = name;
			AlignBoatForward(val, approachDirection);
			IReadOnlyList<PirateWeaponDefinition> readOnlyList = plan.Weapons.OrderBy((PirateWeaponDefinition weapon) => weapon.AttackRange).ToArray();
			int count = readOnlyList.Count;
			float orbitRadius = readOnlyList.Max((PirateWeaponDefinition weapon) => weapon.AttackRange) * 0.25f;
			ConfigureLongRangeNetworkVisibility(val);
			PirateBoatSupport.RegisterServerPirate(val, readOnlyList, team, plan.Worth);
			((Component)val).gameObject.AddComponent<PirateBoatController>().Initialize(val, readOnlyList, orbitRadius, _openSeaBoundary);
			((NetworkBehaviour)Server.Instance).Spawn(((Component)val).gameObject, (NetworkConnection)null, default(Scene));
			val._curSkin.Value = PirateBoatSupport.EncodeIdentity(count, team);
			val._boatUnlocked.Value = true;
			val._boatRadarUnlocked.Value = true;
			val._motorIndex.Value = (byte)plan.MotorIndex;
			_activePirateBoats[val] = plan.Worth;
			return val;
		}

		private void UpdateStreamMode()
		{
			RemoveDestroyedPirateBoats();
			if (!_streamBattleSpawned)
			{
				TryStartStreamBattle();
				return;
			}
			UpdateStreamBattleCenter();
			GetStreamFleetState(PirateTeam.Crimson, out var boatCount, out var worth);
			GetStreamFleetState(PirateTeam.Azure, out var boatCount2, out var worth2);
			if (boatCount == 0 && boatCount2 == 0)
			{
				SpawnMatchedStreamReinforcements();
				return;
			}
			TryCallStreamReinforcements(PirateTeam.Crimson, boatCount, worth, worth2);
			TryCallStreamReinforcements(PirateTeam.Azure, boatCount2, worth2, worth);
		}

		private void GetStreamFleetState(PirateTeam team, out int boatCount, out int worth)
		{
			boatCount = 0;
			worth = 0;
			foreach (KeyValuePair<Boat, int> activePirateBoat in _activePirateBoats)
			{
				if (PirateBoatSupport.IsActiveStreamCombatant(activePirateBoat.Key) && PirateBoatSupport.GetTeam(activePirateBoat.Key) == team)
				{
					boatCount++;
					worth = SaturatingAdd(worth, activePirateBoat.Value);
				}
			}
		}

		private void TryCallStreamReinforcements(PirateTeam team, int ownBoatCount, int ownWorth, int opposingWorth)
		{
			if (ownWorth >= opposingWorth || opposingWorth <= 0)
			{
				return;
			}
			float num = ((team == PirateTeam.Crimson) ? _nextCrimsonReinforcementTime : _nextAzureReinforcementTime);
			if (Time.time < num)
			{
				return;
			}
			int num2 = Mathf.Clamp(_config.StreamBoatsPerTeam, 1, 4) - ownBoatCount;
			if (num2 <= 0)
			{
				return;
			}
			Boat boatPrefab = GetBoatPrefab();
			IReadOnlyList<Weapon> readOnlyList = FindPirateWeapons();
			if (!Object.op_Implicit((Object)(object)boatPrefab) || readOnlyList.Count == 0)
			{
				return;
			}
			int worthRequirement = opposingWorth - ownWorth;
			int preferredBoatCount = Mathf.Min(SelectPreferredReinforcementBoatCount(), num2);
			PirateFleetPlan pirateFleetPlan = SelectFleetForWorth(boatPrefab, readOnlyList, worthRequirement, preferredBoatCount, num2);
			if (pirateFleetPlan != null)
			{
				SpawnStreamReinforcementFleet(boatPrefab, pirateFleetPlan, team, ownBoatCount);
				float num3 = Time.time + 6f;
				if (team == PirateTeam.Crimson)
				{
					_nextCrimsonReinforcementTime = num3;
				}
				else
				{
					_nextAzureReinforcementTime = num3;
				}
				Plugin.Log.LogInfo((object)($"{team} fleet called {pirateFleetPlan.Boats.Count} reinforcement boat(s) " + $"after falling behind {ownWorth} to {opposingWorth} worth."));
			}
		}

		private void TryStartStreamBattle()
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			Boat boatPrefab = GetBoatPrefab();
			IReadOnlyList<Weapon> readOnlyList = FindPirateWeapons();
			if (Object.op_Implicit((Object)(object)boatPrefab) && readOnlyList.Count != 0 && _openSeaBoundary.SampleCount != 0)
			{
				Vector3 val = SpawnManager.BoatSpawnPos - Island.IslandPos;
				val.y = 0f;
				if (((Vector3)(ref val)).sqrMagnitude <= 0.01f)
				{
					val = Vector3.forward;
				}
				((Vector3)(ref val)).Normalize();
				float num = Mathf.Atan2(val.z, val.x);
				if (num < 0f)
				{
					num += MathF.PI * 2f;
				}
				int sampleIndex = Mathf.RoundToInt(num * (float)_openSeaBoundary.SampleCount / (MathF.PI * 2f));
				_streamBattleCenter = _openSeaBoundary.GetBoundaryPoint(sampleIndex, _openSeaBoundary.DistanceBeyondIsland + 350f);
				_streamBattleCenter.y = SpawnManager.BoatSpawnPos.y;
				_streamBattleAxis = Quaternion.AngleAxis(Random.Range(-28f, 28f), Vector3.up) * val;
				Vector3 val2 = Vector3.Cross(Vector3.up, _streamBattleAxis);
				Vector3 normalized = ((Vector3)(ref val2)).normalized;
				int num2 = Mathf.Clamp(_config.StreamBoatsPerTeam, 1, 4);
				for (int i = 0; i < num2; i++)
				{
					PirateBoatPlan plan = CreateRandomStreamBoatPlan(boatPrefab, readOnlyList);
					float formationOffset = ((float)i - (float)(num2 - 1) * 0.5f) * 14f;
					SpawnStreamTeamBoat(boatPrefab, plan, _streamBattleCenter, _streamBattleAxis, normalized, formationOffset, PirateTeam.Crimson, i);
					SpawnStreamTeamBoat(boatPrefab, plan, _streamBattleCenter, _streamBattleAxis, normalized, formationOffset, PirateTeam.Azure, i);
				}
				_streamBattleSpawned = true;
				Plugin.Log.LogInfo((object)$"Started continuous stream combat with {num2} boats per fleet.");
			}
		}

		private void SpawnStreamTeamBoat(Boat boatPrefab, PirateBoatPlan plan, Vector3 battleCenter, Vector3 battleAxis, Vector3 formationAxis, float formationOffset, PirateTeam team, int index)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: U