Decompiled source of Sapienheim v0.1.7

ValheimCompanion.dll

Decompiled 3 days ago
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net.Sockets;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Jotunn;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Splatform;
using UnityEngine;
using UnityEngine.Audio;
using UnityEngine.Networking;
using ValheimCompanion.Bridge;
using ValheimCompanion.Building;
using ValheimCompanion.Companion;
using ValheimCompanion.Conversation;
using ValheimCompanion.Net;
using ValheimCompanion.Travel;
using ValheimCompanion.World;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("ValheimCompanion")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+e5c97b2bafc6b11a5568ad9b761a6668bd28f836")]
[assembly: AssemblyProduct("ValheimCompanion")]
[assembly: AssemblyTitle("ValheimCompanion")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
namespace ValheimCompanion
{
	[BepInPlugin("com.sapienheim.valheimcompanion", "ValheimCompanion", "0.1.7")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	internal class Plugin : BaseUnityPlugin
	{
		public const string PluginGUID = "com.sapienheim.valheimcompanion";

		public const string PluginName = "ValheimCompanion";

		public const string PluginVersion = "0.1.7";

		public const int ProtocolVersion = 1;

		public static ConfigEntry<string> AgentHost;

		public static ConfigEntry<int> AgentPort;

		public static ConfigEntry<string> AgentToken;

		public static ConfigEntry<string> CompanionName;

		public static ConfigEntry<string> DebugAutoSpawnAt;

		public static ConfigEntry<int> RespawnSeconds;

		public static ConfigEntry<int> OfflineMinutes;

		public static ConfigEntry<string> OfflineMode;

		public static ConfigEntry<string> MapMarker;

		public static ConfigEntry<bool> Levelling;

		public static ConfigEntry<bool> Proactive;

		public static ConfigEntry<float> DamageScale;

		public static ConfigEntry<string> Body;

		public static ConfigEntry<float> SoundVolume;

		public static ConfigEntry<string> LookHair;

		public static ConfigEntry<string> LookBeard;

		public static ConfigEntry<string> LookHairColour;

		public static ConfigEntry<float> LookSkinTone;

		public static ConfigEntry<string> LookLegs;

		public static ConfigEntry<string> LookCape;

		public static ConfigEntry<float> LookChest;

		public static ConfigEntry<float> LookArms;

		public static ConfigEntry<float> LookHeight;

		public static ConfigEntry<string> Commanders;

		public static ConfigEntry<string> Friends;

		public static ConfigEntry<string> ChestAccess;

		private Harmony _harmony;

		private FileSystemWatcher _configWatcher;

		private volatile bool _configChanged;

		private void WatchConfig()
		{
			try
			{
				string configFilePath = ((BaseUnityPlugin)this).Config.ConfigFilePath;
				_configWatcher = new FileSystemWatcher(Path.GetDirectoryName(configFilePath), Path.GetFileName(configFilePath));
				_configWatcher.Changed += delegate
				{
					_configChanged = true;
				};
				_configWatcher.EnableRaisingEvents = true;
			}
			catch (Exception ex)
			{
				Logger.LogWarning((object)("Not watching the config file for changes: " + ex.Message));
			}
		}

		private void Update()
		{
			if (_configChanged)
			{
				_configChanged = false;
				((BaseUnityPlugin)this).Config.Reload();
				Logger.LogInfo((object)"Config file changed: reloaded");
			}
		}

		private void Awake()
		{
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Expected O, but got Unknown
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Expected O, but got Unknown
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Expected O, but got Unknown
			//IL_0253: Unknown result type (might be due to invalid IL or missing references)
			//IL_025d: Expected O, but got Unknown
			//IL_03e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f2: Expected O, but got Unknown
			//IL_0469: Unknown result type (might be due to invalid IL or missing references)
			//IL_0473: Expected O, but got Unknown
			DebugAutoSpawnAt = ((BaseUnityPlugin)this).Config.Bind<string>("Debug", "AutoSpawnAt", "", "Server only: if no companion exists when the world loads, spawn one here with no master. 'x,z' or 'StartTemple'. Empty = off.");
			CompanionName = ((BaseUnityPlugin)this).Config.Bind<string>("Companion", "Name", "Alvar", "The companion's name. Changing it renames the existing companion (server only).");
			RespawnSeconds = ((BaseUnityPlugin)this).Config.Bind<int>("Companion", "RespawnSeconds", 60, "After dying, the companion bounces back next to its master after this many seconds (server only).");
			OfflineMinutes = ((BaseUnityPlugin)this).Config.Bind<int>("Companion", "OfflineMinutes", 60, "Minutes the companion keeps working after the last player logs out before going off duty. -1 = never (server only).");
			OfflineMode = ((BaseUnityPlugin)this).Config.Bind<string>("Companion", "OfflineMode", "logout", new ConfigDescription("What 'off duty' means: logout = leave the world and log back in beside the master when someone joins; idle = freeze in place and resume when someone joins (server only).", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[2] { "logout", "idle" }), Array.Empty<object>()));
			Commanders = ((BaseUnityPlugin)this).Config.Bind<string>("Permissions", "Commanders", "friends", new ConfigDescription("Who may give the companion orders: master, friends (master + Friends) or everyone. Anyone can chat (server only).", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[3] { "master", "friends", "everyone" }), Array.Empty<object>()));
			Friends = ((BaseUnityPlugin)this).Config.Bind<string>("Permissions", "Friends", "", "Comma-separated player names who may command the companion, in addition to any its master adds in chat (server only).");
			ChestAccess = ((BaseUnityPlugin)this).Config.Bind<string>("Permissions", "ChestAccess", "own", new ConfigDescription("Which chests the companion may use: own (built by its master or a friend) or any (any chest it may open) (server only).", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[2] { "own", "any" }), Array.Empty<object>()));
			Proactive = ((BaseUnityPlugin)this).Config.Bind<bool>("Companion", "Proactive", true, "Speak up unprompted at dusk, when badly hurt, after a long idle spell, and when the master comes back (server only).");
			DamageScale = ((BaseUnityPlugin)this).Config.Bind<float>("Companion", "DamageScale", 1f, "Multiplier on the companion's damage per hit (18 at level 1, rising to 110 at level 6) (server only).");
			Levelling = ((BaseUnityPlugin)this).Config.Bind<bool>("Companion", "Levelling", true, "Scale the companion with its master: level (damage) from bosses defeated, max health from the master's, armour from theirs (server only).");
			SoundVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Look", "SoundVolume", 1f, "Volume of the companion's voice clips on this machine, 0-1 (before the game's own sound volume).");
			Body = ((BaseUnityPlugin)this).Config.Bind<string>("Look", "Body", "viking", new ConfigDescription("The companion's body: viking (the player model, shows its gear) or dverger. Needs a restart; set it the same on every machine.", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[2] { "viking", "dverger" }), Array.Empty<object>()));
			LookHair = ((BaseUnityPlugin)this).Config.Bind<string>("Look", "Hair", "Hair20", "Viking body: hair style item (e.g. Hair1-Hair30, or none) (server only).");
			LookBeard = ((BaseUnityPlugin)this).Config.Bind<string>("Look", "Beard", "BeardNone", "Viking body: beard item (e.g. Beard1-Beard25, or BeardNone) (server only).");
			LookHairColour = ((BaseUnityPlugin)this).Config.Bind<string>("Look", "HairColour", "dirtyblond", "Viking body: black, brown, dirtyblond (or lightbrown), blond, red, grey, or r,g,b (0-1) (server only).");
			LookSkinTone = ((BaseUnityPlugin)this).Config.Bind<float>("Look", "SkinTone", 0.4f, "Viking body: 0 = pale, 1 = dark (server only).");
			LookLegs = ((BaseUnityPlugin)this).Config.Bind<string>("Look", "Legs", "ArmorRagsLegs", "Viking body: what its legs show when it wears no leg armour (an item name, or none) (server only).");
			LookCape = ((BaseUnityPlugin)this).Config.Bind<string>("Look", "Cape", "CapeWolf", "Viking body: the cape it shows when it wears none (an item name, or none) (server only).");
			LookChest = ((BaseUnityPlugin)this).Config.Bind<float>("Look", "Chest", 1.7f, "Viking body: chest and shoulder size, 1 = a normal player (0.8-1.8) (server only).");
			LookArms = ((BaseUnityPlugin)this).Config.Bind<float>("Look", "Arms", 1.55f, "Viking body: arm size, 1 = a normal player (0.8-1.6) (server only).");
			LookHeight = ((BaseUnityPlugin)this).Config.Bind<float>("Look", "Height", 1.05f, "Viking body: overall height, 1 = a normal player (0.8-1.3) (server only).");
			MapMarker = ((BaseUnityPlugin)this).Config.Bind<string>("Companion", "MapMarker", "everyone", new ConfigDescription("Who sees the companion on the minimap and big map: everyone, master (only its master) or off (server only).", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[3] { "everyone", "master", "off" }), Array.Empty<object>()));
			AgentHost = ((BaseUnityPlugin)this).Config.Bind<string>("Agent", "Host", "127.0.0.1", "Hostname of the companion agent (server only).");
			AgentPort = ((BaseUnityPlugin)this).Config.Bind<int>("Agent", "Port", 7777, "TCP port of the companion agent (server only).");
			AgentToken = ((BaseUnityPlugin)this).Config.Bind<string>("Agent", "Token", "", "Shared secret sent in the agent handshake (server only).");
			_harmony = new Harmony("com.sapienheim.valheimcompanion");
			_harmony.PatchAll(typeof(Plugin).Assembly);
			if (!GUIManager.IsHeadless())
			{
				((MonoBehaviour)this).StartCoroutine(CompanionSounds.LoadAll());
			}
			if (GUIManager.IsHeadless())
			{
				Blueprints.InstallStarters();
				LocalPlayerGuards.Apply(_harmony);
			}
			CompanionPrefab.Register();
			Commands.Register();
			((Component)this).gameObject.AddComponent<ZoneKeeper>();
			((Component)this).gameObject.AddComponent<CompanionSpawner>();
			((Component)this).gameObject.AddComponent<AgentClient>();
			((Component)this).gameObject.AddComponent<CompanionMapMarker>();
			((Component)this).gameObject.AddComponent<PlacePins>();
			((Component)this).gameObject.AddComponent<CompanionExplorer>();
			WatchConfig();
			Logger.LogInfo((object)string.Format("{0} {1} loaded (headless={2})", "ValheimCompanion", "0.1.7", GUIManager.IsHeadless()));
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
	}
	internal enum CompanionRole
	{
		Unknown,
		Server,
		Client
	}
	internal static class Role
	{
		[HarmonyPatch(typeof(ZNet), "Awake")]
		private static class ZNetAwakePatch
		{
			private static void Postfix(ZNet __instance)
			{
				Current = (__instance.IsServer() ? CompanionRole.Server : CompanionRole.Client);
				Logger.LogInfo((object)$"Role: {Current} (dedicated={__instance.IsDedicated()})");
				Rpcs.Register();
			}
		}

		[HarmonyPatch(typeof(ZNet), "OnDestroy")]
		private static class ZNetDestroyPatch
		{
			private static void Postfix()
			{
				Current = CompanionRole.Unknown;
			}
		}

		public static CompanionRole Current { get; private set; }

		public static bool IsServer => Current == CompanionRole.Server;
	}
}
namespace ValheimCompanion.World
{
	internal static class LocalPlayerGuards
	{
		private static readonly Type[] AffectedTypes = new Type[5]
		{
			typeof(Pickable),
			typeof(Container),
			typeof(Trap),
			typeof(Sadle),
			typeof(Ship)
		};

