Decompiled source of PowerfulOar v1.1.1

BepInEx/plugins/PowerfulOar/PowerfulOar.dll

Decompiled 3 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.SceneManagement;
using cakeslice;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")]
[assembly: AssemblyCompany("PowerfulOar")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.1.0")]
[assembly: AssemblyInformationalVersion("1.1.1")]
[assembly: AssemblyProduct("PowerfulOar")]
[assembly: AssemblyTitle("PowerfulOar")]
[assembly: AssemblyVersion("1.1.1.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace PowerfulOar
{
	internal static class BoneIslandBfoPlacement
	{
		private const string BoneIslandSceneName = "island 36 ()";

		private const float SafeSpawnDistance = 500f;

		private static readonly Vector3 LocalPosition = new Vector3(232.5f, 17.88f, 431.6406f);

		private static readonly Quaternion LocalRotation = Quaternion.Euler(-0.415f, 116.637f, 81.422f);

		private static readonly HashSet<int> PendingScenes = new HashSet<int>();

		private static bool initialized;

		internal static void Initialize()
		{
			if (!initialized)
			{
				initialized = true;
				SceneManager.sceneLoaded += OnSceneLoaded;
				QueueLoadedBoneIslandScenes();
			}
		}

		internal static void Shutdown()
		{
			if (initialized)
			{
				SceneManager.sceneLoaded -= OnSceneLoaded;
				PendingScenes.Clear();
				initialized = false;
			}
		}

		internal static void OnPrefabsReady()
		{
			QueueLoadedBoneIslandScenes();
		}

		private static void OnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			QueueScene(scene);
		}

		private static void QueueLoadedBoneIslandScenes()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 0; i < SceneManager.sceneCount; i++)
			{
				QueueScene(SceneManager.GetSceneAt(i));
			}
		}

		private static void QueueScene(Scene scene)
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			PowerfulOarPlugin instance = PowerfulOarPlugin.Instance;
			if (!((Object)(object)instance == (Object)null) && ((Scene)(ref scene)).IsValid() && ((Scene)(ref scene)).isLoaded && !(((Scene)(ref scene)).name != "island 36 ()") && PendingScenes.Add(((Scene)(ref scene)).handle))
			{
				((MonoBehaviour)instance).StartCoroutine(PlaceWhenReady(scene));
			}
		}

		private static IEnumerator PlaceWhenReady(Scene scene)
		{
			//IL_0007: 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)
			int sceneHandle = ((Scene)(ref scene)).handle;
			Transform scenery = null;
			while ((Object)(object)PowerfulOarPlugin.Instance != (Object)null && ((Scene)(ref scene)).IsValid() && ((Scene)(ref scene)).isLoaded)
			{
				if ((Object)(object)scenery == (Object)null)
				{
					scenery = FindSceneryRoot(scene);
				}
				PrefabsDirectory instance = PrefabsDirectory.instance;
				Camera main = Camera.main;
				Vector3 val = (((Object)(object)scenery != (Object)null) ? scenery.TransformPoint(LocalPosition) : Vector3.zero);
				if (GameState.playing && !GameState.currentlyLoading && (Object)(object)scenery != (Object)null && (Object)(object)main != (Object)null && Vector3.Distance(((Component)main).transform.position, val) <= 500f && (Object)(object)instance != (Object)null && instance.directory != null && instance.directory.Length > 666 && (Object)(object)instance.directory[666] != (Object)null)
				{
					if (ScaledOarFactory.ValidateRuntimeCache(instance))
					{
						TryPlace(instance, scenery);
					}
					PendingScenes.Remove(sceneHandle);
					yield break;
				}
				yield return null;
			}
			PendingScenes.Remove(sceneHandle);
		}

		private static void TryPlace(PrefabsDirectory directory, Transform scenery)
		{
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = directory.directory[666];
			if (HasExistingRuntimeBfo(val))
			{
				ManualLogSource logSource = PowerfulOarPlugin.LogSource;
				if (logSource != null)
				{
					logSource.LogInfo((object)"Skipped Bone Island BFO display: an existing collected or display BFO 5000 is already loaded.");
				}
				return;
			}
			GameObject val2 = Object.Instantiate<GameObject>(val);
			ShipItem component = val2.GetComponent<ShipItem>();
			if ((Object)(object)component == (Object)null)
			{
				ManualLogSource logSource2 = PowerfulOarPlugin.LogSource;
				if (logSource2 != null)
				{
					logSource2.LogError((object)"Could not place Bone Island BFO 5000: cloned ShipItem missing.");
				}
				val2.SetActive(false);
				return;
			}
			((Object)val2).name = "BFO 5000 (Bone Island)";
			val2.transform.SetParent(scenery, false);
			val2.transform.localPosition = LocalPosition;
			val2.transform.localRotation = LocalRotation;
			component.sold = true;
			Good component2 = val2.GetComponent<Good>();
			if ((Object)(object)component2 != (Object)null)
			{
				component2.RegisterAsMissionless();
			}
			ItemRigidbody itemRigidbody = component.GetItemRigidbody();
			val2.GetComponent<ScaledOarController>()?.SetPersistentKinematic(state: true);
			if ((Object)(object)itemRigidbody != (Object)null)
			{
				itemRigidbody.debugForceKinematic = true;
				Rigidbody component3 = ((Component)itemRigidbody).GetComponent<Rigidbody>();
				if ((Object)(object)component3 != (Object)null)
				{
					component3.isKinematic = true;
					component3.useGravity = false;
					component3.velocity = Vector3.zero;
					component3.angularVelocity = Vector3.zero;
				}
			}
			BoneIslandBfoDisplay boneIslandBfoDisplay = val2.GetComponent<BoneIslandBfoDisplay>();
			if ((Object)(object)boneIslandBfoDisplay == (Object)null)
			{
				boneIslandBfoDisplay = val2.AddComponent<BoneIslandBfoDisplay>();
			}
			boneIslandBfoDisplay.Initialize(component);
			ManualLogSource logSource3 = PowerfulOarPlugin.LogSource;
			if (logSource3 != null)
			{
				logSource3.LogInfo((object)("Placed one fixed BFO 5000 at the configured Bone Island _scenery-local pose. It will enter normal item/save control when picked up. " + $"Camera was within {500f:0} m of the placement."));
			}
		}

		private static bool HasExistingRuntimeBfo(GameObject registeredPrefab)
		{
			SaveablePrefab[] array = Resources.FindObjectsOfTypeAll<SaveablePrefab>();
			foreach (SaveablePrefab val in array)
			{
				if ((Object)(object)val != (Object)null && val.prefabIndex == 666 && (Object)(object)((Component)val).gameObject != (Object)(object)registeredPrefab)
				{
					return true;
				}
			}
			return false;
		}

		private static Transform FindSceneryRoot(Scene scene)
		{
			GameObject[] rootGameObjects = ((Scene)(ref scene)).GetRootGameObjects();
			foreach (GameObject val in rootGameObjects)
			{
				if (((Object)val).name == "_scenery")
				{
					return val.transform;
				}
			}
			return null;
		}
	}
	internal sealed class BoneIslandBfoDisplay : MonoBehaviour
	{
		private ShipItem item;

		private ItemRigidbody itemBody;

		private SaveablePrefab saveable;

		internal void Initialize(ShipItem newItem)
		{
			item = newItem;
			itemBody = (((Object)(object)item != (Object)null) ? item.GetItemRigidbody() : null);
			saveable = (((Object)(object)item != (Object)null) ? ((Component)item).GetComponent<SaveablePrefab>() : null);
		}

		private void Update()
		{
			if ((Object)(object)item == (Object)null || !Object.op_Implicit((Object)(object)((PickupableItem)item).held))
			{
				return;
			}
			SaveablePrefab obj = saveable;
			if (obj != null)
			{
				obj.RegisterToSave();
			}
			if ((Object)(object)itemBody != (Object)null)
			{
				ScaledOarController component = ((Component)item).GetComponent<ScaledOarController>();
				if ((Object)(object)component != (Object)null)
				{
					component.SetPersistentKinematic(state: false);
				}
				else
				{
					itemBody.debugForceKinematic = false;
				}
				Rigidbody component2 = ((Component)itemBody).GetComponent<Rigidbody>();
				if ((Object)(object)component2 != (Object)null)
				{
					component2.useGravity = true;
				}
			}
			if ((Object)(object)FloatingOriginManager.instance != (Object)null)
			{
				((Component)this).transform.SetParent(((Component)FloatingOriginManager.instance).transform, true);
			}
			((Behaviour)this).enabled = false;
			ManualLogSource logSource = PowerfulOarPlugin.LogSource;
			if (logSource != null)
			{
				logSource.LogInfo((object)"Released the Bone Island BFO 5000 to normal held-item physics and saving.");
			}
		}
	}
	internal static class RadRefinementCompatibility
	{
		internal const string PluginGuid = "com.raddude.radrefinements";

		private const string ConfigsTypeName = "RadRefinements.Configs";

		private static ConfigEntry<float> rowingNeedsReduction;

		private static ConfigEntry<bool> continualRow;

		private static bool needsReductionEnabled;

		private static bool continualRowAvailable;

		internal static bool NeedsReductionEnabled => needsReductionEnabled;

		internal static bool ContinualRowAvailable => continualRowAvailable;

		internal static float NeedsCostMultiplier
		{
			get
			{
				if (!needsReductionEnabled || rowingNeedsReduction == null)
				{
					return 1f;
				}
				return 1f - Mathf.Clamp01(rowingNeedsReduction.Value);
			}
		}

		internal static bool ContinualRowEnabled
		{
			get
			{
				if (continualRowAvailable && continualRow != null)
				{
					return continualRow.Value;
				}
				return false;
			}
		}

		internal static void Initialize(Harmony harmony)
		{
			rowingNeedsReduction = null;
			continualRow = null;
			needsReductionEnabled = false;
			continualRowAvailable = false;
			Type type = AccessTools.TypeByName("RadRefinements.Configs");
			if (type == null)
			{
				return;
			}
			rowingNeedsReduction = AccessTools.Field(type, "rowingNeedsMult")?.GetValue(null) as ConfigEntry<float>;
			continualRow = AccessTools.Field(type, "continualRow")?.GetValue(null) as ConfigEntry<bool>;
			MethodBase methodBase = AccessTools.DeclaredMethod(typeof(ShipItemOar), "ExtraLateUpdate", (Type[])null, (Type[])null);
			MethodBase methodBase2 = AccessTools.DeclaredMethod(typeof(ShipItemOar), "OnAltHeld", (Type[])null, (Type[])null);
			Patches val = ((methodBase != null) ? Harmony.GetPatchInfo(methodBase) : null);
			Patches val2 = ((methodBase2 != null) ? Harmony.GetPatchInfo(methodBase2) : null);
			MethodInfo methodInfo = FindOwnedPatch(val?.Prefixes, "ReduceNeedsPrefix");
			MethodInfo methodInfo2 = FindOwnedPatch(val?.Postfixes, "ReduceNeedsPostfix");
			MethodInfo patchMethod = FindOwnedPatch(val2?.Postfixes, "ContinualRow", "Postfix");
			continualRowAvailable = continualRow != null && ContainsPatch(methodBase2, patchMethod);
			if (harmony == null || rowingNeedsReduction == null || !ContainsPatch(methodBase, methodInfo) || !ContainsPatch(methodBase, methodInfo2))
			{
				ManualLogSource logSource = PowerfulOarPlugin.LogSource;
				if (logSource != null)
				{
					logSource.LogWarning((object)"RadRefinement was detected, but its rowing-needs patches could not be safely replaced. Set RadRefinement's Rowing needs reduction to 0 to avoid incorrect needs costs.");
				}
				LogContinualRowStatus();
				return;
			}
			try
			{
				harmony.Unpatch(methodBase, methodInfo);
				harmony.Unpatch(methodBase, methodInfo2);
				needsReductionEnabled = !ContainsPatch(methodBase, methodInfo) && !ContainsPatch(methodBase, methodInfo2);
				if (needsReductionEnabled)
				{
					ManualLogSource logSource2 = PowerfulOarPlugin.LogSource;
					if (logSource2 != null)
					{
						logSource2.LogInfo((object)"RadRefinement rowing-needs compatibility enabled: its reduction slider now scales PowerfulOar baselines.");
					}
				}
				else
				{
					ManualLogSource logSource3 = PowerfulOarPlugin.LogSource;
					if (logSource3 != null)
					{
						logSource3.LogError((object)"RadRefinement rowing-needs patches remained installed; slider compatibility was disabled.");
					}
				}
			}
			catch (Exception ex)
			{
				needsReductionEnabled = false;
				ManualLogSource logSource4 = PowerfulOarPlugin.LogSource;
				if (logSource4 != null)
				{
					logSource4.LogError((object)("Could not install RadRefinement rowing-needs compatibility: " + ex));
				}
			}
			LogContinualRowStatus();
		}

		private static void LogContinualRowStatus()
		{
			if (continualRowAvailable)
			{
				ManualLogSource logSource = PowerfulOarPlugin.LogSource;
				if (logSource != null)
				{
					logSource.LogInfo((object)"RadRefinement continual-row force compatibility enabled.");
				}
			}
			else if (continualRow != null)
			{
				ManualLogSource logSource2 = PowerfulOarPlugin.LogSource;
				if (logSource2 != null)
				{
					logSource2.LogWarning((object)"RadRefinement's continual-row patch could not be safely identified. Disable its Row continually option to avoid incorrect rowing force.");
				}
			}
		}

		private static MethodInfo FindOwnedPatch(IEnumerable<Patch> patches, params string[] acceptedMethodNames)
		{
			if (patches == null)
			{
				return null;
			}
			MethodInfo methodInfo = null;
			foreach (Patch patch in patches)
			{
				MethodInfo patchMethod = patch.PatchMethod;
				if (patch.owner != "com.raddude.radrefinements" || patchMethod == null || !HasAcceptedName(patchMethod, acceptedMethodNames))
				{
					continue;
				}
				if (methodInfo != null && !object.Equals(methodInfo, patchMethod))
				{
					ManualLogSource logSource = PowerfulOarPlugin.LogSource;
					if (logSource != null)
					{
						logSource.LogWarning((object)"Found multiple RadRefinement rowing patches where exactly one was expected; compatibility was disabled.");
					}
					return null;
				}
				methodInfo = patchMethod;
			}
			return methodInfo;
		}

		private static bool HasAcceptedName(MethodInfo method, IEnumerable<string> acceptedMethodNames)
		{
			foreach (string acceptedMethodName in acceptedMethodNames)
			{
				if (string.Equals(method.Name, acceptedMethodName, StringComparison.Ordinal))
				{
					return true;
				}
			}
			return false;
		}

		private static bool ContainsPatch(MethodBase target, MethodInfo patchMethod)
		{
			if (target == null || patchMethod == null)
			{
				return false;
			}
			Patches patchInfo = Harmony.GetPatchInfo(target);
			if (patchInfo == null)
			{
				return false;
			}
			if (!ContainsPatch(patchInfo.Prefixes, patchMethod) && !ContainsPatch(patchInfo.Postfixes, patchMethod) && !ContainsPatch(patchInfo.Transpilers, patchMethod))
			{
				return ContainsPatch(patchInfo.Finalizers, patchMethod);
			}
			return true;
		}

		private static bool ContainsPatch(IEnumerable<Patch> patches, MethodInfo patchMethod)
		{
			foreach (Patch patch in patches)
			{
				if (patch.PatchMethod == patchMethod)
				{
					return true;
				}
			}
			return false;
		}
	}
	internal static class HookHangMoreCompatibility
	{
		internal const string PluginGuid = "com.raddude.hookshangmore";

		private const string AttachableItemTypeName = "HooksHangMore.AttachableItem";

		internal static bool IsExcluded(ShipItem item)
		{
			return OarStats.IsScaledOar(item);
		}

		internal static void Exclude(ShipItem item)
		{
			if (!IsExcluded(item))
			{
				return;
			}
			HangableItem component = ((Component)item).GetComponent<HangableItem>();
			if ((Object)(object)component != (Object)null && ((Behaviour)component).enabled)
			{
				component.DisconnectJoint();
				((Behaviour)component).enabled = false;
				ManualLogSource logSource = PowerfulOarPlugin.LogSource;
				if (logSource != null)
				{
					logSource.LogInfo((object)("Disabled vanilla hook hanging for " + item.name + "."));
				}
			}
			Type type = AccessTools.TypeByName("HooksHangMore.AttachableItem");
			Component val = ((type != null) ? ((Component)item).GetComponent(type) : null);
			if (!((Object)(object)val == (Object)null))
			{
				Behaviour val2 = (Behaviour)(object)((val is Behaviour) ? val : null);
				if ((Object)(object)val2 != (Object)null)
				{
					val2.enabled = false;
				}
				Object.Destroy((Object)(object)val);
				ManualLogSource logSource2 = PowerfulOarPlugin.LogSource;
				if (logSource2 != null)
				{
					logSource2.LogInfo((object)("Removed HooksHangMore attachment support from " + item.name + "."));
				}
			}
		}
	}
	internal static class HugeOarPurchaseState
	{
		private const string SaveKey = "DogEggz.PowerfulOar.HugeOarPurchases.v1";

		private static int purchaseCount;

		internal static void Reset()
		{
			purchaseCount = 0;
		}

		internal static void Load()
		{
			Reset();
			if (GameState.modData == null || !GameState.modData.TryGetValue("DogEggz.PowerfulOar.HugeOarPurchases.v1", out var value))
			{
				return;
			}
			if (!int.TryParse(value, NumberStyles.None, CultureInfo.InvariantCulture, out var result) || result < 0)
			{
				ManualLogSource logSource = PowerfulOarPlugin.LogSource;
				if (logSource != null)
				{
					logSource.LogWarning((object)"Ignored invalid Huge Oar purchase count in this save.");
				}
			}
			else
			{
				purchaseCount = result;
			}
		}

		internal static int RecordPurchase()
		{
			if (purchaseCount < int.MaxValue)
			{
				purchaseCount++;
			}
			Store();
			return purchaseCount;
		}

		internal static string GetDialogue(int count)
		{
			if (count <= 1)
			{
				return "...What do you even need this for?";
			}
			if (count == 2)
			{
				return "These things actually sell? I'm a genius!";
			}
			return "I'm gonna need a lot more logs...";
		}

		internal static void Store()
		{
			if (GameState.modData == null)
			{
				GameState.modData = new Dictionary<string, string>();
			}
			GameState.modData["DogEggz.PowerfulOar.HugeOarPurchases.v1"] = purchaseCount.ToString(CultureInfo.InvariantCulture);
		}

		internal static void ClearBeforeLoad()
		{
			Reset();
			GameState.modData?.Remove("DogEggz.PowerfulOar.HugeOarPurchases.v1");
		}
	}
	internal sealed class HugeOarDialogue
	{
		private static GameObject template;

		private static string textPath;

		private static string buttonPath;

		private readonly GameObject panel;

		private readonly Transform bubble;

		private HugeOarDialogue(GameObject newPanel, Transform newBubble)
		{
			panel = newPanel;
			bubble = newBubble;
		}

		internal static void Capture(TavernRumorsDude source)
		{
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)template != (Object)null) && !((Object)(object)source == (Object)null) && !((Object)(object)source.speechUI == (Object)null) && !((Object)(object)source.text == (Object)null) && !((Object)(object)source.drinkButton == (Object)null))
			{
				textPath = Path(source.speechUI.transform, ((Component)source.text).transform);
				buttonPath = Path(source.speechUI.transform, source.drinkButton.transform);
				template = Object.Instantiate<GameObject>(source.speechUI);
				((Object)template).name = "PowerfulOar Huge Oar dialogue template";
				template.SetActive(false);
				template.transform.SetParent((Transform)null, false);
				template.transform.localScale = Vector3.one;
				MonoBehaviour[] componentsInChildren = template.GetComponentsInChildren<MonoBehaviour>(true);
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					Object.DestroyImmediate((Object)(object)componentsInChildren[i]);
				}
				if (Application.isPlaying)
				{
					Object.DontDestroyOnLoad((Object)(object)template);
				}
			}
		}

		internal static HugeOarDialogue Create(Transform parent, string content)
		{
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: 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_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: 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: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)template == (Object)null)
			{
				TavernRumorsDude[] array = Resources.FindObjectsOfTypeAll<TavernRumorsDude>();
				foreach (TavernRumorsDude val in array)
				{
					Scene scene = ((Component)val).gameObject.scene;
					if (((Scene)(ref scene)).IsValid())
					{
						Capture(val);
						if ((Object)(object)template != (Object)null)
						{
							break;
						}
					}
				}
			}
			if ((Object)(object)template == (Object)null)
			{
				return null;
			}
			GameObject val2 = Object.Instantiate<GameObject>(template, parent, false);
			((Object)val2).name = "Huge Oar purchase dialogue";
			val2.transform.localPosition = Vector3.zero;
			val2.transform.localRotation = Quaternion.identity;
			val2.transform.localScale = Vector3.one;
			TextMesh component = ((Component)val2.transform.Find(textPath)).GetComponent<TextMesh>();
			Transform parent2 = ((Component)component).transform.parent;
			Transform val3 = parent2.Find("gfx");
			Transform val4 = val2.transform.Find(buttonPath);
			val2.SetActive(true);
			((Component)val4).gameObject.SetActive(false);
			Renderer component2 = ((Component)component).GetComponent<Renderer>();
			Bounds bounds = component2.bounds;
			Vector3 size = ((Bounds)(ref bounds)).size;
			bounds = ((Component)val3).GetComponent<Renderer>().bounds;
			Vector3 size2 = ((Bounds)(ref bounds)).size;
			string text = Wrap(content, 40);
			component.font.RequestCharactersInTexture(text, component.fontSize, component.fontStyle);
			component.text = text;
			bounds = component2.bounds;
			Vector3 size3 = ((Bounds)(ref bounds)).size;
			Vector3 localScale = val3.localScale;
			localScale.x *= Mathf.Max(0.35f, (size2.x + size3.x - size.x) / Mathf.Max(0.001f, size2.x));
			localScale.y *= Mathf.Max(1f, (size2.y + size3.y - size.y) / Mathf.Max(0.001f, size2.y));
			val3.localScale = localScale;
			Collider[] componentsInChildren = val2.GetComponentsInChildren<Collider>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				componentsInChildren[i].enabled = false;
			}
			val2.SetActive(false);
			return new HugeOarDialogue(val2, parent2);
		}

		internal static void Shutdown()
		{
			if ((Object)(object)template != (Object)null)
			{
				Object.Destroy((Object)(object)template);
				template = null;
			}
			textPath = null;
			buttonPath = null;
		}

		internal void Show(Transform anchor)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: 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_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)panel == (Object)null) && !((Object)(object)anchor == (Object)null) && !((Object)(object)Refs.observerMirror == (Object)null))
			{
				Transform transform = ((Component)Refs.observerMirror).transform;
				Vector3 val = Vector3.ProjectOnPlane(transform.position - anchor.position, Vector3.up);
				Vector3 normalized = ((Vector3)(ref val)).normalized;
				Vector3 val2 = anchor.position + normalized * 0.75f;
				val2.y = transform.position.y + 1.2f - bubble.localPosition.y;
				panel.transform.SetPositionAndRotation(val2, transform.rotation);
				panel.SetActive(true);
			}
		}

		internal void Hide()
		{
			if ((Object)(object)panel != (Object)null)
			{
				panel.SetActive(false);
			}
		}

		internal void Dispose()
		{
			if ((Object)(object)panel != (Object)null)
			{
				Object.Destroy((Object)(object)panel);
			}
		}

		private static string Path(Transform root, Transform child)
		{
			List<string> list = new List<string>();
			while ((Object)(object)child != (Object)null && (Object)(object)child != (Object)(object)root)
			{
				list.Add(((Object)child).name);
				child = child.parent;
			}
			if ((Object)(object)child != (Object)(object)root)
			{
				throw new InvalidOperationException("Dialogue element is outside the speech UI.");
			}
			list.Reverse();
			return string.Join("/", list.ToArray());
		}

		private static string Wrap(string value, int width)
		{
			value = value.TrimStart(Array.Empty<char>());
			if (value.Length <= width)
			{
				return value;
			}
			int num = value.LastIndexOf(' ', width);
			if (num < 1)
			{
				num = width;
			}
			return value.Substring(0, num) + "\n" + Wrap(value.Substring(num), width);
		}
	}
	internal sealed class HugeOarPurchaseDialogueArea : MonoBehaviour
	{
		private const float OpenDistance = 4f;

		private const float CloseDistance = 5f;

		private readonly HashSet<Collider> players = new HashSet<Collider>();

		private Transform source;

		private Rigidbody body;

		private Collider trigger;

		private HugeOarDialogue dialogue;

		private string content;

		private float retry;

		private bool pending;

		private bool open;

		private bool missingDialogueLogged;

		internal static HugeOarPurchaseDialogueArea Create(Transform source)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_0019: 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_0041: 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)
			GameObject val = new GameObject("PowerfulOar Huge Oar purchase dialogue trigger");
			try
			{
				val.SetActive(false);
				SceneManager.MoveGameObjectToScene(val, ((Component)source).gameObject.scene);
				val.layer = 2;
				val.transform.position = source.position;
				val.transform.rotation = Quaternion.identity;
				val.transform.localScale = Vector3.one;
				Rigidbody obj = val.AddComponent<Rigidbody>();
				obj.isKinematic = true;
				obj.useGravity = false;
				SphereCollider obj2 = val.AddComponent<SphereCollider>();
				obj2.radius = 4f;
				((Collider)obj2).isTrigger = true;
				HugeOarPurchaseDialogueArea hugeOarPurchaseDialogueArea = val.AddComponent<HugeOarPurchaseDialogueArea>();
				hugeOarPurchaseDialogueArea.source = source;
				val.SetActive(true);
				return hugeOarPurchaseDialogueArea;
			}
			catch
			{
				val.SetActive(false);
				Object.Destroy((Object)(object)val);
				throw;
			}
		}

		internal void ShowPurchase(string newContent)
		{
			content = newContent;
			pending = true;
			retry = 0f;
			missingDialogueLogged = false;
			dialogue?.Dispose();
			dialogue = null;
			float num = ObserverDistance();
			open = num <= 4f;
		}

		private void Awake()
		{
			body = ((Component)this).GetComponent<Rigidbody>();
			trigger = ((Component)this).GetComponent<Collider>();
		}

		private void FixedUpdate()
		{
			//IL_0060: 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)(object)source == (Object)null)
			{
				Object.Destroy((Object)(object)((Component)this).gameObject);
				return;
			}
			trigger.enabled = ((Component)source).gameObject.activeInHierarchy;
			if (!trigger.enabled || GameState.currentlyLoading)
			{
				players.Clear();
			}
			body.position = source.position;
			body.rotation = Quaternion.identity;
		}

		private void Update()
		{
			players.RemoveWhere((Collider player) => (Object)(object)player == (Object)null || !((Component)player).gameObject.activeInHierarchy);
			if (!pending || !Available())
			{
				dialogue?.Hide();
				return;
			}
			float num = ObserverDistance();
			if (!open && players.Count > 0 && num <= 4f)
			{
				open = true;
			}
			if (open && num > 5f)
			{
				ClosePurchase();
				return;
			}
			if (!open)
			{
				dialogue?.Hide();
				return;
			}
			if (dialogue == null && Time.unscaledTime >= retry)
			{
				retry = Time.unscaledTime + 0.5f;
				dialogue = HugeOarDialogue.Create(((Component)this).transform, content);
				if (dialogue == null && !missingDialogueLogged)
				{
					missingDialogueLogged = true;
					ManualLogSource logSource = PowerfulOarPlugin.LogSource;
					if (logSource != null)
					{
						logSource.LogError((object)"Huge Oar was purchased, but the vanilla dialogue template is not available yet; retrying.");
					}
				}
			}
			dialogue?.Show(source);
		}

		private void OnTriggerEnter(Collider other)
		{
			Observe(other);
		}

		private void OnTriggerStay(Collider other)
		{
			Observe(other);
		}

		private void OnTriggerExit(Collider other)
		{
			players.Remove(other);
		}

		private void OnDisable()
		{
			dialogue?.Hide();
		}

		private void OnDestroy()
		{
			dialogue?.Dispose();
			dialogue = null;
		}

		private void Observe(Collider other)
		{
			if (((Component)other).CompareTag("Player"))
			{
				players.Add(other);
			}
		}

		private bool Available()
		{
			if ((Object)(object)source != (Object)null && ((Component)source).gameObject.activeInHierarchy && (Object)(object)Refs.observerMirror != (Object)null && !GameState.currentlyLoading && !GameState.justStarted && !GameState.recovering)
			{
				return !GameState.sleeping;
			}
			return false;
		}

		private float ObserverDistance()
		{
			//IL_002b: 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)
			if (!((Object)(object)Refs.observerMirror != (Object)null) || !((Object)(object)source != (Object)null))
			{
				return float.PositiveInfinity;
			}
			return Vector3.Distance(((Component)Refs.observerMirror).transform.position, source.position);
		}

		private void ClosePurchase()
		{
			pending = false;
			open = false;
			content = null;
			dialogue?.Dispose();
			dialogue = null;
		}
	}
	[HarmonyPatch(typeof(TavernRumorsDude), "Awake")]
	internal static class HugeOarDialogueCapturePatch
	{
		[HarmonyPostfix]
		private static void Postfix(TavernRumorsDude __instance)
		{
			HugeOarDialogue.Capture(__instance);
		}
	}
	[HarmonyPatch(typeof(Shopkeeper), "SellItem")]
	internal static class HugeOarPurchasePatch
	{
		[HarmonyPostfix]
		private static void Postfix(Shopkeeper __instance, ShipItem item)
		{
			if (HugeOarVendorPatch.IsTarget(__instance) && OarStats.GetPrefabIndex(item) == 603)
			{
				int purchaseCount = HugeOarPurchaseState.RecordPurchase();
				((Component)__instance).GetComponent<HugeOarVendorInstaller>()?.ShowPurchaseReaction(purchaseCount);
				ManualLogSource logSource = PowerfulOarPlugin.LogSource;
				if (logSource != null)
				{
					logSource.LogInfo((object)("Kicia Bay Huge Oar purchase count is now " + purchaseCount + "."));
				}
			}
		}
	}
	[HarmonyPatch(typeof(SaveLoadManager), "Awake")]
	internal static class HugeOarPurchaseSessionPatch
	{
		[HarmonyPrefix]
		private static void Prefix()
		{
			HugeOarPurchaseState.Reset();
		}
	}
	[HarmonyPatch(typeof(SaveLoadManager), "LoadGame")]
	internal static class HugeOarPurchaseLoadGamePatch
	{
		[HarmonyPrefix]
		private static void Prefix()
		{
			HugeOarPurchaseState.ClearBeforeLoad();
		}
	}
	[HarmonyPatch(typeof(SaveLoadManager), "LoadModData")]
	internal static class HugeOarPurchaseLoadPatch
	{
		[HarmonyPostfix]
		private static void Postfix()
		{
			HugeOarPurchaseState.Load();
		}
	}
	[HarmonyPatch(typeof(SaveLoadManager), "SaveModData")]
	internal static class HugeOarPurchaseStorePatch
	{
		[HarmonyPrefix]
		private static void Prefix()
		{
			HugeOarPurchaseState.Store();
		}
	}
	[BepInPlugin("DogEggz.PowerfulOar", "PowerfulOar", "1.1.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class PowerfulOarPlugin : BaseUnityPlugin
	{
		private sealed class PatchTarget
		{
			internal Type PatchType { get; }

			internal Type TargetType { get; }

			internal string TargetMethodName { get; }

			internal Type[] ArgumentTypes { get; }

			internal PatchTarget(Type patchType, Type targetType, string targetMethodName, Type[] argumentTypes = null)
			{
				PatchType = patchType;
				TargetType = targetType;
				TargetMethodName = targetMethodName;
				ArgumentTypes = argumentTypes;
			}
		}

		public const string PluginGuid = "DogEggz.PowerfulOar";

		public const string PluginName = "PowerfulOar";

		public const string PluginVersion = "1.1.1";

		internal const string GoPointerInputLoopMethod = "LateUpdate";

		private Harmony harmony;

		private readonly List<Harmony> featureHarmonies = new List<Harmony>();

		internal static PowerfulOarPlugin Instance { get; private set; }

		internal static ManualLogSource LogSource { get; private set; }

		private void Awake()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			Instance = this;
			LogSource = ((BaseUnityPlugin)this).Logger;
			harmony = new Harmony("DogEggz.PowerfulOar");
			RadRefinementCompatibility.Initialize(harmony);
			bool flag = ApplyPatchClass(typeof(OarStatsPatch), typeof(ShipItemOar), "OnAltHeld");
			bool flag2 = ApplyPatchClass(typeof(OarLateUpdatePatch), typeof(ShipItemOar), "ExtraLateUpdate");
			bool flag3 = ApplyPatchGroup("runtime_lifecycle", new PatchTarget(typeof(ScaledOarRigidbodyScalePatch), typeof(ItemRigidbody), "LateUpdate"), new PatchTarget(typeof(ScaledOarSavedStatePatch), typeof(SaveablePrefab), "Load", new Type[1] { typeof(SavePrefabData) }), new PatchTarget(typeof(ScaledOarInventoryEnterPatch), typeof(ItemRigidbody), "EnterInventorySlot", new Type[1] { typeof(Transform) }), new PatchTarget(typeof(ScaledOarInventoryExitPatch), typeof(ItemRigidbody), "ExitInventorySlot"));
			bool flag4 = flag3 && ApplyPatchClass(typeof(ScaledOarPrefabRegistrationPatch), typeof(PrefabsDirectory), "Start");
			bool flag5 = ApplyPatchClass(typeof(ScaledOarOutlineEffectPatch), typeof(OutlineEffect), "OnEnable");
			bool flag6 = ApplyPatchClass(typeof(ReverseOarInputPatch), typeof(GoPointer), "LateUpdate");
			bool flag7 = ApplyPatchClass(typeof(ScaledOarNailingPatch), typeof(ShipItemHammer), "CanNail", new Type[1] { typeof(ShipItem) });
			bool flag8 = flag4 && ApplyPatchGroup("vendor_display", new PatchTarget(typeof(BigOarVendorPatch), typeof(ShopItemSpawner), "Start"), new PatchTarget(typeof(ScaledOarVendorSpawnPatch), typeof(ShopItemSpawner), "SpawnItem"), new PatchTarget(typeof(HugeOarVendorPatch), typeof(Shopkeeper), "Start"));
			bool flag9 = flag8 && ApplyPatchGroup("huge_oar_dialogue", new PatchTarget(typeof(HugeOarDialogueCapturePatch), typeof(TavernRumorsDude), "Awake"), new PatchTarget(typeof(HugeOarPurchasePatch), typeof(Shopkeeper), "SellItem", new Type[3]
			{
				typeof(ShipItem),
				typeof(int),
				typeof(int)
			}), new PatchTarget(typeof(HugeOarPurchaseSessionPatch), typeof(SaveLoadManager), "Awake"), new PatchTarget(typeof(HugeOarPurchaseLoadGamePatch), typeof(SaveLoadManager), "LoadGame", new Type[1] { typeof(int) }), new PatchTarget(typeof(HugeOarPurchaseLoadPatch), typeof(SaveLoadManager), "LoadModData"), new PatchTarget(typeof(HugeOarPurchaseStorePatch), typeof(SaveLoadManager), "SaveModData"));
			bool flag10 = ApplyPatchClass(typeof(HookHangMoreExclusionPatch), typeof(ShipItem), "Awake");
			bool flag11 = flag4 && ApplyPatchGroup("crate_blocker", new PatchTarget(typeof(ScaledOarCrateInsertPatch), typeof(CrateInventory), "InsertItem", new Type[1] { typeof(ShipItem) }), new PatchTarget(typeof(ScaledOarCrateWithdrawPatch), typeof(CrateInventory), "WithdrawItem", new Type[1] { typeof(ShipItem) }), new PatchTarget(typeof(ScaledOarCrateUiPatch), typeof(CrateInventoryButton), "OnActivate", new Type[1] { typeof(GoPointer) }));
			if (flag4)
			{
				BoneIslandBfoPlacement.Initialize();
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)("PowerfulOar 1.1.1 loaded. Fixed per-oar stats and needs costs enabled. Hold Q to row opposite vanilla. Bone Island BFO placement, scaled-oar vendor displays, and Kicia Bay Huge Oar enabled. " + $"Patches: stats={flag}, late update={flag2}, " + $"prefab={flag4}, outline wake fix={flag5}, " + $"reverse input={flag6}, nailing={flag7}, " + $"vendor display group={flag8}, " + $"Huge Oar dialogue group={flag9}, " + $"HookHangMore exclusion={flag10}, " + $"scaled-oar lifecycle group={flag3}, " + $"crate blocker group={flag11}, " + $"RadRefinement needs={RadRefinementCompatibility.NeedsReductionEnabled}, " + $"continual row={RadRefinementCompatibility.ContinualRowAvailable}."));
		}

		private bool ApplyPatchClass(Type patchType, Type targetType, string targetMethodName, Type[] argumentTypes = null)
		{
			if (AccessTools.DeclaredMethod(targetType, targetMethodName, argumentTypes ?? Type.EmptyTypes, (Type[])null) == null)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Skipped " + patchType.Name + ": target method " + targetType.FullName + "." + targetMethodName + " was not found."));
				return false;
			}
			try
			{
				harmony.PatchAll(patchType);
				return true;
			}
			catch (Exception arg)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Failed to apply " + patchType.Name + " to " + $"{targetType.FullName}.{targetMethodName}: {arg}"));
				return false;
			}
		}

		private bool ApplyPatchGroup(string groupName, params PatchTarget[] targets)
		{
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Expected O, but got Unknown
			PatchTarget[] array = targets;
			foreach (PatchTarget patchTarget in array)
			{
				if (AccessTools.DeclaredMethod(patchTarget.TargetType, patchTarget.TargetMethodName, patchTarget.ArgumentTypes ?? Type.EmptyTypes, (Type[])null) == null)
				{
					((BaseUnityPlugin)this).Logger.LogError((object)("Skipped patch group '" + groupName + "': target method " + patchTarget.TargetType.FullName + "." + patchTarget.TargetMethodName + " was not found."));
					return false;
				}
			}
			Harmony val = new Harmony("DogEggz.PowerfulOar." + groupName);
			try
			{
				array = targets;
				foreach (PatchTarget patchTarget2 in array)
				{
					val.PatchAll(patchTarget2.PatchType);
				}
				featureHarmonies.Add(val);
				return true;
			}
			catch (Exception arg)
			{
				val.UnpatchSelf();
				((BaseUnityPlugin)this).Logger.LogError((object)("Failed to apply patch group '" + groupName + "'; all patches in " + $"the group were rolled back: {arg}"));
				return false;
			}
		}

		private void OnDestroy()
		{
			BoneIslandBfoPlacement.Shutdown();
			HugeOarDialogue.Shutdown();
			HugeOarPurchaseState.Reset();
			foreach (Harmony featureHarmony in featureHarmonies)
			{
				featureHarmony.UnpatchSelf();
			}
			featureHarmonies.Clear();
			Harmony obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
			if ((Object)(object)Instance == (Object)(object)this)
			{
				Instance = null;
				LogSource = null;
			}
		}
	}
	internal static class PowerfulOarInput
	{
		internal static bool ReverseRowHeld
		{
			get
			{
				if (GameState.playing && !GameState.inCursorMenu && !GameState.wasInSettingsMenu)
				{
					return Input.GetKey((KeyCode)113);
				}
				return false;
			}
		}
	}
	[HarmonyPatch(typeof(GoPointer), "LateUpdate")]
	internal static class ReverseOarInputPatch
	{
		[HarmonyPostfix]
		private static void Postfix(GoPointer __instance)
		{
			if (!PowerfulOarInput.ReverseRowHeld)
			{
				return;
			}
			PickupableItem heldItem = __instance.GetHeldItem();
			ShipItemOar val = (ShipItemOar)(object)((heldItem is ShipItemOar) ? heldItem : null);
			if (!((Object)(object)val == (Object)null) && !GameInput.GetKey((InputName)9))
			{
				if (Input.GetKeyDown((KeyCode)113))
				{
					((GoPointerButton)val).OnAltActivate();
				}
				((GoPointerButton)val).OnAltHeld();
			}
		}
	}
	[HarmonyPatch(typeof(ShipItemOar), "OnAltHeld")]
	internal static class OarStatsPatch
	{
		private struct RowCallState
		{
			internal float ProgressBefore;

			internal bool Reverse;
		}

		[HarmonyPrefix]
		private static bool Prefix(ShipItemOar __instance, ref bool ___isHoldingButton, bool ___isOverWater, ref bool ___isRowing, ref float ___rowProgress, out RowCallState __state)
		{
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			__state = new RowCallState
			{
				ProgressBefore = ___rowProgress,
				Reverse = PowerfulOarInput.ReverseRowHeld
			};
			OarStats.Apply(__instance);
			if (!__state.Reverse)
			{
				return true;
			}
			___isHoldingButton = true;
			if (Object.op_Implicit((Object)(object)((PickupableItem)__instance).held) && ___isOverWater && Object.op_Implicit((Object)(object)GameState.currentBoat))
			{
				if (___rowProgress <= 1f)
				{
					___isRowing = true;
					___rowProgress += Time.deltaTime;
					Rigidbody component = ((Component)GameState.currentBoat.parent).GetComponent<Rigidbody>();
					float maxBoatSpeed = __instance.maxBoatSpeed;
					Vector3 velocity = component.velocity;
					float num = Mathf.InverseLerp(maxBoatSpeed, 0f, ((Vector3)(ref velocity)).magnitude);
					component.AddForceAtPosition(__instance.waterPos.forward * __instance.rowForce * Time.deltaTime * num, __instance.waterPos.position);
				}
				else
				{
					___isRowing = false;
				}
			}
			return false;
		}

		[HarmonyPostfix]
		[HarmonyAfter(new string[] { "com.raddude.radrefinements" })]
		private static void Postfix(ShipItemOar __instance, bool ___isOverWater, RowCallState __state)
		{
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: 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_0078: 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_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			if (RadRefinementCompatibility.ContinualRowEnabled && Object.op_Implicit((Object)(object)((PickupableItem)__instance).held) && ___isOverWater && Object.op_Implicit((Object)(object)GameState.currentBoat) && !(__state.ProgressBefore > 1f) && !(__state.ProgressBefore + Time.deltaTime > 1f))
			{
				Rigidbody component = ((Component)GameState.currentBoat.parent).GetComponent<Rigidbody>();
				Vector3 val = __instance.waterPos.forward * (0f - __instance.rowForce) * Time.deltaTime;
				component.AddForceAtPosition(-val, __instance.waterPos.position);
				float maxBoatSpeed = __instance.maxBoatSpeed;
				Vector3 velocity = component.velocity;
				float num = Mathf.InverseLerp(maxBoatSpeed, 0f, ((Vector3)(ref velocity)).magnitude);
				float num2 = (__state.Reverse ? 1f : (-1f));
				component.AddForceAtPosition(__instance.waterPos.forward * __instance.rowForce * Time.deltaTime * num * num2, __instance.waterPos.position);
			}
		}
	}
	[HarmonyPatch(typeof(ShipItemOar), "ExtraLateUpdate")]
	internal static class OarLateUpdatePatch
	{
		private const float VanillaWaterCost = 0.4f;

		private const float VanillaFoodCost = 0.6f;

		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Expected O, but got Unknown
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			FieldInfo needsField = AccessTools.Field(typeof(PlayerNeeds), "water");
			FieldInfo needsField2 = AccessTools.Field(typeof(PlayerNeeds), "food");
			FieldInfo rowProgressField = AccessTools.Field(typeof(ShipItemOar), "rowProgress");
			List<int> list2 = FindNeedCostConstants(list, needsField, 0.4f);
			List<int> list3 = FindNeedCostConstants(list, needsField2, 0.6f);
			if (list2.Count == 1 && list3.Count == 1)
			{
				MethodInfo selector = AccessTools.Method(typeof(OarLateUpdatePatch), "SelectWaterCost", (Type[])null, (Type[])null);
				MethodInfo selector2 = AccessTools.Method(typeof(OarLateUpdatePatch), "SelectFoodCost", (Type[])null, (Type[])null);
				ReplaceNeedCostConstant(list, list3[0], selector2);
				ReplaceNeedCostConstant(list, list2[0], selector);
				ManualLogSource logSource = PowerfulOarPlugin.LogSource;
				if (logSource != null)
				{
					logSource.LogInfo((object)"Patched per-oar rowing water and food costs: Original=0.1/s, Big Oar=0.2/s, Huge Oar=0.3/s, BFO 5000=1/s.");
				}
			}
			else
			{
				ManualLogSource logSource2 = PowerfulOarPlugin.LogSource;
				if (logSource2 != null)
				{
					logSource2.LogError((object)("Could not safely patch rowing needs costs: " + $"water matches={list2.Count}, food matches={list3.Count}. " + "Vanilla needs costs were left unchanged."));
				}
			}
			List<int> list4 = FindStrokeProgressLoads(list, rowProgressField);
			if (list4.Count == 1)
			{
				MethodInfo methodInfo = AccessTools.Method(typeof(OarLateUpdatePatch), "SelectStrokeProgress", (Type[])null, (Type[])null);
				list.Insert(list4[0] + 1, new CodeInstruction(OpCodes.Call, (object)methodInfo));
				ManualLogSource logSource3 = PowerfulOarPlugin.LogSource;
				if (logSource3 != null)
				{
					logSource3.LogInfo((object)"Patched reverse oar stroke animation for the Q key.");
				}
			}
			else
			{
				ManualLogSource logSource4 = PowerfulOarPlugin.LogSource;
				if (logSource4 != null)
				{
					logSource4.LogError((object)("Could not safely patch reverse oar stroke animation: " + $"matches={list4.Count}. Reverse thrust remains available on Q."));
				}
			}
			return list;
		}

		private static float SelectStrokeProgress(float progress)
		{
			if (!PowerfulOarInput.ReverseRowHeld)
			{
				return progress;
			}
			return 1f - progress;
		}

		private static float SelectWaterCost(ShipItemOar oar)
		{
			return OarStats.GetWaterCostPerSecond(oar);
		}

		private static float SelectFoodCost(ShipItemOar oar)
		{
			return OarStats.GetFoodCostPerSecond(oar);
		}

		private static void ReplaceNeedCostConstant(IList<CodeInstruction> codes, int constantIndex, MethodInfo selector)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected O, but got Unknown
			CodeInstruction obj = codes[constantIndex];
			obj.opcode = OpCodes.Ldarg_0;
			obj.operand = null;
			codes.Insert(constantIndex + 1, new CodeInstruction(OpCodes.Call, (object)selector));
		}

		private static List<int> FindNeedCostConstants(IList<CodeInstruction> codes, FieldInfo needsField, float expectedConstant)
		{
			List<int> list = new List<int>();
			for (int i = 0; i <= codes.Count - 6; i++)
			{
				if (!(codes[i].opcode != OpCodes.Ldsfld) && object.Equals(codes[i].operand, needsField) && !(codes[i + 2].opcode != OpCodes.Ldc_R4) && codes[i + 2].operand is float num && Mathf.Approximately(num, expectedConstant) && !(codes[i + 3].opcode != OpCodes.Mul) && !(codes[i + 4].opcode != OpCodes.Sub) && !(codes[i + 5].opcode != OpCodes.Stsfld) && object.Equals(codes[i + 5].operand, needsField))
				{
					list.Add(i + 2);
				}
			}
			return list;
		}

		private static List<int> FindStrokeProgressLoads(IList<CodeInstruction> codes, FieldInfo rowProgressField)
		{
			List<int> list = new List<int>();
			for (int i = 0; i <= codes.Count - 6; i++)
			{
				if (LoadsFloat(codes[i], -1f) && LoadsFloat(codes[i + 1], 2f) && !(codes[i + 2].opcode != OpCodes.Ldarg_0) && !(codes[i + 3].opcode != OpCodes.Ldfld) && object.Equals(codes[i + 3].operand, rowProgressField) && !(codes[i + 4].opcode != OpCodes.Mul) && !(codes[i + 5].opcode != OpCodes.Add))
				{
					list.Add(i + 3);
				}
			}
			return list;
		}

		private static bool LoadsFloat(CodeInstruction instruction, float expected)
		{
			if (instruction.opcode == OpCodes.Ldc_R4 && instruction.operand is float num)
			{
				return Mathf.Approximately(num, expected);
			}
			return false;
		}
	}
	internal static class OarStats
	{
		internal const float OriginalForce = 36000f;

		internal const float OriginalMaxBoatSpeed = 2.06f;

		internal const float OriginalNeedsCostPerSecond = 0.1f;

		internal const float BigForce = 93500f;

		internal const float BigMaxBoatSpeed = 3.1f;

		internal const float BigNeedsCostPerSecond = 0.2f;

		internal const float HugeForce = 204000f;

		internal const float HugeMaxBoatSpeed = 5.14f;

		internal const float HugeNeedsCostPerSecond = 0.3f;

		internal const float Bfo5000Force = 510000f;

		internal const float Bfo5000MaxBoatSpeed = 10.29f;

		internal const float Bfo5000NeedsCostPerSecond = 1f;

		internal static bool Apply(ShipItemOar oar)
		{
			switch (GetPrefabIndex((ShipItem)(object)oar))
			{
			case 168:
				oar.rowForce = 36000f;
				oar.maxBoatSpeed = 2.06f;
				return true;
			case 602:
				oar.rowForce = 93500f;
				oar.maxBoatSpeed = 3.1f;
				return true;
			case 169:
				if (!IsLegacyBigOar((ShipItem)(object)oar))
				{
					return false;
				}
				oar.rowForce = 93500f;
				oar.maxBoatSpeed = 3.1f;
				return true;
			case 603:
				oar.rowForce = 204000f;
				oar.maxBoatSpeed = 5.14f;
				return true;
			case 666:
				oar.rowForce = 510000f;
				oar.maxBoatSpeed = 10.29f;
				return true;
			default:
				return false;
			}
		}

		internal static float GetWaterCostPerSecond(ShipItemOar oar)
		{
			return GetNeedsCostPerSecond(oar, 0.4f) * RadRefinementCompatibility.NeedsCostMultiplier;
		}

		internal static float GetFoodCostPerSecond(ShipItemOar oar)
		{
			return GetNeedsCostPerSecond(oar, 0.6f) * RadRefinementCompatibility.NeedsCostMultiplier;
		}

		private static float GetNeedsCostPerSecond(ShipItemOar oar, float fallback)
		{
			switch (GetPrefabIndex((ShipItem)(object)oar))
			{
			case 168:
				return 0.1f;
			case 602:
				return 0.2f;
			case 169:
				if (!IsLegacyBigOar((ShipItem)(object)oar))
				{
					return fallback;
				}
				return 0.2f;
			case 603:
				return 0.3f;
			case 666:
				return 1f;
			default:
				return fallback;
			}
		}

		internal static int GetPrefabIndex(ShipItem item)
		{
			SaveablePrefab val = (((Object)(object)item != (Object)null) ? ((Component)item).GetComponent<SaveablePrefab>() : null);
			if (!((Object)(object)val != (Object)null))
			{
				return -1;
			}
			return val.prefabIndex;
		}

		internal static bool IsScaledOar(ShipItem item)
		{
			int prefabIndex = GetPrefabIndex(item);
			if (prefabIndex != 602 && !IsLegacyBigOar(item) && prefabIndex != 603)
			{
				return prefabIndex == 666;
			}
			return true;
		}

		private static bool IsLegacyBigOar(ShipItem item)
		{
			if ((Object)(object)item != (Object)null && GetPrefabIndex(item) == 169)
			{
				return (Object)(object)((Component)item).GetComponent<ScaledOarController>() != (Object)null;
			}
			return false;
		}
	}
	internal sealed class ScaledOarDefinition
	{
		internal int PrefabIndex { get; }

		internal string ItemName { get; }

		internal float Scale { get; }

		internal float WaterPosDistance { get; }

		internal float WaterPosHeight { get; }

		internal float RowDipHeight { get; }

		internal float MassMultiplier { get; }

		internal int ValueMultiplier { get; }

		internal GameObject Prefab { get; set; }

		internal bool CacheValidationLogged { get; set; }

		internal ScaledOarDefinition(int prefabIndex, string itemName, float scale, float waterPosDistance, float waterPosHeight, float rowDipHeight, float massMultiplier, int valueMultiplier)
		{
			PrefabIndex = prefabIndex;
			ItemName = itemName;
			Scale = scale;
			WaterPosDistance = waterPosDistance;
			WaterPosHeight = waterPosHeight;
			RowDipHeight = rowDipHeight;
			MassMultiplier = massMultiplier;
			ValueMultiplier = valueMultiplier;
		}
	}
	internal static class ScaledOarFactory
	{
		internal const int VanillaOarPrefabIndex = 168;

		internal const int LegacyBigOarPrefabIndex = 169;

		internal const int BigOarPrefabIndex = 602;

		internal const int HugeOarPrefabIndex = 603;

		internal const int Bfo5000PrefabIndex = 666;

		internal const float BigOarScale = 2f;

		internal const float HugeOarScale = 3f;

		internal const float Bfo5000Scale = 5f;

		private static readonly ScaledOarDefinition[] Definitions = new ScaledOarDefinition[3]
		{
			new ScaledOarDefinition(602, "Big Oar", 2f, 1.5f, 2.8f, 1f, 8f, 4),
			new ScaledOarDefinition(603, "Huge Oar", 3f, 2.25f, 4.2f, 1.5f, 27f, 12),
			new ScaledOarDefinition(666, "BFO 5000", 5f, 3.75f, 7f, 2.5f, 125f, 10)
		};

		private static readonly ScaledOarDefinition LegacyBigOarDefinition = new ScaledOarDefinition(169, "Big Oar", 2f, 1.5f, 2.8f, 1f, 8f, 4);

		internal static bool EnsureRegistered(PrefabsDirectory directory)
		{
			if ((Object)(object)directory == (Object)null || directory.directory == null)
			{
				ManualLogSource logSource = PowerfulOarPlugin.LogSource;
				if (logSource != null)
				{
					logSource.LogError((object)"Could not register scaled oars: PrefabsDirectory is unavailable.");
				}
				return false;
			}
			if (directory.directory.Length <= 168 || (Object)(object)directory.directory[168] == (Object)null)
			{
				ManualLogSource logSource2 = PowerfulOarPlugin.LogSource;
				if (logSource2 != null)
				{
					logSource2.LogError((object)("Could not register scaled oars: vanilla oar prefab " + $"{168} was not found."));
				}
				return false;
			}
			ShipItemOar component = directory.directory[168].GetComponent<ShipItemOar>();
			if ((Object)(object)component == (Object)null)
			{
				ManualLogSource logSource3 = PowerfulOarPlugin.LogSource;
				if (logSource3 != null)
				{
					logSource3.LogError((object)"Could not register scaled oars: prefab 168 is not a ShipItemOar.");
				}
				return false;
			}
			OarStats.Apply(component);
			EnsureDirectoryCapacity(directory);
			bool flag = true;
			ScaledOarDefinition[] definitions = Definitions;
			foreach (ScaledOarDefinition definition in definitions)
			{
				flag &= EnsureRegistered(directory, definition, component);
			}
			return flag & EnsureLegacyBigOarRegistered(directory, component);
		}

		internal static bool ValidateRuntimeCache(PrefabsDirectory directory)
		{
			if (!EnsureRegistered(directory))
			{
				return false;
			}
			EnsureDirectoryCapacity(directory);
			EnsureShipItemCacheCapacity(directory);
			bool result = true;
			ScaledOarDefinition[] definitions = Definitions;
			foreach (ScaledOarDefinition scaledOarDefinition in definitions)
			{
				GameObject val = directory.directory[scaledOarDefinition.PrefabIndex];
				ShipItem val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<ShipItem>() : null);
				SaveablePrefab val3 = (((Object)(object)val != (Object)null) ? val.GetComponent<SaveablePrefab>() : null);
				ScaledOarController scaledOarController = (((Object)(object)val != (Object)null) ? val.GetComponent<ScaledOarController>() : null);
				if ((Object)(object)val2 == (Object)null || (Object)(object)val3 == (Object)null || (Object)(object)scaledOarController == (Object)null || val3.prefabIndex != scaledOarDefinition.PrefabIndex || scaledOarController.PrefabIndex != scaledOarDefinition.PrefabIndex)
				{
					ManualLogSource logSource = PowerfulOarPlugin.LogSource;
					if (logSource != null)
					{
						logSource.LogError((object)(scaledOarDefinition.ItemName + " registration failed validation: directory entry is missing ShipItem, ScaledOarController, or the expected prefab index."));
					}
					result = false;
					continue;
				}
				directory.shipItems[scaledOarDefinition.PrefabIndex] = val2;
				if (!scaledOarDefinition.CacheValidationLogged)
				{
					scaledOarDefinition.CacheValidationLogged = true;
					ManualLogSource logSource2 = PowerfulOarPlugin.LogSource;
					if (logSource2 != null)
					{
						logSource2.LogInfo((object)("Validated " + scaledOarDefinition.ItemName + " prefab and item cache at index " + $"{scaledOarDefinition.PrefabIndex}."));
					}
				}
			}
			GameObject val4 = directory.directory[169];
			ShipItem val5 = (((Object)(object)val4 != (Object)null) ? val4.GetComponent<ShipItem>() : null);
			SaveablePrefab val6 = (((Object)(object)val4 != (Object)null) ? val4.GetComponent<SaveablePrefab>() : null);
			ScaledOarController scaledOarController2 = (((Object)(object)val4 != (Object)null) ? val4.GetComponent<ScaledOarController>() : null);
			if ((Object)(object)val5 == (Object)null || (Object)(object)val6 == (Object)null || (Object)(object)scaledOarController2 == (Object)null || val6.prefabIndex != 169 || scaledOarController2.PrefabIndex != 169)
			{
				ManualLogSource logSource3 = PowerfulOarPlugin.LogSource;
				if (logSource3 != null)
				{
					logSource3.LogError((object)("Legacy Big Oar compatibility failed validation at prefab index " + $"{169}."));
				}
				result = false;
			}
			else
			{
				directory.shipItems[169] = val5;
			}
			return result;
		}

		internal static bool MigrateLegacyBigOar(SaveablePrefab saveable, SavePrefabData data)
		{
			if ((Object)(object)saveable == (Object)null || data == null || data.prefabIndex != 169)
			{
				return false;
			}
			ScaledOarController component = ((Component)saveable).GetComponent<ScaledOarController>();
			ShipItemOar component2 = ((Component)saveable).GetComponent<ShipItemOar>();
			if ((Object)(object)component == (Object)null || (Object)(object)component2 == (Object)null || saveable.prefabIndex != 169)
			{
				return false;
			}
			saveable.prefabIndex = 602;
			component.Initialize(602, 2f);
			OarStats.Apply(component2);
			ManualLogSource logSource = PowerfulOarPlugin.LogSource;
			if (logSource != null)
			{
				logSource.LogInfo((object)("Migrated saved Big Oar from legacy prefab " + $"{169} to {602}; " + "the new index will be written on the next save."));
			}
			return true;
		}

		private static bool EnsureLegacyBigOarRegistered(PrefabsDirectory directory, ShipItemOar vanillaOar)
		{
			GameObject val = directory.directory[169];
			if ((Object)(object)val != (Object)null)
			{
				ScaledOarController component = val.GetComponent<ScaledOarController>();
				SaveablePrefab component2 = val.GetComponent<SaveablePrefab>();
				ShipItemOar component3 = val.GetComponent<ShipItemOar>();
				if ((Object)(object)component != (Object)null && (Object)(object)component2 != (Object)null && (Object)(object)component3 != (Object)null && component.PrefabIndex == 169 && component2.prefabIndex == 169)
				{
					ConfigureScaledOar(val, component3, vanillaOar, LegacyBigOarDefinition);
					component.Initialize(169, 2f);
					return true;
				}
				ManualLogSource logSource = PowerfulOarPlugin.LogSource;
				if (logSource != null)
				{
					logSource.LogError((object)("Could not reserve legacy Big Oar prefab index " + $"{169}: it is already occupied by " + "'" + ((Object)val).name + "'. Old PowerfulOar saves using that index cannot be migrated safely."));
				}
				return false;
			}
			GameObject val2 = directory.directory[602];
			if ((Object)(object)(((Object)(object)val2 != (Object)null) ? val2.GetComponent<ShipItemOar>() : null) == (Object)null)
			{
				ManualLogSource logSource2 = PowerfulOarPlugin.LogSource;
				if (logSource2 != null)
				{
					logSource2.LogError((object)("Could not create legacy Big Oar compatibility prefab: " + $"current prefab {602} is unavailable."));
				}
				return false;
			}
			GameObject val3 = null;
			try
			{
				val3 = Object.Instantiate<GameObject>(val2);
				ShipItemOar component4 = val3.GetComponent<ShipItemOar>();
				ScaledOarController component5 = val3.GetComponent<ScaledOarController>();
				if ((Object)(object)component4 == (Object)null || (Object)(object)component5 == (Object)null)
				{
					ManualLogSource logSource3 = PowerfulOarPlugin.LogSource;
					if (logSource3 != null)
					{
						logSource3.LogError((object)"Could not create legacy Big Oar compatibility prefab: required components are missing.");
					}
					Object.Destroy((Object)(object)val3);
					return false;
				}
				ConfigureScaledOar(val3, component4, vanillaOar, LegacyBigOarDefinition);
				component5.Initialize(169, 2f);
				directory.directory[169] = val3;
				ManualLogSource logSource4 = PowerfulOarPlugin.LogSource;
				if (logSource4 != null)
				{
					logSource4.LogInfo((object)($"Reserved prefab {169} for legacy " + $"Big Oar saves; new Big Oars use prefab {602}."));
				}
				return true;
			}
			catch (Exception ex)
			{
				if ((Object)(object)val3 != (Object)null)
				{
					Object.Destroy((Object)(object)val3);
				}
				ManualLogSource logSource5 = PowerfulOarPlugin.LogSource;
				if (logSource5 != null)
				{
					logSource5.LogError((object)("Could not create legacy Big Oar compatibility prefab: " + ex));
				}
				return false;
			}
		}

		private static bool EnsureRegistered(PrefabsDirectory directory, ScaledOarDefinition definition, ShipItemOar vanillaOar)
		{
			GameObject val = directory.directory[definition.PrefabIndex];
			if ((Object)(object)val != (Object)null)
			{
				ScaledOarController scaledOarController = val.GetComponent<ScaledOarController>();
				if ((Object)(object)val == (Object)(object)definition.Prefab || ((Object)(object)scaledOarController != (Object)null && scaledOarController.PrefabIndex == definition.PrefabIndex))
				{
					ShipItemOar component = val.GetComponent<ShipItemOar>();
					if ((Object)(object)component == (Object)null)
					{
						ManualLogSource logSource = PowerfulOarPlugin.LogSource;
						if (logSource != null)
						{
							logSource.LogError((object)("Could not configure " + definition.ItemName + ": ShipItemOar is missing."));
						}
						return false;
					}
					if ((Object)(object)scaledOarController == (Object)null)
					{
						scaledOarController = val.AddComponent<ScaledOarController>();
					}
					ConfigureScaledOar(val, component, vanillaOar, definition);
					definition.Prefab = val;
					scaledOarController.Initialize(definition.PrefabIndex, definition.Scale);
					return true;
				}
				ManualLogSource logSource2 = PowerfulOarPlugin.LogSource;
				if (logSource2 != null)
				{
					logSource2.LogError((object)("Could not register " + definition.ItemName + ": prefab index " + $"{definition.PrefabIndex} is already occupied by '{((Object)val).name}'."));
				}
				return false;
			}
			if ((Object)(object)definition.Prefab != (Object)null)
			{
				ShipItemOar component2 = definition.Prefab.GetComponent<ShipItemOar>();
				ScaledOarController component3 = definition.Prefab.GetComponent<ScaledOarController>();
				if ((Object)(object)component2 == (Object)null || (Object)(object)component3 == (Object)null)
				{
					ManualLogSource logSource3 = PowerfulOarPlugin.LogSource;
					if (logSource3 != null)
					{
						logSource3.LogError((object)("Could not restore " + definition.ItemName + ": cached components are missing."));
					}
					return false;
				}
				ConfigureScaledOar(definition.Prefab, component2, vanillaOar, definition);
				component3.Initialize(definition.PrefabIndex, definition.Scale);
				directory.directory[definition.PrefabIndex] = definition.Prefab;
				return true;
			}
			GameObject val2 = null;
			try
			{
				val2 = Object.Instantiate<GameObject>(directory.directory[168]);
				SaveablePrefab component4 = val2.GetComponent<SaveablePrefab>();
				ShipItemOar component5 = val2.GetComponent<ShipItemOar>();
				if ((Object)(object)component4 == (Object)null || (Object)(object)component5 == (Object)null)
				{
					ManualLogSource logSource4 = PowerfulOarPlugin.LogSource;
					if (logSource4 != null)
					{
						logSource4.LogError((object)("Could not register " + definition.ItemName + ": the cloned vanilla prefab is missing SaveablePrefab or ShipItemOar."));
					}
					Object.Destroy((Object)(object)val2);
					return false;
				}
				ConfigureScaledOar(val2, component5, vanillaOar, definition);
				ScaledOarController scaledOarController2 = val2.GetComponent<ScaledOarController>();
				if ((Object)(object)scaledOarController2 == (Object)null)
				{
					scaledOarController2 = val2.AddComponent<ScaledOarController>();
				}
				scaledOarController2.Initialize(definition.PrefabIndex, definition.Scale);
				directory.directory[definition.PrefabIndex] = val2;
				definition.Prefab = val2;
				ManualLogSource logSource5 = PowerfulOarPlugin.LogSource;
				if (logSource5 != null)
				{
					logSource5.LogInfo((object)("Registered " + definition.ItemName + " at prefab index " + $"{definition.PrefabIndex}. Scale={definition.Scale:0.0}x, " + $"mass={((ShipItem)component5).mass:0.0}, value={((ShipItem)component5).value}, " + $"water distance={definition.WaterPosDistance:0.00}, " + $"water height={definition.WaterPosHeight:0.00}, " + $"dip={definition.RowDipHeight:0.00}, big=false."));
				}
				return true;
			}
			catch (Exception arg)
			{
				if ((Object)(object)val2 != (Object)null)
				{
					Object.Destroy((Object)(object)val2);
				}
				ManualLogSource logSource6 = PowerfulOarPlugin.LogSource;
				if (logSource6 != null)
				{
					logSource6.LogError((object)$"Could not register {definition.ItemName}: {arg}");
				}
				return false;
			}
		}

		private static void ConfigureScaledOar(GameObject prefab, ShipItemOar oar, ShipItemOar vanillaOar, ScaledOarDefinition definition)
		{
			//IL_0037: 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)
			SaveablePrefab component = prefab.GetComponent<SaveablePrefab>();
			if ((Object)(object)component == (Object)null)
			{
				throw new InvalidOperationException(definition.ItemName + " is missing SaveablePrefab.");
			}
			((Object)prefab).name = definition.ItemName;
			prefab.transform.localScale = Vector3.one * definition.Scale;
			Object.DontDestroyOnLoad((Object)(object)prefab);
			component.prefabIndex = definition.PrefabIndex;
			((ShipItem)oar).name = definition.ItemName;
			((PickupableItem)oar).big = false;
			((ShipItem)oar).wallAttachment = false;
			((ShipItem)oar).mass = ((ShipItem)vanillaOar).mass * definition.MassMultiplier;
			((ShipItem)oar).value = ((ShipItem)vanillaOar).value * definition.ValueMultiplier;
			oar.waterPosDistance = definition.WaterPosDistance;
			oar.waterPosHeight = definition.WaterPosHeight;
			oar.rowDipHeight = definition.RowDipHeight;
			OarStats.Apply(oar);
			HookHangMoreCompatibility.Exclude((ShipItem)(object)oar);
		}

		private static void EnsureDirectoryCapacity(PrefabsDirectory directory)
		{
			if (directory.directory.Length <= 666)
			{
				Array.Resize(ref directory.directory, 667);
			}
		}

		private static void EnsureShipItemCacheCapacity(PrefabsDirectory directory)
		{
			if (directory.shipItems == null)
			{
				directory.shipItems = (ShipItem[])(object)new ShipItem[directory.directory.Length];
				for (int i = 0; i < directory.directory.Length; i++)
				{
					GameObject val = directory.directory[i];
					if ((Object)(object)val != (Object)null)
					{
						directory.shipItems[i] = val.GetComponent<ShipItem>();
					}
				}
			}
			else if (directory.shipItems.Length < directory.directory.Length)
			{
				Array.Resize(ref directory.shipItems, directory.directory.Length);
			}
		}
	}
	[DefaultExecutionOrder(10000)]
	internal sealed class ScaledOarController : MonoBehaviour
	{
		private static readonly HashSet<ScaledOarController> ActiveControllers = new HashSet<ScaledOarController>();

		private static readonly FieldInfo CollidedCollidersField = AccessTools.Field(typeof(PickupableItemCollisionChecker), "collidedCols");

		private static readonly FieldInfo CurrentDecolDistanceField = AccessTools.Field(typeof(PickupableItemCollisionChecker), "currentDecolDistance");

		[SerializeField]
		private int prefabIndex;

		[SerializeField]
		private float targetScale = 1f;

		private ShipItemOar item;

		private ItemRigidbody itemRigidbody;

		private Outline outline;

		private bool wasInSleepOrLoadTransition;

		private Coroutine initializationRoutine;

		private bool initializationGuardActive;

		private bool ownsKinematicGuard;

		private bool persistentKinematic;

		private bool waitingForSavedCrate;

		private bool waitingForSavedInventory;

		private int savedCrateId;

		internal int PrefabIndex => prefabIndex;

		internal void Initialize(int newPrefabIndex, float newTargetScale)
		{
			prefabIndex = newPrefabIndex;
			targetScale = newTargetScale;
			CacheItemComponents();
			BeginPhysicsInitialization();
			HookHangMoreCompatibility.Exclude((ShipItem)(object)item);
		}

		internal bool CanRestoreSavedCrate(int crateId)
		{
			if (waitingForSavedCrate && savedCrateId > 0)
			{
				return savedCrateId == crateId;
			}
			return false;
		}

		internal void PrepareForSavedState(SavePrefabData data)
		{
			//IL_009f: 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_00b9: Unknown result type (might be due to invalid IL or missing references)
			if (data == null)
			{
				return;
			}
			CacheItemComponents();
			BeginPhysicsInitialization();
			waitingForSavedCrate = data.crateId > 0;
			waitingForSavedInventory = !waitingForSavedCrate && data.inventorySlot > -1;
			savedCrateId = (waitingForSavedCrate ? data.crateId : 0);
			if (waitingForSavedCrate && !((Object)(object)item == (Object)null) && !((Object)(object)itemRigidbody == (Object)null))
			{
				itemRigidbody.attached = true;
				itemRigidbody.disableCol = true;
				itemRigidbody.inStove = true;
				((Component)this).transform.localScale = Vector3.one * ((ShipItem)item).inventoryScale * 0.33f;
				Collider component = ((Component)item).GetComponent<Collider>();
				if ((Object)(object)component != (Object)null)
				{
					component.enabled = false;
				}
			}
		}

		internal void CompleteSavedCrateRestore(int crateId)
		{
			if (CanRestoreSavedCrate(crateId))
			{
				waitingForSavedCrate = false;
				savedCrateId = 0;
			}
		}

		internal void OnEnteredInventory()
		{
			waitingForSavedInventory = false;
		}

		internal void RestoreWorldScaleAfterStorage()
		{
			waitingForSavedCrate = false;
			waitingForSavedInventory = false;
			savedCrateId = 0;
			CacheItemComponents();
			Collider val = (((Object)(object)item != (Object)null) ? ((Component)item).GetComponent<Collider>() : null);
			if ((Object)(object)val != (Object)null)
			{
				val.enabled = true;
			}
			BeginPhysicsInitialization();
		}

		internal void SetPersistentKinematic(bool state)
		{
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			persistentKinematic = state;
			CacheItemComponents();
			if ((Object)(object)itemRigidbody == (Object)null)
			{
				return;
			}
			if (state)
			{
				itemRigidbody.debugForceKinematic = true;
			}
			else if (!initializationGuardActive)
			{
				itemRigidbody.debugForceKinematic = false;
			}
			Rigidbody body = itemRigidbody.GetBody();
			if ((Object)(object)body != (Object)null)
			{
				if (state)
				{
					body.isKinematic = true;
					body.velocity = Vector3.zero;
					body.angularVelocity = Vector3.zero;
				}
				body.useGravity = !state;
			}
		}

		internal static void SuppressTransitionOutlines()
		{
			foreach (ScaledOarController activeController in ActiveControllers)
			{
				if ((Object)(object)activeController != (Object)null)
				{
					activeController.SuppressStaleOutline();
				}
			}
		}

		private void Awake()
		{
			CacheItemComponents();
			BeginPhysicsInitialization();
			HookHangMoreCompatibility.Exclude((ShipItem)(object)item);
		}

		private void OnEnable()
		{
			ActiveControllers.Add(this);
			StartInitializationRoutineIfNeeded();
		}

		private void OnDisable()
		{
			ActiveControllers.Remove(this);
			if (initializationRoutine != null)
			{
				((MonoBehaviour)this).StopCoroutine(initializationRoutine);
				initializationRoutine = null;
			}
		}

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

		private void LateUpdate()
		{
			CacheItemComponents();
			if ((Object)(object)item == (Object)null)
			{
				return;
			}
			bool flag = GameState.sleeping || GameState.recovering || GameState.currentlyLoading || GameState.justWokeUp;
			if (flag)
			{
				if (!GameState.sleeping && !GameState.currentlyLoading)
				{
					ReconcileCollisionState();
				}
				SuppressStaleOutline();
			}
			else if (wasInSleepOrLoadTransition)
			{
				ReconcileCollisionState();
				SuppressStaleOutline();
			}
			wasInSleepOrLoadTransition = flag;
		}

		private void ApplyScale(Transform target)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = Vector3.one * targetScale;
			if (target.localScale != val)
			{
				target.localScale = val;
			}
		}

		private void CacheItemComponents()
		{
			if ((Object)(object)item == (Object)null)
			{
				item = ((Component)this).GetComponent<ShipItemOar>();
			}
			if ((Object)(object)itemRigidbody == (Object)null && (Object)(object)item != (Object)null)
			{
				itemRigidbody = ((ShipItem)item).itemRigidbodyC;
			}
		}

		private void BeginPhysicsInitialization()
		{
			CacheItemComponents();
			if ((Object)(object)item == (Object)null || (Object)(object)itemRigidbody == (Object)null)
			{
				return;
			}
			ApplyScale(((Component)this).transform);
			ApplyScale(((Component)itemRigidbody).transform);
			if (!initializationGuardActive)
			{
				initializationGuardActive = true;
				if (!itemRigidbody.debugForceKinematic)
				{
					itemRigidbody.debugForceKinematic = true;
					ownsKinematicGuard = true;
				}
			}
			StartInitializationRoutineIfNeeded();
		}

		private void StartInitializationRoutineIfNeeded()
		{
			if (initializationGuardActive && initializationRoutine == null && ((Behaviour)this).isActiveAndEnabled && ((Component)this).gameObject.activeInHierarchy)
			{
				initializationRoutine = ((MonoBehaviour)this).StartCoroutine(CompletePhysicsInitialization());
			}
		}

		private IEnumerator CompletePhysicsInitialization()
		{
			while ((Object)(object)itemRigidbody == (Object)null || (Object)(object)itemRigidbody.GetBody() == (Object)null || (Object)(object)((Component)itemRigidbody).GetComponent<Collider>() == (Object)null)
			{
				CacheItemComponents();
				yield return null;
			}
			int storageRestoreGraceFrames = 0;
			while (GameState.currentlyLoading || GameState.loadingBoatLocalItems || GameState.recovering || waitingForSavedCrate || waitingForSavedInventory)
			{
				if (!GameState.currentlyLoading && !GameState.loadingBoatLocalItems && !GameState.recovering && (waitingForSavedCrate || waitingForSavedInventory))
				{
					storageRestoreGraceFrames++;
					if (storageRestoreGraceFrames > 30)
					{
						RecoverFailedStorageRestore();
					}
				}
				else
				{
					storageRestoreGraceFrames = 0;
				}
				yield return null;
			}
			Rigidbody body = itemRigidbody.GetBody();
			if ((Object)(object)body != (Object)null)
			{
				body.isKinematic = true;
				body.velocity = Vector3.zero;
				body.angularVelocity = Vector3.zero;
				if (persistentKinematic)
				{
					body.useGravity = false;
				}
			}
			Physics.SyncTransforms();
			yield return (object)new WaitForFixedUpdate();
			ReleaseInitializationGuard();
		}

		private void RecoverFailedStorageRestore()
		{
			bool num = waitingForSavedCrate;
			waitingForSavedCrate = false;
			waitingForSavedInventory = false;
			savedCrateId = 0;
			SaveablePrefab val = (((Object)(object)item != (Object)null) ? ((Component)item).GetComponent<SaveablePrefab>() : null);
			if (num && (Object)(object)val != (Object)null)
			{
				val.currentCrateId = 0;
			}
			if ((Object)(object)itemRigidbody != (Object)null)
			{
				itemRigidbody.attached = false;
				itemRigidbody.disableCol = false;
				itemRigidbody.inStove = false;
			}
			Collider val2 = (((Object)(object)item != (Object)null) ? ((Component)item).GetComponent<Collider>() : null);
			if ((Object)(object)val2 != (Object)null)
			{
				val2.enabled = true;
			}
			ApplyScale(((Component)this).transform);
			if ((Object)(object)itemRigidbody != (Object)null)
			{
				ApplyScale(((Component)itemRigidbody).transform);
			}
			ManualLogSource logSource = PowerfulOarPlugin.LogSource;
			if (logSource != null)
			{
				logSource.LogWarning((object)("Recovered " + (((ShipItem)(item?)).name ?? "scaled oar") + " after its saved inventory or crate location could not be restored."));
			}
		}

		private void ReleaseInitializationGuard()
		{
			initializationRoutine = null;
			initializationGuardActive = false;
			if (ownsKinematicGuard && !persistentKinematic && (Object)(object)itemRigidbody != (Object)null)
			{
				itemRigidbody.debugForceKinematic = false;
			}
			ownsKinematicGuard = false;
		}

		private void SuppressStaleOutline()
		{
			if ((Object)(object)item == (Object)null)
			{
				item = ((Component)this).GetComponent<ShipItemOar>();
			}
			if ((Object)(object)item != (Object)null)
			{
				((GoPointerButton)item).enableRedOutline = false;
			}
			if ((Object)(object)outline == (Object)null)
			{
				outline = ((Component)this).GetComponent<Outline>();
			}
			if ((Object)(object)outline != (Object)null)
			{
				((Behaviour)outline).enabled = false;
			}
		}

		private void ReconcileCollisionState()
		{
			//IL_010c: 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_0125: 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)
			PickupableItemCollisionChecker val = ((PickupableItem)(item?)).colChecker;
			if ((Object)(object)val == (Object)null || CollidedCollidersField == null || CurrentDecolDistanceField == null)
			{
				return;
			}
			List<Collider> list = CollidedCollidersField.GetValue(val) as List<Collider>;
			Collider component = ((Component)val).GetComponent<Collider>();
			int num = 0;
			float num2 = 0f;
			if (Object.op_Implicit((Object)(object)((PickupableItem)item).held) && ((ShipItem)item).GetCurrentInventorySlot() < 0 && (Object)(object)component != (Object)null && component.enabled && list != null)
			{
				Vector3 val2 = default(Vector3);
				float num3 = default(float);
				foreach (Collider item in list)
				{
					if (!((Object)(object)item == (Object)null) && item.enabled && ((Component)item).gameObject.activeInHierarchy && !item.isTrigger && !((Object)(object)((Component)item).gameObject == (Object)(object)((Component)this.item).gameObject) && !((Component)item).CompareTag("Boat") && Physics.ComputePenetration(component, ((Component)component).transform.position, ((Component)component).transform.rotation, item, ((Component)item).transform.position, ((Component)item).transform.rotation, ref val2, ref num3) && num3 > 0f)
					{
						num++;
						num2 = Mathf.Max(num2, num3);
					}
				}
			}
			val.collisions = num;
			CurrentDecolDistanceField.SetValue(val, num2);
			val.allowObstructedDropping = num2 < 0.06f;
			((GoPointerButton)this.item).enableRedOutline = false;
		}
	}
	[HarmonyPatch(typeof(PrefabsDirectory), "Start")]
	internal static class ScaledOarPrefabRegistrationPatch
	{
		[HarmonyPrefix]
		[HarmonyPriority(0)]
		private static void Prefix(PrefabsDirectory __instance)
		{
			ScaledOarFactory.EnsureRegistered(__instance);
		}

		[HarmonyPostfix]
		[HarmonyPriority(0)]
		private static void Postfix(PrefabsDirectory __instance)
		{
			ScaledOarFactory.ValidateRuntimeCache(__instance);
			BoneIslandBfoPlacement.OnPrefabsReady();
		}
	}
	[HarmonyPatch(typeof(OutlineEffect), "OnEnable")]
	internal static class ScaledOarOutlineEffectPatch
	{
		[HarmonyPostfix]
		[HarmonyPriority(0)]
		private static void Postfix()
		{
			ScaledOarController.SuppressTransitionOutlines();
		}
	}
	[HarmonyPatch(typeof(ShipItemHammer), "CanNail")]
	internal static class ScaledOarNailingPatch
	{
		[HarmonyPostfix]
		private static void Postfix(ShipItem item, ref bool __result)
		{
			if (HookHangMoreCompatibility.IsExcluded(item))
			{
				__result = item.sold;
			}
		}
	}
	[HarmonyPatch(typeof(ShipItem), "Awake")]
	[HarmonyAfter(new string[] { "com.raddude.hookshangmore" })]
	internal static class HookHangMoreExclusionPatch
	{
		[HarmonyPostfix]
		[HarmonyPriority(0)]
		private static void Postfix(ShipItem __instance)
		{
			HookHangMoreCompatibility.Exclude(__instance);
		}
	}
	[HarmonyPatch(typeof(ItemRigidbody), "LateUpdate")]
	internal static class ScaledOarRigidbodyScalePatch
	{
		[HarmonyPrefix]
		private static bool Prefix(ItemRigidbody __instance)
		{
			if (!OarStats.IsScaledOar(__instance.GetShipItem()))
			{
				return true;
			}
			return (Object)(object)__instance.GetCurrentInventorySlot() != (Object)null;
		}
	}
	[HarmonyPatch(typeof(SaveablePrefab), "Load")]
	internal static class ScaledOarSavedStatePatch
	{
		[HarmonyPostfix]
		private static void Postfix(SaveablePrefab __instance, SavePrefabData data)
		{
			ScaledOarFactory.MigrateLegacyBigOar(__instance, data);
			((Component)__instance).GetComponent<ScaledOarController>()?.PrepareForSavedState(data);
		}
	}
	[HarmonyPatch(typeof(ItemRigidbody), "EnterInventorySlot")]
	internal static class ScaledOarInventoryEnterPatch
	{
		[HarmonyPostfix]
		private static void Postfix(ItemRigidbody __instance)
		{
			ShipItem shipItem = __instance.GetShipItem();
			if (shipItem != null)
			{
				((Component)shipItem).GetComponent<ScaledOarController>()?.OnEnteredInventory();
			}
		}
	}
	[HarmonyPatch(typeof(ItemRigidbody), "ExitInventorySlot")]
	internal static class ScaledOarInventoryExitPatch
	{
		[HarmonyPostfix]
		private static void Postfix(ItemRigidbody __instance)
		{
			ShipItem shipItem = __instance.GetShipItem();
			if (shipItem != null)
			{
				((Component)shipItem).GetComponent<ScaledOarController>()?.RestoreWorldScaleAfterStorage();
			}
		}
	}
	[HarmonyPatch(typeof(CrateInventory), "InsertItem")]
	internal static class ScaledOarCrateInsertPatch
	{
		[HarmonyPrefix]
		private static bool Prefix(CrateInventory __instance, ShipItem item)
		{
			if (!OarStats.IsScaledOar(item))
			{
				return true;
			}
			SaveablePrefab component = ((Component)item).GetComponent<SaveablePrefab>();
			SaveablePrefab component2 = ((Component)__instance).GetComponent<SaveablePrefab>();
			int num = (((Object)(object)component2 != (Object)null) ? component2.instanceId : 0);
			ScaledOarController component3 = ((Component)item).GetComponent<ScaledOarController>();
			if (num > 0 && __instance.containedItems.Contains(item))
			{
				if ((Object)(object)component != (Object)null)
				{
					component.currentCrateId = num;
				}
				component3?.CompleteSavedCrateRestore(num);
				return false;
			}
			bool num2;
			if (!((Object)(object)component3 != (Object)null))
			{
				if (num <= 0 || !((Object)(object)component != (Object)null))
				{
					goto IL_009c;
				}
				num2 = component.currentCrateId == num;
			}
			else
			{
				num2 = component3.CanRestoreSavedCrate(num);
			}
			if (num2)
			{
				component3?.CompleteSavedCrateRestore(num);
				return true;
			}
			goto IL_009c;
			IL_009c:
			if ((Object)(object)component != (Object)null && component.currentCrateId == num)
			{
				component.currentCrateId = 0;
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(CrateInventory), "WithdrawItem")]
	internal static class ScaledOarCrateWithdrawPatch
	{
		[HarmonyPostfix]
		private static void Postfix(ShipItem item)
		{
			if (item != null)
			{
				((Component)item).GetComponent<ScaledOarController>()?.RestoreWorldScaleAfterStorage();
			}
		}
	}
	[HarmonyPatch(typeof(CrateInventoryButton), "OnActivate")]
	internal static class ScaledOarCrateUiPatch
	{
		[HarmonyPrefix]
		private static bool Prefix(GoPointer activatingPointer)
		{
			PickupableItem val = (((Object)(object)activatingPointer != (Object)null) ? activatingPointer.GetHeldItem() : null);
			if (!OarStats.IsScaledOar(((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<ShipItem>() : null))
			{
				return true;
			}
			if ((Object)(object)NotificationUi.instance != (Object)null)
			{
				NotificationUi.instance.ShowNotification("Scaled oars cannot be stored in crates.");
			}
			CrateInventoryUI instance = CrateInventoryUI.instance;
			if (instance != null)
			{
				instance.RefreshButtons();
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(ShopItemSpawner), "Start")]
	internal static class BigOarVendorPatch
	{
		private sealed class VendorPlacement
		{
			internal readonly string SpawnerName;

			internal readonly Vector3 LocalPosition;

			internal readonly Vector3 LocalEuler;

			internal VendorPlacement(string spawnerName, Vector3 localPosition, Vector3 localEuler)
			{
				//IL_000e: Unknown result type (might be due to invalid IL or missing references)
				//IL_000f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0015: Unknown result type (might be due to invalid IL or missing references)
				//IL_0016: Unknown result type (might be due to invalid IL or missing references)
				SpawnerName = spawnerName;
				LocalPosition = localPosition;
				LocalEuler = localEuler;
			}
		}

		private static readonly Dictionary<string, VendorPlacement> TargetPlacements = new Dictionary<string, VendorPlacement>
		{
			{
				"island 9 E Dragon Cliffs",
				new VendorPlacement("shop item spawner (236)", new Vector3(0.198f, 1.5f, -0.049f), new Vector3(0.625f, -176.864f, 0.7f))
			},
			{
				"island 1 A Gold Rock",
				new VendorPlacement("shop item (224)", new Vector3(0.145f, 1.467f, -0.004f), new Vector3(0f, -12.273f, 0f))
			},
			{
				"island 15 M (Fort)",
				new VendorPlacement("shop item (284)", new Vector3(0.287f, 1.46f, -0.251f), new Vector3(-2.876f, -2.876f, -1.02f))
			}
		};

		[HarmonyPrefix]
		[HarmonyPriority(0)]
		private static void Prefix(ShopItemSpawner __instance)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: 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)
			Scene scene = ((Component)__instance).gameObject.scene;
			if (!((Scene)(ref scene)).IsValid() || !TargetPlacements.TryGetValue(((Scene)(ref scene)).name, out var value) || ((Object)((Component)__instance).gameObject).name != value.SpawnerName)
			{
				return;
			}
			PrefabsDirectory instance = PrefabsDirectory.instance;
			if ((Object)(object)instance == (Object)null || !ScaledOarFactory.ValidateRuntimeCache(instance))
			{
				ManualLogSource logSource = PowerfulOarPlugin.LogSource;
				if (logSource != null)
				{
					logSource.LogError((object)("Could not add Big Oar to vendor in " + ((Scene)(ref scene)).name + ": prefab directory unavailable."));
				}
				return;
			}
			int prefabIndex = OarStats.GetPrefabIndex(((Object)(object)__instance.itemPrefab != (Object)null) ? __instance.itemPrefab.GetComponent<ShipItem>() : null);
			switch (prefabIndex)
			{
			case 602:
				break;
			default:
			{
				ManualLogSource logSource3 = PowerfulOarPlugin.LogSource;
				if (logSource3 != null)
				{
					logSource3.LogWarning((object)("Configured Big Oar vendor slot '" + value.SpawnerName + "' in " + ((Scene)(ref scene)).name + " does not contain vanilla oar prefab " + $"{168}; found {prefabIndex}."));
				}
				break;
			}
			case 168:
			{
				__instance.itemPrefab = instance.directory[602];
				ScaledOarVendorDisplaySpawner scaledOarVendorDisplaySpawner = ((Component)__instance).GetComponent<ScaledOarVendorDisplaySpawner>();
				if ((Object)(object)scaledOarVendorDisplaySpawner == (Object)null)
				{
					scaledOarVendorDisplaySpawner = ((Component)__instance).gameObject.AddComponent<ScaledOarVendorDisplaySpawner>();
				}
				scaledOarVendorDisplaySpawner.Initialize(((Scene)(ref scene)).name, "Big Oar", 602, value.LocalPosition, value.LocalEuler, 2f);
				ManualLogSource logSource2 = PowerfulOarPlugin.LogSource;
				if (logSource2 != null)
				{
					logSource2.LogInfo((object)("Replaced one vanilla-oar vendor slot with Big Oar in " + ((Scene)(ref scene)).name + " at '" + value.SpawnerName + "' using its configured local pose."));
				}
				break;
			}
			}
		}
	}
	[HarmonyPatch(typeof(Shopkeeper), "Start")]
	internal static class HugeOarVendorPatch
	{
		internal const string SceneName = "island 27 Lagoon SwampShipyard";

		internal const string ShopkeeperName = "shopkeeper (16)";

		internal const string NpcName = "Modular NPC";

		[HarmonyPostfix]
		private static void Postfix(Shopkeeper __instance)
		{
			if (IsTarget(__instance))
			{
				HugeOarVendorInstaller hugeOarVendorInstaller = ((Component)__instance).GetComponent<HugeOarVendorInstaller>();
				if ((Object)(object)hugeOarVendorInstaller == (Object)null)
				{
					hugeOarVendorInstaller = ((Component)__instance).gameObject.AddComponent<HugeOarVendorInstaller>();
				}
				hugeOarVendorInstaller.Initialize(__instance);
			}
		}

		internal static bool IsTarget(Shopkeeper shopkeeper)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)shopkeeper == (Object)null || ((Object)((Component)shopkeeper).gameObject).name != "shopkeeper (16)")
			{
				return false;
			}
			Scene scene = ((Component)shopkeeper).gameObject.scene;
			if (((Scene)(ref scene)).IsValid())
			{
				return ((Scene)(ref scene)).name == "island 27 Lagoon SwampShipyard";
			}
			return false;
		}
	}
	internal sealed class HugeOarVendorInstaller : MonoBehaviour
	{
		private const string SpawnerName = "PowerfulOar Huge Oar shop spawner";

		private static readonly Vector3 LocalPosition = new Vector3(-1.444f, 4.292f, 0.854f);

		private static readonly Vector3 LocalEuler = new Vector3(8.857f, -110.947f, 1.63f);

		private Shopkeeper shopkeeper;

		private HugeOarPurchaseDialogueArea dialogueArea;

		private float nextAttempt;

		private bool complete;

		private bool reportedMissingNpc;

		internal void Initialize(Shopkeeper newShopkeeper)
		{
			shopkeeper = newShopkeeper;
			nextAttempt = 0f;
		}

		internal void ShowPurchaseReaction(int purchaseCount)
		{
			if ((Object)(object)dialogueArea != (Object)null)
			{
				dialogueArea.ShowPurchase(HugeOarPurchaseState.GetDialogue(purchaseCount));
			}
		}

		private void Update()
		{
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Expected O, but got Unknown
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0200: Unknown result type (might be due to invalid IL or missing references)
			//IL_0205: Unknown result type (might be due to invalid IL or missing references)
			if (complete || Time.unscaledTime < nextAttempt)
			{
				return;
			}
			if ((Object)(object)shopkeeper == (Object)null)
			{
				((Behaviour)this).enabled = false;
				return;
			}
			nextAttempt = Time.unscaledTime + 1f;
			Transform val = ((Component)shopkeeper).transform.Find("Modular NPC");
			if ((Object)(object)val == (Object)null)
			{
				if (!reportedMissingNpc)
				{
					reportedMissingNpc = true;
					ManualLogSource logSource = PowerfulOarPlugin.LogSource;
					if (logSource != null)
					{
						logSource.LogError((object)"Could not add Huge Oar to Kicia Bay: shopkeeper (16)/Modular NPC was not found; retrying.");
					}
				}
				nextAttempt = Time.unscaledTime + 5f;
				return;
			}
			PrefabsDirectory instance = PrefabsDirectory.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return;
			}
			if (!ScaledOarFactory.ValidateRuntimeCache(instance))
			{
				ManualLogSource logSource2 = PowerfulOarPlugin.LogSource;
				if (logSource2 != null)
				{
					logSource2.LogError((object)"Could not add Huge Oar to Kicia Bay: scaled-oar prefab validation failed.");
				}
				((Behaviour)this).enabled = false;
				return;
			}
			if ((Object)(object)val.Find("PowerfulOar Huge Oar shop spawner") != (Object)null)
			{
				ManualLogSource logSource3 = PowerfulOarPlugin.LogSource;
				if (logSource3 != null)
				{
					logSource3.LogWarning((object)"Skipped duplicate Kicia Bay Huge Oar shop spawner.");
				}
				complete = true;
				((Behaviour)this).enabled = false;
				return;
			}
			GameObject val2 = null;
			try
			{
				val2 = new GameObject("PowerfulOar Huge Oar shop spawner");
				val2.SetActive(false);
				val2.transform.SetParent(val, false);
				val2.transform.localPosition = LocalPosition;
				val2.transform.localRotation = Quaternion.Euler(LocalEuler);
				val2.transform.localScale = Vector3.one;
				ShopItemSpawner obj = val2.AddComponent<ShopItemSpawner>();
				obj.itemPrefab = instance.directory[603];
				obj.availableAtNight = false;
				obj.priceMult = 1f;
				val2.AddComponent<ScaledOarVendorDisplaySpawner>().Initialize("island 27 Lagoon SwampShipyard", "Huge Oar", 603, Vector3.zero, Vector3.zero, 3f);
				dialogueArea = HugeOarPurchaseDialogueArea.Create(val);
				val2.SetActive(true);
				complete = true;
				((Behaviour)this).enabled = false;
				ManualLogSource logSource4 = PowerfulOarPlugin.LogSource;
				if (logSource4 != null)
				{
					logSource4.LogInfo((object)("Added Huge Oar prefab 603 beneath Kicia Bay shopkeeper (16)/Modular NPC at local position " + ((object)LocalPosition/*cast due to .constrained prefix*/).ToString() + " and local rotation " + ((object)LocalEuler/*cast due to .constrained prefix*/).ToString() + "."));
				}
			}
			catch (Exception ex)
			{
				if ((Object)(object)dialogueArea != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)dialogueArea).gameObject);
					dialogueArea = null;
				}
				if ((Object)(object)val2 != (Object)null)
				{
					Object.Destroy((Object)(object)val2);
				}
				nextAttempt = Time.unscaledTime + 10f;
				ManualLogSource logSource5 = PowerfulOarPlugin.LogSource;
				if (logSource5 != null)
				{
					logSource5.LogError((object)("Could not install the Kicia Bay Huge Oar vendor; retrying: " + ex));
				}
			}
		}
	}
	[HarmonyPatch(typeof(ShopItemSpawner), "SpawnItem")]
	internal static class ScaledOarVendorSpawnPatch
	{
		[HarmonyPostfix]
		[HarmonyPriority(0)]
		private static void Postfix(ShopItemSpawner __instance, ShipItem ___item)
		{
			ScaledOarVendorDisplaySpawner component = ((Component)__instance).GetComponent<ScaledOarVendorDisplaySpawner>();
			if ((Object)(object)component != (Object)null)
			{
				component.ConfigureSpawnedItem(___item);
			}
		}
	}
	internal sealed class ScaledOarVendorDisplaySpawner : MonoBehaviour
	{
		private string sceneName;

		private string itemName;

		private int prefabIndex;

		private Vector3 localPosition;

		private Quaternion localRotation;

		private float targetWorldScale;

		internal void Initialize(string newSceneName, string newItemName, int newPrefabIndex, Vector3 newLocalPosition, Vector3 newLocalEuler, float newTargetWorldScale)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: 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)
			sceneName = newSceneName;
			itemName = newItemName;
			prefabIndex = newPrefabIndex;
			localPosition = newLocalPosition;
			localRotation = Quaternion.Euler(newLocalEuler);
			targetWorldScale = newTargetWorldScale;
		}

		internal void ConfigureSpawnedItem(ShipItem item)
		{
			//IL_0037: 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)
			if