Decompiled source of BjornsHitchingPost v1.0.1

plugins/BjornsHitchingPost/BjornsHitchingPost.dll

Decompiled 2 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("BjornsHitchingPost")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: AssemblyInformationalVersion("1.0.1")]
[assembly: AssemblyProduct("BjornsHitchingPost")]
[assembly: AssemblyTitle("BjornsHitchingPost")]
[assembly: AssemblyVersion("1.0.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 BjornsHitchingPost
{
	public sealed class AnimalTether : MonoBehaviour
	{
		[HarmonyPatch(typeof(Player), "Interact")]
		private static class IndividualRelease
		{
			private static bool Prefix(Player __instance, GameObject go, bool hold, bool alt)
			{
				//IL_0029: Unknown result type (might be due to invalid IL or missing references)
				//IL_002e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0049: Unknown result type (might be due to invalid IL or missing references)
				//IL_004e: Unknown result type (might be due to invalid IL or missing references)
				//IL_008d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0092: Unknown result type (might be due to invalid IL or missing references)
				KeyboardShortcut value;
				if (Object.op_Implicit((Object)(object)(Object.op_Implicit((Object)(object)go) ? go.GetComponentInParent<HitchingPost>() : null)))
				{
					if (Settings.Custom(Settings.HitchKey))
					{
						value = Settings.HitchKey.Value;
						if (((KeyboardShortcut)(ref value)).IsDown())
						{
							goto IL_0058;
						}
					}
					if (Settings.Custom(Settings.ReleaseAllKey))
					{
						value = Settings.ReleaseAllKey.Value;
						if (((KeyboardShortcut)(ref value)).IsDown())
						{
							goto IL_0058;
						}
					}
				}
				AnimalTether animalTether = (Object.op_Implicit((Object)(object)go) ? go.GetComponentInParent<AnimalTether>() : null);
				if (Object.op_Implicit((Object)(object)animalTether) && animalTether.IsAttached && Settings.Custom(Settings.ReleaseAnimalKey))
				{
					value = Settings.ReleaseAnimalKey.Value;
					if (((KeyboardShortcut)(ref value)).IsDown())
					{
						return false;
					}
				}
				if (Settings.Custom(Settings.ReleaseAnimalKey) || !alt || !Object.op_Implicit((Object)(object)animalTether) || !animalTether.IsAttached)
				{
					return true;
				}
				if (!hold && OptionalClients.Ready && !((Character)__instance).InAttack() && !((Character)__instance).InDodge())
				{
					animalTether.RequestRelease(__instance);
				}
				return false;
				IL_0058:
				return false;
			}
		}

		[HarmonyPatch(typeof(Character), "GetHoverText")]
		private static class AnimalHover
		{
			private static void Postfix(Character __instance, ref string __result)
			{
				AnimalTether component = ((Component)__instance).GetComponent<AnimalTether>();
				if (component != null && component.IsAttached)
				{
					__result += ReleaseHint;
				}
			}
		}

		[HarmonyPatch(typeof(Sadle), "GetHoverText")]
		private static class SaddleHover
		{
			private static void Postfix(Sadle __instance, ref string __result)
			{
				AnimalTether componentInParent = ((Component)__instance).GetComponentInParent<AnimalTether>();
				if (componentInParent != null && componentInParent.IsAttached)
				{
					__result += ReleaseHint;
				}
			}
		}

		[HarmonyPatch(typeof(Character), "CustomFixedUpdate")]
		private static class MovementPatch
		{
			private static void Postfix(Character __instance, float dt)
			{
				((Component)__instance).GetComponent<AnimalTether>()?.Constrain(dt);
			}
		}

		[HarmonyPatch(typeof(Growup), "GrowUpdate")]
		private static class GrowthPatch
		{
			private sealed class State
			{
				internal HashSet<int> Existing;

				internal ZDOID Post;

				internal Vector3 Position;

				internal Vector3 Anchor;
			}

			private static void Prefix(Growup __instance, out State __state)
			{
				//IL_0064: Unknown result type (might be due to invalid IL or missing references)
				//IL_0069: Unknown result type (might be due to invalid IL or missing references)
				//IL_0075: Unknown result type (might be due to invalid IL or missing references)
				//IL_007a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0096: Unknown result type (might be due to invalid IL or missing references)
				//IL_009b: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
				__state = null;
				AnimalTether component = ((Component)__instance).GetComponent<AnimalTether>();
				if (Object.op_Implicit((Object)(object)component) && component.IsAttached && component.view.IsOwner())
				{
					__state = new State
					{
						Existing = new HashSet<int>(from c in Character.GetAllCharacters()
							select ((Object)c).GetInstanceID()),
						Post = component.PostId,
						Position = ((Component)__instance).transform.position,
						Anchor = component.view.GetZDO().GetVec3("bhp_anchor", ((Component)__instance).transform.position)
					};
				}
			}

			private static void Postfix(State __state)
			{
				//IL_003d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0043: Unknown result type (might be due to invalid IL or missing references)
				//IL_007f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0095: Unknown result type (might be due to invalid IL or missing references)
				if (__state == null)
				{
					return;
				}
				foreach (Character allCharacter in Character.GetAllCharacters())
				{
					if (!__state.Existing.Contains(((Object)allCharacter).GetInstanceID()) && Plugin.Eligible(allCharacter) && !(Vector3.Distance(((Component)allCharacter).transform.position, __state.Position) > 0.1f))
					{
						ZNetView component = ((Component)allCharacter).GetComponent<ZNetView>();
						if (Object.op_Implicit((Object)(object)component) && component.IsValid() && component.IsOwner())
						{
							component.GetZDO().Set("bhp_post", __state.Post);
							component.GetZDO().Set("bhp_anchor", __state.Anchor);
							OptionalClients.Track(component.GetZDO());
						}
					}
				}
			}
		}

		internal const string PostKey = "bhp_post";

		internal const string AnchorKey = "bhp_anchor";

		private Character creature;

		private ZNetView view;

		private Rigidbody body;

		private LineRenderer rope;

		private float missingTime;

		private float leaseTimer;

		private LineConnect ropeSettings;

		private float maxLineSlack;

		public ZDOID PostId
		{
			get
			{
				//IL_001a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0030: Unknown result type (might be due to invalid IL or missing references)
				if (!Object.op_Implicit((Object)(object)view) || !view.IsValid())
				{
					return ZDOID.None;
				}
				return view.GetZDO().GetZDOID("bhp_post");
			}
		}

		public bool IsAttached => PostId != ZDOID.None;

		private static string ReleaseHint => "\n[<color=yellow><b>" + Settings.Label(Settings.ReleaseAnimalKey, alternate: true) + "</b></color>] Release from hitching post";

		private void Awake()
		{
			creature = ((Component)this).GetComponent<Character>();
			view = ((Component)this).GetComponent<ZNetView>();
			body = ((Component)this).GetComponent<Rigidbody>();
			if (Object.op_Implicit((Object)(object)view) && view.IsValid())
			{
				view.Register<ZDOID, ZDOID, bool>("BHP_Request", (Action<long, ZDOID, ZDOID, bool>)Request);
			}
			if (Object.op_Implicit((Object)(object)view) && view.IsValid())
			{
				view.Register<ZDOID>("BHP_ReleaseAnimal", (Action<long, ZDOID>)ReleaseAnimal);
			}
		}

		private void Update()
		{
			Player localPlayer = Player.m_localPlayer;
			if (IsAttached && Object.op_Implicit((Object)(object)localPlayer) && (Object)(object)RiddenBy(localPlayer) == (Object)(object)creature)
			{
				localPlayer.StopDoodadControl();
			}
			if (Object.op_Implicit((Object)(object)view) && view.IsValid() && view.IsOwner() && !(Time.unscaledTime < leaseTimer))
			{
				leaseTimer = Time.unscaledTime + 1f;
				if (!IsAttached && Object.op_Implicit((Object)(object)Plugin.Harpoon(creature)))
				{
					OptionalClients.Lease(view.GetZDO());
				}
			}
		}

		private void OnDestroy()
		{
			if (Object.op_Implicit((Object)(object)view) && view.IsValid())
			{
				view.Unregister("BHP_Request");
			}
			if (Object.op_Implicit((Object)(object)view) && view.IsValid())
			{
				view.Unregister("BHP_ReleaseAnimal");
			}
			if (Object.op_Implicit((Object)(object)rope))
			{
				Object.Destroy((Object)(object)((Component)rope).gameObject);
			}
		}

		private void Request(long sender, ZDOID playerId, ZDOID postId, bool release)
		{
			//IL_003a: 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_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0214: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			if (!view.IsValid() || !view.IsOwner() || !Plugin.Eligible(creature) || creature.IsDead())
			{
				return;
			}
			GameObject val = ZNetScene.instance.FindInstance(playerId);
			GameObject val2 = ZNetScene.instance.FindInstance(postId);
			Player val3 = (Object.op_Implicit((Object)(object)val) ? val.GetComponent<Player>() : null);
			if (!Object.op_Implicit((Object)(object)val3) || !Object.op_Implicit((Object)(object)val2) || !Object.op_Implicit((Object)(object)val2.GetComponent<HitchingPost>()) || ((Component)val3).GetComponent<ZNetView>().GetZDO().GetOwner() != sender || ((Character)val3).IsDead() || Vector3.Distance(((Component)val3).transform.position, val2.transform.position) > 4f || !WardAccess.Allowed(val3, val2.transform.position))
			{
				return;
			}
			if (release)
			{
				if (PostId == postId)
				{
					Clear();
				}
				return;
			}
			if (IsAttached || Vector3.Distance(((Component)this).transform.position, val2.transform.position) > Plugin.Radius || creature.IsAttached() || !WardAccess.Allowed(val3, ((Component)this).transform.position) || (!Settings.AllowUntamed && !creature.IsTamed()))
			{
				return;
			}
			SE_Harpooned val4 = Plugin.Harpoon(creature);
			Tameable component = ((Component)creature).GetComponent<Tameable>();
			if (creature.IsTamed() && Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)component.m_saddle) && view.GetZDO().GetBool(ZDOVars.s_haveSaddleHash, false))
			{
				long num = view.GetZDO().GetLong(ZDOVars.s_user, 0L);
				ZDOID zDOID = ((Character)val3).GetZDOID();
				if (num == ((ZDOID)(ref zDOID)).UserID)
				{
					goto IL_01e8;
				}
			}
			if (!Object.op_Implicit((Object)(object)val4) || (Object)(object)Plugin.HarpoonOwner(val4) != (Object)(object)val3 || ((StatusEffect)val4).IsDone())
			{
				return;
			}
			goto IL_01e8;
			IL_01e8:
			view.GetZDO().Set("bhp_post", postId);
			view.GetZDO().Set("bhp_anchor", val2.transform.position);
			view.GetZDO().Set("bhp_lease_until", 0L);
			OptionalClients.Track(view.GetZDO());
			if (Object.op_Implicit((Object)(object)val4))
			{
				creature.GetSEMan().RemoveStatusEffect((StatusEffect)(object)val4, false);
			}
			missingTime = 0f;
			((Character)val3).Message((MessageType)2, "Animal attached to Bjørn's Hitching Post.", 0, (Sprite)null, false);
		}

		internal static Character RiddenBy(Player player)
		{
			IDoodadController doodadController = player.GetDoodadController();
			Sadle val = (Sadle)(object)((doodadController is Sadle) ? doodadController : null);
			if (val == null)
			{
				return null;
			}
			return ((Component)val).GetComponentInParent<Character>();
		}

		internal void RequestRelease(Player player)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			view.InvokeRPC("BHP_ReleaseAnimal", new object[1] { ((Character)player).GetZDOID() });
		}

		private void ReleaseAnimal(long sender, ZDOID playerId)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: 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_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)view) && view.IsValid() && view.IsOwner() && IsAttached)
			{
				GameObject val = ZNetScene.instance.FindInstance(playerId);
				Player val2 = (Object.op_Implicit((Object)(object)val) ? val.GetComponent<Player>() : null);
				ZDO zDO = ZDOMan.instance.GetZDO(PostId);
				if (Object.op_Implicit((Object)(object)val2) && !((Character)val2).IsDead() && ((Component)val2).GetComponent<ZNetView>().GetZDO().GetOwner() == sender && !(Vector3.Distance(((Component)val2).transform.position, creature.GetCenterPoint()) > 4f) && WardAccess.Allowed(val2, ((Component)this).transform.position) && WardAccess.Allowed(val2, (zDO != null) ? zDO.GetPosition() : view.GetZDO().GetVec3("bhp_anchor", ((Component)this).transform.position)))
				{
					Clear();
				}
			}
		}

		internal void Clear()
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)view) && view.IsValid() && view.IsOwner())
			{
				view.GetZDO().Set("bhp_post", ZDOID.None);
			}
			if (Object.op_Implicit((Object)(object)rope))
			{
				((Renderer)rope).enabled = false;
			}
		}

		internal void Constrain(float dt)
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			if (!IsAttached || !view.IsOwner() || !Object.op_Implicit((Object)(object)body))
			{
				return;
			}
			if (creature.IsDead() || !Plugin.Eligible(creature))
			{
				Clear();
				return;
			}
			ZDO zDO = ZDOMan.instance.GetZDO(PostId);
			if (zDO != null && !Plugin.IsPost(zDO))
			{
				Clear();
				return;
			}
			if (zDO == null)
			{
				missingTime += dt;
				if (missingTime > 15f)
				{
					Clear();
					return;
				}
			}
			else
			{
				missingTime = 0f;
			}
			Vector3 val = ((zDO != null) ? zDO.GetPosition() : view.GetZDO().GetVec3("bhp_anchor", ((Component)this).transform.position));
			Vector3 val2 = body.position - val;
			Vector3 linearVelocity = body.linearVelocity;
			if (TetherMath.Constrain(Plugin.Radius, ref val2.x, ref val2.y, ref val2.z, ref linearVelocity.x, ref linearVelocity.y, ref linearVelocity.z))
			{
				body.position = val + val2;
				body.linearVelocity = linearVelocity;
			}
		}

		private void LateUpdate()
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: 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_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			if (!IsAttached || creature.IsDead())
			{
				if (Object.op_Implicit((Object)(object)rope))
				{
					((Renderer)rope).enabled = false;
				}
				return;
			}
			ZDO zDO = ZDOMan.instance.GetZDO(PostId);
			Vector3 val = ((zDO != null) ? zDO.GetPosition() : view.GetZDO().GetVec3("bhp_anchor", ((Component)this).transform.position)) + ((zDO != null) ? zDO.GetRotation() : Quaternion.identity) * (Vector3.up * Plugin.RopeHeight);
			if (!Object.op_Implicit((Object)(object)rope))
			{
				CreateRope();
			}
			if (Object.op_Implicit((Object)(object)rope))
			{
				((Renderer)rope).enabled = true;
				Vector3 centerPoint = creature.GetCenterPoint();
				((Component)rope).transform.position = val;
				float num = Vector3.Distance(val, centerPoint);
				float num2 = (1f - Utils.LerpStep(Plugin.Radius / 2f, Plugin.Radius, num)) * maxLineSlack;
				for (int i = 0; i < rope.positionCount; i++)
				{
					float num3 = (float)i / (float)(rope.positionCount - 1);
					float num4 = (ropeSettings.m_dynamicSlack ? (num * 0.5f * num2 * (1f - Mathf.Pow(Mathf.Abs(0.5f - num3) * 2f, 2f))) : 0f);
					rope.SetPosition(i, Vector3.Lerp(val, centerPoint, num3) + Vector3.down * num4);
				}
				if (ropeSettings.m_dynamicThickness)
				{
					rope.widthMultiplier = Mathf.Lerp(ropeSettings.m_maxThickness, ropeSettings.m_minThickness, Mathf.Pow(Utils.LerpStep(ropeSettings.m_minDistance, ropeSettings.m_maxDistance, num), ropeSettings.m_thicknessPower));
				}
			}
		}

		private void CreateRope()
		{
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Expected O, but got Unknown
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			if ((!Object.op_Implicit((Object)(object)ZNet.instance) || !ZNet.instance.IsDedicated()) && Object.op_Implicit((Object)(object)ObjectDB.instance))
			{
				StatusEffect statusEffect = ObjectDB.instance.GetStatusEffect(Plugin.HarpoonHash);
				SE_Harpooned val = (SE_Harpooned)(object)((statusEffect is SE_Harpooned) ? statusEffect : null);
				LineConnect val2 = ((StatusEffect)(val?)).m_startEffects?.m_effectPrefabs?.SelectMany((EffectData e) => (IEnumerable<LineConnect>)((!Object.op_Implicit((Object)(object)e.m_prefab)) ? ((Array)new LineConnect[0]) : ((Array)e.m_prefab.GetComponentsInChildren<LineConnect>(true)))).FirstOrDefault((Func<LineConnect, bool>)((LineConnect line) => Object.op_Implicit((Object)(object)((Component)line).GetComponent<LineRenderer>())));
				if (Object.op_Implicit((Object)(object)val2))
				{
					LineRenderer component = ((Component)val2).GetComponent<LineRenderer>();
					ropeSettings = val2;
					maxLineSlack = val.m_maxLineSlack;
					GameObject val3 = new GameObject("BHP_HarpoonRope");
					val3.transform.SetParent(((Component)this).transform, false);
					rope = val3.AddComponent<LineRenderer>();
					((Renderer)rope).sharedMaterials = ((Renderer)component).sharedMaterials;
					rope.widthCurve = component.widthCurve;
					rope.widthMultiplier = component.widthMultiplier;
					rope.colorGradient = component.colorGradient;
					rope.textureMode = component.textureMode;
					rope.textureScale = component.textureScale;
					rope.alignment = component.alignment;
					rope.numCornerVertices = component.numCornerVertices;
					rope.numCapVertices = component.numCapVertices;
					rope.generateLightingData = component.generateLightingData;
					((Renderer)rope).shadowCastingMode = ((Renderer)component).shadowCastingMode;
					((Renderer)rope).receiveShadows = ((Renderer)component).receiveShadows;
					((Renderer)rope).lightProbeUsage = ((Renderer)component).lightProbeUsage;
					((Renderer)rope).reflectionProbeUsage = ((Renderer)component).reflectionProbeUsage;
					((Renderer)rope).sortingLayerID = ((Renderer)component).sortingLayerID;
					((Renderer)rope).sortingOrder = ((Renderer)component).sortingOrder;
					rope.useWorldSpace = true;
					rope.positionCount = Mathf.Max(2, component.positionCount);
				}
			}
		}
	}
	internal static class WardAccess
	{
		private static readonly FieldInfo Areas = AccessTools.Field(typeof(PrivateArea), "m_allAreas");

		private static readonly MethodInfo Enabled = AccessTools.Method(typeof(PrivateArea), "IsEnabled", (Type[])null, (Type[])null);

		private static readonly MethodInfo Inside = AccessTools.Method(typeof(PrivateArea), "IsInside", (Type[])null, (Type[])null);

		private static readonly MethodInfo Permitted = AccessTools.Method(typeof(PrivateArea), "IsPermitted", (Type[])null, (Type[])null);

		internal static bool Allowed(Player player, Vector3 point)
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			bool flag = false;
			foreach (PrivateArea item in (List<PrivateArea>)Areas.GetValue(null))
			{
				if ((bool)Enabled.Invoke(item, null) && (bool)Inside.Invoke(item, new object[2] { point, 0f }))
				{
					if (((Component)item).GetComponent<Piece>().GetCreator() == player.GetPlayerID() || (bool)Permitted.Invoke(item, new object[1] { player.GetPlayerID() }))
					{
						return true;
					}
					flag = true;
				}
			}
			return !flag;
		}
	}
	internal static class OptionalClients
	{
		[HarmonyPatch(typeof(ZNet), "Awake")]
		private static class Reset
		{
			private static void Prefix()
			{
				Clients.Clear();
				Tracked.Clear();
				Parked.Clear();
				MissingPosts.Clear();
				initialScan = false;
				nextTick = (nextHello = 0f);
				acknowledged = float.NegativeInfinity;
			}
		}

		[HarmonyPatch(typeof(ZNet), "OnNewConnection")]
		private static class Handshake
		{
			private static void Postfix(ZNetPeer peer)
			{
				peer.m_rpc.Register<string>("BHP_Hello", (Action<ZRpc, string>)delegate(ZRpc rpc, string version)
				{
					if (Server && peer.IsReady() && !(version != "1.0.1"))
					{
						Clients[peer.m_uid] = Time.unscaledTime;
						rpc.Invoke("BHP_Ready", new object[3]
						{
							"1.0.1",
							Settings.Length.Value,
							Settings.Untamed.Value
						});
					}
				});
				peer.m_rpc.Register<string, float, bool>("BHP_Ready", (Action<ZRpc, string, float, bool>)delegate(ZRpc rpc, string version, float length, bool untamed)
				{
					if (!Server && peer == ZNet.instance.GetServerPeer() && version == "1.0.1")
					{
						Settings.Receive(length, untamed);
						acknowledged = Time.unscaledTime;
					}
				});
			}
		}

		[HarmonyPatch(typeof(ZNet), "Disconnect")]
		private static class Disconnect
		{
			private static void Prefix(ZNetPeer peer)
			{
				Clients.Remove(peer.m_uid);
			}
		}

		[HarmonyPatch(typeof(ZDO), "Deserialize")]
		private static class Received
		{
			private static void Postfix(ZDO __instance)
			{
				Track(__instance);
			}
		}

		[HarmonyPatch(typeof(ZDOMan), "Load")]
		private static class LoadedLegacy
		{
			private static void Postfix()
			{
				Scan();
			}
		}

		[HarmonyPatch(typeof(ZDOMan), "LoadChunks")]
		private static class LoadedChunks
		{
			private static void Postfix()
			{
				Scan();
			}
		}

		[HarmonyPatch(typeof(ZDOMan), "RPC_ZDOData")]
		private static class ReceivedBatch
		{
			private static void Postfix()
			{
				//IL_0019: 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_0024: Unknown result type (might be due to invalid IL or missing references)
				if (!Server)
				{
					return;
				}
				ZDOID[] array = Tracked.ToArray();
				foreach (ZDOID val in array)
				{
					ZDO zDO = ZDOMan.instance.GetZDO(val);
					if (zDO != null && Protected(zDO))
					{
						Enforce(zDO);
					}
				}
			}
		}

		[HarmonyPatch(typeof(ZDO), "SetOwner")]
		private static class ProtectOwner
		{
			private static void Prefix(ZDO __instance, ref long uid)
			{
				if (Server && Protected(__instance))
				{
					uid = SelectOwner(__instance);
				}
			}
		}

		internal const string DriverKey = "bhp_driver";

		internal const string LeaseKey = "bhp_lease_until";

		private const string Protocol = "1.0.1";

		private static readonly Dictionary<long, float> Clients = new Dictionary<long, float>();

		private static readonly HashSet<ZDOID> Tracked = new HashSet<ZDOID>();

		private static readonly FieldInfo Objects = AccessTools.Field(typeof(ZDOMan), "m_objectsByID");

		private static float nextTick;

		private static float nextHello;

		private static float acknowledged;

		private static bool initialScan;

		private static readonly Dictionary<ZDOID, Vector3> Parked = new Dictionary<ZDOID, Vector3>();

		private static readonly Dictionary<ZDOID, float> MissingPosts = new Dictionary<ZDOID, float>();

		internal static bool Server
		{
			get
			{
				if (Object.op_Implicit((Object)(object)ZNet.instance))
				{
					return ZNet.instance.IsServer();
				}
				return false;
			}
		}

		internal static bool Ready
		{
			get
			{
				if (Object.op_Implicit((Object)(object)ZNet.instance))
				{
					if (!Server)
					{
						return Time.unscaledTime - acknowledged < 15f;
					}
					return true;
				}
				return false;
			}
		}

		private static bool Leased(ZDO zdo)
		{
			if (Object.op_Implicit((Object)(object)ZNet.instance))
			{
				return zdo.GetLong("bhp_lease_until", 0L) > ZNet.instance.GetTime().Ticks;
			}
			return false;
		}

		private static bool Protected(ZDO zdo)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			if (!Plugin.IsPost(zdo) && !(zdo.GetZDOID("bhp_post") != ZDOID.None))
			{
				return Leased(zdo);
			}
			return true;
		}

		internal static void Lease(ZDO zdo)
		{
			if (zdo.IsOwner())
			{
				zdo.Set("bhp_driver", ZDOMan.GetSessionID());
				zdo.Set("bhp_lease_until", ZNet.instance.GetTime().AddSeconds(8.0).Ticks);
				Track(zdo);
			}
		}

		internal static void Track(ZDO zdo)
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			if (zdo != null && zdo.IsValid())
			{
				if (zdo.GetPrefab() == StringExtensionMethods.GetStableHashCode("BjornsHitchingPost") && Server)
				{
					zdo.SetPrefab(StringExtensionMethods.GetStableHashCode("wood_pole"));
					zdo.Set("bhp_is_post", true);
				}
				if (Protected(zdo))
				{
					Tracked.Add(zdo.m_uid);
				}
			}
		}

		private static bool Capable(long uid, Vector3 point)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: 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)
			if (uid == ZDOMan.GetSessionID())
			{
				return ZNetScene.InActiveArea(point, ZNet.instance.GetReferencePosition());
			}
			if (!Clients.TryGetValue(uid, out var value) || Time.unscaledTime - value > 15f)
			{
				return false;
			}
			ZNetPeer peer = ZNet.instance.GetPeer(uid);
			if (peer != null && peer.IsReady())
			{
				return ZNetScene.InActiveArea(point, peer.GetRefPos());
			}
			return false;
		}

		private static long SelectOwner(ZDO zdo)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			Vector3 position = zdo.GetPosition();
			List<long> list = new List<long>();
			foreach (long key in Clients.Keys)
			{
				if (Capable(key, position))
				{
					list.Add(key);
				}
			}
			bool serverActive = Capable(ZDOMan.GetSessionID(), position);
			long preferred = (Leased(zdo) ? zdo.GetLong("bhp_driver", 0L) : zdo.GetOwner());
			return OwnershipPolicy.Select(ZDOMan.GetSessionID(), preferred, serverActive, list);
		}

		internal static void Tick()
		{
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)ZNet.instance) || ZDOMan.instance == null)
			{
				return;
			}
			if (!Server && Object.op_Implicit((Object)(object)Player.m_localPlayer) && Time.unscaledTime >= nextHello)
			{
				nextHello = Time.unscaledTime + 3f;
				ZNetPeer serverPeer = ZNet.instance.GetServerPeer();
				if (serverPeer != null && serverPeer.IsReady())
				{
					serverPeer.m_rpc.Invoke("BHP_Hello", new object[1] { "1.0.1" });
				}
			}
			if (Time.unscaledTime < nextTick)
			{
				return;
			}
			nextTick = Time.unscaledTime + 0.5f;
			if (!initialScan && Object.op_Implicit((Object)(object)ZNetScene.instance) && PlayerReadyForScan())
			{
				initialScan = true;
				Scan();
			}
			ZDOID[] array = Tracked.ToArray();
			foreach (ZDOID val in array)
			{
				ZDO zDO = ZDOMan.instance.GetZDO(val);
				if (zDO == null || !Protected(zDO))
				{
					Tracked.Remove(val);
					Parked.Remove(val);
					MissingPosts.Remove(val);
					continue;
				}
				if (Server)
				{
					Enforce(zDO);
				}
				if (Object.op_Implicit((Object)(object)ZNetScene.instance))
				{
					GameObject val2 = ZNetScene.instance.FindInstance(val);
					if (Object.op_Implicit((Object)(object)val2))
					{
						Plugin.Decorate(val2.GetComponent<ZNetView>());
					}
				}
			}
		}

		private static bool PlayerReadyForScan()
		{
			if (!Server)
			{
				return Object.op_Implicit((Object)(object)Player.m_localPlayer);
			}
			return true;
		}

		private static void Scan()
		{
			if (ZDOMan.instance == null)
			{
				return;
			}
			foreach (ZDO value in ((Dictionary<ZDOID, ZDO>)Objects.GetValue(ZDOMan.instance)).Values)
			{
				Track(value);
			}
		}

		private static void Enforce(ZDO zdo)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: 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_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: 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_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_011e: 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_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			long num = SelectOwner(zdo);
			if (zdo.GetOwner() != num)
			{
				zdo.SetOwner(num);
			}
			ZDOID zDOID = zdo.GetZDOID("bhp_post");
			if (zDOID == ZDOID.None)
			{
				return;
			}
			ZDO zDO = ZDOMan.instance.GetZDO(zDOID);
			if (!Plugin.IsPost(zDO))
			{
				if (!MissingPosts.TryGetValue(zdo.m_uid, out var value))
				{
					MissingPosts[zdo.m_uid] = Time.unscaledTime;
				}
				else if (Time.unscaledTime - value > 15f)
				{
					zdo.Set("bhp_post", ZDOID.None);
					zdo.Set("bhp_lease_until", 0L);
					Parked.Remove(zdo.m_uid);
					MissingPosts.Remove(zdo.m_uid);
				}
				return;
			}
			MissingPosts.Remove(zdo.m_uid);
			if (num != ZDOMan.GetSessionID() || Capable(num, zdo.GetPosition()))
			{
				Parked.Remove(zdo.m_uid);
				return;
			}
			if (!Parked.TryGetValue(zdo.m_uid, out var value2))
			{
				value2 = zdo.GetPosition();
			}
			Vector3 val = value2 - zDO.GetPosition();
			float vx = 0f;
			float vy = 0f;
			float vz = 0f;
			TetherMath.Constrain(Plugin.Radius, ref val.x, ref val.y, ref val.z, ref vx, ref vy, ref vz);
			value2 = zDO.GetPosition() + val;
			Parked[zdo.m_uid] = value2;
			zdo.SetPosition(value2);
			zdo.UpdateConnection((ConnectionType)2, ZDOID.None);
			zdo.Set(ZDOVars.s_attachJointHash, "");
			zdo.Set(ZDOVars.s_velRelHash, Vector3.zero);
			zdo.Set(ZDOVars.s_velHash, Vector3.zero);
			zdo.Set(ZDOVars.s_bodyVelHash, Vector3.zero);
			zdo.Set(ZDOVars.s_bodyAVelHash, Vector3.zero);
		}
	}
	internal static class OwnershipPolicy
	{
		internal static long Select(long server, long preferred, bool serverActive, IReadOnlyList<long> compatibleNearby)
		{
			if (preferred == server && serverActive)
			{
				return server;
			}
			for (int i = 0; i < compatibleNearby.Count; i++)
			{
				if (compatibleNearby[i] == preferred)
				{
					return preferred;
				}
			}
			if (serverActive)
			{
				return server;
			}
			if (compatibleNearby.Count > 0)
			{
				return compatibleNearby[0];
			}
			return server;
		}
	}
	[BepInPlugin("bjorns.hitchingpost", "Bjørn's Hitching Post", "1.0.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public sealed class Plugin : BaseUnityPlugin
	{
		[HarmonyPatch(typeof(ZNetView), "GetPrefabName")]
		private static class VanillaWirePrefab
		{
			private static void Postfix(ref string __result)
			{
				if (__result == "BjornsHitchingPost")
				{
					__result = "wood_pole";
				}
			}
		}

		[HarmonyPatch(typeof(ZNetView), "Awake")]
		private static class MarkPost
		{
			private static void Postfix(ZNetView __instance)
			{
				if (__instance.IsValid())
				{
					if (Utils.GetPrefabName(((Component)__instance).gameObject) == "BjornsHitchingPost" && __instance.IsOwner())
					{
						__instance.GetZDO().SetPrefab(StringExtensionMethods.GetStableHashCode("wood_pole"));
						__instance.GetZDO().Set("bhp_is_post", true);
					}
					OptionalClients.Track(__instance.GetZDO());
					Decorate(__instance);
				}
			}
		}

		[HarmonyPatch(typeof(Player), "TryPlacePiece")]
		private static class RequireServer
		{
			private static bool Prefix(Player __instance, Piece piece, ref bool __result)
			{
				if (Utils.GetPrefabName(((Component)piece).gameObject) != "BjornsHitchingPost" || OptionalClients.Ready)
				{
					return true;
				}
				((Character)__instance).Message((MessageType)2, "Waiting for Bjørn's Hitching Post on the server.", 0, (Sprite)null, false);
				__result = false;
				return false;
			}
		}

		[HarmonyPatch(typeof(Character), "Damage")]
		private static class ClaimHarpoonTarget
		{
			private static bool Prefix(Character __instance, HitData hit)
			{
				//IL_0068: Unknown result type (might be due to invalid IL or missing references)
				//IL_0081: Unknown result type (might be due to invalid IL or missing references)
				//IL_0086: Unknown result type (might be due to invalid IL or missing references)
				if (hit.m_statusEffectHash != HarpoonHash || !Eligible(__instance) || (Object)(object)hit.GetAttacker() != (Object)(object)Player.m_localPlayer || !Object.op_Implicit((Object)(object)Player.m_localPlayer))
				{
					return true;
				}
				if (!OptionalClients.Ready)
				{
					return false;
				}
				ZNetView component = ((Component)__instance).GetComponent<ZNetView>();
				if (!Object.op_Implicit((Object)(object)component) || !component.IsValid() || __instance.IsDead() || !WardAccess.Allowed(Player.m_localPlayer, ((Component)__instance).transform.position))
				{
					return false;
				}
				if (component.GetZDO().GetZDOID("bhp_post") != ZDOID.None)
				{
					return false;
				}
				component.ClaimOwnership();
				OptionalClients.Lease(component.GetZDO());
				return true;
			}
		}

		[HarmonyPatch(typeof(Piece), "DropResources")]
		private static class PostRefund
		{
			private static void Prefix(Piece __instance)
			{
				((Component)__instance).GetComponent<HitchingPost>()?.Configure();
			}
		}

		[HarmonyPatch(typeof(Character), "Awake")]
		private static class AddTether
		{
			private static void Postfix(Character __instance)
			{
				if (Eligible(__instance) && !Object.op_Implicit((Object)(object)((Component)__instance).GetComponent<AnimalTether>()))
				{
					((Component)__instance).gameObject.AddComponent<AnimalTether>();
				}
			}
		}

		[HarmonyPatch(typeof(Projectile), "IsValidTarget")]
		private static class FriendlyHarpoon
		{
			private static void Postfix(IDestructible destr, Character ___m_owner, int ___m_statusEffectHash, ref bool __result)
			{
				if (___m_owner is Player && ___m_statusEffectHash == HarpoonHash)
				{
					Character val = (Character)(object)((destr is Character) ? destr : null);
					if (val != null && Eligible(val) && !val.IsDead() && !val.IsDodgeInvincible())
					{
						__result = true;
					}
				}
			}
		}

		[HarmonyPatch(typeof(Character), "RPC_Damage")]
		private static class HarpoonSafety
		{
			private static bool Prefix(Character __instance, HitData hit)
			{
				//IL_0076: Unknown result type (might be due to invalid IL or missing references)
				if (hit.m_statusEffectHash == HarpoonHash && Eligible(__instance))
				{
					Character attacker = hit.GetAttacker();
					Player val = (Player)(object)((attacker is Player) ? attacker : null);
					if (val != null)
					{
						ZNetView component = ((Component)__instance).GetComponent<ZNetView>();
						if (!Object.op_Implicit((Object)(object)component) || !component.IsValid() || !component.IsOwner() || __instance.IsDead() || __instance.IsTeleporting() || __instance.InCutscene() || (hit.m_dodgeable && __instance.IsDodgeInvincible()))
						{
							return false;
						}
						if (!WardAccess.Allowed(val, ((Component)__instance).transform.position))
						{
							return false;
						}
						AnimalTether component2 = ((Component)__instance).GetComponent<AnimalTether>();
						if (Object.op_Implicit((Object)(object)component2) && component2.IsAttached)
						{
							((Character)val).Message((MessageType)2, "Release this animal at its hitching post first.", 0, (Sprite)null, false);
							return false;
						}
						StatusEffect obj = __instance.GetSEMan().AddStatusEffect(HarpoonHash, true, 0, 0f, (short)(-1));
						SE_Harpooned val2 = (SE_Harpooned)(object)((obj is SE_Harpooned) ? obj : null);
						if (Object.op_Implicit((Object)(object)val2))
						{
							((StatusEffect)val2).SetAttacker((Character)(object)val);
						}
						return false;
					}
				}
				return true;
			}
		}

		public const string Guid = "bjorns.hitchingpost";

		public const string PrefabName = "BjornsHitchingPost";

		internal const string VanillaPrefab = "wood_pole";

		internal const string PostMarker = "bhp_is_post";

		internal static GameObject PostTemplate;

		internal static float RopeHeight;

		internal const float Reach = 4f;

		internal static readonly int HarpoonHash = StringExtensionMethods.GetStableHashCode("Harpooned");

		internal static readonly FieldInfo AttackerField = AccessTools.Field(typeof(SE_Harpooned), "m_attacker");

		private Harmony harmony;

		internal static float Radius => Settings.Radius;

		private void Awake()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			Settings.Initialize(((BaseUnityPlugin)this).Config);
			harmony = new Harmony("bjorns.hitchingpost");
			harmony.PatchAll();
			PrefabManager.OnVanillaPrefabsAvailable += RegisterPiece;
			((BaseUnityPlugin)this).Logger.LogInfo((object)("Bjørn's Hitching Post 1.0.1 — optional clients, server required; Valheim " + Version.GetVersionString(false)));
		}

		private void Update()
		{
			OptionalClients.Tick();
		}

		private void OnDestroy()
		{
			PrefabManager.OnVanillaPrefabsAvailable -= RegisterPiece;
			Harmony obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
		}

		private void RegisterPiece()
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Expected O, but got Unknown
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Expected O, but got Unknown
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Expected O, but got Unknown
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0207: Unknown result type (might be due to invalid IL or missing references)
			//IL_020c: Unknown result type (might be due to invalid IL or missing references)
			//IL_021c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0228: Expected O, but got Unknown
			//IL_0245: Unknown result type (might be due to invalid IL or missing references)
			//IL_0259: Unknown result type (might be due to invalid IL or missing references)
			//IL_027a: Unknown result type (might be due to invalid IL or missing references)
			//IL_028e: 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_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			PieceConfig val = new PieceConfig();
			val.Name = "Bjørn's Hitching Post";
			val.Description = "Hitch a harpooned animal or your mount. Tether distance and controls are configurable.";
			val.PieceTable = "Hammer";
			val.Category = "Furniture";
			val.CraftingStation = "piece_workbench";
			val.Icon = LoadIcon();
			val.Requirements = (RequirementConfig[])(object)new RequirementConfig[2]
			{
				new RequirementConfig("FineWood", 10, 0, true),
				new RequirementConfig("BronzeNails", 10, 0, true)
			};
			CustomPiece val2 = new CustomPiece("BjornsHitchingPost", "wood_pole", val);
			GameObject val3 = (PostTemplate = val2.PiecePrefab);
			val3.AddComponent<HitchingPost>();
			val3.GetComponent<WearNTear>().m_health = 1000f;
			Material sharedMaterial = ((Renderer)val3.GetComponentInChildren<MeshRenderer>()).sharedMaterial;
			float num = float.NegativeInfinity;
			MeshFilter[] componentsInChildren = val3.GetComponentsInChildren<MeshFilter>(true);
			foreach (MeshFilter val4 in componentsInChildren)
			{
				if (Object.op_Implicit((Object)(object)val4.sharedMesh))
				{
					Bounds bounds = val4.sharedMesh.bounds;
					for (int j = 0; j < 8; j++)
					{
						Vector3 val5 = ((Bounds)(ref bounds)).center + Vector3.Scale(((Bounds)(ref bounds)).extents, new Vector3((float)(((j & 1) != 0) ? 1 : (-1)), (float)(((j & 2) != 0) ? 1 : (-1)), (float)(((j & 4) != 0) ? 1 : (-1))));
						num = Mathf.Max(num, val3.transform.InverseTransformPoint(((Component)val4).transform.TransformPoint(val5)).y);
					}
				}
			}
			RopeHeight = (float.IsNegativeInfinity(num) ? 0.45f : (num - 0.05f));
			AddBeam(val3.transform, sharedMaterial, new Vector3(0f, RopeHeight, 0f), new Vector3(1.3f, 0.18f, 0.22f));
			AddBeam(val3.transform, sharedMaterial, new Vector3(0f, 0.12f, 0f), new Vector3(0.4f, 0.2f, 0.4f));
			Material material = new Material(sharedMaterial)
			{
				color = new Color(0.55f, 0.29f, 0.1f)
			};
			AddBeam(val3.transform, material, new Vector3(0f, RopeHeight - 0.12f, 0f), new Vector3(0.25f, 0.12f, 0.25f));
			AddBeam(val3.transform, material, new Vector3(0f, 0.45f, 0f), new Vector3(0.25f, 0.12f, 0.25f));
			PieceManager.Instance.AddPiece(val2);
			PrefabManager.OnVanillaPrefabsAvailable -= RegisterPiece;
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Registered hitching post: 10 FineWood + 10 BronzeNails.");
		}

		private static void AddBeam(Transform parent, Material material, Vector3 position, Vector3 scale)
		{
			//IL_0035: 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)
			GameObject obj = GameObject.CreatePrimitive((PrimitiveType)3);
			((Object)obj).name = "HitchingPostDetail";
			obj.layer = ((Component)parent).gameObject.layer;
			obj.transform.SetParent(parent, false);
			obj.transform.localPosition = position;
			obj.transform.localScale = scale;
			((Renderer)obj.GetComponent<MeshRenderer>()).sharedMaterial = material;
			Collider component = obj.GetComponent<Collider>();
			component.enabled = false;
			Object.Destroy((Object)(object)component);
		}

		internal static bool IsPost(ZDO zdo)
		{
			if (zdo != null)
			{
				if (zdo.GetPrefab() != StringExtensionMethods.GetStableHashCode("BjornsHitchingPost"))
				{
					if (zdo.GetPrefab() == StringExtensionMethods.GetStableHashCode("wood_pole"))
					{
						return zdo.GetBool("bhp_is_post", false);
					}
					return false;
				}
				return true;
			}
			return false;
		}

		internal static void Decorate(ZNetView view)
		{
			if (Object.op_Implicit((Object)(object)view) && view.IsValid() && IsPost(view.GetZDO()) && !Object.op_Implicit((Object)(object)((Component)view).GetComponent<HitchingPost>()))
			{
				((Component)view).gameObject.AddComponent<HitchingPost>();
			}
		}

		private static Sprite LoadIcon()
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Expected O, but got Unknown
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Expected O, but got Unknown
			using Stream stream = typeof(Plugin).Assembly.GetManifestResourceStream("BjornsHitchingPost.icon.png");
			byte[] array = new byte[stream.Length];
			stream.Read(array, 0, array.Length);
			Texture2D val = new Texture2D(256, 256);
			ImageConversion.LoadImage(val, array);
			return Sprite.Create(val, new Rect(0f, 0f, 256f, 256f), new Vector2(0.5f, 0.5f));
		}

		internal static bool Eligible(Character creature)
		{
			if (Object.op_Implicit((Object)(object)creature) && !creature.IsPlayer() && !creature.IsBoss())
			{
				return EligiblePrefab(((Component)creature).gameObject, 0);
			}
			return false;
		}

		private static bool EligiblePrefab(GameObject prefab, int depth)
		{
			if (!Object.op_Implicit((Object)(object)prefab) || depth > 3)
			{
				return false;
			}
			if (Object.op_Implicit((Object)(object)prefab.GetComponent<Tameable>()))
			{
				return true;
			}
			Growup component = prefab.GetComponent<Growup>();
			if (!Object.op_Implicit((Object)(object)component))
			{
				return false;
			}
			if (EligiblePrefab(component.m_grownPrefab, depth + 1))
			{
				return true;
			}
			if (component.m_altGrownPrefabs != null && component.m_altGrownPrefabs.Count > 0)
			{
				return component.m_altGrownPrefabs.All((GrownEntry entry) => EligiblePrefab(entry.m_prefab, depth + 1));
			}
			return false;
		}

		internal static SE_Harpooned Harpoon(Character creature)
		{
			SEMan sEMan = creature.GetSEMan();
			StatusEffect obj = ((sEMan != null) ? sEMan.GetStatusEffect(HarpoonHash) : null);
			return (SE_Harpooned)(object)((obj is SE_Harpooned) ? obj : null);
		}

		internal static Character HarpoonOwner(SE_Harpooned effect)
		{
			if (!Object.op_Implicit((Object)(object)effect))
			{
				return null;
			}
			object? value = AttackerField.GetValue(effect);
			return (Character)((value is Character) ? value : null);
		}
	}
	public sealed class HitchingPost : MonoBehaviour, Hoverable, Interactable
	{
		private bool configured;

		private void Update()
		{
			Configure();
		}

		internal void Configure()
		{
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Expected O, but got Unknown
			if (configured || !Object.op_Implicit((Object)(object)Plugin.PostTemplate) || !Object.op_Implicit((Object)(object)ObjectDB.instance))
			{
				return;
			}
			ZNetView component = ((Component)this).GetComponent<ZNetView>();
			if (!Object.op_Implicit((Object)(object)component) || !component.IsValid() || !Plugin.IsPost(component.GetZDO()))
			{
				return;
			}
			Piece component2 = ((Component)this).GetComponent<Piece>();
			Piece component3 = Plugin.PostTemplate.GetComponent<Piece>();
			component2.m_name = component3.m_name;
			component2.m_description = component3.m_description;
			component2.m_icon = component3.m_icon;
			component2.m_resources = component3.m_resources;
			((Component)this).GetComponent<WearNTear>().m_health = 1000f;
			if (Utils.GetPrefabName(((Component)this).gameObject) != "BjornsHitchingPost")
			{
				foreach (Transform item in Plugin.PostTemplate.transform)
				{
					Transform val = item;
					if (((Object)val).name == "HitchingPostDetail")
					{
						Object.Instantiate<GameObject>(((Component)val).gameObject, ((Component)this).transform, false);
					}
				}
			}
			configured = true;
		}

		public float GetHoverOffset()
		{
			return Plugin.RopeHeight;
		}

		public string GetHoverName()
		{
			return "Bjørn's Hitching Post";
		}

		public string GetHoverText()
		{
			return "Bjørn's Hitching Post\n[<color=yellow><b>" + Settings.Label(Settings.HitchKey) + "</b></color>] Hitch harpooned animal or mount\n[<color=yellow><b>" + Settings.Label(Settings.ReleaseAllKey, alternate: true) + "</b></color>] Release all animals\nTether distance: " + Plugin.Radius.ToString("0.#") + " m";
		}

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

		public bool Interact(Humanoid user, bool hold, bool alt)
		{
			if (!hold)
			{
				Player val = (Player)(object)((user is Player) ? user : null);
				if (val != null)
				{
					if (Settings.Custom(alt ? Settings.ReleaseAllKey : Settings.HitchKey))
					{
						return false;
					}
					return Act(val, alt);
				}
			}
			return false;
		}

		internal bool Act(Player player, bool alt)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: 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_0127: Unknown result type (might be due to invalid IL or missing references)
			if (!OptionalClients.Ready)
			{
				((Character)player).Message((MessageType)2, "Waiting for the server mod.", 0, (Sprite)null, false);
				return false;
			}
			ZNetView component = ((Component)this).GetComponent<ZNetView>();
			if (!Object.op_Implicit((Object)(object)component) || !component.IsValid() || Vector3.Distance(((Component)player).transform.position, ((Component)this).transform.position) > 4f || !PrivateArea.CheckAccess(((Component)this).transform.position, 0f, true, false))
			{
				return false;
			}
			int num = 0;
			Character val = AnimalTether.RiddenBy(player);
			foreach (Character allCharacter in Character.GetAllCharacters())
			{
				if (alt || !Object.op_Implicit((Object)(object)val) || !((Object)(object)allCharacter != (Object)(object)val))
				{
					AnimalTether component2 = ((Component)allCharacter).GetComponent<AnimalTether>();
					if (Object.op_Implicit((Object)(object)component2) && (alt ? (component2.PostId == component.GetZDO().m_uid) : (Vector3.Distance(((Component)allCharacter).transform.position, ((Component)this).transform.position) <= Plugin.Radius)))
					{
						((Component)allCharacter).GetComponent<ZNetView>().InvokeRPC("BHP_Request", new object[3]
						{
							((Character)player).GetZDOID(),
							component.GetZDO().m_uid,
							alt
						});
						num++;
					}
				}
			}
			((Character)player).Message((MessageType)2, (num == 0) ? $"Bring a harpooned animal or mount within {Plugin.Radius:0.#} meters of the post." : (alt ? "Releasing this post's animals." : "Checking nearby animals for your harpoon line."), 0, (Sprite)null, false);
			return true;
		}
	}
	internal static class Settings
	{
		[HarmonyPatch(typeof(Player), "Update")]
		private static class CustomControls
		{
			private static void Postfix(Player __instance)
			{
				//IL_0077: Unknown result type (might be due to invalid IL or missing references)
				//IL_007c: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
				if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer || !OptionalClients.Ready || !(bool)TakeInput.Invoke(__instance, null) || Hud.InRadial() || ((Character)__instance).InAttack() || ((Character)__instance).InDodge() || ((Character)__instance).IsDead())
				{
					return;
				}
				GameObject hoverObject = ((Humanoid)__instance).GetHoverObject();
				if (!Object.op_Implicit((Object)(object)hoverObject))
				{
					return;
				}
				HitchingPost componentInParent = hoverObject.GetComponentInParent<HitchingPost>();
				KeyboardShortcut value;
				if (Object.op_Implicit((Object)(object)componentInParent))
				{
					if (Custom(ReleaseAllKey))
					{
						value = ReleaseAllKey.Value;
						if (((KeyboardShortcut)(ref value)).IsDown())
						{
							componentInParent.Act(__instance, alt: true);
							return;
						}
					}
					if (Custom(HitchKey))
					{
						value = HitchKey.Value;
						if (((KeyboardShortcut)(ref value)).IsDown())
						{
							componentInParent.Act(__instance, alt: false);
						}
					}
					return;
				}
				AnimalTether componentInParent2 = hoverObject.GetComponentInParent<AnimalTether>();
				if (Object.op_Implicit((Object)(object)componentInParent2) && componentInParent2.IsAttached && Custom(ReleaseAnimalKey))
				{
					value = ReleaseAnimalKey.Value;
					if (((KeyboardShortcut)(ref value)).IsDown())
					{
						componentInParent2.RequestRelease(__instance);
					}
				}
			}
		}

		internal static ConfigEntry<float> Length;

		internal static ConfigEntry<bool> Untamed;

		internal static ConfigEntry<KeyboardShortcut> HitchKey;

		internal static ConfigEntry<KeyboardShortcut> ReleaseAnimalKey;

		internal static ConfigEntry<KeyboardShortcut> ReleaseAllKey;

		private static float serverLength = 5f;

		private static bool serverUntamed = true;

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

		internal static float Radius
		{
			get
			{
				if (!OptionalClients.Server)
				{
					return serverLength;
				}
				return SafeLength(Length.Value);
			}
		}

		internal static bool AllowUntamed
		{
			get
			{
				if (!OptionalClients.Server)
				{
					return serverUntamed;
				}
				return Untamed.Value;
			}
		}

		internal static void Initialize(ConfigFile config)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Expected O, but got Unknown
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			Length = config.Bind<float>("General", "TetherLength", 5f, new ConfigDescription("Maximum tether distance in meters. Server/host setting, synchronized to modded clients.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 30f), Array.Empty<object>()));
			Untamed = config.Bind<bool>("General", "AllowUntamedAnimals", true, "Allow new attachments of untamed animals. Server/host setting. Existing attachments remain when disabled.");
			HitchKey = config.Bind<KeyboardShortcut>("Controls", "HitchKey", new KeyboardShortcut((KeyCode)101, Array.Empty<KeyCode>()), "Local shortcut for hitching at a post. None follows the game's Use binding.");
			ReleaseAnimalKey = config.Bind<KeyboardShortcut>("Controls", "ReleaseAnimalKey", new KeyboardShortcut((KeyCode)101, (KeyCode[])(object)new KeyCode[1] { (KeyCode)304 }), "Local shortcut for releasing the animal you look at. None follows alternate Use (normally Shift+E).");
			ReleaseAllKey = config.Bind<KeyboardShortcut>("Controls", "ReleaseAllKey", new KeyboardShortcut((KeyCode)101, (KeyCode[])(object)new KeyCode[1] { (KeyCode)304 }), "Local shortcut for releasing all animals at the post you look at. None follows alternate Use (normally Shift+E).");
		}

		internal static void Receive(float length, bool untamed)
		{
			serverLength = SafeLength(length);
			serverUntamed = untamed;
		}

		private static float SafeLength(float length)
		{
			if (!float.IsNaN(length) && !float.IsInfinity(length))
			{
				return Mathf.Clamp(length, 1f, 30f);
			}
			return 5f;
		}

		internal static bool Custom(ConfigEntry<KeyboardShortcut> key)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Invalid comparison between Unknown and I4
			KeyboardShortcut value = key.Value;
			return (int)((KeyboardShortcut)(ref value)).MainKey > 0;
		}

		internal static string Label(ConfigEntry<KeyboardShortcut> key, bool alternate = false)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			if (!Custom(key))
			{
				return Localization.instance.Localize((!alternate) ? "$KEY_Use" : ((ZInput.IsNonClassicFunctionality() && ZInput.IsGamepadActive()) ? "$KEY_AltKeys + $KEY_Use" : "$KEY_AltPlace + $KEY_Use"));
			}
			return ((object)key.Value/*cast due to .constrained prefix*/).ToString();
		}
	}
	internal static class TetherMath
	{
		internal static bool Constrain(float radius, ref float x, ref float y, ref float z, ref float vx, ref float vy, ref float vz)
		{
			double num = Math.Sqrt((double)x * (double)x + (double)y * (double)y + (double)z * (double)z);
			if (num <= (double)radius || num == 0.0)
			{
				return false;
			}
			float num2 = (float)((double)x / num);
			float num3 = (float)((double)y / num);
			float num4 = (float)((double)z / num);
			x = num2 * radius;
			y = num3 * radius;
			z = num4 * radius;
			float num5 = vx * num2 + vy * num3 + vz * num4;
			if (num5 > 0f)
			{
				vx -= num2 * num5;
				vy -= num3 * num5;
				vz -= num4 * num5;
			}
			return true;
		}
	}
}