		private static readonly FieldInfo LocalPlayer = AccessTools.Field(typeof(Player), "m_localPlayer");

		private static readonly MethodInfo GetZdoid = AccessTools.Method(typeof(Character), "GetZDOID", (Type[])null, (Type[])null);

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

		private static readonly MethodInfo SafeZdoid = AccessTools.Method(typeof(LocalPlayerGuards), "LocalPlayerZdoid", (Type[])null, (Type[])null);

		private static readonly MethodInfo SafePlayerId = AccessTools.Method(typeof(LocalPlayerGuards), "LocalPlayerId", (Type[])null, (Type[])null);

		public static ZDOID LocalPlayerZdoid()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)Player.m_localPlayer))
			{
				return ZDOID.None;
			}
			return ((Character)Player.m_localPlayer).GetZDOID();
		}

		public static long LocalPlayerId()
		{
			if (!Object.op_Implicit((Object)(object)Player.m_localPlayer))
			{
				return 0L;
			}
			return Player.m_localPlayer.GetPlayerID();
		}

		public static void Apply(Harmony harmony)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			HarmonyMethod val = new HarmonyMethod(AccessTools.Method(typeof(LocalPlayerGuards), "Transpiler", (Type[])null, (Type[])null));
			int num = 0;
			Type[] affectedTypes = AffectedTypes;
			foreach (Type type in affectedTypes)
			{
				foreach (MethodInfo declaredMethod in AccessTools.GetDeclaredMethods(type))
				{
					if (!declaredMethod.IsAbstract && declaredMethod.GetMethodBody() != null && UsesPattern(declaredMethod))
					{
						harmony.Patch((MethodBase)declaredMethod, (HarmonyMethod)null, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null);
						num++;
						Logger.LogDebug((object)("LocalPlayerGuards: patched " + type.Name + "." + declaredMethod.Name));
					}
				}
			}
			Logger.LogInfo((object)$"LocalPlayerGuards: made {num} vanilla owner-side methods safe without a local player");
		}

		private static bool UsesPattern(MethodBase method)
		{
			List<CodeInstruction> originalInstructions = PatchProcessor.GetOriginalInstructions(method, (ILGenerator)null);
			for (int i = 0; i + 1 < originalInstructions.Count; i++)
			{
				if (CodeInstructionExtensions.LoadsField(originalInstructions[i], LocalPlayer, false) && (CodeInstructionExtensions.Calls(originalInstructions[i + 1], GetZdoid) || CodeInstructionExtensions.Calls(originalInstructions[i + 1], GetPlayerId)))
				{
					return true;
				}
			}
			return false;
		}

		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			List<CodeInstruction> code = new List<CodeInstruction>(instructions);
			for (int i = 0; i < code.Count; i++)
			{
				if (i + 1 < code.Count && CodeInstructionExtensions.LoadsField(code[i], LocalPlayer, false))
				{
					MethodInfo methodInfo = (CodeInstructionExtensions.Calls(code[i + 1], GetZdoid) ? SafeZdoid : (CodeInstructionExtensions.Calls(code[i + 1], GetPlayerId) ? SafePlayerId : null));
					if (methodInfo != null)
					{
						yield return new CodeInstruction(OpCodes.Call, (object)methodInfo)
						{
							labels = code[i].labels,
							blocks = code[i].blocks
						};
						i++;
						continue;
					}
				}
				yield return code[i];
			}
		}
	}
	internal class ZoneKeeper : MonoBehaviour
	{
		[HarmonyPatch(typeof(Game), "FixedUpdate")]
		private static class GameFixedUpdatePatch
		{
			private static void Postfix()
			{
				ApplyAnchor();
			}
		}

		private const float SearchInterval = 5f;

		private static Vector3? s_pendingAnchor;

		private readonly List<ZDO> _found = new List<ZDO>();

		private ZDOID _companion = ZDOID.None;

		private float _nextSearch;

		private static Vector3? s_anchor;

		public static ZoneKeeper Instance { get; private set; }

		public static bool Suspended { get; set; }

		public static bool IsActive
		{
			get
			{
				if (Object.op_Implicit((Object)(object)ZNet.instance) && ZNet.instance.IsDedicated())
				{
					return ZDOMan.instance != null;
				}
				return false;
			}
		}

		public static void SetPendingAnchor(Vector3? pos)
		{
			s_pendingAnchor = pos;
		}

		private void Awake()
		{
			Instance = this;
		}

		public ZDO FindCompanion(bool forceSearch = false)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: 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_00e5: 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_0111: Unknown result type (might be due to invalid IL or missing references)
			if (!IsActive)
			{
				return null;
			}
			if (_companion != ZDOID.None)
			{
				ZDO zDO = ZDOMan.instance.GetZDO(_companion);
				if (zDO != null && zDO.IsValid())
				{
					return zDO;
				}
				_companion = ZDOID.None;
				Logger.LogInfo((object)"ZoneKeeper: companion ZDO gone");
			}
			if (!forceSearch && Time.time < _nextSearch)
			{
				return null;
			}
			_nextSearch = Time.time + 5f;
			_found.Clear();
			int num = 0;
			while (!ZDOMan.instance.GetAllZDOsWithPrefabIterative("SapienCompanion", _found, ref num))
			{
			}
			if (_found.Count == 0)
			{
				return null;
			}
			if (_found.Count > 1)
			{
				Logger.LogWarning((object)$"ZoneKeeper: {_found.Count} companions in the world; only the first is kept loaded");
			}
			_companion = _found[0].m_uid;
			s_pendingAnchor = null;
			Logger.LogInfo((object)$"ZoneKeeper: anchoring server to companion {_companion} at {_found[0].GetPosition():F0}");
			return _found[0];
		}

		public void Forget()
		{
			//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)
			_companion = ZDOID.None;
		}

		private static void ApplyAnchor()
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			if (s_anchor.HasValue && IsActive && !Suspended)
			{
				ZNet.instance.SetReferencePosition(s_anchor.Value);
			}
		}

		private void Update()
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			if (!IsActive || Suspended)
			{
				_companion = ZDOID.None;
				s_anchor = null;
				return;
			}
			ZDO val = FindCompanion();
			if (val != null)
			{
				ZNetView val2 = ZNetScene.instance.FindInstance(val);
				s_anchor = (Object.op_Implicit((Object)(object)val2) ? ((Component)val2).transform.position : val.GetPosition());
				long sessionID = ZDOMan.GetSessionID();
				if (val.GetOwner() != sessionID)
				{
					Logger.LogInfo((object)$"ZoneKeeper: reclaiming companion ownership from {val.GetOwner()}");
					val.SetOwner(sessionID);
				}
			}
			else
			{
				s_anchor = s_pendingAnchor;
			}
			ApplyAnchor();
		}
	}
}
namespace ValheimCompanion.Travel
{
	internal static class PortalNetwork
	{
		public struct Portal
		{
			public ZDO Zdo;

			public string Tag;

			public ZDO Target;
		}

		public static List<Portal> All()
		{
			//IL_0044: 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_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			List<Portal> list = new List<Portal>();
			foreach (List<ZDO> value in ZDOMan.instance.m_portalObjects.Values)
			{
				foreach (ZDO item in value)
				{
					if (item != null && item.IsValid())
					{
						ZDOID connectionZDOID = item.GetConnectionZDOID((ConnectionType)1);
						list.Add(new Portal
						{
							Zdo = item,
							Tag = item.GetString(ZDOVars.s_tag, ""),
							Target = ((connectionZDOID != ZDOID.None) ? ZDOMan.instance.GetZDO(connectionZDOID) : null)
						});
					}
				}
			}
			return list;
		}

		public static Portal? Find(string id)
		{
			foreach (Portal item in All())
			{
				if (((object)Unsafe.As<ZDOID, ZDOID>(ref item.Zdo.m_uid)/*cast due to .constrained prefix*/).ToString() == id)
				{
					return item;
				}
			}
			return null;
		}

		public static Portal? Nearest(Vector3 from, string tag, float range)
		{
			//IL_0044: 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)
			Portal? result = null;
			float num = range;
			foreach (Portal item in All())
			{
				if (item.Target != null && (string.IsNullOrEmpty(tag) || string.Equals(item.Tag, tag, StringComparison.OrdinalIgnoreCase)))
				{
					float num2 = Vector3.Distance(item.Zdo.GetPosition(), from);
					if (num2 < num)
					{
						result = item;
						num = num2;
					}
				}
			}
			return result;
		}

