Decompiled source of ASKA Fox v0.6.49

BepInEx/plugins/AskaFox/AskaFox.dll

Decompiled a month ago
using System;
using System.Buffers.Binary;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using Cinemachine;
using Fusion;
using HarmonyLib;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem;
using Il2CppSystem.Collections;
using Il2CppSystem.Collections.Generic;
using Il2CppSystem.Reflection;
using Microsoft.CodeAnalysis;
using SSSGame;
using SSSGame.AI;
using SSSGame.Combat;
using SSSGame.Controllers;
using SSSGame.Localization;
using SSSGame.Network;
using SSSGame.UI;
using SSSGame.Water;
using SandSailorStudio;
using SandSailorStudio.Attributes;
using SandSailorStudio.Inventory;
using SandSailorStudio.Parameters;
using SandSailorStudio.Storage;
using SandSailorStudio.UI;
using SandSailorStudio.Utils;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Rendering;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("AskaFox")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("AskaFox")]
[assembly: AssemblyTitle("AskaFox")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace AskaWolfPrototype
{
	internal sealed class AnimalBowString : IDisposable
	{
		private static bool _warned;

		private readonly RangedWeapon _bow;

		private readonly Transform _sourceRoot;

		private readonly LineRenderer _source;

		private readonly LineRenderer _copy;

		private readonly bool _hidden;

		internal bool IsValid
		{
			get
			{
				if ((Object)(object)_bow != (Object)null && (Object)(object)_sourceRoot != (Object)null && (Object)(object)_source != (Object)null && (Object)(object)_copy != (Object)null && (Object)(object)_bow.stringRenderer == (Object)(object)_source && (Object)(object)_bow.localStringPoint0 != (Object)null && (Object)(object)_bow.localStringPoint1 != (Object)null)
				{
					return (Object)(object)_bow.localStringPointArrow != (Object)null;
				}
				return false;
			}
		}

		private AnimalBowString(RangedWeapon bow, Transform sourceRoot, LineRenderer copy)
		{
			_bow = bow;
			_sourceRoot = sourceRoot;
			_source = bow.stringRenderer;
			_copy = copy;
			_hidden = ((Renderer)_source).forceRenderingOff;
		}

		internal static AnimalBowString Create(RangedWeapon bow, Transform sourceRoot, Transform displayRoot)
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Expected O, but got Unknown
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)bow == (Object)null || (Object)(object)bow.stringRenderer == (Object)null || (Object)(object)bow.localStringPoint0 == (Object)null || (Object)(object)bow.localStringPoint1 == (Object)null || (Object)(object)bow.localStringPointArrow == (Object)null)
			{
				return null;
			}
			GameObject val = new GameObject("Animal bow string visual");
			try
			{
				val.layer = ((Component)displayRoot).gameObject.layer;
				val.transform.SetParent(displayRoot, false);
				LineRenderer val2 = val.AddComponent<LineRenderer>();
				LineRenderer stringRenderer = bow.stringRenderer;
				((Renderer)val2).sharedMaterials = ((Renderer)stringRenderer).sharedMaterials;
				val2.useWorldSpace = false;
				val2.positionCount = 3;
				val2.loop = false;
				val2.startWidth = stringRenderer.startWidth;
				val2.endWidth = stringRenderer.endWidth;
				val2.startColor = stringRenderer.startColor;
				val2.endColor = stringRenderer.endColor;
				val2.numCapVertices = stringRenderer.numCapVertices;
				val2.numCornerVertices = stringRenderer.numCornerVertices;
				val2.alignment = stringRenderer.alignment;
				val2.textureMode = stringRenderer.textureMode;
				((Renderer)val2).shadowCastingMode = ((Renderer)stringRenderer).shadowCastingMode;
				((Renderer)val2).receiveShadows = ((Renderer)stringRenderer).receiveShadows;
				((Renderer)val2).enabled = false;
				return new AnimalBowString(bow, sourceRoot, val2);
			}
			catch (Exception ex)
			{
				Object.Destroy((Object)(object)val);
				if (!_warned)
				{
					_warned = true;
					Plugin.Logger.LogWarning((object)("Bow string visual unavailable; fox display retained: " + ex.Message));
				}
				return null;
			}
		}

		internal void Tick()
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: 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_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)
			if (!IsValid)
			{
				if ((Object)(object)_copy != (Object)null)
				{
					((Renderer)_copy).enabled = false;
				}
				return;
			}
			_copy.SetPosition(0, _sourceRoot.InverseTransformPoint(_bow.localStringPoint0.position));
			_copy.SetPosition(1, _sourceRoot.InverseTransformPoint(_bow.localStringPointArrow.position));
			_copy.SetPosition(2, _sourceRoot.InverseTransformPoint(_bow.localStringPoint1.position));
			((Renderer)_copy).enabled = ((Renderer)_source).enabled && ((Component)_source).gameObject.activeInHierarchy;
			((Renderer)_copy).forceRenderingOff = false;
			((Renderer)_source).forceRenderingOff = true;
		}

		public void Dispose()
		{
			if ((Object)(object)_source != (Object)null)
			{
				((Renderer)_source).forceRenderingOff = _hidden;
			}
			if ((Object)(object)_copy != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)_copy).gameObject);
			}
		}
	}
	internal sealed class AnimalCarryVisuals
	{
		private sealed class Display
		{
			internal GameObject Source;

			internal GameObject Root;

			internal Transform Parent;

			internal Vector3 Center;

			internal Vector3 SourceScale;

			internal bool Tool;

			internal bool Shield;

			internal bool Bow;

			internal bool BuildHammer;

			internal bool SmithHammer;

			internal bool HarvestTool;

			internal float BuildWeight;

			internal float SmithWeight;

			internal float HarvestWeight;

			internal FoxSoilToolKind SoilKind;

			internal float SoilWeight;

			internal float SoilTilt;

			internal float SoilTwist;

			internal AnimalBowString BowString;

			internal float RetryAfter;

			internal readonly List<(Renderer source, Renderer copy, bool hidden)> Parts = new List<(Renderer, Renderer, bool)>();

			internal readonly List<Mesh> Baked = new List<Mesh>();
		}

		private readonly Dictionary<int, Display> _shown = new Dictionary<int, Display>();

		private readonly Dictionary<int, GameObject> _wanted = new Dictionary<int, GameObject>();

		private readonly HashSet<int> _tools = new HashSet<int>();

		private readonly List<int> _remove = new List<int>();

		private readonly List<ItemPrefabStackSlot> _slots = new List<ItemPrefabStackSlot>();

		private float _nextScan;

		private static bool Same(ItemContainer a, ItemContainer b)
		{
			if (a != null && b != null)
			{
				return ((Il2CppObjectBase)a).Pointer == ((Il2CppObjectBase)b).Pointer;
			}
			return false;
		}

		private static bool Below(Transform child, Transform root)
		{
			if ((Object)(object)child != (Object)null && (Object)(object)root != (Object)null)
			{
				if (!((Object)(object)child == (Object)(object)root))
				{
					return child.IsChildOf(root);
				}
				return true;
			}
			return false;
		}

		private static bool Restricted(ItemContainer container, CharacterInventory inventory, ItemContainerComponent target = null)
		{
			if (container != null)
			{
				if (!Same(container, (inventory != null) ? inventory.RestrictedCarryContainer : null))
				{
					ItemContainerType containerType = container.containerType;
					if (containerType != null)
					{
						CharacterItemContainerType obj = ((Il2CppObjectBase)containerType).TryCast<CharacterItemContainerType>();
						if (((obj != null) ? new bool?(obj.restrictedCarry) : ((bool?)null)) == true)
						{
							goto IL_005f;
						}
					}
					return (Object)(object)((target != null) ? ((Il2CppObjectBase)target).TryCast<CharacterCarrySlot>() : null) != (Object)null;
				}
				goto IL_005f;
			}
			return false;
			IL_005f:
			return true;
		}

		internal bool Contains(GameObject item)
		{
			if ((Object)(object)item != (Object)null)
			{
				return _wanted.ContainsKey(((Object)item).GetInstanceID());
			}
			return false;
		}

		internal bool Owns(Renderer renderer)
		{
			foreach (Display value in _shown.Values)
			{
				if ((Object)(object)value.Source != (Object)null && (Object)(object)renderer != (Object)null && Below(((Component)renderer).transform, value.Source.transform))
				{
					return true;
				}
			}
			return false;
		}

		internal unsafe void Refresh(Character player, GameObject geometry, EquipmentManager equipment, WolfVisual visual, Action<GameObject> exclude, Action<GameObject> releaseVisibility)
		{
			//IL_067b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0680: Unknown result type (might be due to invalid IL or missing references)
			_wanted.Clear();
			_tools.Clear();
			InventoryComponent inventory = player.Inventory;
			CharacterInventory inventory2 = ((inventory != null) ? ((Il2CppObjectBase)inventory).TryCast<CharacterInventory>() : null);
			PlayerCharacter val = ((Il2CppObjectBase)player).TryCast<PlayerCharacter>();
			Villager val2 = ((Il2CppObjectBase)player).TryCast<Villager>();
			PlayerInteractionAgent val3 = (((Object)(object)val == (Object)null) ? null : FoxCoop.Agent(val));
			if ((Object)(object)val2 == (Object)null)
			{
				if (!((Object)(object)val3 == (Object)null))
				{
					PlayerCharacter character = val3.GetCharacter();
					if (((character != null) ? new int?(((Object)character).GetInstanceID()) : ((int?)null)) == ((Object)player).GetInstanceID())
					{
						goto IL_00a4;
					}
				}
				Release(releaseVisibility);
				return;
			}
			goto IL_00a4;
			IL_00a4:
			Transform root = (((Object)(object)val2 != (Object)null) ? val2.GetGrabbingHand() : val3.grabbingHand);
			Transform root2 = (((Object)(object)val2 != (Object)null) ? val2.GetGrabbingOffHand() : val3.grabbingOffHand);
			if (Time.unscaledTime >= _nextScan)
			{
				_nextScan = Time.unscaledTime + 0.5f;
				_slots.Clear();
				HashSet<int> hashSet = new HashSet<int>();
				GameObject[] array = (GameObject[])(object)new GameObject[2]
				{
					((Component)player).gameObject,
					geometry
				};
				foreach (GameObject val4 in array)
				{
					if (!((Object)(object)val4 != (Object)null))
					{
						continue;
					}
					foreach (ItemPrefabStackSlot componentsInChild in val4.GetComponentsInChildren<ItemPrefabStackSlot>(true))
					{
						if (hashSet.Add(((Object)componentsInChild).GetInstanceID()))
						{
							_slots.Add(componentsInChild);
						}
					}
				}
			}
			foreach (ItemPrefabStackSlot slot in _slots)
			{
				if ((Object)(object)slot == (Object)null || slot._instances == null)
				{
					continue;
				}
				bool flag = (Object)(object)val2 != (Object)null && (Below(((ItemDisplaySlot)slot).handle, root) || Below(((ItemDisplaySlot)slot).handle, root2));
				if (!flag && (Object)(object)val2 != (Object)null && ((equipment != null) ? equipment.equipPoints : null) != null && (Object)(object)equipment.pickupHandleId != (Object)null)
				{
					Enumerator<EquipPoint> enumerator3 = equipment.equipPoints.GetEnumerator();
					while (enumerator3.MoveNext())
					{
						EquipPoint current3 = enumerator3.Current;
						if (current3 != null && current3.HasId(equipment.pickupHandleId) && Below(((ItemDisplaySlot)slot).handle, current3.handle))
						{
							flag = true;
							break;
						}
					}
				}
				if (!Restricted(((ItemDisplaySlot)slot)._container, inventory2, ((ItemDisplaySlot)slot).target) && !flag)
				{
					continue;
				}
				Enumerator<DisplayStack> enumerator4 = slot._instances.GetEnumerator();
				while (enumerator4.MoveNext())
				{
					DisplayStack current4 = enumerator4.Current;
					if (((current4 != null) ? current4.item : null) != null && current4.item.count > 0 && Same(current4.item.Container, ((ItemDisplaySlot)slot)._container))
					{
						Want(current4.gameObject);
					}
				}
			}
			if (((equipment != null) ? equipment.equipPoints : null) != null)
			{
				Enumerator<EquipPoint> enumerator3 = equipment.equipPoints.GetEnumerator();
				while (enumerator3.MoveNext())
				{
					EquipPoint current5 = enumerator3.Current;
					EquipmentItem val5 = ((current5 != null) ? current5.GetCurrentItem() : null);
					if (val5 == null || !val5.IsEquipped() || ((Item)val5).count <= 0)
					{
						continue;
					}
					bool flag2 = false;
					List<EquipPoint> activePoints = val5.GetActivePoints();
					if (activePoints != null)
					{
						Enumerator<EquipPoint> enumerator5 = activePoints.GetEnumerator();
						while (enumerator5.MoveNext())
						{
							EquipPoint current6 = enumerator5.Current;
							if (current6 != null && ((Il2CppObjectBase)current6).Pointer == ((Il2CppObjectBase)current5).Pointer)
							{
								flag2 = true;
								break;
							}
						}
					}
					if (!flag2)
					{
						continue;
					}
					GameObject val6 = val5.GetObject();
					bool flag3 = Below(current5.handle, root) || Below(current5.handle, root2) || Below((val6 != null) ? val6.transform.parent : null, root) || Below((val6 != null) ? val6.transform.parent : null, root2);
					if (!flag3 && ((val3 != null) ? val3.lockableEquipmentIds : null) != null)
					{
						Enumerator<EquipHandleId> enumerator6 = val3.lockableEquipmentIds.GetEnumerator();
						while (enumerator6.MoveNext())
						{
							EquipHandleId current7 = enumerator6.Current;
							if (current5.HasId(current7))
							{
								flag3 = true;
								break;
							}
						}
					}
					bool flag4 = Restricted(((Item)val5).Container, inventory2);
					if (flag3 || flag4)
					{
						Want(val6, !flag4);
					}
				}
			}
			_remove.Clear();
			foreach (KeyValuePair<int, Display> item in _shown)
			{
				if (!_wanted.ContainsKey(item.Key) || NeedsRefresh(item.Value, _tools.Contains(item.Key)))
				{
					Dispose(item.Value, releaseVisibility);
					_remove.Add(item.Key);
				}
			}
			foreach (int item2 in _remove)
			{
				_shown.Remove(item2);
			}
			foreach (KeyValuePair<int, GameObject> item3 in _wanted)
			{
				exclude(item3.Value);
				if (!_shown.ContainsKey(item3.Key))
				{
					Display display = Create(item3.Value, visual.Root.transform, _tools.Contains(item3.Key));
					_shown.Add(item3.Key, display);
					ManualLogSource logger = Plugin.Logger;
					string[] obj = new string[12]
					{
						"Animal continuous held display: ",
						((Object)item3.Value).name,
						"; mesh parts=",
						display.Parts.Count.ToString(),
						"; tool=",
						display.Tool.ToString(),
						"; shield=",
						display.Shield.ToString(),
						"; bowString=",
						(display.BowString != null).ToString(),
						"; source scale=",
						null
					};
					Vector3 sourceScale = display.SourceScale;
					obj[11] = ((object)(*(Vector3*)(&sourceScale))/*cast due to .constrained prefix*/).ToString();
					logger.LogInfo((object)string.Concat(obj));
				}
			}
		}

		private static bool ValidScale(Vector3 scale)
		{
			//IL_0000: 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_001a: 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_0039: 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)
			if (float.IsFinite(scale.x) && float.IsFinite(scale.y) && float.IsFinite(scale.z) && Mathf.Abs(scale.x) > 1E-05f && Mathf.Abs(scale.y) > 1E-05f)
			{
				return Mathf.Abs(scale.z) > 1E-05f;
			}
			return false;
		}

		private void Want(GameObject obj, bool tool = false)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)obj == (Object)null) && obj.activeInHierarchy && ValidScale(obj.transform.lossyScale))
			{
				int instanceID = ((Object)obj).GetInstanceID();
				_wanted[instanceID] = obj;
				if (tool)
				{
					_tools.Add(instanceID);
				}
			}
		}

		private static bool NeedsRefresh(Display d, bool tool)
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)d.Source == (Object)null || (Object)(object)d.Root == (Object)null || (Object)(object)d.Source.transform.parent != (Object)(object)d.Parent || d.Tool != tool)
			{
				return true;
			}
			Vector3 val = d.Source.transform.lossyScale - d.SourceScale;
			if (((Vector3)(ref val)).sqrMagnitude > 1E-05f)
			{
				return true;
			}
			if (d.BowString != null && !d.BowString.IsValid)
			{
				return true;
			}
			if (d.Parts.Count == 0)
			{
				return Time.unscaledTime >= d.RetryAfter;
			}
			foreach (var part in d.Parts)
			{
				if ((Object)(object)part.source == (Object)null || (Object)(object)part.copy == (Object)null)
				{
					return true;
				}
			}
			return false;
		}

		private static Display Create(GameObject source, Transform parent, bool tool)
		{
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Expected O, but got Unknown
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_036b: Unknown result type (might be due to invalid IL or missing references)
			//IL_035f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0364: Unknown result type (might be due to invalid IL or missing references)
			//IL_0370: Unknown result type (might be due to invalid IL or missing references)
			//IL_0238: 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)
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Expected O, but got Unknown
			//IL_0387: Unknown result type (might be due to invalid IL or missing references)
			//IL_0391: Unknown result type (might be due to invalid IL or missing references)
			//IL_025f: Unknown result type (might be due to invalid IL or missing references)
			//IL_026c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0276: Unknown result type (might be due to invalid IL or missing references)
			//IL_0283: Unknown result type (might be due to invalid IL or missing references)
			//IL_028d: Unknown result type (might be due to invalid IL or missing references)
			//IL_029a: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_031e: Unknown result type (might be due to invalid IL or missing references)
			//IL_030f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0314: Unknown result type (might be due to invalid IL or missing references)
			RangedWeapon val = (tool ? source.GetComponentInChildren<RangedWeapon>(true) : null);
			Display obj = new Display
			{
				Bow = ((Object)(object)val != (Object)null),
				Source = source,
				Parent = source.transform.parent,
				Tool = tool
			};
			int shield;
			if (tool)
			{
				MeleeObject componentInChildren = source.GetComponentInChildren<MeleeObject>(true);
				shield = ((componentInChildren != null && componentInChildren.isShield) ? 1 : 0);
			}
			else
			{
				shield = 0;
			}
			obj.Shield = (byte)shield != 0;
			obj.SourceScale = source.transform.lossyScale;
			obj.RetryAfter = Time.unscaledTime + 0.25f;
			obj.Root = new GameObject("Animal held visual");
			Display display = obj;
			try
			{
				if (tool && !display.Shield && !display.Bow)
				{
					display.SoilKind = FoxSoilGrip.Classify((Object)(object)source.GetComponentInChildren<HeightmapTool>(true) != (Object)null, ((Object)source).name);
				}
				display.SmithHammer = tool && !display.Shield && !display.Bow && FoxSmithGrip.IsHammer(((Object)source).name);
				display.BuildHammer = tool && !display.Shield && !display.Bow && FoxBuildGrip.IsHammer(((Object)source).name);
				display.HarvestTool = tool && !display.Shield && !display.Bow && FoxHarvestGrip.IsTool(((Object)source).name);
				display.Root.layer = ((Component)parent).gameObject.layer;
				Transform transform = display.Root.transform;
				transform.position = source.transform.position;
				transform.rotation = source.transform.rotation;
				transform.localScale = display.SourceScale;
				bool flag = true;
				Bounds val2 = default(Bounds);
				foreach (Renderer componentsInChild in source.GetComponentsInChildren<Renderer>(true))
				{
					if (tool && !ValidScale(((Component)componentsInChild).transform.lossyScale))
					{
						continue;
					}
					MeshFilter component = ((Component)componentsInChild).GetComponent<MeshFilter>();
					Mesh val3 = ((component != null) ? component.sharedMesh : null);
					SkinnedMeshRenderer val4 = ((Il2CppObjectBase)componentsInChild).TryCast<SkinnedMeshRenderer>();
					if ((Object)(object)val3 == (Object)null && (Object)(object)val4 != (Object)null)
					{
						val3 = new Mesh();
						val4.BakeMesh(val3);
						display.Baked.Add(val3);
					}
					if (!((Object)(object)val3 == (Object)null))
					{
						GameObject val5 = new GameObject(((Object)((Component)componentsInChild).gameObject).name + " mouth visual")
						{
							layer = (tool ? ((Component)parent).gameObject.layer : ((Component)componentsInChild).gameObject.layer)
						};
						val5.transform.position = ((Component)componentsInChild).transform.position;
						val5.transform.rotation = ((Component)componentsInChild).transform.rotation;
						val5.transform.localScale = ((Component)componentsInChild).transform.lossyScale;
						val5.transform.SetParent(transform, true);
						val5.AddComponent<MeshFilter>().sharedMesh = val3;
						MeshRenderer val6 = val5.AddComponent<MeshRenderer>();
						((Renderer)val6).sharedMaterials = componentsInChild.sharedMaterials;
						((Renderer)val6).shadowCastingMode = componentsInChild.shadowCastingMode;
						((Renderer)val6).receiveShadows = componentsInChild.receiveShadows;
						display.Parts.Add((componentsInChild, (Renderer)(object)val6, componentsInChild.forceRenderingOff));
						if (flag)
						{
							val2 = ((Renderer)val6).bounds;
							flag = false;
						}
						else
						{
							((Bounds)(ref val2)).Encapsulate(((Renderer)val6).bounds);
						}
					}
				}
				if (tool)
				{
					display.BowString = AnimalBowString.Create(val, source.transform, transform);
				}
				display.Center = (flag ? Vector3.zero : transform.InverseTransformPoint(((Bounds)(ref val2)).center));
				transform.SetParent(parent, true);
				if (display.Shield)
				{
					transform.localScale *= 0.65f;
				}
				return display;
			}
			catch
			{
				Dispose(display, null);
				throw;
			}
		}

		internal void Place(WolfVisual visual)
		{
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: 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_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01de: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0237: Unknown result type (might be due to invalid IL or missing references)
			//IL_024e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0253: Unknown result type (might be due to invalid IL or missing references)
			//IL_0258: Unknown result type (might be due to invalid IL or missing references)
			//IL_025a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0274: Unknown result type (might be due to invalid IL or missing references)
			//IL_027f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0284: 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_02bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02db: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0303: Unknown result type (might be due to invalid IL or missing references)
			//IL_0308: Unknown result type (might be due to invalid IL or missing references)
			//IL_0386: Unknown result type (might be due to invalid IL or missing references)
			//IL_0398: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_03aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_03af: Unknown result type (might be due to invalid IL or missing references)
			//IL_0359: Unknown result type (might be due to invalid IL or missing references)
			//IL_0370: Unknown result type (might be due to invalid IL or missing references)
			//IL_0375: Unknown result type (might be due to invalid IL or missing references)
			//IL_037a: Unknown result type (might be due to invalid IL or missing references)
			foreach (Display value in _shown.Values)
			{
				Transform val = ((!value.Shield) ? visual?.ItemSocket(working: false) : visual?.ShieldSide);
				if ((Object)(object)value.Root == (Object)null || (Object)(object)value.Source == (Object)null || (Object)(object)val == (Object)null)
				{
					continue;
				}
				Quaternion val2 = val.rotation * (value.Shield ? Quaternion.Euler(0f, 0f, 90f) : (value.Bow ? Quaternion.Euler(0f, 90f, -90f) : Quaternion.Euler(0f, (float)(value.Tool ? 90 : 180), 0f)));
				Vector3 val3 = value.Center;
				if (value.SoilKind != FoxSoilToolKind.None)
				{
					FoxSoilGripPose foxSoilGripPose = FoxSoilGrip.Read(value.SoilKind, visual.ClipName, visual.PlaybackTime, visual.Length(visual.ClipName));
					float num = Mathf.Max(0f, Time.deltaTime);
					value.SoilWeight = Mathf.MoveTowards(value.SoilWeight, foxSoilGripPose.Weight, num * 12f);
					value.SoilTilt = Mathf.MoveTowards(value.SoilTilt, foxSoilGripPose.Tilt, num * 720f);
					value.SoilTwist = Mathf.MoveTowards(value.SoilTwist, foxSoilGripPose.Twist, num * 1080f);
					val2 *= Quaternion.Euler(value.SoilTilt, 0f, 0f) * Quaternion.Euler(0f, 0f, value.SoilTwist);
					val3 = Vector3.Lerp(value.Center, new Vector3(0f, 0f, value.Center.z), value.SoilWeight);
				}
				if (value.BuildHammer)
				{
					float num2 = FoxBuildGrip.Weight(visual.ClipName, visual.PlaybackTime, visual.Length(visual.ClipName));
					value.BuildWeight = Mathf.MoveTowards(value.BuildWeight, num2, Mathf.Max(0f, Time.deltaTime) * 24f);
					val2 *= Quaternion.Euler(0f, 0f, 90f * value.BuildWeight);
					val3 = Vector3.Lerp(value.Center, new Vector3(0f, 0f, value.Center.z), value.BuildWeight);
				}
				if (value.SmithHammer)
				{
					value.SmithWeight = Mathf.MoveTowards(value.SmithWeight, FoxSmithGrip.Weight(visual.ClipName), Mathf.Max(0f, Time.deltaTime) * 24f);
					val2 *= Quaternion.Euler(0f, 0f, 90f * value.SmithWeight);
					val3 = Vector3.Lerp(val3, new Vector3(0f, 0f, value.Center.z), value.SmithWeight);
				}
				if (value.HarvestTool)
				{
					float num3 = FoxHarvestGrip.Weight(visual.ClipName, visual.PlaybackTime, visual.Length(visual.ClipName));
					value.HarvestWeight = Mathf.MoveTowards(value.HarvestWeight, num3, Mathf.Max(0f, Time.deltaTime) * 24f);
					val2 *= Quaternion.Euler(0f, 0f, 26f * value.HarvestWeight);
				}
				value.Root.transform.rotation = val2;
				value.Root.transform.position = val.position - value.Root.transform.TransformVector(val3);
				value.BowString?.Tick();
				foreach (var part in value.Parts)
				{
					if ((Object)(object)part.source != (Object)null && (Object)(object)part.copy != (Object)null)
					{
						part.copy.enabled = value.Tool || (part.source.enabled && ((Component)part.source).gameObject.activeInHierarchy);
						part.copy.forceRenderingOff = false;
						part.source.forceRenderingOff = true;
					}
				}
			}
		}

		private static void Dispose(Display d, Action<GameObject> releaseVisibility)
		{
			d.BowString?.Dispose();
			if ((Object)(object)d.Source != (Object)null)
			{
				foreach (var part in d.Parts)
				{
					if ((Object)(object)part.source != (Object)null)
					{
						part.source.forceRenderingOff = part.hidden;
					}
				}
				releaseVisibility?.Invoke(d.Source);
			}
			if ((Object)(object)d.Root != (Object)null)
			{
				Object.Destroy((Object)(object)d.Root);
			}
			foreach (Mesh item in d.Baked)
			{
				if ((Object)(object)item != (Object)null)
				{
					Object.Destroy((Object)(object)item);
				}
			}
		}

		internal void Release(Action<GameObject> releaseVisibility)
		{
			foreach (Display value in _shown.Values)
			{
				Dispose(value, releaseVisibility);
			}
			_shown.Clear();
			_wanted.Clear();
			_tools.Clear();
			_slots.Clear();
			_nextScan = 0f;
		}
	}
	internal sealed class AnimalHeldItem
	{
		private GameObject _item;

		private Transform _parent;

		private Vector3 _localPosition;

		private Vector3 _center;

		private Quaternion _localRotation;

		private readonly List<(Renderer renderer, bool hidden)> _renderers = new List<(Renderer, bool)>();

		internal bool Owns(Renderer renderer)
		{
			if ((Object)(object)_item != (Object)null && (Object)(object)renderer != (Object)null)
			{
				if (!((Object)(object)((Component)renderer).gameObject == (Object)(object)_item))
				{
					return ((Component)renderer).transform.IsChildOf(_item.transform);
				}
				return true;
			}
			return false;
		}

		internal bool Observe(GameObject item)
		{
			//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_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_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: 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_00d2: 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_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_item == (Object)(object)item)
			{
				return false;
			}
			Release();
			if ((Object)(object)item == (Object)null)
			{
				return false;
			}
			_item = item;
			Transform transform = item.transform;
			_parent = transform.parent;
			_localPosition = transform.localPosition;
			_localRotation = transform.localRotation;
			bool flag = true;
			Bounds val = default(Bounds);
			foreach (Renderer componentsInChild in item.GetComponentsInChildren<Renderer>(true))
			{
				_renderers.Add((componentsInChild, componentsInChild.forceRenderingOff));
				if (flag)
				{
					val = componentsInChild.bounds;
					flag = false;
				}
				else
				{
					((Bounds)(ref val)).Encapsulate(componentsInChild.bounds);
				}
			}
			_center = (flag ? Vector3.zero : transform.InverseTransformPoint(((Bounds)(ref val)).center));
			Plugin.Logger.LogInfo((object)("Animal temporary item attached: " + ((Object)item).name));
			return true;
		}

		internal void Place(Transform socket, float yaw = 90f)
		{
			//IL_004b: 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_006c: 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_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_item == (Object)null || (Object)(object)socket == (Object)null)
			{
				return;
			}
			if ((Object)(object)_item.transform.parent != (Object)(object)_parent)
			{
				Release();
				return;
			}
			Transform transform = _item.transform;
			transform.rotation = socket.rotation * Quaternion.Euler(0f, yaw, 0f);
			transform.position = socket.position - transform.TransformVector(_center);
			foreach (var renderer in _renderers)
			{
				if ((Object)(object)renderer.renderer != (Object)null)
				{
					renderer.renderer.forceRenderingOff = false;
				}
			}
		}

		internal void Release(bool hide = false)
		{
			//IL_003c: 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)
			bool flag = (Object)(object)_item != (Object)null && (Object)(object)_item.transform.parent == (Object)(object)_parent;
			if (flag)
			{
				_item.transform.localPosition = _localPosition;
				_item.transform.localRotation = _localRotation;
			}
			foreach (var renderer in _renderers)
			{
				if (flag && (Object)(object)renderer.renderer != (Object)null)
				{
					renderer.renderer.forceRenderingOff = hide || renderer.hidden;
				}
			}
			_renderers.Clear();
			_item = null;
			_parent = null;
		}
	}
	[HarmonyPatch]
	internal static class AnimalHandSpawnHook
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			return from m in AccessTools.GetDeclaredMethods(typeof(ItemInfo))
				where m.Name == "SpawnObject"
				select m;
		}

		private static void Postfix(GameObject __result, Transform parent)
		{
			try
			{
				if ((Object)(object)__result != (Object)null && (Object)(object)parent != (Object)null)
				{
					Plugin.Behaviour?.SpawnedHandProp(__result, parent);
				}
			}
			catch (Exception ex)
			{
				Plugin.Logger.LogWarning((object)("Animal hand prop skipped: " + ex.Message));
			}
		}
	}
	[HarmonyPatch(typeof(CraftInteractionDisplay), "BeginCraftingSequence")]
	internal static class AnimalCraftDisplayHook
	{
		private static void Postfix(CraftInteractionDisplay __instance, InteractionSession interactionSession)
		{
			try
			{
				Plugin.Behaviour?.CraftProps(__instance, interactionSession);
			}
			catch (Exception ex)
			{
				Plugin.Logger.LogWarning((object)("Animal craft props skipped: " + ex.Message));
			}
		}
	}
	[HarmonyPatch(typeof(EquipmentStackSlot), "_SetupInstance")]
	internal static class AnimalStackDisplayHook
	{
		private static void Postfix(DisplayStack displayStack)
		{
			try
			{
				EquipmentStack val = ((displayStack != null) ? ((Il2CppObjectBase)displayStack).TryCast<EquipmentStack>() : null);
				if (val != null)
				{
					Item item = ((DisplayStack)val).item;
					if (((item != null) ? ((Il2CppObjectBase)item).TryCast<EquipmentItem>() : null) == null)
					{
						Plugin.Behaviour?.StackProp(val._eqManager, ((DisplayStack)val).gameObject);
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Logger.LogWarning((object)("Animal stack prop skipped: " + ex.Message));
			}
		}
	}
	[HarmonyPatch(typeof(ItemPrefabStackSlot), "_SetupInstance")]
	internal static class AnimalResourceDisplayHook
	{
		private static void Postfix(ItemPrefabStackSlot __instance, DisplayStack displayStack)
		{
			try
			{
				if (displayStack != null)
				{
					Item item = displayStack.item;
					if (((item != null) ? ((Il2CppObjectBase)item).TryCast<EquipmentItem>() : null) == null)
					{
						Plugin.Behaviour?.SlotProp(__instance, displayStack.gameObject);
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Logger.LogWarning((object)("Animal resource prop skipped: " + ex.Message));
			}
		}
	}
	[HarmonyPatch(typeof(GatherInteraction), "GatherItemsCharge")]
	internal static class FoxQuickGatherHook
	{
		private static void Postfix(IInteractionAgent interactionAgent, int __result)
		{
			try
			{
				if (__result > 0 && (Input.GetKey((KeyCode)304) || Input.GetKey((KeyCode)303)))
				{
					object obj;
					if (interactionAgent == null)
					{
						obj = null;
					}
					else
					{
						PlayerInteractionAgent obj2 = ((Il2CppObjectBase)interactionAgent).TryCast<PlayerInteractionAgent>();
						obj = ((obj2 != null) ? obj2.GetCharacter() : null);
					}
					PlayerCharacter val = (PlayerCharacter)obj;
					if ((Object)(object)val != (Object)null)
					{
						Plugin.Behaviour?.QuickPickup(((Component)val).gameObject);
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Logger.LogWarning((object)("Fox quick gather skipped: " + ex.Message));
			}
		}
	}
	[HarmonyPatch]
	internal static class FoxTakeItemsHook
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			return from m in AccessTools.GetDeclaredMethods(typeof(CharacterInventory))
				where m.Name == "TakeItems"
				select m;
		}

		private static void Postfix(CharacterInventory __instance, int __result)
		{
			try
			{
				if (__result > 0)
				{
					Character character = __instance.character;
					PlayerCharacter val = ((character != null) ? ((Il2CppObjectBase)character).TryCast<PlayerCharacter>() : null);
					if ((Object)(object)val != (Object)null)
					{
						Plugin.Behaviour?.QuickPickup(((Component)val).gameObject);
					}
					Character character2 = __instance.character;
					FoxVillagers.Action((character2 != null) ? ((Il2CppObjectBase)character2).TryCast<Villager>() : null, "fox_pickup");
				}
			}
			catch (Exception ex)
			{
				Plugin.Logger.LogWarning((object)("Fox take-items animation skipped: " + ex.Message));
			}
		}
	}
	internal enum AnimalPropKind
	{
		Pickup,
		Craft
	}
	internal sealed class AnimalPropLifetime
	{
		internal const float PickupSeconds = 1f;

		private float _expires;

		internal AnimalPropKind Kind { get; private set; }

		internal AnimalPropLifetime(AnimalPropKind kind, float now)
		{
			Kind = kind;
			_expires = now + ((kind == AnimalPropKind.Pickup) ? 1f : 0.25f);
		}

		internal void Observe(AnimalPropKind kind, float now)
		{
			if (kind == AnimalPropKind.Craft)
			{
				Kind = kind;
				_expires = now + 0.25f;
			}
		}

		internal bool Expired(float now)
		{
			return now >= _expires;
		}
	}
	internal sealed class AnimalPropSet
	{
		private sealed class Entry
		{
			internal GameObject Item;

			internal Transform Parent;

			internal AnimalPropLifetime Lifetime;

			internal AnimalHeldItem Binding = new AnimalHeldItem();
		}

		private readonly Dictionary<int, Entry> _items = new Dictionary<int, Entry>();

		private readonly List<int> _expired = new List<int>();

		private readonly Dictionary<int, GameObject> _retired = new Dictionary<int, GameObject>();

		internal bool IsRetired(GameObject item)
		{
			if ((Object)(object)item != (Object)null && _retired.TryGetValue(((Object)item).GetInstanceID(), out var value))
			{
				return (Object)(object)value == (Object)(object)item;
			}
			return false;
		}

		internal void Add(GameObject item, AnimalPropKind kind)
		{
			if ((Object)(object)item == (Object)null)
			{
				return;
			}
			int instanceID = ((Object)item).GetInstanceID();
			if (!_retired.TryGetValue(instanceID, out var value) || !((Object)(object)value == (Object)(object)item) || kind != AnimalPropKind.Pickup)
			{
				if (_items.TryGetValue(instanceID, out var value2))
				{
					value2.Lifetime.Observe(kind, Time.time);
					return;
				}
				Entry entry = new Entry
				{
					Item = item,
					Parent = item.transform.parent,
					Lifetime = new AnimalPropLifetime(kind, Time.time)
				};
				entry.Binding.Observe(item);
				_items[instanceID] = entry;
			}
		}

		internal bool Owns(Renderer renderer)
		{
			foreach (Entry value in _items.Values)
			{
				if (value.Binding.Owns(renderer))
				{
					return true;
				}
			}
			return false;
		}

		internal void Exclude(GameObject item)
		{
			if (!((Object)(object)item == (Object)null))
			{
				int instanceID = ((Object)item).GetInstanceID();
				if (_items.TryGetValue(instanceID, out var value))
				{
					value.Binding.Release();
					_items.Remove(instanceID);
				}
				_retired[instanceID] = item;
			}
		}

		internal void Place(WolfVisual visual, bool working)
		{
			_expired.Clear();
			foreach (KeyValuePair<int, Entry> item in _items)
			{
				Entry value = item.Value;
				if ((Object)(object)value.Item == (Object)null || !value.Item.activeInHierarchy || (Object)(object)value.Item.transform.parent != (Object)(object)value.Parent || value.Lifetime.Expired(Time.time))
				{
					if ((Object)(object)value.Item != (Object)null)
					{
						_retired[item.Key] = value.Item;
					}
					value.Binding.Release(Plugin.HideEquipment.Value);
					_expired.Add(item.Key);
				}
				else
				{
					bool flag = value.Lifetime.Kind == AnimalPropKind.Craft && working;
					value.Binding.Place(visual.ItemSocket(flag), flag ? 90 : 180);
				}
			}
			foreach (int item2 in _expired)
			{
				_items.Remove(item2);
			}
			_expired.Clear();
			foreach (KeyValuePair<int, GameObject> item3 in _retired)
			{
				if ((Object)(object)item3.Value == (Object)null)
				{
					_expired.Add(item3.Key);
				}
			}
			foreach (int item4 in _expired)
			{
				_retired.Remove(item4);
			}
		}

		internal void Release()
		{
			foreach (Entry value in _items.Values)
			{
				value.Binding.Release();
			}
			_items.Clear();
			_retired.Clear();
		}
	}
	internal static class FoxActionMapping
	{
		private static readonly HashSet<string> WorkActions = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "Gather", "GatherLow", "GatherMiddle", "GatherHigh", "Harvest", "Carpentry", "Grinding", "Cooking", "Forge", "Painting" };

		internal static string Action(string name)
		{
			if (string.IsNullOrWhiteSpace(name))
			{
				return null;
			}
			string text = name.Trim().TrimStart('_').Replace(" ", "")
				.Replace("_", "");
			if (text.StartsWith("Pickup", StringComparison.OrdinalIgnoreCase))
			{
				return "fox_pickup";
			}
			if (text.Equals("Chop", StringComparison.OrdinalIgnoreCase))
			{
				return "fox_chop_side";
			}
			if (text.Equals("ChopGround", StringComparison.OrdinalIgnoreCase))
			{
				return "fox_chop_down";
			}
			if (text.Equals("Shovel", StringComparison.OrdinalIgnoreCase) || text.Equals("Till", StringComparison.OrdinalIgnoreCase))
			{
				return "fox_soil_rake";
			}
			if (text.Equals("Build", StringComparison.OrdinalIgnoreCase) || text.Equals("Repair", StringComparison.OrdinalIgnoreCase))
			{
				return "fox_build_strike";
			}
			if (text.Equals("Skinning", StringComparison.OrdinalIgnoreCase))
			{
				return "fox_skin_pull";
			}
			if (text.Equals("Craft", StringComparison.OrdinalIgnoreCase))
			{
				return "fox_craft_work";
			}
			if (text.Equals("Anvil", StringComparison.OrdinalIgnoreCase))
			{
				return "fox_anvil_tap";
			}
			if (text.StartsWith("Bellows", StringComparison.OrdinalIgnoreCase))
			{
				return "fox_bellows_up";
			}
			if (!WorkActions.Contains(text))
			{
				return null;
			}
			return "fox_dig";
		}

		internal static bool ImpactHarvest(string moveset)
		{
			return !(moveset?.Contains("Skinning", StringComparison.OrdinalIgnoreCase) ?? false);
		}
	}
	internal sealed class FoxAnvilPlacement
	{
		private static AnvilInteraction[] _stations = Array.Empty<AnvilInteraction>();

		private static float _nextScan;

		private AnvilInteraction _station;

		private bool _active;

		private Vector3 _offset;

		private float _blend;

		private float _retry;

		internal void Apply(Transform root, string clip, float dt)
		{
			//IL_0161: 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_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_00cd: 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_00dd: 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_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			bool flag = ((clip == "fox_anvil_tap" || clip == "fox_anvil_idle") ? true : false);
			bool flag2 = flag;
			if (flag2 && (!_active || ((Object)(object)_station == (Object)null && Time.unscaledTime >= _retry)))
			{
				Resolve(root);
				_retry = Time.unscaledTime + 0.75f;
			}
			_active = flag2;
			bool flag3 = flag2 && (Object)(object)_station != (Object)null && ((Behaviour)_station).isActiveAndEnabled && (Object)(object)_station.hitFxPos != (Object)null;
			float num = (flag3 ? Approach(_station) : 0f);
			flag3 = flag3 && num > 0f;
			if (flag3)
			{
				Vector3 val = _station.hitFxPos.position - root.parent.position;
				val.y = 0f;
				float magnitude = ((Vector3)(ref val)).magnitude;
				flag3 = magnitude > 0.35f && magnitude < 1.5f;
				if (flag3)
				{
					float num2 = Mathf.Min(num, magnitude - 0.35f);
					_offset = val / magnitude * num2;
				}
			}
			_blend = Mathf.MoveTowards(_blend, (float)(flag3 ? 1 : 0), Mathf.Max(0f, dt) * 8f);
			root.position += _offset * _blend;
			if (_blend == 0f)
			{
				_offset = Vector3.zero;
				_station = null;
			}
		}

		private static float Approach(AnvilInteraction station)
		{
			ItemContainerComponent bloomBlockContainer = station.bloomBlockContainer;
			string text = ((bloomBlockContainer != null) ? ((Object)((Component)bloomBlockContainer).gameObject).name : null);
			if (!(text == "bloomBlockStorageAnvil"))
			{
				if (text == "anvilContainer")
				{
					return 0.3f;
				}
				return 0f;
			}
			return 0.3f;
		}

		private void Resolve(Transform root)
		{
			//IL_0098: 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_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			_station = null;
			if (Time.unscaledTime >= _nextScan)
			{
				Il2CppArrayBase<AnvilInteraction> val = Object.FindObjectsOfType<AnvilInteraction>();
				_stations = (AnvilInteraction[])(object)new AnvilInteraction[val.Length];
				for (int i = 0; i < val.Length; i++)
				{
					_stations[i] = val[i];
				}
				_nextScan = Time.unscaledTime + 5f;
			}
			float num = 2.25f;
			AnvilInteraction[] stations = _stations;
			foreach (AnvilInteraction val2 in stations)
			{
				if (!((Object)(object)val2 == (Object)null) && ((Behaviour)val2).isActiveAndEnabled && !((Object)(object)val2.hitFxPos == (Object)null))
				{
					Vector3 val3 = val2.hitFxPos.position - root.parent.position;
					val3.y = 0f;
					float sqrMagnitude = ((Vector3)(ref val3)).sqrMagnitude;
					if (!(sqrMagnitude >= num))
					{
						num = sqrMagnitude;
						_station = val2;
					}
				}
			}
		}
	}
	internal sealed class FoxBellowsPlacement
	{
		private static BellowsInteraction[] _stations = Array.Empty<BellowsInteraction>();

		private static float _nextScan;

		private BellowsInteraction _station;

		private Transform _board;

		private bool _tier2;

		private bool _active;

		private Vector3 _offset;

		private float _blend;

		private float _retry;

		internal void Apply(Transform root, string clip, float dt)
		{
			//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01db: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: 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)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: 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_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_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: 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_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01af: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			bool flag = FoxSmithAnimation.IsBellows(clip);
			if (flag && (!_active || (((Object)(object)_station == (Object)null || (Object)(object)_board == (Object)null) && Time.unscaledTime >= _retry)))
			{
				Resolve(root);
				_retry = Time.unscaledTime + 0.75f;
			}
			_active = flag;
			Vector3 val;
			int num;
			if (flag && (Object)(object)_station != (Object)null && (Object)(object)_station.matchTargetPos != (Object)null && (Object)(object)_board != (Object)null)
			{
				val = _station.matchTargetPos.position - root.parent.position;
				num = ((((Vector3)(ref val)).sqrMagnitude < 9f) ? 1 : 0);
			}
			else
			{
				num = 0;
			}
			bool flag2 = (byte)num != 0;
			_blend = Mathf.MoveTowards(_blend, (float)(flag2 ? 1 : 0), Mathf.Max(0f, dt) * 8f);
			if (flag2)
			{
				Vector3 val2 = (_tier2 ? new Vector3(-0.01f, 1.68f, 0.56f) : new Vector3(0.01f, 1.02f, 0.39f));
				val = _board.TransformDirection(new Vector3(0f, -0.31f, 1f));
				Vector3 normalized = ((Vector3)(ref val)).normalized;
				val = _board.TransformDirection(new Vector3(0f, -1f, -0.31f));
				Vector3 normalized2 = ((Vector3)(ref val)).normalized;
				Vector3 val3 = _board.TransformPoint(val2) + normalized * Plugin.HeightOffset.Value;
				_offset = val3 - root.position;
				root.rotation = Quaternion.Slerp(root.rotation, Quaternion.LookRotation(normalized2, normalized), _blend);
			}
			root.position += _offset * _blend;
			if (_blend == 0f)
			{
				_offset = Vector3.zero;
				_station = null;
				_board = null;
			}
		}

		private void Resolve(Transform root)
		{
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			_station = null;
			_board = null;
			if (Time.unscaledTime >= _nextScan)
			{
				Il2CppArrayBase<BellowsInteraction> val = Object.FindObjectsOfType<BellowsInteraction>();
				_stations = (BellowsInteraction[])(object)new BellowsInteraction[val.Length];
				for (int i = 0; i < val.Length; i++)
				{
					_stations[i] = val[i];
				}
				_nextScan = Time.unscaledTime + 5f;
			}
			float num = 9f;
			BellowsInteraction[] stations = _stations;
			foreach (BellowsInteraction val2 in stations)
			{
				if ((Object)(object)val2 == (Object)null || !((Behaviour)val2).isActiveAndEnabled || (Object)(object)val2.matchTargetPos == (Object)null || (Object)(object)val2.bellowsAnimator == (Object)null)
				{
					continue;
				}
				Vector3 val3 = val2.matchTargetPos.position - root.parent.position;
				float sqrMagnitude = ((Vector3)(ref val3)).sqrMagnitude;
				if (!(sqrMagnitude >= num))
				{
					Transform val4 = ((Component)val2.bellowsAnimator).transform.Find("b_bellows_down/b_bellows_arm");
					if (!((Object)(object)val4 == (Object)null))
					{
						num = sqrMagnitude;
						_station = val2;
						_board = val4;
						_tier2 = ((Object)((Component)val2.bellowsAnimator).gameObject).name.Contains("t2");
					}
				}
			}
		}
	}
	internal static class FoxBuildAnimation
	{
		internal const string State = "Actions.Build";

		internal const string Clip = "fox_build_strike";

		internal const float ContactPhase = 0.22f;

		internal const float PlayerContact = 0.17844622f;

		internal const float RagnarContact = 0.18667318f;

		internal const float VillagerContact = 0.15012468f;

		internal static bool IsBuild(string clip)
		{
			return clip == "fox_build_strike";
		}

		internal static bool Read(int state, int buildState, float time, bool loop, bool villager, bool alternate, out string clip, out float phase)
		{
			clip = null;
			phase = 0f;
			if (state != buildState || !float.IsFinite(time) || time < 0f)
			{
				return false;
			}
			float num = (loop ? (time - MathF.Floor(time)) : Math.Clamp(time, 0f, 1f));
			float num2 = (villager ? 0.15012468f : (alternate ? 0.18667318f : 0.17844622f));
			phase = ((num <= num2) ? (num / num2 * 0.22f) : (0.22f + (num - num2) / (1f - num2) * 0.78f));
			clip = "fox_build_strike";
			return true;
		}
	}
	internal static class FoxBuildGrip
	{
		internal static bool IsHammer(string name)
		{
			if (name != null)
			{
				if (!name.Equals("1HBuildHammer", StringComparison.OrdinalIgnoreCase) && !name.Equals("1HBuildIronHammer", StringComparison.OrdinalIgnoreCase) && !name.Equals("1HBuildWoodHammer1", StringComparison.OrdinalIgnoreCase) && !name.Equals("1HBuildHammer(Clone)", StringComparison.OrdinalIgnoreCase) && !name.Equals("1HBuildIronHammer(Clone)", StringComparison.OrdinalIgnoreCase))
				{
					return name.Equals("1HBuildWoodHammer1(Clone)", StringComparison.OrdinalIgnoreCase);
				}
				return true;
			}
			return false;
		}

		internal static float Weight(string clip, float time, float duration)
		{
			if (!FoxBuildAnimation.IsBuild(clip) || !float.IsFinite(time) || !float.IsFinite(duration) || duration <= 0f)
			{
				return 0f;
			}
			float num = Math.Clamp(time / duration, 0f, 1f);
			float num2 = ((num < 0.015f) ? 0f : ((num < 0.08f) ? ((num - 0.015f) / 0.065f) : ((num <= 0.36f) ? 1f : ((num < 0.88f) ? ((0.88f - num) / 0.52f) : 0f))));
			return num2 * num2 * (3f - 2f * num2);
		}
	}
	internal static class FoxCamera
	{
		[HarmonyPatch(typeof(InputManager), "UpdateCamera")]
		private static class UpdateCamera
		{
			private static void Postfix(InputManager __instance)
			{
				try
				{
					Refresh(__instance);
				}
				catch (Exception ex)
				{
					Reset();
					Plugin.Logger.LogWarning((object)("Fox camera offset skipped: " + ex.Message));
				}
			}
		}

		private static readonly Dictionary<int, (Cinemachine3rdPersonFollow follow, Vector3 original)> Saved = new Dictionary<int, (Cinemachine3rdPersonFollow, Vector3)>();

		private static InputManager _manager;

		private static void Apply(CameraObject camera)
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			Cinemachine3rdPersonFollow val = ((camera != null) ? camera.baseComp : null);
			if (!((Object)(object)val == (Object)null))
			{
				int instanceID = ((Object)val).GetInstanceID();
				if (!Saved.TryGetValue(instanceID, out (Cinemachine3rdPersonFollow, Vector3) value) || (Object)(object)value.Item1 != (Object)(object)val)
				{
					value = (Saved[instanceID] = (val, val.ShoulderOffset));
				}
				Vector3 item = value.Item2;
				item.y += Plugin.CameraHeightOffset.Value;
				val.ShoulderOffset = item;
			}
		}

		internal static void Reset()
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			foreach (var value in Saved.Values)
			{
				if ((Object)(object)value.follow != (Object)null)
				{
					value.follow.ShoulderOffset = value.original;
				}
			}
			Saved.Clear();
			_manager = null;
		}

		private static void Refresh(InputManager manager)
		{
			if ((Object)(object)_manager != (Object)(object)manager)
			{
				Reset();
			}
			_manager = manager;
			if (Plugin.Behaviour?.LocalCameraVisual == null || Plugin.CameraHeightOffset.Value == 0f)
			{
				Reset();
				return;
			}
			Apply(manager.normalCamera);
			Apply(manager.aimCamera);
			Apply(manager.climbingCamera);
			Apply(manager.lockCamera);
			Apply(manager.buildCamera);
			Apply(manager.insideBuildingCamera);
			Apply(manager.caveCamera);
		}
	}
	internal static class FoxCarpentryContext
	{
		private static readonly Dictionary<int, (Transform Actor, InteractionSession Session, CarpenterInteraction Station)> Running = new Dictionary<int, (Transform, InteractionSession, CarpenterInteraction)>();

		private static bool _warned;

		internal static void Start(CarpenterInteraction station, InteractionSession session)
		{
			try
			{
				object obj;
				if (session == null)
				{
					obj = null;
				}
				else
				{
					IInteractionAgent agent = session.Agent;
					obj = ((agent != null) ? agent.GetTransform() : null);
				}
				Transform val = (Transform)obj;
				if (!((Object)(object)val == (Object)null) && !((Object)(object)station == (Object)null))
				{
					if (Running.Count > 256)
					{
						Running.Clear();
					}
					Running[((Object)val).GetInstanceID()] = (val, session, station);
				}
			}
			catch (Exception ex)
			{
				Warn(ex);
			}
		}

		internal static void End(InteractionSession session)
		{
			try
			{
				object obj;
				if (session == null)
				{
					obj = null;
				}
				else
				{
					IInteractionAgent agent = session.Agent;
					obj = ((agent != null) ? agent.GetTransform() : null);
				}
				Transform val = (Transform)obj;
				if ((Object)(object)val != (Object)null && Running.TryGetValue(((Object)val).GetInstanceID(), out (Transform, InteractionSession, CarpenterInteraction) value) && value.Item2 == session)
				{
					Running.Remove(((Object)val).GetInstanceID());
				}
			}
			catch (Exception ex)
			{
				Warn(ex);
			}
		}

		internal static CarpenterInteraction For(Transform root)
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Invalid comparison between Unknown and I4
			if ((Object)(object)root == (Object)null)
			{
				return null;
			}
			foreach (var value in Running.Values)
			{
				if (!((Object)(object)value.Actor == (Object)null) && !((Object)(object)value.Station == (Object)null) && value.Session != null && (int)value.Session.SessionState == 2 && !((Object)(object)value.Session.Interaction != (Object)(object)value.Station) && ((Object)(object)root == (Object)(object)value.Actor || root.IsChildOf(value.Actor)))
				{
					return value.Station;
				}
			}
			return null;
		}

		private static void Warn(Exception ex)
		{
			if (!_warned)
			{
				_warned = true;
				Plugin.Logger.LogWarning((object)("Fox carpentry session tracking skipped: " + ex.Message));
			}
		}
	}
	[HarmonyPatch(typeof(CarpenterInteraction), "_OnStartSession")]
	internal static class FoxCarpentryStartHook
	{
		private static void Postfix(CarpenterInteraction __instance, InteractionSession __0)
		{
			FoxCarpentryContext.Start(__instance, __0);
		}
	}
	[HarmonyPatch(typeof(CarpenterInteraction), "_OnFinishSession")]
	internal static class FoxCarpentryEndHook
	{
		private static void Prefix(InteractionSession __0)
		{
			FoxCarpentryContext.End(__0);
		}
	}
	internal sealed class FoxCarpentryPlacement
	{
		private static CarpenterInteraction[] _stations = Array.Empty<CarpenterInteraction>();

		private static float _nextScan;

		private static int _traced;

		private CarpenterInteraction _station;

		private CarpentryDisplay _display;

		private Side _side;

		private bool _active;

		private float _blend;

		private float _retry;

		private float _surfaceAboveAnchor;

		private static int _failedTraces;

		private Vector3 _offset;

		private static bool IsCarpentry(string clip)
		{
			switch (clip)
			{
			case "fox_carpentry_idle":
			case "fox_carpentry_draw":
			case "fox_carpentry_rotate":
				return true;
			default:
				return false;
			}
		}

		internal void Apply(Transform root, string clip, float dt)
		{
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0203: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: 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_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0361: Unknown result type (might be due to invalid IL or missing references)
			//IL_0366: Unknown result type (might be due to invalid IL or missing references)
			//IL_0236: Unknown result type (might be due to invalid IL or missing references)
			//IL_023d: Expected O, but got Unknown
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: 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_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: 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_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0258: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: 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)
			//IL_0303: Unknown result type (might be due to invalid IL or missing references)
			//IL_0321: Unknown result type (might be due to invalid IL or missing references)
			bool flag = IsCarpentry(clip);
			if (flag && (!_active || Time.unscaledTime >= _retry))
			{
				Resolve(root);
				_retry = Time.unscaledTime + 0.75f;
			}
			_active = flag;
			bool flag2 = flag && (Object)(object)_station != (Object)null && ((Component)_station).gameObject.activeInHierarchy && _display != null && (Object)(object)_display.rootObject != (Object)null && _side != null && (Object)(object)_side.mtPos != (Object)null && (Object)(object)_side.closestHitPos != (Object)null;
			if (flag2)
			{
				Vector3 val = _side.mtPos.position - root.parent.position;
				flag2 = HorizontalSquare(val) < 4f && Mathf.Abs(val.y) < 2f;
				if (flag2)
				{
					Vector3 val2 = root.TransformPoint(new Vector3(0f, 0.005f, 0.345f));
					Vector3 position = _side.closestHitPos.position;
					position.y += _surfaceAboveAnchor;
					Vector3 val3 = position - val2;
					Vector3 val4 = default(Vector3);
					((Vector3)(ref val4))..ctor(val3.x, 0f, val3.z);
					flag2 = float.IsFinite(val3.x) && float.IsFinite(val3.y) && float.IsFinite(val3.z) && ((Vector3)(ref val4)).sqrMagnitude <= 1.44f && val3.y >= -0.1f && val3.y <= 1.35f;
					if (flag2)
					{
						_offset = val3;
					}
				}
			}
			_blend = Mathf.MoveTowards(_blend, (float)(flag2 ? 1 : 0), Mathf.Max(0f, dt) * 4f);
			root.position += _offset * _blend;
			if (flag && !flag2 && _failedTraces++ < 8)
			{
				ManualLogSource logger = Plugin.Logger;
				bool flag3 = default(bool);
				BepInExInfoLogInterpolatedStringHandler val5 = new BepInExInfoLogInterpolatedStringHandler(78, 5, ref flag3);
				if (flag3)
				{
					((BepInExLogInterpolatedStringHandler)val5).AppendLiteral("Fox carpentry placement unavailable: actor=");
					((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<Vector3>(root.parent.position);
					((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(", station=");
					CarpenterInteraction station = _station;
					((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<string>(((station != null) ? ((Object)station).name : null) ?? "none");
					((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(", log=");
					CarpentryDisplay display = _display;
					object obj;
					if (display == null)
					{
						obj = null;
					}
					else
					{
						GameObject rootObject = display.rootObject;
						obj = ((rootObject != null) ? ((Object)rootObject).name : null);
					}
					if (obj == null)
					{
						obj = "none";
					}
					((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<string>((string)obj);
					((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(", anchor=");
					Side side = _side;
					Vector3? obj2;
					if (side == null)
					{
						obj2 = null;
					}
					else
					{
						Transform closestHitPos = side.closestHitPos;
						obj2 = ((closestHitPos != null) ? new Vector3?(closestHitPos.position) : ((Vector3?)null));
					}
					((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<Vector3?>(obj2);
					((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(", offset=");
					((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<Vector3>(_offset);
					((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(".");
				}
				logger.LogInfo(val5);
			}
			if (_blend == 0f)
			{
				_station = null;
				_display = null;
				_side = null;
				_offset = Vector3.zero;
			}
		}

		private static float HorizontalSquare(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_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			return v.x * v.x + v.z * v.z;
		}

		private void Resolve(Transform root)
		{
			//IL_003d: 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_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: 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_01e6: Expected O, but got Unknown
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_027f: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a2: Unknown result type (might be due to invalid IL or missing references)
			_station = null;
			_display = null;
			_side = null;
			_surfaceAboveAnchor = 0f;
			CarpenterInteraction val = FoxCarpentryContext.For(root.parent);
			if ((Object)(object)val != (Object)null)
			{
				FindSide(val, root.parent.position, inactiveTemplates: false);
				if (_side == null)
				{
					FindSide(val, root.parent.position, inactiveTemplates: true);
				}
			}
			else
			{
				if (Time.unscaledTime >= _nextScan)
				{
					Il2CppArrayBase<CarpenterInteraction> val2 = Object.FindObjectsOfType<CarpenterInteraction>();
					_stations = (CarpenterInteraction[])(object)new CarpenterInteraction[val2.Length];
					for (int i = 0; i < val2.Length; i++)
					{
						_stations[i] = val2[i];
					}
					_nextScan = Time.unscaledTime + 5f;
				}
				CarpenterInteraction[] stations = _stations;
				foreach (CarpenterInteraction station in stations)
				{
					FindSide(station, root.parent.position, inactiveTemplates: false);
				}
			}
			if (_display == null || _side == null)
			{
				return;
			}
			float y = _side.closestHitPos.position.y;
			float num = y;
			foreach (Renderer componentsInChild in _display.rootObject.GetComponentsInChildren<Renderer>(false))
			{
				if (!((Object)(object)componentsInChild == (Object)null) && componentsInChild.enabled && ((Component)componentsInChild).gameObject.activeInHierarchy)
				{
					Bounds bounds = componentsInChild.bounds;
					float y2 = ((Bounds)(ref bounds)).max.y;
					if (float.IsFinite(y2) && y2 >= y && y2 <= y + 0.7f)
					{
						num = Mathf.Max(num, y2);
					}
				}
			}
			_surfaceAboveAnchor = num - y;
			if (_traced++ < 8)
			{
				ManualLogSource logger = Plugin.Logger;
				bool flag = default(bool);
				BepInExInfoLogInterpolatedStringHandler val3 = new BepInExInfoLogInterpolatedStringHandler(110, 7, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("Fox carpentry placement: nativeSession=");
					((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<bool>((Object)(object)val != (Object)null);
					((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(", station=");
					((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(((Object)_station).name);
					((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(", componentEnabled=");
					((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<bool>(((Behaviour)_station).isActiveAndEnabled);
					((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(", log=");
					((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(((Object)_display.rootObject).name);
					((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(", nativeMatch=");
					((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<Vector3>(_side.mtPos.position);
					((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(", contact=");
					((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<Vector3>(_side.closestHitPos.position);
					((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(", surfaceY=");
					((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<float>(num, "F3");
					((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(".");
				}
				logger.LogInfo(val3);
			}
		}

		private void FindSide(CarpenterInteraction station, Vector3 actor, bool inactiveTemplates)
		{
			//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_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)station == (Object)null || !((Component)station).gameObject.activeInHierarchy || station.carpentries == null)
			{
				return;
			}
			float num = ((_side == null) ? 4f : HorizontalSquare(_side.mtPos.position - actor));
			foreach (CarpentryDisplay item in (Il2CppArrayBase<CarpentryDisplay>)(object)station.carpentries)
			{
				if (item == null || (Object)(object)item.rootObject == (Object)null || (!inactiveTemplates && !item.rootObject.activeInHierarchy) || item.sides == null)
				{
					continue;
				}
				foreach (Side item2 in (Il2CppArrayBase<Side>)(object)item.sides)
				{
					if (item2 != null && !((Object)(object)item2.mtPos == (Object)null) && !((Object)(object)item2.closestHitPos == (Object)null))
					{
						Vector3 val = item2.mtPos.position - actor;
						float num2 = HorizontalSquare(val);
						if (!(num2 >= num) && !(Mathf.Abs(val.y) >= 2f))
						{
							num = num2;
							_station = station;
							_display = item;
							_side = item2;
						}
					}
				}
			}
		}
	}
	internal static class FoxChairPose
	{
		internal const float Height = 0.55f;

		internal static bool IsChair(string clip)
		{
			return clip?.StartsWith("fox_chair_") ?? false;
		}

		internal static string OnChair(string clip)
		{
			return clip switch
			{
				"fox_toast_seated" => "fox_chair_toast", 
				"fox_eat" => "fox_chair_eat", 
				"fox_drink" => "fox_chair_drink", 
				"fox_sit" => "fox_chair_sit", 
				"fox_sit_down" => "fox_chair_sit_down", 
				"fox_sit_up" => "fox_chair_sit_up", 
				"fox_emote_wave_seated" => "fox_chair_wave", 
				"fox_emote_cheer_seated" => "fox_chair_cheer", 
				_ => clip, 
			};
		}

		internal static string Animation(string clip)
		{
			return clip switch
			{
				"fox_chair_toast" => "fox_toast_seated", 
				"fox_chair_eat" => "fox_sit_eat", 
				"fox_chair_drink" => "fox_sit_drink", 
				"fox_chair_sit" => "fox_sit", 
				"fox_chair_sit_down" => "fox_sit_down", 
				"fox_chair_sit_up" => "fox_sit_up", 
				"fox_chair_wave" => "fox_emote_wave_seated", 
				"fox_chair_cheer" => "fox_emote_cheer_seated", 
				_ => clip, 
			};
		}
	}
	internal sealed class FoxConsumeAnimation
	{
		private string _clip;

		private float _remaining;

		internal bool Active => _remaining > 0f;

		internal static string Classify(string action, string moveset)
		{
			if (string.Equals(action, "Drink", StringComparison.OrdinalIgnoreCase) || (moveset != null && moveset.StartsWith("Moveset_Drink", StringComparison.OrdinalIgnoreCase)))
			{
				return "fox_drink";
			}
			if (string.Equals(action, "Eat", StringComparison.OrdinalIgnoreCase) || (moveset != null && moveset.StartsWith("Moveset_Eat", StringComparison.OrdinalIgnoreCase)))
			{
				return "fox_eat";
			}
			return null;
		}

		internal void Begin(string clip, float duration)
		{
			if (!(clip != "fox_eat") || !(clip != "fox_drink"))
			{
				_clip = clip;
				_remaining = ((float.IsFinite(duration) && duration > 0f) ? Math.Clamp(duration, 1.2f, 5f) : 2.5f);
			}
		}

		internal string Tick(float delta, bool interrupted)
		{
			if (interrupted)
			{
				Reset();
			}
			_remaining = Math.Max(0f, _remaining - Math.Max(0f, delta));
			if (!(_remaining > 0f))
			{
				return null;
			}
			return _clip;
		}

		internal void Reset()
		{
			_clip = null;
			_remaining = 0f;
		}
	}
	internal static class FoxConsumeHooks
	{
		[HarmonyPatch(typeof(Consumable), "_TryPlayConsumeAnimation")]
		private static class ConsumeStarted
		{
			private static void Postfix(Consumable __instance, GameObject owner, bool __result)
			{
				if (__result)
				{
					Notify(__instance, owner);
				}
			}
		}

		[HarmonyPatch(typeof(Consumable), "_ApplyEffect")]
		private static class ConsumeApplied
		{
			private static void Postfix(Consumable __instance, StatusEffectManager sem)
			{
				if ((Object)(object)sem != (Object)null)
				{
					Notify(__instance, ((Component)sem).gameObject);
				}
			}
		}

		[HarmonyPatch(typeof(ConsumableDisplayer), "ShowConsumableItem")]
		private static class ConsumableShown
		{
			private static void Postfix(ConsumableDisplayer __instance)
			{
				try
				{
					Plugin.Behaviour?.ConsumptionDisplay(__instance);
				}
				catch (Exception ex)
				{
					Plugin.Logger.LogWarning((object)("Animal food display skipped: " + ex.Message));
				}
			}
		}

		[HarmonyPatch(typeof(ConsumableDisplayer), "_RefreshShowingConsumable")]
		private static class ConsumableRefreshed
		{
			private static void Postfix(ConsumableDisplayer __instance)
			{
				try
				{
					Plugin.Behaviour?.ConsumptionDisplay(__instance);
				}
				catch (Exception ex)
				{
					Plugin.Logger.LogWarning((object)("Animal food display refresh skipped: " + ex.Message));
				}
			}
		}

		private static void Notify(Consumable item, GameObject owner)
		{
			try
			{
				if (item == null || (Object)(object)owner == (Object)null)
				{
					return;
				}
				ConsumableInfo consumableInfo = item.ConsumableInfo;
				InteractionMoveset val = ((consumableInfo != null) ? consumableInfo.moveSet : null);
				if (!((Object)(object)val == (Object)null))
				{
					string text = FoxConsumeAnimation.Classify(val.attackActionName, ((Object)val).name);
					if (text != null)
					{
						Plugin.Behaviour?.Consume(owner, text, val.displayDuration);
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Logger.LogWarning((object)("Fox consume visual skipped: " + ex.Message));
			}
		}
	}
	internal static class FoxCoop
	{
		[HarmonyPatch(typeof(NetworkRunner), "Fusion_Simulation_ICallbacks_OnReliableData")]
		private static class ReliableData
		{
			private static bool Prefix(NetworkRunner __instance, PlayerRef __0, Il2CppStructArray<byte> __1)
			{
				//IL_0044: Unknown result type (might be due to invalid IL or missing references)
				if (__1 == null || ((Il2CppArrayBase<byte>)(object)__1).Length < FoxCoopProtocol.Magic.Length)
				{
					return true;
				}
				for (int i = 0; i < FoxCoopProtocol.Magic.Length; i++)
				{
					if (((Il2CppArrayBase<byte>)(object)__1)[i] != FoxCoopProtocol.Magic[i])
					{
						return true;
					}
				}
				try
				{
					if (((Il2CppArrayBase<byte>)(object)__1).Length == 48)
					{
						Receive(__instance, __0, ((IEnumerable<byte>)__1).ToArray());
					}
				}
				catch (Exception ex)
				{
					TransportError(ex);
				}
				return false;
			}
		}

		internal static PlayerManager Manager;

		private static NetworkRunner _runner;

		private static readonly FoxCoopStateBuffer Buffer = new FoxCoopStateBuffer();

		private static readonly Dictionary<int, FoxMovement> Movement = new Dictionary<int, FoxMovement>();

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

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

		private static readonly Dictionary<int, float> Waiting = new Dictionary<int, float>();

		private static readonly List<int> Removed = new List<int>();

		private static float _nextSend;

		private static float _nextScan;

		private static uint _sequence;

		private static bool _loggedTransportError;

		private static Dictionary<int, (FoxNetState state, float received)> States => Buffer.Entries;

		internal static PlayerCharacter Local
		{
			get
			{
				PlayerEntity instance = PlayerEntity.Instance;
				if (instance == null)
				{
					return null;
				}
				PlayerInteractionAgent agent = instance.Agent;
				if (agent == null)
				{
					return null;
				}
				return agent.GetCharacter();
			}
		}

		internal static PlayerInteractionAgent Agent(PlayerCharacter player)
		{
			if ((Object)(object)player == (Object)null)
			{
				return null;
			}
			PlayerManager manager = Manager;
			if (((manager != null) ? manager._players : null) != null)
			{
				foreach (Player item in (Il2CppArrayBase<Player>)(object)Manager._players)
				{
					if ((Object)(object)((item != null) ? item.playerCharacter : null) == (Object)(object)player)
					{
						IInteractionAgent playerInteractionAgent = item.playerInteractionAgent;
						PlayerInteractionAgent val = ((playerInteractionAgent != null) ? ((Il2CppObjectBase)playerInteractionAgent).TryCast<PlayerInteractionAgent>() : null);
						if ((Object)(object)val != (Object)null)
						{
							return val;
						}
					}
				}
			}
			PlayerEntity instance = PlayerEntity.Instance;
			PlayerInteractionAgent val2 = ((instance != null) ? instance.Agent : null);
			if ((Object)(object)val2 != (Object)null && (Object)(object)val2.GetCharacter() == (Object)(object)player)
			{
				return val2;
			}
			return ((Component)player).GetComponent<PlayerInteractionAgent>() ?? ((Component)player).GetComponentInChildren<PlayerInteractionAgent>(true);
		}

		internal static IEnumerable<PlayerCharacter> Players()
		{
			PlayerManager manager = Manager;
			if (((manager != null) ? manager._players : null) == null)
			{
				yield break;
			}
			foreach (Player item in (Il2CppArrayBase<Player>)(object)Manager._players)
			{
				if ((Object)(object)((item != null) ? item.playerCharacter : null) != (Object)null && (Object)(object)item.playerObject != (Object)null && item.playerObject.IsValid)
				{
					yield return item.playerCharacter;
				}
			}
		}

		internal static bool MaySimulate(PlayerCharacter player)
		{
			NetworkObject val = ((player != null) ? ((Character)player).NetworkObject : null);
			if ((Object)(object)player != (Object)null)
			{
				if (!((Character)player).HasAuthority)
				{
					if ((Object)(object)val != (Object)null && val.IsValid)
					{
						if (!val.HasStateAuthority)
						{
							return val.HasInputAuthority;
						}
						return true;
					}
					return false;
				}
				return true;
			}
			return false;
		}

		internal static bool TryState(PlayerCharacter player, out FoxNetState state, out float age)
		{
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			state = default(FoxNetState);
			age = 0f;
			NetworkObject val = ((player != null) ? ((Character)player).NetworkObject : null);
			if ((Object)(object)val == (Object)null || !val.IsValid)
			{
				return false;
			}
			foreach (var value in States.Values)
			{
				if (value.state.ObjectId == val.Id.Raw)
				{
					state = value.state;
					age = Time.unscaledTime - value.received;
					return true;
				}
			}
			return false;
		}

		internal static void Tick()
		{
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Expected O, but got Unknown
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0362: Unknown result type (might be due to invalid IL or missing references)
			//IL_036c: Unknown result type (might be due to invalid IL or missing references)
			//IL_037d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0382: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fd: Expected O, but got Unknown
			PlayerManager manager = Manager;
			object obj;
			if (manager == null)
			{
				obj = null;
			}
			else
			{
				NetworkSession session = manager._session;
				obj = ((session != null) ? session.runner : null);
			}
			NetworkRunner val = (NetworkRunner)obj;
			if ((Object)(object)val == (Object)null || !val.IsRunning)
			{
				if ((Object)(object)_runner != (Object)null)
				{
					Plugin.Behaviour?.ClearPlayers();
					Reset();
				}
				return;
			}
			bool flag = default(bool);
			PlayerRef val3;
			if ((Object)(object)val != (Object)(object)_runner)
			{
				Plugin.Behaviour?.ClearPlayers();
				Reset();
				_runner = val;
				ManualLogSource logger = Plugin.Logger;
				BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(51, 3, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Fox co-op session: mode=");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<GameMode>(val.GameMode);
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(", local player=");
					val3 = val.LocalPlayer;
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(((PlayerRef)(ref val3)).RawEncoded);
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(", protocol=");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<byte>((byte)1);
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(".");
				}
				logger.LogInfo(val2);
			}
			if (Time.unscaledTime < _nextScan)
			{
				return;
			}
			_nextScan = Time.unscaledTime + 0.25f;
			Seen.Clear();
			foreach (PlayerCharacter item in Players())
			{
				int instanceID = ((Object)item).GetInstanceID();
				Seen.Add(instanceID);
				if (!Movement.TryGetValue(instanceID, out var value))
				{
					value = (Movement[instanceID] = new FoxMovement());
				}
				value.Tick(item);
				if (WolfSelection.IsFox(item) && MaySimulate(item))
				{
					WolfStats.EnsureSimulationProfile(item);
				}
			}
			Removed.Clear();
			foreach (KeyValuePair<int, FoxMovement> item2 in Movement)
			{
				if (!Seen.Contains(item2.Key))
				{
					item2.Value.Dispose();
					Removed.Add(item2.Key);
				}
			}
			foreach (int item3 in Removed)
			{
				Movement.Remove(item3);
			}
			Removed.Clear();
			foreach (KeyValuePair<int, (FoxNetState, float)> state in States)
			{
				if ((Object)(object)Find(state.Key, state.Value.Item1.ObjectId) == (Object)null)
				{
					Removed.Add(state.Key);
				}
			}
			foreach (int item4 in Removed)
			{
				States.Remove(item4);
			}
			PlayerManager manager2 = Manager;
			if (((manager2 != null) ? manager2._players : null) == null || _runner.IsSinglePlayer)
			{
				return;
			}
			foreach (Player item5 in (Il2CppArrayBase<Player>)(object)Manager._players)
			{
				if ((Object)(object)((item5 != null) ? item5.playerObject : null) == (Object)null || !item5.playerObject.IsValid || item5.reference == _runner.LocalPlayer)
				{
					continue;
				}
				val3 = item5.reference;
				int rawEncoded = ((PlayerRef)(ref val3)).RawEncoded;
				float value2;
				if (States.ContainsKey(rawEncoded))
				{
					Waiting.Remove(rawEncoded);
				}
				else if (!Waiting.TryGetValue(rawEncoded, out value2))
				{
					Waiting[rawEncoded] = Time.unscaledTime;
				}
				else if (Time.unscaledTime - value2 > 20f && Warned.Add(rawEncoded))
				{
					ManualLogSource logger2 = Plugin.Logger;
					BepInExWarningLogInterpolatedStringHandler val4 = new BepInExWarningLogInterpolatedStringHandler(111, 2, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("Fox co-op: no compatible state from player ");
						((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<int>(rawEncoded);
						((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(". Both players need ASKA Fox ");
						((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>("0.6.49");
						((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("; inspect both logs if it is installed.");
					}
					logger2.LogWarning(val4);
				}
			}
		}

		internal static void Send(WolfController local)
		{
			//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_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: 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_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Invalid comparison between Unknown and I4
			if ((Object)(object)_runner == (Object)null || !_runner.IsRunning || _runner.IsSinglePlayer || Time.unscaledTime < _nextSend)
			{
				return;
			}
			PlayerCharacter local2 = Local;
			NetworkObject val = ((local2 != null) ? ((Character)local2).NetworkObject : null);
			if ((Object)(object)val == (Object)null || !val.IsValid)
			{
				return;
			}
			PlayerRef localPlayer = _runner.LocalPlayer;
			if ((Object)(object)Find(((PlayerRef)(ref localPlayer)).RawEncoded, val.Id.Raw) != (Object)(object)local2)
			{
				return;
			}
			localPlayer = _runner.LocalPlayer;
			FoxNetState state = local.Snapshot(local2, ((PlayerRef)(ref localPlayer)).RawEncoded, val.Id.Raw, ++_sequence);
			_nextSend = Time.unscaledTime + (state.Visible ? 0.1f : 1f);
			try
			{
				byte[] array = FoxCoopProtocol.Encode(state);
				if (_runner.IsServer || (int)_runner.GameMode == 2)
				{
					localPlayer = _runner.LocalPlayer;
					Broadcast(array, ((PlayerRef)(ref localPlayer)).RawEncoded);
				}
				else
				{
					_runner.SendReliableDataToServer(Il2CppStructArray<byte>.op_Implicit(array));
				}
			}
			catch (Exception ex)
			{
				TransportError(ex);
			}
		}

		private static PlayerCharacter Find(int owner, uint objectId)
		{
			//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_0063: Unknown result type (might be due to invalid IL or missing references)
			PlayerManager manager = Manager;
			if (((manager != null) ? manager._players : null) == null)
			{
				return null;
			}
			foreach (Player item in (Il2CppArrayBase<Player>)(object)Manager._players)
			{
				if (item != null)
				{
					PlayerRef reference = item.reference;
					if (((PlayerRef)(ref reference)).RawEncoded == owner && (Object)(object)item.playerObject != (Object)null && item.playerObject.IsValid && item.playerObject.Id.Raw == objectId)
					{
						return item.playerCharacter;
					}
				}
			}
			return null;
		}

		private static void Broadcast(byte[] bytes, int exceptOwner)
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_007c: Unknown result type (might be due to invalid IL or missing references)
			PlayerManager manager = Manager;
			if (((manager != null) ? manager._players : null) == null)
			{
				return;
			}
			foreach (Player item in (Il2CppArrayBase<Player>)(object)Manager._players)
			{
				if ((Object)(object)((item != null) ? item.playerObject : null) != (Object)null && item.playerObject.IsValid && item.reference != _runner.LocalPlayer)
				{
					PlayerRef reference = item.reference;
					if (((PlayerRef)(ref reference)).RawEncoded != exceptOwner)
					{
						_runner.SendReliableDataToPlayer(item.reference, Il2CppStructArray<byte>.op_Implicit(bytes));
					}
				}
			}
		}

		private static void Receive(NetworkRunner runner, PlayerRef sender, byte[] bytes)
		{
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Invalid comparison between Unknown and I4
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: 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_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Expected O, but got Unknown
			if ((Object)(object)runner == (Object)null || (Object)(object)runner != (Object)(object)_runner || !runner.IsRunning)
			{
				return;
			}
			if (!FoxCoopProtocol.TryDecode(bytes, out var state))
			{
				if (Warned.Add(-((PlayerRef)(ref sender)).RawEncoded - 1000))
				{
					Plugin.Logger.LogWarning((object)"Fox co-op rejected incompatible or malformed state. Install matching Fox builds on every peer.");
				}
				return;
			}
			PlayerRef val;
			int num;
			if (!runner.IsServer && (int)runner.GameMode != 2)
			{
				if (!((PlayerRef)(ref sender)).IsNone)
				{
					val = sender;
					PlayerManager manager = Manager;
					PlayerRef? obj;
					if (manager == null)
					{
						obj = null;
					}
					else
					{
						Player masterPlayer = manager.MasterPlayer;
						obj = ((masterPlayer != null) ? new PlayerRef?(masterPlayer.reference) : ((PlayerRef?)null));
					}
					PlayerRef? val2 = obj;
					num = ((val2.HasValue && val == val2.GetValueOrDefault()) ? 1 : 0);
				}
				else
				{
					num = 1;
				}
			}
			else
			{
				num = 0;
			}
			bool serverRelay = (byte)num != 0;
			PlayerCharacter val3 = Find(state.Owner, state.ObjectId);
			if ((Object)(object)val3 == (Object)null)
			{
				return;
			}
			int owner = state.Owner;
			val = runner.LocalPlayer;
			if (owner == ((PlayerRef)(ref val)).RawEncoded || !FoxCoopProtocol.MatchesOwner(((PlayerRef)(ref sender)).RawEncoded, state.Owner, state.ObjectId, state.Owner, ((Character)val3).NetworkObject.Id.Raw, serverRelay) || !Buffer.Accept(state, Time.unscaledTime, out var first))
			{
				return;
			}
			WolfSelection.SetIdentity(val3, state.Fox, new FoxPalette(state.Coat, state.Eye));
			if (first)
			{
				ManualLogSource logger = Plugin.Logger;
				bool flag = default(bool);
				BepInExInfoLogInterpolatedStringHandler val4 = new BepInExInfoLogInterpolatedStringHandler(58, 5, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("Fox co-op recognized player ");
					((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<int>(state.Owner);
					((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(", object ");
					((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<uint>(state.ObjectId);
					((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(": Fox=");
					((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<bool>(state.Fox);
					((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(", coat=");
					((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<byte>(state.Coat);
					((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(", eyes=");
					((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<byte>(state.Eye);
					((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(".");
				}
				logger.LogInfo(val4);
			}
			if (runner.Is