Decompiled source of Bjorns Hitching Post v0.2.1

plugins/BjornsHitchingPost/BjornsHitchingPost.dll

Decompiled a month 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 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("0.2.1.0")]
[assembly: AssemblyInformationalVersion("0.2.1")]
[assembly: AssemblyProduct("BjornsHitchingPost")]
[assembly: AssemblyTitle("BjornsHitchingPost")]
[assembly: AssemblyVersion("0.2.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(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 static Material ropeMaterial;

		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 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);
			}
		}

		private void Update()
		{
			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)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_016d: 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 (!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();
				}
			}
			else if (!IsAttached && !(Vector3.Distance(((Component)this).transform.position, val2.transform.position) > 5f) && !creature.IsAttached() && WardAccess.Allowed(val3, ((Component)this).transform.position))
			{
				SE_Harpooned val4 = Plugin.Harpoon(creature);
				if (Object.op_Implicit((Object)(object)val4) && !((Object)(object)Plugin.HarpoonOwner(val4) != (Object)(object)val3) && !((StatusEffect)val4).IsDone())
				{
					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());
					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 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(5f, 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_006b: 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_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: 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_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: 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)
			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)) + Vector3.up * 1.35f;
			if (!Object.op_Implicit((Object)(object)rope))
			{
				CreateRope();
			}
			if (Object.op_Implicit((Object)(object)rope))
			{
				((Renderer)rope).enabled = true;
				Vector3 centerPoint = creature.GetCenterPoint();
				float num = Mathf.Clamp01(1f - Vector3.Distance(val, centerPoint) / 5f) * 0.6f;
				for (int i = 0; i < rope.positionCount; i++)
				{
					float num2 = (float)i / (float)(rope.positionCount - 1);
					rope.SetPosition(i, Vector3.Lerp(val, centerPoint, num2) + Vector3.down * (4f * num2 * (1f - num2) * num));
				}
			}
		}

		private void CreateRope()
		{
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Expected O, but got Unknown
			//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_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Expected O, but got Unknown
			if (Object.op_Implicit((Object)(object)ZNet.instance) && ZNet.instance.IsDedicated())
			{
				return;
			}
			if (!Object.op_Implicit((Object)(object)ropeMaterial))
			{
				LineRenderer val = ObjectDB.instance.GetStatusEffect(Plugin.HarpoonHash)?.m_startEffects?.m_effectPrefabs?.Select((EffectData e) => (!Object.op_Implicit((Object)(object)e.m_prefab)) ? null : e.m_prefab.GetComponentInChildren<LineRenderer>(true)).FirstOrDefault((Func<LineRenderer, bool>)((LineRenderer line) => Object.op_Implicit((Object)(object)line)));
				if (Object.op_Implicit((Object)(object)val))
				{
					ropeMaterial = ((Renderer)val).sharedMaterial;
				}
				else
				{
					Shader val2 = Shader.Find("Sprites/Default");
					if (!Object.op_Implicit((Object)(object)val2))
					{
						return;
					}
					ropeMaterial = new Material(val2)
					{
						color = new Color(0.55f, 0.43f, 0.27f)
					};
				}
			}
			GameObject val3 = new GameObject("BHP_HarpoonRope");
			val3.transform.SetParent(((Component)this).transform, false);
			rope = val3.AddComponent<LineRenderer>();
			((Renderer)rope).sharedMaterial = ropeMaterial;
			rope.useWorldSpace = true;
			rope.positionCount = 17;
			LineRenderer obj = rope;
			float startWidth = (rope.endWidth = 0.035f);
			obj.startWidth = startWidth;
			rope.numCornerVertices = 2;
		}
	}
	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 != "0.2.1"))
					{
						Clients[peer.m_uid] = Time.unscaledTime;
						rpc.Invoke("BHP_Ready", new object[1] { "0.2.1" });
					}
				});
				peer.m_rpc.Register<string>("BHP_Ready", (Action<ZRpc, string>)delegate(ZRpc rpc, string version)
				{
					if (!Server && peer == ZNet.instance.GetServerPeer() && version == "0.2.1")
					{
						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 = "0.2.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] { "0.2.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_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)
			//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)
			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(5f, 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", "0.2.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 const float Radius = 5f;

		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;

		private void Awake()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			harmony = new Harmony("bjorns.hitchingpost");
			harmony.PatchAll();
			PrefabManager.OnVanillaPrefabsAvailable += RegisterPiece;
			((BaseUnityPlugin)this).Logger.LogInfo((object)("Bjørn's Hitching Post 0.2.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_0010: Expected O, but got Unknown
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Expected O, but got Unknown
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Expected O, but got Unknown
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Expected O, but got Unknown
			//IL_00cc: 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_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Expected O, but got Unknown
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			PieceConfig val = new PieceConfig();
			val.Name = "Bjørn's Hitching Post";
			val.Description = "Transfer a harpooned animal to this post. Five-meter tether. Shift + Use to release all animals.";
			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 obj = (PostTemplate = val2.PiecePrefab);
			obj.AddComponent<HitchingPost>();
			obj.GetComponent<WearNTear>().m_health = 1000f;
			Material sharedMaterial = ((Renderer)obj.GetComponentInChildren<MeshRenderer>()).sharedMaterial;
			AddBeam(obj.transform, sharedMaterial, new Vector3(0f, 1.35f, 0f), new Vector3(1.3f, 0.18f, 0.22f));
			AddBeam(obj.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(obj.transform, material, new Vector3(0f, 1.2f, 0f), new Vector3(0.25f, 0.12f, 0.25f));
			AddBeam(obj.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 1.35f;
		}

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

		public string GetHoverText()
		{
			return Localization.instance.Localize("Bjørn's Hitching Post\n[<color=yellow><b>$KEY_Use</b></color>] Attach harpooned animal\n[<color=yellow><b>Shift + $KEY_Use</b></color>] Release all animals");
		}

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

		public bool Interact(Humanoid user, bool hold, bool alt)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: 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_00e3: 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_00c0: 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_0117: Unknown result type (might be due to invalid IL or missing references)
			if (!hold)
			{
				Player val = (Player)(object)((user is Player) ? user : null);
				if (val != null)
				{
					if (!OptionalClients.Ready)
					{
						((Character)val).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)val).transform.position, ((Component)this).transform.position) > 4f || !PrivateArea.CheckAccess(((Component)this).transform.position, 0f, true, false))
					{
						return false;
					}
					int num = 0;
					foreach (Character allCharacter in Character.GetAllCharacters())
					{
						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) <= 5f)))
						{
							((Component)allCharacter).GetComponent<ZNetView>().InvokeRPC("BHP_Request", new object[3]
							{
								((Character)val).GetZDOID(),
								component.GetZDO().m_uid,
								alt
							});
							num++;
						}
					}
					((Character)val).Message((MessageType)2, (num == 0) ? "Bring a harpooned animal within five meters of the post." : (alt ? "Releasing this post's animals." : "Checking nearby animals for your harpoon line."), 0, (Sprite)null, false);
					return true;
				}
			}
			return false;
		}
	}
	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;
		}
	}
}