		public static void Exit(Portal portal, out Vector3 pos, out Quaternion rot)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			rot = portal.Target.GetRotation();
			pos = portal.Target.GetPosition() + rot * Vector3.forward * 1f + Vector3.up;
		}

		public static bool Teleportable(Inventory inventory, ZDO portal, out string blocking)
		{
			blocking = null;
			GameObject prefab = ZNetScene.instance.GetPrefab(portal.GetPrefab());
			TeleportWorld val = (Object.op_Implicit((Object)(object)prefab) ? prefab.GetComponent<TeleportWorld>() : null);
			if (Object.op_Implicit((Object)(object)val) && val.m_allowAllItems)
			{
				return true;
			}
			foreach (ItemData allItem in inventory.GetAllItems())
			{
				if (!allItem.m_shared.m_teleportable)
				{
					blocking = CompanionInventory.PrefabName(allItem);
					return false;
				}
			}
			return true;
		}

		public static JArray Describe(Vector3 from)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Expected O, but got Unknown
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			JArray val = new JArray();
			foreach (Portal item in All())
			{
				Vector3 position = item.Zdo.GetPosition();
				JObject val2 = new JObject
				{
					["id"] = JToken.op_Implicit(((object)Unsafe.As<ZDOID, ZDOID>(ref item.Zdo.m_uid)/*cast due to .constrained prefix*/).ToString()),
					["tag"] = JToken.op_Implicit(item.Tag),
					["pos"] = (JToken)(object)Pos(position),
					["dist"] = JToken.op_Implicit(Mathf.Round(Vector3.Distance(position, from))),
					["paired"] = JToken.op_Implicit(item.Target != null)
				};
				if (item.Target != null)
				{
					val2["exit"] = (JToken)(object)Pos(item.Target.GetPosition());
				}
				val.Add((JToken)(object)val2);
			}
			return val;
		}

		private static JArray Pos(Vector3 p)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Expected O, but got Unknown
			return new JArray(new object[3]
			{
				Mathf.Round(p.x),
				Mathf.Round(p.y),
				Mathf.Round(p.z)
			});
		}
	}
}
namespace ValheimCompanion.Net
{
	internal class CompanionExplorer : MonoBehaviour
	{
		private const string RpcExplore = "CMP_Explore";

		private const string RpcPin = "CMP_Pin";

		private const string KeyPending = "cmp_explore_pending";

		private const string KeyPendingPins = "cmp_pins_pending";

		private const string KeyFound = "cmp_found";

		private const string KeyBiomes = "cmp_biomes";

		private const float Interval = 2f;

		private const float StepMetres = 30f;

		private const float SightMetres = 90f;

		private const int MaxPending = 3000;

		private static readonly (string match, string label, PinType pin)[] Notable = new(string, string, PinType)[17]
		{
			("Eikthyrnir", "Eikthyr's altar", (PinType)9),
			("GDKing", "The Elder's altar", (PinType)9),
			("Bonemass", "Bonemass's altar", (PinType)9),
			("Dragonqueen", "Moder's altar", (PinType)9),
			("GoblinKing", "Yagluth's altar", (PinType)9),
			("DvergrBossEntrance", "The Queen's gate", (PinType)9),
			("FaderLocation", "Fader's altar", (PinType)9),
			("Vendor_BlackForest", "Haldor the trader", (PinType)3),
			("Hildir_camp", "Hildir's camp", (PinType)3),
			("BogWitch", "The Bog Witch", (PinType)3),
			("SunkenCrypt", "Sunken crypt", (PinType)3),
			("Crypt", "Burial chamber", (PinType)3),
			("TrollCave", "Troll cave", (PinType)3),
			("MountainCave", "Frost cave", (PinType)3),
			("GoblinCamp", "Fuling village", (PinType)3),
			("DvergrTownEntrance", "Infested mine", (PinType)3),
			("Runestone", "Runestone", (PinType)3)
		};

		private float _next;

		private Vector3 _lastPoint = new Vector3(float.MaxValue, 0f, 0f);

		private ZDOID _zdoFor = ZDOID.None;

		private HashSet<string> _found = new HashSet<string>();

		public static void Register()
		{
			ZRoutedRpc.instance.Register<string>("CMP_Explore", (Action<long, string>)RPC_Explore);
			ZRoutedRpc.instance.Register<Vector3, string, int>("CMP_Pin", (Action<long, Vector3, string, int>)RPC_Pin);
		}

		private void Update()
		{
			//IL_0065: 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_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: 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_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			if (!Role.IsServer || !Object.op_Implicit((Object)(object)ZNet.instance) || Time.time < _next)
			{
				return;
			}
			_next = Time.time + 2f;
			ZDO val = (ZoneKeeper.IsActive ? ZoneKeeper.Instance.FindCompanion() : CompanionAI.FindOwned()?.ZDO);
			if (val == null || !val.IsOwner())
			{
				return;
			}
			if (val.m_uid != _zdoFor)
			{
				_zdoFor = val.m_uid;
				_found = new HashSet<string>(from k in (val.GetString("cmp_found", "") ?? "").Split(new char[1] { ';' })
					where k.Length > 0
					select k);
				_lastPoint = new Vector3(float.MaxValue, 0f, 0f);
			}
			ZNetView val2 = ZNetScene.instance.FindInstance(val);
			Vector3 val3 = (Object.op_Implicit((Object)(object)val2) ? ((Component)val2).transform.position : val.GetPosition());
			if (Flat(val3 - _lastPoint) >= 30f)
			{
				_lastPoint = val3;
				AddPending(val, "cmp_explore_pending", $"{Mathf.RoundToInt(val3.x)},{Mathf.RoundToInt(val3.z)}", ';');
				Discover(val, val3);
			}
			Deliver(val);
		}

		private unsafe void Discover(ZDO zdo, Vector3 pos)
		{
			//IL_0005: 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_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Expected I4, but got Unknown
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: 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_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Expected O, but got Unknown
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: 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_00c6: 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_00e2: 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_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Expected I4, but got Unknown
			//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)
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0206: 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_0211: Unknown result type (might be due to invalid IL or missing references)
			//IL_022f: Expected O, but got Unknown
			//IL_023c: Unknown result type (might be due to invalid IL or missing references)
			//IL_023d: Unknown result type (might be due to invalid IL or missing references)
			Biome biome = WorldGenerator.instance.GetBiome(pos);
			int num = zdo.GetInt("cmp_biomes", 0);
			if ((int)biome != 0 && (num & biome) == 0)
			{
				zdo.Set("cmp_biomes", num | biome);
				AgentClient.SendEvent("discovered", new JObject
				{
					["kind"] = JToken.op_Implicit("biome"),
					["name"] = JToken.op_Implicit(((object)(*(Biome*)(&biome))/*cast due to .constrained prefix*/).ToString()),
					["pos"] = (JToken)(object)Pos(pos)
				});
			}
			foreach (LocationInstance value in ZoneSystem.instance.m_locationInstances.Values)
			{
				if (Flat(value.m_position - pos) > 90f || value.m_location == null)
				{
					continue;
				}
				string id = value.m_location.m_prefabName ?? value.m_location.m_name ?? "";
				(string, string, PinType) tuple = Notable.FirstOrDefault(((string match, string label, PinType pin) n) => id.IndexOf(n.match, StringComparison.OrdinalIgnoreCase) >= 0);
				if (tuple.Item2 != null)
				{
					string text = $"{Mathf.RoundToInt(value.m_position.x)},{Mathf.RoundToInt(value.m_position.z)}";
					if (_found.Add(text))
					{
						zdo.Set("cmp_found", string.Join(";", _found));
						AddPending(zdo, "cmp_pins_pending", $"{text},{(int)tuple.Item3},{tuple.Item2}", '|');
						AgentClient.SendEvent("discovered", new JObject
						{
							["kind"] = JToken.op_Implicit("place"),
							["name"] = JToken.op_Implicit(tuple.Item2),
							["pos"] = (JToken)(object)Pos(value.m_position),
							["biome"] = JToken.op_Implicit(((object)WorldGenerator.instance.GetBiome(value.m_position)/*cast due to .constrained prefix*/).ToString())
						});
						Logger.LogInfo((object)$"Explorer: found {tuple.Item2} at {value.m_position:F0}");
					}
				}
			}
		}

		private static void AddPending(ZDO zdo, string key, string item, char sep)
		{
			string text = zdo.GetString(key, "");
			List<string> list = (string.IsNullOrEmpty(text) ? new List<string>() : text.Split(new char[1] { sep }).ToList());
			list.Add(item);
			if (list.Count > 3000)
			{
				list.RemoveRange(0, list.Count - 3000);
			}
			zdo.Set(key, string.Join(sep.ToString(), list));
		}

		private static void Deliver(ZDO zdo)
		{
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			string text = zdo.GetString("cmp_explore_pending", "");
			string text2 = zdo.GetString("cmp_pins_pending", "");
			if (string.IsNullOrEmpty(text) && string.IsNullOrEmpty(text2))
			{
				return;
			}
			long num = CompanionMapMarker.MasterPeer(CompanionState.GetMaster(zdo));
			if (num == 0L)
			{
				return;
			}
			if (!string.IsNullOrEmpty(text))
			{
				ZRoutedRpc.instance.InvokeRoutedRPC(num, "CMP_Explore", new object[1] { text });
				zdo.Set("cmp_explore_pending", "");
			}
			if (string.IsNullOrEmpty(text2))
			{
				return;
			}
			string[] array = text2.Split(new char[1] { '|' });
			for (int i = 0; i < array.Length; i++)
			{
				string[] array2 = array[i].Split(new char[1] { ',' }, 4);
				if (array2.Length == 4 && int.TryParse(array2[0], out var result) && int.TryParse(array2[1], out var result2) && int.TryParse(array2[2], out var result3))
				{
					ZRoutedRpc.instance.InvokeRoutedRPC(num, "CMP_Pin", new object[3]
					{
						(object)new Vector3((float)result, 0f, (float)result2),
						array2[3],
						result3
					});
				}
			}
			zdo.Set("cmp_pins_pending", "");
		}

