Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of BjornsHitchingPost v1.0.1
plugins/BjornsHitchingPost/BjornsHitchingPost.dll
Decompiled 2 days agousing 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; } } }