		private static float Flat(Vector3 v)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			Vector2 val = new Vector2(v.x, v.z);
			return ((Vector2)(ref val)).magnitude;
		}

		private static JArray Pos(Vector3 p)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Expected O, but got Unknown
			return new JArray(new object[2]
			{
				Mathf.Round(p.x),
				Mathf.Round(p.z)
			});
		}

		private static void RPC_Explore(long sender, string path)
		{
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)Minimap.instance) || !Object.op_Implicit((Object)(object)Player.m_localPlayer))
			{
				return;
			}
			string[] array = path.Split(new char[1] { ';' });
			for (int i = 0; i < array.Length; i++)
			{
				string[] array2 = array[i].Split(new char[1] { ',' });
				if (array2.Length == 2 && float.TryParse(array2[0], NumberStyles.Float, CultureInfo.InvariantCulture, out var result) && float.TryParse(array2[1], NumberStyles.Float, CultureInfo.InvariantCulture, out var result2))
				{
					Minimap.instance.Explore(new Vector3(result, 0f, result2), Minimap.instance.m_exploreRadius);
				}
			}
		}

		private static void RPC_Pin(long sender, Vector3 pos, string name, int type)
		{
			//IL_001d: 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_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)Minimap.instance) && Object.op_Implicit((Object)(object)Player.m_localPlayer) && !Minimap.instance.HaveSimilarPin(pos, (PinType)type, name, true))
			{
				Minimap.instance.AddPin(pos, (PinType)type, name, true, false, 0L, default(PlatformUserID));
			}
		}
	}
	internal class CompanionMapMarker : MonoBehaviour
	{
		private const string Rpc = "CMP_MapPos";

		private const float BroadcastInterval = 2f;

		private const float PinTimeout = 10f;

		private float _nextBroadcast;

		private static PinData s_pin;

		private static float s_lastUpdate;

		public static void Register()
		{
			ZRoutedRpc.instance.Register<string, Vector3>("CMP_MapPos", (Action<long, string, Vector3>)RPC_MapPos);
		}

		private void Update()
		{
			if (Role.IsServer && Object.op_Implicit((Object)(object)ZNet.instance) && Time.time >= _nextBroadcast)
			{
				_nextBroadcast = Time.time + 2f;
				Broadcast();
			}
			ExpirePin();
		}

		private static void Broadcast()
		{
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: 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_00aa: Unknown result type (might be due to invalid IL or missing references)
			string value = Plugin.MapMarker.Value;
			if (value == "off")
			{
				return;
			}
			ZDO val = (ZoneKeeper.IsActive ? ZoneKeeper.Instance.FindCompanion() : CompanionAI.FindOwned()?.ZDO);
			if (val == null)
			{
				return;
			}
			ZNetView val2 = ZNetScene.instance.FindInstance(val);
			Vector3 val3 = (Object.op_Implicit((Object)(object)val2) ? ((Component)val2).transform.position : val.GetPosition());
			string name = CompanionState.GetName(val);
			if (value == "master")
			{
				long num = MasterPeer(CompanionState.GetMaster(val));
				if (num != 0L)
				{
					ZRoutedRpc.instance.InvokeRoutedRPC(num, "CMP_MapPos", new object[2] { name, val3 });
				}
			}
			else
			{
				ZRoutedRpc.instance.InvokeRoutedRPC(0L, "CMP_MapPos", new object[2] { name, val3 });
			}
		}

		public static long MasterPeer(long masterId)
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			if (masterId == 0L)
			{
				return 0L;
			}
			if (Object.op_Implicit((Object)(object)Player.m_localPlayer) && Player.m_localPlayer.GetPlayerID() == masterId)
			{
				return ZDOMan.GetSessionID();
			}
			foreach (ZNetPeer peer in ZNet.instance.GetPeers())
			{
				ZDO zDO = ZDOMan.instance.GetZDO(peer.m_characterID);
				if (zDO != null && zDO.GetLong(ZDOVars.s_playerID, 0L) == masterId)
				{
					return peer.m_uid;
				}
			}
			return 0L;
		}

		private static void RPC_MapPos(long sender, string name, Vector3 pos)
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)Minimap.instance) && Object.op_Implicit((Object)(object)Player.m_localPlayer))
			{
				s_lastUpdate = Time.time;
				if (s_pin == null)
				{
					s_pin = Minimap.instance.AddPin(pos, (PinType)10, name, false, false, 0L, default(PlatformUserID));
					return;
				}
				s_pin.m_pos = pos;
				s_pin.m_name = name;
			}
		}

		private static void ExpirePin()
		{
			if (s_pin != null)
			{
				if (!Object.op_Implicit((Object)(object)Minimap.instance))
				{
					s_pin = null;
				}
				else if (Time.time - s_lastUpdate > 10f)
				{
					Minimap.instance.RemovePin(s_pin);
					s_pin = null;
				}
			}
		}
	}
	internal class PlacePins : MonoBehaviour
	{
		private const string Rpc = "CMP_Places";

		private const float BroadcastInterval = 30f;

		private const float PinTimeout = 600f;

		private static string s_payload = "";

		private static bool s_dirty;

		private float _nextBroadcast;

		private static readonly List<PinData> s_pins = new List<PinData>();

		private static float s_lastUpdate;

		public static void Register()
		{
			ZRoutedRpc.instance.Register<string>("CMP_Places", (Action<long, string>)RPC_Places);
		}

		public static void Set(IEnumerable<(string name, float x, float z)> places)
		{
			StringBuilder stringBuilder = new StringBuilder();
			foreach (var place in places)
			{
				string item = place.name;
				float item2 = place.x;
				float item3 = place.z;
				string value = item.Replace("\n", " ").Replace("\t", " ");
				stringBuilder.Append(value).Append('\t').Append(item2.ToString(CultureInfo.InvariantCulture))
					.Append('\t')
					.Append(item3.ToString(CultureInfo.InvariantCulture))
					.Append('\n');
			}
			s_payload = stringBuilder.ToString();
			s_dirty = true;
		}

		private void Update()
		{
			if (Role.IsServer && Object.op_Implicit((Object)(object)ZNet.instance) && ZRoutedRpc.instance != null && (s_dirty || Time.time >= _nextBroadcast))
			{
				_nextBroadcast = Time.time + 30f;
				s_dirty = false;
				if (s_payload.Length > 0)
				{
					ZRoutedRpc.instance.InvokeRoutedRPC(0L, "CMP_Places", new object[1] { s_payload });
				}
			}
			if (s_pins.Count > 0 && (!Object.op_Implicit((Object)(object)Minimap.instance) || Time.time - s_lastUpdate > 600f))
			{
				Clear();
			}
		}

		private static void RPC_Places(long sender, string payload)
		{
			//IL_0097: 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_00be: 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)
			if (!Object.op_Implicit((Object)(object)Minimap.instance) || !Object.op_Implicit((Object)(object)Player.m_localPlayer))
			{
				return;
			}
			s_lastUpdate = Time.time;
			Clear();
			string[] array = payload.Split(new char[1] { '\n' });
			Vector3 val = default(Vector3);
			for (int i = 0; i < array.Length; i++)
			{
				string[] array2 = array[i].Split(new char[1] { '\t' });
				if (array2.Length == 3 && float.TryParse(array2[1], NumberStyles.Float, CultureInfo.InvariantCulture, out var result) && float.TryParse(array2[2], NumberStyles.Float, CultureInfo.InvariantCulture, out var result2))
				{
					((Vector3)(ref val))..ctor(result, ZoneSystem.instance.GetGroundHeight(new Vector3(result, 0f, result2)), result2);
					s_pins.Add(Minimap.instance.AddPin(val, (PinType)1, array2[0], false, false, 0L, default(PlatformUserID)));
				}
			}
		}

		private static void Clear()
		{
			if (Object.op_Implicit((Object)(object)Minimap.instance))
			{
				foreach (PinData s_pin in s_pins)
				{
					Minimap.instance.RemovePin(s_pin);
				}
			}
			s_pins.Clear();
		}
	}
	internal static class Rpcs
	{
		private const string SpawnRequest = "CMP_SpawnRequest";

		private const string DespawnRequest = "CMP_DespawnRequest";

		private const string Message = "CMP_Message";

		private const string PlayerChat = "CMP_PlayerChat";

		private const string KillRequest = "CMP_KillRequest";

		public static void Register()
		{
			ZRoutedRpc.instance.Register<Vector3, long, string>("CMP_SpawnRequest", (Action<long, Vector3, long, string>)RPC_SpawnRequest);
			ZRoutedRpc.instance.Register("CMP_DespawnRequest", (Action<long>)RPC_DespawnRequest);
			ZRoutedRpc.instance.Register<string>("CMP_Message", (Action<long, string>)RPC_Message);
			ZRoutedRpc.instance.Register<string, string>("CMP_PlayerChat", (Action<long, string, string>)RPC_PlayerChat);
			ZRoutedRpc.instance.Register("CMP_KillRequest", (Action<long>)RPC_KillRequest);
			CompanionMapMarker.Register();
			PlacePins.Register();
			CompanionExplorer.Register();
		}

		public static void SendPlayerChat(string text, string via)
		{
			ZRoutedRpc.instance.InvokeRoutedRPC("CMP_PlayerChat", new object[2] { text, via });
		}

		private static void RPC_PlayerChat(long sender, string text, string via)
		{
			if (Role.IsServer)
			{
				ChatForwarding.HandlePlayerChat(sender, text, via);
			}
		}

		public static void SendSpawnRequest(Vector3 pos, long masterId, string masterName)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			ZRoutedRpc.instance.InvokeRoutedRPC("CMP_SpawnRequest", new object[3] { pos, masterId, masterName });
		}

		public static void SendDespawnRequest()
		{
			ZRoutedRpc.instance.InvokeRoutedRPC("CMP_DespawnRequest", Array.Empty<object>());
		}

		public static void SendKillRequest()
		{
			ZRoutedRpc.instance.InvokeRoutedRPC("CMP_KillRequest", Array.Empty<object>());
		}

		private static void RPC_KillRequest(long sender)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Expected O, but got Unknown
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			if (Role.IsServer && IsAllowed(sender))
			{
				CompanionAI companionAI = CompanionAI.FindOwned();
				if (!Object.op_Implicit((Object)(object)companionAI))
				{
					Reply(sender, "No companion loaded.");
					return;
				}
				HitData val = new HitData();
				val.m_damage.m_damage = 1000000f;
				val.m_point = ((Component)companionAI).transform.position;
				((Component)companionAI).GetComponent<Character>().Damage(val);
				Reply(sender, companionAI.Name + " has been struck down. Give it a minute.");
			}
		}

		public static void Reply(long target, string text)
		{
			ZRoutedRpc.instance.InvokeRoutedRPC(target, "CMP_Message", new object[1] { text });
		}

		private static void RPC_SpawnRequest(long sender, Vector3 pos, long masterId, string masterName)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			if (Role.IsServer && IsAllowed(sender))
			{
				CompanionSpawner.RequestSpawn(sender, pos, masterId, masterName);
			}
		}

		private static void RPC_DespawnRequest(long sender)
		{
			if (Role.IsServer && IsAllowed(sender))
			{
				CompanionSpawner.Despawn(sender);
			}
		}

		private static void RPC_Message(long sender, string text)
		{
			Logger.LogInfo((object)("[server] " + text));
			if (Object.op_Implicit((Object)(object)Console.instance))
			{
				Console.instance.Print(text);
			}
			if (Object.op_Implicit((Object)(object)MessageHud.instance))
			{
				MessageHud.instance.ShowMessage((MessageType)1, text, 0, (Sprite)null, false, true);
			}
		}

		private static bool IsAllowed(long sender)
		{
			if (sender == ZDOMan.GetSessionID())
			{
				return true;
			}
			ZNetPeer peer = ZNet.instance.GetPeer(sender);
			if (peer != null && ZNet.instance.IsAdmin(peer.m_socket.GetHostName()))
			{
				return true;
			}
			Logger.LogWarning((object)$"Rejected companion admin request from non-admin peer {sender}");
			Reply(sender, "Only server admins can spawn or despawn the companion (add your SteamID to adminlist.txt).");
			return false;
		}
	}
}
namespace ValheimCompanion.Companion
{
	internal static class Commands
	{
		private class SpawnCommand : ConsoleCommand
		{
			public override string Name => "cmp_spawn";

			public override string Help => "Spawn your companion in front of you (admin only)";

			public override void Run(string[] args)
			{
				//IL_0024: Unknown result type (might be due to invalid IL or missing references)
				//IL_002f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0039: Unknown result type (might be due to invalid IL or missing references)
				//IL_003e: 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_004d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0052: Unknown result type (might be due to invalid IL or missing references)
				Player localPlayer = Player.m_localPlayer;
				if (!Object.op_Implicit((Object)(object)localPlayer))
				{
					Console.instance.Print("You need to be in a world.");
				}
				else
				{
					Rpcs.SendSpawnRequest(((Component)localPlayer).transform.position + ((Component)localPlayer).transform.forward * 2f + Vector3.up * 0.5f, localPlayer.GetPlayerID(), localPlayer.GetPlayerName());
				}
			}
		}

		private class DespawnCommand : ConsoleCommand
		{
			public override string Name => "cmp_despawn";

			public override string Help => "Remove the companion from the world (admin only)";

			public override void Run(string[] args)
			{
				Rpcs.SendDespawnRequest();
			}
		}

		private class KillCommand : ConsoleCommand
		{
			public override string Name => "cmp_kill";

			public override string Help => "Debug: kill the companion to test bouncing back (admin only)";

			public override void Run(string[] args)
			{
				Rpcs.SendKillRequest();
			}
		}

		public static void Register()
		{
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new SpawnCommand());
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new DespawnCommand());
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new KillCommand());
		}
	}
	internal class CompanionAI : MonoBehaviour
	{
		[HarmonyPatch(typeof(BaseAI), "IsEnemy", new Type[]
		{
			typeof(Character),
			typeof(Character)
		})]
		private static class IgnorePassiveWildlife
		{
			private static void Postfix(Character a, Character b, ref bool __result)
			{
				//IL_003f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0045: Invalid comparison between Unknown and I4
				//IL_005f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0065: Invalid comparison between Unknown and I4
				if (IsCommandedTarget(a, b) || IsCommandedTarget(b, a))
				{
					__result = true;
				}
				else if (__result)
				{
					if (IsGivenUp(a, b) || IsGivenUp(b, a))
					{
						__result = false;
					}
					else if (s_companions.Contains(a) && (int)b.GetFaction() == 1)
					{
						__result = IsHostileTowardUs(b, a);
					}
					else if (s_companions.Contains(b) && (int)a.GetFaction() == 1)
					{
						__result = IsHostileTowardUs(a, b);
					}
				}
			}

			private static bool IsGivenUp(Character companion, Character other)
			{
				if (!s_companions.Contains(companion))
				{
					return false;
				}
				CompanionAI component = ((Component)companion).GetComponent<CompanionAI>();
				if (Object.op_Implicit((Object)(object)component) && component._tasks != null)
				{
					return component._tasks.IsIgnored(other);
				}
				return false;
			}

			private static bool IsCommandedTarget(Character companion, Character other)
			{
				if (!s_companions.Contains(companion))
				{
					return false;
				}
				CompanionAI component = ((Component)companion).GetComponent<CompanionAI>();
				if (Object.op_Implicit((Object)(object)component) && component._tasks != null)
				{
					return (Object)(object)component._tasks.AttackTarget == (Object)(object)other;
				}
				return false;
			}

			private static bool IsHostileTowardUs(Character animal, Character companion)
			{
				BaseAI baseAI = animal.GetBaseAI();
				MonsterAI val = (MonsterAI)(object)((baseAI is MonsterAI) ? baseAI : null);
				if (val == null)
				{
					return false;
				}
				Character targetCreature = ((BaseAI)val).GetTargetCreature();
				if (Object.op_Implicit((Object)(object)targetCreature))
				{
					if (!((Object)(object)targetCreature == (Object)(object)companion))
					{
						return targetCreature.IsPlayer();
					}
					return true;
				}
				return false;
			}
		}

		[HarmonyPatch(typeof(Character), "Damage")]
		private static class DamageDealtLog
		{
			private static void Prefix(Character __instance, HitData hit)
			{
				Character attacker = hit.GetAttacker();
				if (Object.op_Implicit((Object)(object)attacker) && Object.op_Implicit((Object)(object)((Component)attacker).GetComponent<CompanionAI>()))
				{
					float totalDamage = hit.GetTotalDamage();
					if (totalDamage > 0f)
					{
						hit.ApplyModifier(CompanionLevelling.HitDamage(attacker.GetLevel()) * Random.Range(0.9f, 1.1f) / totalDamage);
					}
					Logger.LogInfo((object)($"[hit] {attacker.m_name} hit {__instance.m_name} for {hit.GetTotalDamage():F0} " + $"({__instance.GetHealth():F0}hp before)"));
				}
			}
		}

		[HarmonyPatch(typeof(Character), "RPC_Damage")]
		private static class NoPlayerDamage
		{
			private static bool Prefix(Character __instance, HitData hit)
			{
				if (!Object.op_Implicit((Object)(object)((Component)__instance).GetComponent<CompanionAI>()))
				{
					return true;
				}
				Character attacker = hit.GetAttacker();
				if (Object.op_Implicit((Object)(object)attacker))
				{
					return !attacker.IsPlayer();
				}
				return true;
			}
		}

		private const float TickInterval = 0.25f;

		private const float StatusInterval = 10f;

		private const string RpcSay = "CMP_Say";

		private const string RpcSound = "CMP_Sound";

		private const string RpcThinking = "CMP_Thinking";

		private const float ThinkingSeconds = 15f;

		private const float BubbleHeight = 2.2f;

		private const float BubbleCullDistance = 20f;

		private const float BubbleSeconds = 8f;

		private const float ChatLineDistance = 30f;

		private static readonly HashSet<Character> s_companions = new HashSet<Character>();

		private static readonly List<CompanionAI> s_instances = new List<CompanionAI>();

		private ZNetView _nview;

		private Humanoid _character;

		private MonsterAI _ai;

		private CompanionTasks _tasks;

		private CompanionInventory _inventory;

		private CompanionLevelling _levelling;

		private CompanionDoors _doors;

		private CompanionProactive _proactive;

		private float _nextTick;

		private float _nextStatus;

		private string _queuedMoment;

		private float _queuedAt;

		private readonly Dictionary<string, string> _swingTriggers = new Dictionary<string, string>();

		public CompanionTasks Tasks => _tasks;

		public CompanionDoors Doors => _doors;

		public CompanionInventory Inventory => _inventory;

		public CompanionLevelling Levelling => _levelling;

		public ZDO ZDO => _nview.GetZDO();

		public string Name => ((Character)_character).m_name;

		private void Awake()
		{
			_nview = ((Component)this).GetComponent<ZNetView>();
			_character = ((Component)this).GetComponent<Humanoid>();
			_ai = ((Component)this).GetComponent<MonsterAI>();
			if (!_nview.IsValid())
			{
				return;
			}
			s_companions.Add((Character)(object)_character);
			s_instances.Add(this);
			_nview.Register<string>("CMP_Say", (Action<long, string>)RPC_Say);
			_nview.Register<string, bool>("CMP_Sound", (Action<long, string, bool>)RPC_Sound);
			_nview.Register("CMP_Thinking", (Action<long>)RPC_Thinking);
			_inventory = new CompanionInventory(_nview, _character);
			_levelling = new CompanionLevelling(_nview, _character);
			_doors = new CompanionDoors(_nview, _character, _ai);
			_tasks = new CompanionTasks(_nview, _character, _ai, _inventory);
			_proactive = new CompanionProactive(_nview, (Character)(object)_character, _tasks);
			ApplyName();
			if (GUIManager.IsHeadless())
			{
				Animator[] componentsInChildren = ((Component)this).GetComponentsInChildren<Animator>();
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					componentsInChildren[i].cullingMode = (AnimatorCullingMode)0;
				}
			}
		}

		private void OnDestroy()
		{
			s_companions.Remove((Character)(object)_character);
			s_instances.Remove(this);
			_tasks?.OnDestroy();
		}

		public static CompanionAI FindOwned()
		{
			foreach (CompanionAI s_instance in s_instances)
			{
				if (s_instance._nview.IsValid() && s_instance._nview.IsOwner())
				{
					return s_instance;
				}
			}
			return null;
		}

		public static bool AnyWithin(Vector3 point, float range)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			foreach (CompanionAI s_instance in s_instances)
			{
				if (s_instance._nview.IsValid() && Vector3.Distance(((Component)s_instance).transform.position, point) <= range)
				{
					return true;
				}
			}
			return false;
		}

		public void Say(string text)
		{
			_nview.InvokeRPC(ZNetView.Everybody, "CMP_Say", new object[1] { text });
		}

		public bool PlaySound(string clip, bool follow = true)
		{
			clip = (clip ?? "").Trim().ToLowerInvariant();
			if (!CompanionSounds.Names.Contains(clip) || !CompanionSounds.TakeTurn())
			{
				return false;
			}
			Logger.LogInfo((object)(((Character)_character).m_name + ": plays clip " + clip));
			_nview.InvokeRPC(ZNetView.Everybody, "CMP_Sound", new object[2] { clip, follow });
			return true;
		}

		public void PlayMoment(string moment, bool follow = true, string subject = null, string fallbackLine = null)
		{
			string text = CompanionSounds.ForMoment(moment, subject);
			bool flag = text != null && PlaySound(text, follow);
			if (fallbackLine != null)
			{
				Say((flag ? CompanionSounds.Caption(text) : null) ?? fallbackLine);
			}
		}

		public void QueueMoment(string moment, float delay)
		{
			_queuedMoment = moment;
			_queuedAt = Time.time + delay;
		}

		private void RPC_Sound(long sender, string clip, bool follow)
		{
			if (Object.op_Implicit((Object)(object)Player.m_localPlayer))
			{
				CompanionSounds.Play(clip, ((Component)this).transform, follow);
			}
		}

		public void PlaySwing(ItemData tool)
		{
			if (tool != null)
			{
				string name = tool.m_shared.m_name;
				if (!_swingTriggers.TryGetValue(name, out var value))
				{
					value = ResolveSwingTrigger(tool);
					_swingTriggers[name] = value;
					Logger.LogInfo((object)(((Character)_character).m_name + ": swing animation for " + name + " = " + (value ?? "(none available)")));
				}
				if (value != null)
				{
					((Character)_character).m_zanim.SetTrigger(value);
				}
			}
		}

		private string ResolveSwingTrigger(ItemData tool)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Invalid comparison between Unknown and I4
			HashSet<string> hashSet = new HashSet<string>();
			Animator[] componentsInChildren = ((Component)this).GetComponentsInChildren<Animator>();
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				AnimatorControllerParameter[] parameters = componentsInChildren[i].parameters;
				foreach (AnimatorControllerParameter val in parameters)
				{
					if ((int)val.type == 9)
					{
						hashSet.Add(val.name);
					}
				}
			}
			string text = SwingTrigger(tool.m_shared.m_attack);
			if (hashSet.Count == 0)
			{
				return text ?? "swing_axe0";
			}
			List<string> list = new List<string> { text };
			foreach (ItemData allItem in _character.GetInventory().GetAllItems())
			{
				list.Add(SwingTrigger(allItem.m_shared.m_attack));
			}
			list.AddRange(new string[5] { "swing_axe0", "swing_axe", "attack", "attack_melee", "swing_sledge" });
			foreach (string item in list)
			{
				if (!string.IsNullOrEmpty(item) && hashSet.Contains(item))
				{
					return item;
				}
			}
			Logger.LogInfo((object)(((Character)_character).m_name + ": animator triggers: " + string.Join(", ", hashSet)));
			return null;
		}

		private static string SwingTrigger(Attack attack)
		{
			if (attack == null || string.IsNullOrEmpty(attack.m_attackAnimation))
			{
				return null;
			}
			if (attack.m_attackChainLevels <= 1 && attack.m_attackRandomAnimations < 2)
			{
				return attack.m_attackAnimation;
			}
			return attack.m_attackAnimation + "0";
		}

		public void ShowThinking()
		{
			_nview.InvokeRPC(ZNetView.Everybody, "CMP_Thinking", Array.Empty<object>());
		}

		private void RPC_Thinking(long sender)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)Chat.instance) && Object.op_Implicit((Object)(object)Player.m_localPlayer))
			{
				Chat.instance.SetNpcText(((Component)this).gameObject, Vector3.up * 2.2f, 20f, 15f, "", "...", false);
			}
		}

		private void RPC_Say(long sender, string text)
		{
			//IL_0024: 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_0053: 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)
			if (Object.op_Implicit((Object)(object)Chat.instance) && Object.op_Implicit((Object)(object)Player.m_localPlayer))
			{
				Chat.instance.SetNpcText(((Component)this).gameObject, Vector3.up * 2.2f, 20f, 8f, "", text, false);
				if (Vector3.Distance(((Component)Player.m_localPlayer).transform.position, ((Component)this).transform.position) <= 30f || ChatForwarding.RecentlyAddressed)
				{
					((Terminal)Chat.instance).AddString(((Character)_character).m_name, text, (Type)1, false);
				}
			}
		}

		public void InitNew(string name, long masterId, string masterName, byte[] inventory = null)
		{
			ZDO zDO = _nview.GetZDO();
			if (inventory != null)
			{
				zDO.Set("cmp_inventory", inventory);
			}
			zDO.Set("cmp_name", name);
			CompanionState.SetMaster(zDO, masterId, masterName);
			CompanionState.SetTask(zDO, "follow");
			((Character)_character).SetTamed(true);
			ApplyName();
		}

		private void ApplyName()
		{
			string name = CompanionState.GetName(_nview.GetZDO());
			if (name.Length > 0)
			{
				((Character)_character).m_name = name;
			}
		}

		private void Update()
		{
			if (!_nview.IsValid() || Time.time < _nextTick)
			{
				return;
			}
			_nextTick = Time.time + 0.25f;
			if (!_nview.IsOwner())
			{
				ApplyName();
				return;
			}
			if (!((Character)_character).IsTamed())
			{
				((Character)_character).SetTamed(true);
			}
			SyncNameFromConfig();
			_inventory.EnsureRestored();
			_inventory.KeepRepaired();
			_levelling.Update();
			_doors.Update();
			if (_queuedMoment != null && Time.time >= _queuedAt)
			{
				PlayMoment(_queuedMoment);
				_queuedMoment = null;
			}
			_tasks.Update();
			_proactive.Update();
			if (Time.time >= _nextStatus)
			{
				_nextStatus = Time.time + 10f;
				LogStatus();
			}
		}

		private void SyncNameFromConfig()
		{
			string text = Plugin.CompanionName.Value.Trim();
			if (text.Length > 0 && text != CompanionState.GetName(_nview.GetZDO()))
			{
				Logger.LogInfo((object)("Renaming companion " + ((Character)_character).m_name + " -> " + text));
				_nview.GetZDO().Set("cmp_name", text);
				ApplyName();
			}
		}

		private void LogStatus()
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			Character targetCreature = _ai.m_targetCreature;
			GameObject followTarget = _ai.GetFollowTarget();
			Logger.LogInfo((object)($"[status] {((Character)_character).m_name} pos={((Component)this).transform.position:F0} hp={((Character)_character).GetHealth():F0}/{((Character)_character).GetMaxHealth():F0} " + $"owner={_nview.GetZDO().GetOwner()} task={_tasks.Current} " + "follow=" + (Object.op_Implicit((Object)(object)followTarget) ? ((Object)followTarget).name : "-") + " target=" + (Object.op_Implicit((Object)(object)targetCreature) ? $"{targetCreature.m_name}({targetCreature.GetHealth():F0}hp)" : "-")));
		}
	}
	internal static class CompanionBoat
	{
		public const float MaxSwim = 15f;

		public const float SwimBack = 30f;

		public const float FindRadius = 40f;

		private static Ship[] s_ships = (Ship[])(object)new Ship[0];

		private static float s_shipsAt = -10f;

		public const float ClimbReach = 4.5f;

		public static Ship[] All()
		{
			if (Time.time - s_shipsAt > 2f)
			{
				s_ships = Object.FindObjectsByType<Ship>((FindObjectsSortMode)0);
				s_shipsAt = Time.time;
			}
			return s_ships;
		}

		public static Ship Nearest(Vector3 pos, float radius)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			Ship result = null;
			float num = radius;
			Ship[] array = All();
			foreach (Ship val in array)
			{
				if (Object.op_Implicit((Object)(object)val))
				{
					float num2 = Vector3.Distance(((Component)val).transform.position, pos);
					if (num2 < num)
					{
						result = val;
						num = num2;
					}
				}
			}
			return result;
		}

		public static bool Aboard(Ship ship, Vector3 pos)
		{
			//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_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: 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_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: 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_009c: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)ship) || !Object.op_Implicit((Object)(object)ship.m_floatCollider))
			{
				return false;
			}
			Vector3 val = ((Component)ship.m_floatCollider).transform.InverseTransformPoint(pos) - ship.m_floatCollider.center;
			Vector3 val2 = ship.m_floatCollider.size * 0.5f;
			if (Mathf.Abs(val.x) < val2.x + 0.3f && Mathf.Abs(val.z) < val2.z + 0.3f && val.y > 0f - val2.y - 0.2f)
			{
				return val.y < val2.y + 4f;
			}
			return false;
		}

		public static Ship Under(Character who)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)who))
			{
				return null;
			}
			Ship[] array = All();
			foreach (Ship val in array)
			{
				if (Object.op_Implicit((Object)(object)val) && Aboard(val, ((Component)who).transform.position))
				{
					return val;
				}
			}
			return null;
		}

		public static Ladder LadderOf(Ship ship)
		{
			if (!Object.op_Implicit((Object)(object)ship))
			{
				return null;
			}
			return ((Component)ship).GetComponentInChildren<Ladder>();
		}

		public static Vector3 ClimbPoint(Ship ship)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			Ladder val = LadderOf(ship);
			if (!Object.op_Implicit((Object)(object)val))
			{
				return ((Component)ship).transform.position;
			}
			return ((Component)val).transform.position;
		}

		public static Vector3 MastSpotLocal(Ship ship)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//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_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: 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_00b2: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = (Object.op_Implicit((Object)(object)ship.m_mastObject) ? ((Component)ship).transform.InverseTransformPoint(ship.m_mastObject.transform.position) : Vector3.zero);
			float num = (Object.op_Implicit((Object)(object)ship.m_floatCollider) ? ((Component)ship).transform.InverseTransformPoint(((Component)ship.m_floatCollider).transform.TransformPoint(ship.m_floatCollider.center + Vector3.up * ship.m_floatCollider.size.y * 0.5f)).y : 0.5f);
			return new Vector3(val.x + 0.7f, num, val.z - 0.6f);
		}

		public static float Speed(Ship ship)
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			ZNetView val = (Object.op_Implicit((Object)(object)ship) ? ((Component)ship).GetComponent<ZNetView>() : null);
			if ((Object)(object)val == (Object)null || !val.IsValid())
			{
				return 0f;
			}
			Rigidbody component = ((Component)ship).GetComponent<Rigidbody>();
			Vector3 val2 = ((val.IsOwner() && Object.op_Implicit((Object)(object)component)) ? component.linearVelocity : val.GetZDO().GetVec3(ZDOVars.s_bodyVelHash, Vector3.zero));
			val2.y = 0f;
			return ((Vector3)(ref val2)).magnitude;
		}

		public static float Height(float x, float z)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			float result = default(float);
			if (!ZoneSystem.instance.GetGroundHeight(new Vector3(x, 0f, z), ref result))
			{
				return WorldGenerator.instance.GetHeight(x, z);
			}
			return result;
		}

		public static float DistanceToShore(Vector3 pos, float max, out Vector3 land)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: 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)
			//IL_00ac: 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_00bc: 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)
			float waterLevel = ZoneSystem.instance.m_waterLevel;
			land = pos;
			if (Height(pos.x, pos.z) > waterLevel + 0.2f)
			{
				return 0f;
			}
			for (float num = 2f; num <= max; num += 2f)
			{
				int num2 = Mathf.CeilToInt((float)Math.PI * 2f * num / 3f);
				for (int i = 0; i < num2; i++)
				{
					float num3 = (float)i * (float)Math.PI * 2f / (float)num2;
					Vector3 val = pos + new Vector3(Mathf.Cos(num3) * num, 0f, Mathf.Sin(num3) * num);
					float num4 = Height(val.x, val.z);
					if (num4 > waterLevel + 0.5f)
					{
						land = new Vector3(val.x, num4, val.z);
						return num;
					}
				}
			}
			return max + 1f;
		}

		public static bool TryClimb(Humanoid who, Ship ship)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: 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_00de: 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_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: 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_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			Ladder val = LadderOf(ship);
			Vector3 val2 = (Object.op_Implicit((Object)(object)val) ? ((Component)val).transform.position : ((Component)ship).transform.position);
			Vector3 val3 = val2 - ((Component)who).transform.position;
			val3.y = 0f;
			if (((Vector3)(ref val3)).magnitude > 4.5f)
			{
				return false;
			}
			if (Object.op_Implicit((Object)(object)val))
			{
				((Component)who).transform.position = new Vector3(val2.x, Mathf.Max(((Component)who).transform.position.y, val2.y - 1f), val2.z) - ((Vector3)(ref val3)).normalized * 0.5f;
				Physics.SyncTransforms();
				val.Interact(who, false, false);
				return true;
			}
			((Component)who).transform.position = ((Component)ship).transform.TransformPoint(MastSpotLocal(ship) + Vector3.up * 0.3f);
			Physics.SyncTransforms();
			return true;
		}
	}
	internal class DebugBoatPush : MonoBehaviour
	{
		public float Speed;

		public float Turn;

		public float Until;

		public Vector3 Dir;

		private void FixedUpdate()
		{
			//IL_001e: 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_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			if (!(Time.time > Until))
			{
				Rigidbody component = ((Component)this).GetComponent<Rigidbody>();
				if (Object.op_Implicit((Object)(object)component))
				{
					Vector3 linearVelocity = ((Dir == Vector3.zero) ? ((Component)this).transform.forward : Dir) * Speed;
					linearVelocity.y = component.linearVelocity.y;
					component.linearVelocity = linearVelocity;
					component.angularVelocity = new Vector3(0f, Turn, 0f);
				}
			}
		}
	}
	internal class CompanionBody : MonoBehaviour
	{
		[HarmonyPatch(typeof(Humanoid), "SetupVisEquipment")]
		private static class LookPatch
		{
			private static void Postfix(Humanoid __instance, VisEquipment visEq, bool isRagdoll, ItemData ___m_legItem, ItemData ___m_shoulderItem)
			{
				if (Object.op_Implicit((Object)(object)((Component)__instance).GetComponent<CompanionBody>()) || (isRagdoll && Object.op_Implicit((Object)(object)((Component)__instance).GetComponent<CompanionAI>()) && CompanionPrefab.IsViking))
				{
					ApplyLook(visEq, __instance, ___m_legItem == null, ___m_shoulderItem == null);
				}
			}
		}

		private const string KeyChest = "cmp_body_chest";

		private const string KeyArms = "cmp_body_arms";

		private const string KeyHeight = "cmp_body_height";

		private const float LookInterval = 5f;

		private static readonly string[] Torso = new string[3] { "Spine", "Spine1", "Spine2" };

		private static readonly string[] Shoulders = new string[2] { "LeftShoulder", "RightShoulder" };

		private static readonly string[] UpperArms = new string[2] { "LeftArm", "RightArm" };

		private static readonly string[] ForeArms = new string[2] { "LeftForeArm", "RightForeArm" };

		private static readonly string[] Hands = new string[2] { "LeftHand", "RightHand" };

		private ZNetView _nview;

		private Humanoid _humanoid;

		private VisEquipment _vis;

		private Transform _visual;

		private readonly Dictionary<string, Transform> _bones = new Dictionary<string, Transform>();

		private float _nextLook;

		private bool _logged;

		private void Awake()
		{
			_nview = ((Component)this).GetComponent<ZNetView>();
			_humanoid = ((Component)this).GetComponent<Humanoid>();
			_vis = ((Component)this).GetComponent<VisEquipment>();
			_visual = ((Component)this).transform.Find("Visual");
			Transform[] componentsInChildren = ((Component)this).GetComponentsInChildren<Transform>(true);
			foreach (Transform val in componentsInChildren)
			{
				if (!_bones.ContainsKey(((Object)val).name))
				{
					_bones[((Object)val).name] = val;
				}
			}
		}

		private void Update()
		{
			//IL_00b0: 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_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)
			if (!Object.op_Implicit((Object)(object)_nview) || !_nview.IsValid() || !_nview.IsOwner() || Time.time < _nextLook)
			{
				return;
			}
			_nextLook = Time.time + 5f;
			ZDO zDO = _nview.GetZDO();
			zDO.Set("cmp_body_chest", Plugin.LookChest.Value);
			zDO.Set("cmp_body_arms", Plugin.LookArms.Value);
			zDO.Set("cmp_body_height", Plugin.LookHeight.Value);
			_vis.SetModel(0);
			_vis.SetSkinColor(Vector3.Lerp(new Vector3(1f, 1f, 1f), new Vector3(0.45f, 0.32f, 0.24f), Mathf.Clamp01(Plugin.LookSkinTone.Value)));
			_vis.SetHairColor(Colour(Plugin.LookHairColour.Value));
			ApplyLook(_vis);
			if (_logged)
			{
				return;
			}
			_logged = true;
			List<string> list = new List<string>();
			foreach (string item in Managed())
			{
				if (!_bones.ContainsKey(item))
				{
					list.Add(item);
				}
			}
			Logger.LogInfo((object)($"{((Character)_humanoid).m_name}: viking body, {_bones.Count} transforms" + ((list.Count > 0) ? (", bones not found: " + string.Join(", ", list)) : ", all bones found")));
		}

		private void LateUpdate()
		{
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)_nview) && _nview.IsValid() && !GUIManager.IsHeadless())
			{
				ZDO zDO = _nview.GetZDO();
				float num = Mathf.Clamp(zDO.GetFloat("cmp_body_chest", 1f), 0.8f, 1.8f);
				float num2 = Mathf.Clamp(zDO.GetFloat("cmp_body_arms", 1f), 0.8f, 1.6f);
				float num3 = Mathf.Clamp(zDO.GetFloat("cmp_body_height", 1f), 0.8f, 1.3f);
				if (Object.op_Implicit((Object)(object)_visual))
				{
					_visual.localScale = Vector3.one * num3;
				}
				Set("Spine", 1f + (num - 1f) * 0.35f, 1f);
				Set("Spine1", 1f + (num - 1f) * 0.7f, 1f + (num - 1f) * 0.35f);
				Set("Spine2", num, 1f + (num - 1f) * 0.7f);
				Set("Neck", 1f + (num - 1f) * 0.6f, num);
				Set("Head", 1f, 1f + (num - 1f) * 0.6f);
				string[] shoulders = Shoulders;
				foreach (string bone in shoulders)
				{
					Set(bone, num, num);
				}
				shoulders = UpperArms;
				foreach (string bone2 in shoulders)
				{
					Set(bone2, num2, num);
				}
				shoulders = ForeArms;
				foreach (string bone3 in shoulders)
				{
					Set(bone3, 1f + (num2 - 1f) * 0.8f, num2);
				}
				shoulders = Hands;
				foreach (string bone4 in shoulders)
				{
					Set(bone4, 1f, 1f + (num2 - 1f) * 0.8f);
				}
			}
		}

		private void Set(string bone, float wanted, float parent)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			if (_bones.TryGetValue(bone, out var value))
			{
				value.localScale = Vector3.one * (wanted / parent);
			}
		}

		private static IEnumerable<string> Managed()
		{
			string[][] array = new string[5][] { Torso, Shoulders, UpperArms, ForeArms, Hands };
			foreach (string[] array2 in array)
			{
				string[] array3 = array2;
				for (int j = 0; j < array3.Length; j++)
				{
					yield return array3[j];
				}
			}
			yield return "Neck";
			yield return "Head";
		}

		private static void ApplyLook(VisEquipment vis, Humanoid humanoid = null, bool legsEmpty = true, bool shouldersEmpty = true)
		{
			vis.SetHairItem(Hash(Plugin.LookHair.Value));
			vis.SetBeardItem(Hash(Plugin.LookBeard.Value));
			if (legsEmpty)
			{
				vis.SetLegItem(Hash(Plugin.LookLegs.Value));
			}
			if (shouldersEmpty)
			{
				vis.SetShoulderItem(Hash(Plugin.LookCape.Value), 0, 1);
			}
		}

		private static int Hash(string item)
		{
			if (!string.IsNullOrWhiteSpace(item) && !(item == "none"))
			{
				return StringExtensionMethods.GetStableHashCode(item.Trim());
			}
			return 0;
		}

		private static Vector3 Colour(string name)
		{
			//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_01df: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: 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_0128: Unknown result type (might be due to invalid IL or missing references)
			switch ((name ?? "").Trim().ToLowerInvariant())
			{
			case "black":
				return new Vector3(0.12f, 0.1f, 0.09f);
			case "brown":
				return new Vector3(0.45f, 0.3f, 0.2f);
			case "blond":
				return new Vector3(1f, 0.85f, 0.55f);
			case "dirtyblond":
			case "lightbrown":
				return new Vector3(0.78f, 0.6f, 0.38f);
			case "red":
				return new Vector3(0.8f, 0.35f, 0.15f);
			case "grey":
				return new Vector3(0.7f, 0.7f, 0.7f);
			default:
			{
				string[] array = name.Split(new char[1] { ',' });
				if (array.Length == 3 && float.TryParse(array[0], NumberStyles.Float, CultureInfo.InvariantCulture, out var result) && float.TryParse(array[1], NumberStyles.Float, CultureInfo.InvariantCulture, out var result2) && float.TryParse(array[2], NumberStyles.Float, CultureInfo.InvariantCulture, out var result3))
				{
					return new Vector3(result, result2, result3);
				}
				return new Vector3(0.12f, 0.1f, 0.09f);
			}
			}
		}

		public string DescribeBones()
		{
			StringBuilder stringBuilder = new StringBuilder();
			foreach (string item in Managed())
			{
				stringBuilder.Append(item).Append(_bones.ContainsKey(item) ? " ok, " : " MISSING, ");
			}
			return stringBuilder.ToString();
		}
	}
	internal class CompanionDoors
	{
		private const float StuckSeconds = 2f;

		private const float StuckDistance = 0.3f;

		private const float DoorRange = 4f;

		private const float Cooldown = 4f;

		private readonly Humanoid _character;

		private readonly MonsterAI _ai;

		private readonly ZNetView _nview;

		private Vector3 _lastPos;

		private float _stillSince;

		private float _nextTry;

		private Door _opened;

		private float _openedAt;

		private const float StepThroughAfter = 3f;

		private readonly List<(Door door, float at)> _steps = new List<(Door, float)>();

		private Door _leftBuilding;

		private Door _closeBehind;

		private float _closeAt;

		public CompanionDoors(ZNetView nview, Humanoid character, MonsterAI ai)
		{
			_nview = nview;
			_character = character;
			_ai = ai;
		}

		private static bool Indoors(Vector3 pos)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			RaycastHit[] array = Physics.RaycastAll(pos + Vector3.up * 0.5f, Vector3.up, 5f, -1, (QueryTriggerInteraction)1);
			for (int i = 0; i < array.Length; i++)
			{
				RaycastHit val = array[i];
				if (Object.op_Implicit((Object)(object)((Component)((RaycastHit)(ref val)).collider).GetComponentInParent<Piece>()))
				{
					return true;
				}
			}
			return false;
		}

		public static Vector3? ExitTowards(Vector3 pos, Vector3 goal, float radius, long master, HashSet<Door> tried = null)
		{
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: 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)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: 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_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			Door val = null;
			Door val2 = null;
			float num = radius;
			float num2 = radius;
			Door[] array = Object.FindObjectsByType<Door>((FindObjectsSortMode)0);
			foreach (Door val3 in array)
			{
				if (Object.op_Implicit((Object)(object)val3) && Object.op_Implicit((Object)(object)val3.m_nview) && val3.m_nview.IsValid() && !((Object)(object)val3.m_keyItem != (Object)null) && Builder.WardAllows(((Component)val3).transform.position, master) && (tried == null || !tried.Contains(val3)))
				{
					float num3 = Vector3.Distance(((Component)val3).transform.position, pos);
					if (num3 < num && GoalBeyond(val3, pos, goal))
					{
						val = val3;
						num = num3;
					}
					else if (num3 < num2 && Utils.GetPrefabName(((Component)val3).gameObject).Contains("gate"))
					{
						val2 = val3;
						num2 = num3;
					}
				}
			}
			Door val4 = (Object.op_Implicit((Object)(object)val) ? val : val2);
			if (!Object.op_Implicit((Object)(object)val4))
			{
				return null;
			}
			tried?.Add(val4);
			Vector3 forward = ((Component)val4).transform.forward;
			forward.y = 0f;
			((Vector3)(ref forward)).Normalize();
			float num4 = Mathf.Sign(Vector3.Dot(forward, pos - ((Component)val4).transform.position));
			return Object.op_Implicit((Object)(object)val) ? (((Component)val4).transform.position + forward * num4 * 1.5f) : (((Component)val4).transform.position - forward * num4 * 2.5f);
		}

		public static bool InsideRing(Vector3 pos, out Vector3 gateExit)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: 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_0056: 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_0061: 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_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: 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_016a: 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_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			gateExit = pos;
			int mask = LayerMask.GetMask(new string[3] { "piece", "piece_nonsolid", "Default" });
			int num = 0;
			RaycastHit val2 = default(RaycastHit);
			for (int i = 0; i < 8; i++)
			{
				Vector3 val = Quaternion.Euler(0f, (float)i * 45f, 0f) * Vector3.forward;
				if (Physics.Raycast(pos + Vector3.up * 0.7f, val, ref val2, 30f, mask, (QueryTriggerInteraction)1))
				{
					Piece componentInParent = ((Component)((RaycastHit)(ref val2)).collider).GetComponentInParent<Piece>();
					if (componentInParent != null && IsRingPiece(Utils.GetPrefabName(((Component)componentInParent).gameObject)))
					{
						num++;
					}
				}
			}
			if (num < 6)
			{
				return false;
			}
			Door val3 = null;
			float num2 = 35f;
			Door[] array = Object.FindObjectsByType<Door>((FindObjectsSortMode)0);
			foreach (Door val4 in array)
			{
				float num3 = (Object.op_Implicit((Object)(object)val4) ? Vector3.Distance(((Component)val4).transform.position, pos) : float.MaxValue);
				if (num3 < num2 && (Object)(object)val4.m_keyItem == (Object)null && Utils.GetPrefabName(((Component)val4).gameObject).Contains("gate"))
				{
					val3 = val4;
					num2 = num3;
				}
			}
			if (!Object.op_Implicit((Object)(object)val3))
			{
				return false;
			}
			Vector3 forward = ((Component)val3).transform.forward;
			forward.y = 0f;
			((Vector3)(ref forward)).Normalize();
			float num4 = Mathf.Sign(Vector3.Dot(forward, pos - ((Component)val3).transform.position));
			gateExit = ((Component)val3).transform.position - forward * num4 * 2.5f;
			return true;
		}

		private static bool IsRingPiece(string prefab)
		{
			if (!prefab.Contains("fence") && !prefab.Contains("stake_wall") && !prefab.Contains("stone_wall"))
			{
				return prefab.Contains("gate");
			}
			return true;
		}

		private static bool GoalBeyond(Door door, Vector3 pos, Vector3 goal)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			Vector3 forward = ((Component)door).transform.forward;
			forward.y = 0f;
			return Mathf.Sign(Vector3.Dot(forward, pos - ((Component)door).transform.position)) != Mathf.Sign(Vector3.Dot(forward, goal - ((Component)door).transform.position));
		}

		private bool PingPong(Door door)
		{
			_steps.RemoveAll(((Door door, float at) s) => Time.time - s.at > 90f);
			int num = 0;
			foreach (var step in _steps)
			{
				if ((Object)(object)step.door == (Object)(object)door && Time.time - step.at < 60f)
				{
					num++;
				}
			}
			return num >= 3;
		}

		private static Vector3 Beyond(Door door, Vector3 pos)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			Vector3 forward = ((Component)door).transform.forward;
			forward.y = 0f;
			((Vector3)(ref forward)).Normalize();
			float num = Mathf.Sign(Vector3.Dot(forward, pos - ((Component)door).transform.position));
			return ((Component)door).transform.position - forward * num * 1.6f;
		}

		private static bool LeadsOut(Door door, Vector3 pos, bool indoors)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			if (indoors)
			{
				return !Indoors(Beyond(door, pos));
			}
			return false;
		}

		private static bool EntersNeedlessly(Door door, Vector3 pos, bool indoors, Vector3 goal)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			if (!indoors && Indoors(Beyond(door, pos)))
			{
				return Vector3.Distance(goal, ((Component)door).transform.position) > 8f;
			}
			return false;
		}

		private void StepThrough(Door door, Vector3 pos)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: 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_004b: Unknown result type (might be due to invalid IL or missing references)
			//I