Decompiled source of AnimalFeedingTrough v1.0.4

AnimalFeedingTrough.dll

Decompiled a week ago
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using BepInEx;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using UnityEngine;

[assembly: Guid("55912d84-4458-440a-b4d5-ee0eb383d22e")]
[assembly: AssemblyFileVersion("1.0.4.0")]
[assembly: CompilationRelaxations(8)]
[assembly: ComVisible(false)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyTitle("Animal Feeding Trough")]
[assembly: AssemblyDescription("Adds a functional animal feeding trough to Valheim.")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("xNeliox")]
[assembly: AssemblyProduct("Animal Feeding Trough")]
[assembly: AssemblyCopyright("Copyright © 2026 xNeliox")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyVersion("1.0.4.0")]
namespace AnimalFeedingTrough;

[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
[BepInPlugin("xneliox.animalfeedingtrough", "Animal Feeding Trough", "1.0.4")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public sealed class AnimalFeedingTroughPlugin : BaseUnityPlugin
{
	public const string PluginGuid = "xneliox.animalfeedingtrough";

	public const string PluginName = "Animal Feeding Trough";

	public const string PluginVersion = "1.0.4";

	internal const string PrefabName = "xneliox_FeedingTrough";

	private void Awake()
	{
		//IL_000a: Unknown result type (might be due to invalid IL or missing references)
		TroughTranslations.Register();
		new Harmony("xneliox.animalfeedingtrough").PatchAll(typeof(AnimalFeedingTroughPlugin).Assembly);
		PrefabManager.OnVanillaPrefabsAvailable += RegisterTrough;
	}

	private void OnDestroy()
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		new Harmony("xneliox.animalfeedingtrough").UnpatchSelf();
		PrefabManager.OnVanillaPrefabsAvailable -= RegisterTrough;
	}

	private void RegisterTrough()
	{
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0018: Expected O, but got Unknown
		//IL_0076: Unknown result type (might be due to invalid IL or missing references)
		//IL_007c: Expected O, but got Unknown
		//IL_0087: Unknown result type (might be due to invalid IL or missing references)
		//IL_008d: Expected O, but got Unknown
		//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a8: Expected O, but got Unknown
		//IL_0174: 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_01c8: Unknown result type (might be due to invalid IL or missing references)
		PrefabManager.OnVanillaPrefabsAvailable -= RegisterTrough;
		try
		{
			PieceConfig val = new PieceConfig();
			val.Name = "$xneliox_trough_name";
			val.Description = "$xneliox_trough_description";
			val.PieceTable = "_HammerPieceTable";
			val.Category = "Furniture";
			val.CraftingStation = "piece_workbench";
			val.Icon = TroughModelV3.CreateIcon();
			val.Requirements = (RequirementConfig[])(object)new RequirementConfig[2]
			{
				new RequirementConfig("Wood", 20, 0, true),
				new RequirementConfig("BronzeNails", 4, 0, true)
			};
			PieceConfig val2 = val;
			CustomPiece val3 = new CustomPiece("xneliox_FeedingTrough", "piece_chest_wood", val2);
			GameObject piecePrefab = val3.PiecePrefab;
			((Object)piecePrefab).name = "xneliox_FeedingTrough";
			Renderer componentInChildren = piecePrefab.GetComponentInChildren<Renderer>(true);
			Material val4 = (Object.op_Implicit((Object)(object)componentInChildren) ? componentInChildren.sharedMaterial : null);
			if (!Object.op_Implicit((Object)(object)val4))
			{
				throw new InvalidOperationException("No Valheim piece material was available.");
			}
			Renderer[] componentsInChildren = piecePrefab.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val5 in componentsInChildren)
			{
				val5.enabled = false;
			}
			Collider[] componentsInChildren2 = piecePrefab.GetComponentsInChildren<Collider>(true);
			foreach (Collider val6 in componentsInChildren2)
			{
				val6.enabled = false;
			}
			AssetBundleTroughModel.Instantiate(piecePrefab.transform);
			BoxCollider val7 = piecePrefab.GetComponent<BoxCollider>();
			if (!Object.op_Implicit((Object)(object)val7))
			{
				val7 = piecePrefab.AddComponent<BoxCollider>();
			}
			val7.center = new Vector3(0f, 0.5f, 0f);
			val7.size = new Vector3(5.24f, 1f, 1.34f);
			((Collider)val7).enabled = true;
			Container component = piecePrefab.GetComponent<Container>();
			component.m_name = "$xneliox_trough_name";
			component.m_width = 6;
			component.m_height = 1;
			component.m_privacy = (PrivacySetting)2;
			Piece component2 = piecePrefab.GetComponent<Piece>();
			component2.m_name = "$xneliox_trough_name";
			component2.m_description = "$xneliox_trough_description";
			if (!Object.op_Implicit((Object)(object)piecePrefab.GetComponent<TroughFeeder>()))
			{
				piecePrefab.AddComponent<TroughFeeder>();
			}
			PieceManager.Instance.AddPiece(val3);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Registered the networked animal feeding trough.");
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("Could not register feeding trough: " + ex));
		}
	}
}
[HarmonyPatch(typeof(ZNetScene), "CreateObject")]
internal static class TroughPrefabHashMigration
{
	private const int PreviousPrefabHash = 160077371;

	private static void Prefix(ZDO zdo)
	{
		if (zdo != null && zdo.GetPrefab() == 160077371)
		{
			zdo.SetPrefab(StringExtensionMethods.GetStableHashCode("xneliox_FeedingTrough"));
		}
	}
}
[HarmonyPatch(typeof(ZNetScene), "GetPrefab", new Type[] { typeof(int) })]
internal static class TroughPrefabHashLookup
{
	private const int PreviousPrefabHash = 160077371;

	private static void Prefix(ref int hash)
	{
		if (hash == 160077371)
		{
			hash = StringExtensionMethods.GetStableHashCode("xneliox_FeedingTrough");
		}
	}
}
internal static class AssetBundleTroughModel
{
	private const string BundleResource = "animalfeedingtrough_v4";

	private const string PrefabAsset = "Assets/AnimalFeedingTrough/FeedingTroughV4.prefab";

	private static AssetBundle _bundle;

	private static GameObject _prefab;

	internal static void Instantiate(Transform parent)
	{
		//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0101: 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_011a: Unknown result type (might be due to invalid IL or missing references)
		//IL_011f: Unknown result type (might be due to invalid IL or missing references)
		//IL_012f: Unknown result type (might be due to invalid IL or missing references)
		if (!Object.op_Implicit((Object)(object)_bundle))
		{
			Assembly assembly = typeof(AnimalFeedingTroughPlugin).Assembly;
			using Stream stream = assembly.GetManifestResourceStream("animalfeedingtrough_v4");
			if (stream == null)
			{
				throw new InvalidOperationException("The embedded feeding trough AssetBundle resource is missing.");
			}
			using MemoryStream memoryStream = new MemoryStream();
			stream.CopyTo(memoryStream);
			_bundle = AssetBundle.LoadFromMemory(memoryStream.ToArray());
		}
		if (!Object.op_Implicit((Object)(object)_bundle))
		{
			throw new InvalidOperationException("The embedded feeding trough AssetBundle could not be loaded.");
		}
		if (!Object.op_Implicit((Object)(object)_prefab))
		{
			_prefab = _bundle.LoadAsset<GameObject>("Assets/AnimalFeedingTrough/FeedingTroughV4.prefab");
		}
		if (!Object.op_Implicit((Object)(object)_prefab))
		{
			throw new InvalidOperationException("The feeding trough prefab is missing from the AssetBundle.");
		}
		GameObject val = Object.Instantiate<GameObject>(_prefab, parent, false);
		((Object)val).name = "AnimalFeedingTroughModelV3";
		Transform[] componentsInChildren = val.GetComponentsInChildren<Transform>(true);
		foreach (Transform val2 in componentsInChildren)
		{
			if (((Object)val2).name.EndsWith(" foot", StringComparison.Ordinal))
			{
				Vector3 localPosition = val2.localPosition;
				localPosition.y = 0.16f;
				val2.localPosition = localPosition;
				Vector3 localScale = val2.localScale;
				localScale.y = 0.36f;
				val2.localScale = localScale;
			}
		}
	}
}
public sealed class TroughFeeder : MonoBehaviour
{
	private const float AttractionRange = 16f;

	private const string ServingMarker = "xneliox_trough_serving";

	private static readonly MethodInfo CanConsumeMethod = AccessTools.Method(typeof(MonsterAI), "CanConsume", (Type[])null, (Type[])null);

	private static readonly MethodInfo InventoryChangedMethod = AccessTools.Method(typeof(Inventory), "Changed", new Type[2]
	{
		typeof(bool),
		typeof(bool)
	}, (Type[])null);

	private static readonly MethodInfo ContainerSaveMethod = AccessTools.Method(typeof(Container), "Save", (Type[])null, (Type[])null);

	private static readonly FieldInfo ConsumeTargetField = AccessTools.Field(typeof(MonsterAI), "m_consumeTarget");

	private static readonly FieldInfo ConsumeSearchTimerField = AccessTools.Field(typeof(MonsterAI), "m_consumeSearchTimer");

	private Container _container;

	private ZNetView _view;

	private GameObject _visibleFeed;

	private float _nextSearch;

	private float _nextVisualRefresh;

	private ItemDrop _currentServing;

	private void Awake()
	{
		_container = ((Component)this).GetComponent<Container>();
		_view = ((Component)this).GetComponent<ZNetView>();
		Transform val = ((Component)this).transform.Find("AnimalFeedingTroughModelV3/VisibleFeed");
		_visibleFeed = (Object.op_Implicit((Object)(object)val) ? ((Component)val).gameObject : null);
	}

	private void Update()
	{
		//IL_00d7: 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)
		RefreshFeedVisual();
		if (!Object.op_Implicit((Object)(object)_container) || !Object.op_Implicit((Object)(object)_view) || !_view.IsValid() || Time.time < _nextSearch)
		{
			return;
		}
		_nextSearch = Time.time + 2f;
		EnableTroughSearchForOwnedAnimals();
		if (!_view.IsOwner())
		{
			return;
		}
		if (Object.op_Implicit((Object)(object)_currentServing))
		{
			ZNetView component = ((Component)_currentServing).GetComponent<ZNetView>();
			if (_currentServing.m_itemData != null && _currentServing.m_itemData.m_stack > 0 && Object.op_Implicit((Object)(object)component) && component.IsValid())
			{
				return;
			}
			_currentServing = null;
		}
		List<Character> allCharacters = Character.GetAllCharacters();
		foreach (Character item in allCharacters)
		{
			if (!Object.op_Implicit((Object)(object)item))
			{
				continue;
			}
			float num = Vector3.Distance(((Component)this).transform.position, ((Component)item).transform.position);
			if (num > 16f)
			{
				continue;
			}
			Tameable component2 = ((Component)item).GetComponent<Tameable>();
			MonsterAI component3 = ((Component)item).GetComponent<MonsterAI>();
			if (Object.op_Implicit((Object)(object)component2) && Object.op_Implicit((Object)(object)component3) && CanUseTrough(item, component2))
			{
				ItemData val = FindFood(component3);
				if (val != null)
				{
					SpawnServing(val, item);
					break;
				}
			}
		}
	}

	private void EnableTroughSearchForOwnedAnimals()
	{
		//IL_002c: 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)
		List<Character> allCharacters = Character.GetAllCharacters();
		foreach (Character item in allCharacters)
		{
			if (!Object.op_Implicit((Object)(object)item))
			{
				continue;
			}
			float num = Vector3.Distance(((Component)this).transform.position, ((Component)item).transform.position);
			if (num > 16f)
			{
				continue;
			}
			Tameable component = ((Component)item).GetComponent<Tameable>();
			MonsterAI component2 = ((Component)item).GetComponent<MonsterAI>();
			ZNetView component3 = ((Component)item).GetComponent<ZNetView>();
			if (Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)component2) && Object.op_Implicit((Object)(object)component3) && component3.IsValid() && CanUseTrough(item, component) && component3.IsOwner())
			{
				ItemData val = FindFood(component2);
				if (val != null && component2.m_consumeSearchRange < 16f)
				{
					component2.m_consumeSearchRange = 16f;
				}
			}
		}
	}

	private static bool CanUseTrough(Character character, Tameable tameable)
	{
		if (!Object.op_Implicit((Object)(object)character) || !Object.op_Implicit((Object)(object)tameable) || !tameable.IsHungry())
		{
			return false;
		}
		return true;
	}

	private void SpawnServing(ItemData food, Character animal)
	{
		//IL_0034: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d5: 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_00ef: 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 (food == null || (Object)(object)animal == (Object)null || (Object)(object)_container == (Object)null || _container.GetInventory() == null)
		{
			return;
		}
		Vector3 val = ((Component)this).transform.InverseTransformPoint(((Component)animal).transform.position);
		float[] array = new float[4] { -1.65f, -0.55f, 0.55f, 1.65f };
		float num = array[0];
		float num2 = Mathf.Abs(val.x - num);
		float[] array2 = array;
		foreach (float num3 in array2)
		{
			float num4 = Mathf.Abs(val.x - num3);
			if (num4 < num2)
			{
				num2 = num4;
				num = num3;
			}
		}
		float num5 = ((!(val.z < 0f)) ? 1f : (-1f));
		Vector3 val2 = ((Component)this).transform.TransformPoint(new Vector3(num, 0.12f, num5 * 0.95f));
		ItemData val3 = food.Clone();
		val3.m_stack = 1;
		ItemDrop val4 = ItemDrop.DropItem(val3, 1, val2, Quaternion.identity);
		if (!Object.op_Implicit((Object)(object)val4))
		{
			Debug.LogWarning((object)"[Animal Feeding Trough] Could not create a food serving.");
			return;
		}
		_currentServing = val4;
		MonsterAI component = ((Component)animal).GetComponent<MonsterAI>();
		ZNetView component2 = ((Component)animal).GetComponent<ZNetView>();
		if (Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)component2) && component2.IsValid() && component2.IsOwner())
		{
			component.m_consumeSearchRange = Mathf.Max(component.m_consumeSearchRange, 16f);
			if (ConsumeTargetField != null)
			{
				ConsumeTargetField.SetValue(component, val4);
			}
			if (ConsumeSearchTimerField != null)
			{
				ConsumeSearchTimerField.SetValue(component, 0f);
			}
		}
		ZNetView component3 = ((Component)val4).GetComponent<ZNetView>();
		if (Object.op_Implicit((Object)(object)component3) && component3.IsValid() && component3.IsOwner())
		{
			component3.GetZDO().Set("xneliox_trough_serving", true);
		}
		Renderer[] componentsInChildren = ((Component)val4).GetComponentsInChildren<Renderer>(true);
		foreach (Renderer val5 in componentsInChildren)
		{
			val5.enabled = false;
		}
		ParticleSystem[] componentsInChildren2 = ((Component)val4).GetComponentsInChildren<ParticleSystem>(true);
		foreach (ParticleSystem val6 in componentsInChildren2)
		{
			val6.Stop(true, (ParticleSystemStopBehavior)0);
			Renderer component4 = ((Component)val6).GetComponent<Renderer>();
			if (Object.op_Implicit((Object)(object)component4))
			{
				component4.enabled = false;
			}
		}
		Light[] componentsInChildren3 = ((Component)val4).GetComponentsInChildren<Light>(true);
		foreach (Light val7 in componentsInChildren3)
		{
			((Behaviour)val7).enabled = false;
		}
		Inventory inventory = _container.GetInventory();
		inventory.RemoveItem(food, 1);
		if (InventoryChangedMethod != null)
		{
			InventoryChangedMethod.Invoke(inventory, new object[2] { false, false });
		}
		if (ContainerSaveMethod != null)
		{
			ContainerSaveMethod.Invoke(_container, null);
		}
	}

	private void RefreshFeedVisual()
	{
		if (!Object.op_Implicit((Object)(object)_visibleFeed) || Time.time < _nextVisualRefresh)
		{
			return;
		}
		_nextVisualRefresh = Time.time + 0.35f;
		bool active = false;
		if (Object.op_Implicit((Object)(object)_container) && _container.GetInventory() != null)
		{
			foreach (ItemData allItem in _container.GetInventory().GetAllItems())
			{
				if (allItem != null && allItem.m_stack > 0 && TroughFoodRules.IsFood(allItem))
				{
					active = true;
					break;
				}
			}
		}
		if (Object.op_Implicit((Object)(object)_currentServing) && _currentServing.m_itemData != null && _currentServing.m_itemData.m_stack > 0)
		{
			active = true;
		}
		_visibleFeed.SetActive(active);
	}

	private ItemData FindFood(MonsterAI ai)
	{
		if ((Object)(object)ai == (Object)null || (Object)(object)_container == (Object)null)
		{
			return null;
		}
		Inventory inventory = _container.GetInventory();
		if (inventory == null)
		{
			return null;
		}
		foreach (ItemData allItem in inventory.GetAllItems())
		{
			if (allItem != null && allItem.m_stack > 0 && !(CanConsumeMethod == null))
			{
				object obj = CanConsumeMethod.Invoke(ai, new object[1] { allItem });
				if (obj is bool && (bool)obj)
				{
					return allItem;
				}
			}
		}
		return null;
	}
}
internal static class TroughModelV3
{
	internal const string RootName = "AnimalFeedingTroughModelV3";

	internal const string FeedName = "VisibleFeed";

	private const string WoodResource = "AnimalFeedingTroughV3.Wood";

	private const string MetalResource = "AnimalFeedingTroughV3.Metal";

	private const string FeedResource = "AnimalFeedingTroughV3.Feed";

	private const string IconResource = "AnimalFeedingTroughV3.Icon";

	private static Material _wood;

	private static Material _darkWood;

	private static Material _iron;

	private static Material _feed;

	internal static void Build(Transform parent, Shader fallbackShader)
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Expected O, but got Unknown
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: 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_0082: Unknown result type (might be due to invalid IL or missing references)
		//IL_0091: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bf: 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_00e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_0115: Unknown result type (might be due to invalid IL or missing references)
		//IL_0124: Unknown result type (might be due to invalid IL or missing references)
		//IL_0129: Unknown result type (might be due to invalid IL or missing references)
		//IL_0143: Unknown result type (might be due to invalid IL or missing references)
		//IL_0152: Unknown result type (might be due to invalid IL or missing references)
		//IL_0157: Unknown result type (might be due to invalid IL or missing references)
		//IL_017b: 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_01be: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_0201: Unknown result type (might be due to invalid IL or missing references)
		//IL_021a: Unknown result type (might be due to invalid IL or missing references)
		//IL_023e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0243: Unknown result type (might be due to invalid IL or missing references)
		//IL_0259: Unknown result type (might be due to invalid IL or missing references)
		//IL_0272: Unknown result type (might be due to invalid IL or missing references)
		//IL_0298: 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_02f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_031a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0333: Unknown result type (might be due to invalid IL or missing references)
		//IL_0388: Unknown result type (might be due to invalid IL or missing references)
		//IL_03a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_03c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_03ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_0413: Unknown result type (might be due to invalid IL or missing references)
		//IL_043b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0462: Unknown result type (might be due to invalid IL or missing references)
		//IL_048a: Unknown result type (might be due to invalid IL or missing references)
		//IL_04b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_04d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_0500: Unknown result type (might be due to invalid IL or missing references)
		//IL_0519: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = new GameObject("AnimalFeedingTroughModelV3");
		Transform transform = val.transform;
		transform.SetParent(parent, false);
		transform.localPosition = Vector3.zero;
		transform.localRotation = Quaternion.identity;
		transform.localScale = Vector3.one;
		Shader val2 = Shader.Find("Standard") ?? fallbackShader;
		if (!Object.op_Implicit((Object)(object)val2))
		{
			throw new InvalidOperationException("No supported shader is available for the feeding trough.");
		}
		_wood = CreateMaterial("AFT V3 - aged oak", val2, "AnimalFeedingTroughV3.Wood", Color.white, 0f, 0.22f, new Vector2(2.15f, 0.135f), new Vector2(0f, 0.335f));
		_darkWood = CreateMaterial("AFT V3 - carved oak", val2, "AnimalFeedingTroughV3.Wood", new Color(0.47f, 0.39f, 0.31f, 1f), 0f, 0.16f, new Vector2(2.15f, 0.135f), new Vector2(0f, 0.335f));
		_iron = CreateMaterial("AFT V3 - forged iron", val2, "AnimalFeedingTroughV3.Metal", new Color(0.58f, 0.6f, 0.61f, 1f), 0.72f, 0.28f, Vector2.one, Vector2.zero);
		_feed = CreateMaterial("AFT V3 - straw vegetables and berries", val2, "AnimalFeedingTroughV3.Feed", Color.white, 0f, 0.12f, Vector2.one, Vector2.zero);
		CreateBeam(transform, "Front solid oak wall", new Vector3(0f, 0.625f, -0.505f), 4.92f, 0.55f, 0.23f, 0.045f, Quaternion.identity, _wood, 3.6f);
		CreateBeam(transform, "Rear solid oak wall", new Vector3(0f, 0.625f, 0.505f), 4.92f, 0.55f, 0.23f, 0.045f, Quaternion.identity, _wood, 3.6f);
		CreateBeam(transform, "Solid basin floor", new Vector3(0f, 0.385f, 0f), 4.72f, 0.16f, 0.79f, 0.035f, Quaternion.identity, _darkWood, 3.5f);
		Quaternion rotation = Quaternion.Euler(0f, 90f, 0f);
		CreateBeam(transform, "Closed left end", new Vector3(-2.48f, 0.62f, 0f), 1.18f, 0.58f, 0.3f, 0.05f, rotation, _wood, 0.9f);
		CreateBeam(transform, "Closed right end", new Vector3(2.48f, 0.62f, 0f), 1.18f, 0.58f, 0.3f, 0.05f, rotation, _wood, 0.9f);
		CreateBeam(transform, "Left wooden locking peg", new Vector3(-2.665f, 0.61f, 0f), 0.13f, 0.17f, 0.17f, 0.025f, Quaternion.identity, _darkWood, 0.25f);
		CreateBeam(transform, "Right wooden locking peg", new Vector3(2.665f, 0.61f, 0f), 0.13f, 0.17f, 0.17f, 0.025f, Quaternion.identity, _darkWood, 0.25f);
		float[] array = new float[3] { -2.02f, 0f, 2.02f };
		foreach (float num in array)
		{
			CreateBeam(transform, "Cross support", new Vector3(num, 0.255f, 0f), 1.17f, 0.15f, 0.23f, 0.025f, rotation, _darkWood, 0.9f);
			CreateBeam(transform, "Front foot", new Vector3(num, 0.13f, -0.4f), 0.43f, 0.28f, 0.31f, 0.035f, Quaternion.Euler(-7f, 0f, 0f), _wood, 0.7f);
			CreateBeam(transform, "Rear foot", new Vector3(num, 0.13f, 0.4f), 0.43f, 0.28f, 0.31f, 0.035f, Quaternion.Euler(7f, 0f, 0f), _wood, 0.7f);
			CreateBeam(transform, "Front flush iron band", new Vector3(num, 0.625f, -0.626f), 0.54f, 0.105f, 0.028f, 0.012f, Quaternion.Euler(0f, 0f, 90f), _iron, 0.55f);
			CreateBeam(transform, "Rear flush iron band", new Vector3(num, 0.625f, 0.626f), 0.54f, 0.105f, 0.028f, 0.012f, Quaternion.Euler(0f, 0f, 90f), _iron, 0.55f);
			CreateBeam(transform, "Top flush iron band", new Vector3(num, 0.905f, 0f), 1.15f, 0.055f, 0.105f, 0.012f, rotation, _iron, 0.9f);
		}
		AddCarvedRunes(transform, -0.626f, reverse: false);
		AddCarvedRunes(transform, 0.626f, reverse: true);
		GameObject val3 = CreateFeedSurface(transform);
		val3.SetActive(false);
	}

	private static void AddCarvedRunes(Transform root, float z, bool reverse)
	{
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0065: Unknown result type (might be due to invalid IL or missing references)
		//IL_0087: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
		float[] array = new float[6] { -1.54f, -1.12f, -0.7f, 0.7f, 1.12f, 1.54f };
		foreach (float num in array)
		{
			float num2 = (reverse ? (-1f) : 1f);
			CreateBeam(root, "Shallow carved rune", new Vector3(num, 0.61f, z), 0.26f, 0.042f, 0.016f, 0.006f, Quaternion.Euler(0f, 0f, 38f * num2), _darkWood, 0.25f);
			CreateBeam(root, "Shallow carved rune", new Vector3(num, 0.61f, z), 0.26f, 0.042f, 0.016f, 0.006f, Quaternion.Euler(0f, 0f, -38f * num2), _darkWood, 0.25f);
		}
	}

	private static GameObject CreateFeedSurface(Transform root)
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Expected O, but got Unknown
		//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0101: Unknown result type (might be due to invalid IL or missing references)
		//IL_0117: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b3: Expected O, but got Unknown
		GameObject val = new GameObject("VisibleFeed");
		val.transform.SetParent(root, false);
		int num = 49;
		List<Vector3> list = new List<Vector3>(539);
		List<Vector3> list2 = new List<Vector3>(539);
		List<Vector2> list3 = new List<Vector2>(539);
		List<int> list4 = new List<int>(2880);
		for (int i = 0; i <= 10; i++)
		{
			float num2 = (float)i / 10f;
			for (int j = 0; j <= 48; j++)
			{
				float num3 = (float)j / 48f;
				float num4 = Mathf.Sin(num3 * (float)Math.PI) * Mathf.Sin(num2 * (float)Math.PI);
				float num5 = 0.012f * num4 * (Mathf.Sin((float)j * 1.31f + (float)i * 0.73f) + Mathf.Sin((float)j * 0.43f - (float)i * 1.19f));
				list.Add(new Vector3((num3 - 0.5f) * 4.53f, 0.76f + 0.1f * num4 + num5, (num2 - 0.5f) * 0.69f));
				list2.Add(Vector3.up);
				list3.Add(new Vector2(num3 * 6.55f, num2));
			}
		}
		for (int k = 0; k < 10; k++)
		{
			for (int l = 0; l < 48; l++)
			{
				int num6 = k * num + l;
				int num7 = num6 + num;
				list4.Add(num6);
				list4.Add(num7);
				list4.Add(num6 + 1);
				list4.Add(num6 + 1);
				list4.Add(num7);
				list4.Add(num7 + 1);
			}
		}
		Mesh val2 = new Mesh();
		((Object)val2).name = "AFT V3 continuous feed surface";
		Mesh val3 = val2;
		val3.SetVertices(list);
		val3.SetNormals(list2);
		val3.SetUVs(0, list3);
		val3.SetTriangles(list4, 0);
		val3.RecalculateNormals();
		val3.RecalculateBounds();
		val.AddComponent<MeshFilter>().sharedMesh = val3;
		((Renderer)val.AddComponent<MeshRenderer>()).sharedMaterial = _feed;
		return val;
	}

	private static GameObject CreateBeam(Transform parent, string name, Vector3 position, float length, float height, float depth, float bevel, Quaternion rotation, Material material, float uvLength)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Expected O, but got Unknown
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = new GameObject(name);
		val.transform.SetParent(parent, false);
		val.transform.localPosition = position;
		val.transform.localRotation = rotation;
		val.AddComponent<MeshFilter>().sharedMesh = BuildBevelledBeamMesh(name + " mesh", length, height, depth, bevel, uvLength);
		((Renderer)val.AddComponent<MeshRenderer>()).sharedMaterial = material;
		return val;
	}

	private static Mesh BuildBevelledBeamMesh(string name, float length, float height, float depth, float bevel, float uvLength)
	{
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_005d: 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_0075: Unknown result type (might be due to invalid IL or missing references)
		//IL_007a: Unknown result type (might be due to invalid IL or missing references)
		//IL_008c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0091: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_00bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_00ec: 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_0147: 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_0195: 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_01d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
		//IL_020f: 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_028a: Expected O, but got Unknown
		float num = length * 0.5f;
		float num2 = height * 0.5f;
		float num3 = depth * 0.5f;
		bevel = Mathf.Min(bevel, Mathf.Min(num2, num3) * 0.7f);
		Vector2[] array = (Vector2[])(object)new Vector2[8]
		{
			new Vector2(0f - num2 + bevel, 0f - num3),
			new Vector2(num2 - bevel, 0f - num3),
			new Vector2(num2, 0f - num3 + bevel),
			new Vector2(num2, num3 - bevel),
			new Vector2(num2 - bevel, num3),
			new Vector2(0f - num2 + bevel, num3),
			new Vector2(0f - num2, num3 - bevel),
			new Vector2(0f - num2, 0f - num3 + bevel)
		};
		List<Vector3> list = new List<Vector3>();
		List<Vector2> list2 = new List<Vector2>();
		List<int> list3 = new List<int>();
		for (int i = 0; i < array.Length; i++)
		{
			int num4 = (i + 1) % array.Length;
			int count = list.Count;
			list.Add(new Vector3(0f - num, array[i].x, array[i].y));
			list.Add(new Vector3(num, array[i].x, array[i].y));
			list.Add(new Vector3(num, array[num4].x, array[num4].y));
			list.Add(new Vector3(0f - num, array[num4].x, array[num4].y));
			list2.Add(new Vector2(0f, 0f));
			list2.Add(new Vector2(uvLength, 0f));
			list2.Add(new Vector2(uvLength, 1f));
			list2.Add(new Vector2(0f, 1f));
			list3.AddRange(new int[6]
			{
				count,
				count + 1,
				count + 2,
				count,
				count + 2,
				count + 3
			});
		}
		AddCap(list, list2, list3, array, 0f - num, positive: false);
		AddCap(list, list2, list3, array, num, positive: true);
		Mesh val = new Mesh();
		((Object)val).name = name;
		Mesh val2 = val;
		val2.SetVertices(list);
		val2.SetUVs(0, list2);
		val2.SetTriangles(list3, 0);
		val2.RecalculateNormals();
		val2.RecalculateBounds();
		return val2;
	}

	private static void AddCap(List<Vector3> vertices, List<Vector2> uv, List<int> triangles, Vector2[] profile, float x, bool positive)
	{
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_0052: Unknown result type (might be due to invalid IL or missing references)
		//IL_0081: Unknown result type (might be due to invalid IL or missing references)
		int count = vertices.Count;
		vertices.Add(new Vector3(x, 0f, 0f));
		uv.Add(new Vector2(0.5f, 0.5f));
		for (int i = 0; i < profile.Length; i++)
		{
			vertices.Add(new Vector3(x, profile[i].x, profile[i].y));
			uv.Add(new Vector2(0.5f + profile[i].y, 0.5f + profile[i].x));
		}
		for (int j = 0; j < profile.Length; j++)
		{
			int num = count + 1 + j;
			int num2 = count + 1 + (j + 1) % profile.Length;
			if (positive)
			{
				triangles.AddRange(new int[3] { count, num, num2 });
			}
			else
			{
				triangles.AddRange(new int[3] { count, num2, num });
			}
		}
	}

	private static Material CreateMaterial(string name, Shader shader, string resource, Color tint, float metallic, float smoothness, Vector2 scale, Vector2 offset)
	{
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Expected O, but got Unknown
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_010d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0115: Unknown result type (might be due to invalid IL or missing references)
		//IL_0161: Unknown result type (might be due to invalid IL or missing references)
		//IL_017a: Unknown result type (might be due to invalid IL or missing references)
		Texture2D val = LoadTexture(resource, name + " albedo");
		((Texture)val).wrapMode = (TextureWrapMode)0;
		((Texture)val).filterMode = (FilterMode)2;
		((Texture)val).anisoLevel = 4;
		Material val2 = new Material(shader);
		((Object)val2).name = name;
		val2.color = tint;
		val2.enableInstancing = true;
		Material val3 = val2;
		string[] array = new string[8] { "_BumpMap", "_MetallicGlossMap", "_SpecGlossMap", "_EmissionMap", "_OcclusionMap", "_DetailAlbedoMap", "_DetailNormalMap", "_ParallaxMap" };
		foreach (string text in array)
		{
			if (val3.HasProperty(text))
			{
				val3.SetTexture(text, (Texture)null);
			}
		}
		val3.DisableKeyword("_NORMALMAP");
		val3.DisableKeyword("_METALLICGLOSSMAP");
		val3.DisableKeyword("_SPECGLOSSMAP");
		val3.DisableKeyword("_EMISSION");
		val3.DisableKeyword("_DETAIL_MULX2");
		val3.DisableKeyword("_PARALLAXMAP");
		val3.mainTexture = (Texture)(object)val;
		val3.mainTextureScale = scale;
		val3.mainTextureOffset = offset;
		if (val3.HasProperty("_MainTex"))
		{
			val3.SetTexture("_MainTex", (Texture)(object)val);
		}
		if (val3.HasProperty("_BaseMap"))
		{
			val3.SetTexture("_BaseMap", (Texture)(object)val);
		}
		if (val3.HasProperty("_Color"))
		{
			val3.SetColor("_Color", tint);
		}
		if (val3.HasProperty("_BaseColor"))
		{
			val3.SetColor("_BaseColor", tint);
		}
		if (val3.HasProperty("_Metallic"))
		{
			val3.SetFloat("_Metallic", metallic);
		}
		if (val3.HasProperty("_Glossiness"))
		{
			val3.SetFloat("_Glossiness", smoothness);
		}
		if (val3.HasProperty("_Smoothness"))
		{
			val3.SetFloat("_Smoothness", smoothness);
		}
		return val3;
	}

	private static Texture2D LoadTexture(string resourceName, string textureName)
	{
		//IL_0004: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Expected O, but got Unknown
		Texture2D val = new Texture2D(2, 2, (TextureFormat)4, true);
		((Object)val).name = textureName;
		Texture2D val2 = val;
		using Stream stream = typeof(TroughModelV3).Assembly.GetManifestResourceStream(resourceName);
		if (stream == null)
		{
			throw new InvalidOperationException("New embedded texture is missing: " + resourceName);
		}
		using MemoryStream memoryStream = new MemoryStream();
		stream.CopyTo(memoryStream);
		Type type = Type.GetType("UnityEngine.ImageConversion, UnityEngine.ImageConversionModule", throwOnError: true);
		MethodInfo method = type.GetMethod("LoadImage", new Type[3]
		{
			typeof(Texture2D),
			typeof(byte[]),
			typeof(bool)
		});
		if (method == null || !(bool)method.Invoke(null, new object[3]
		{
			val2,
			memoryStream.ToArray(),
			false
		}))
		{
			throw new InvalidOperationException("New embedded texture could not be decoded: " + resourceName);
		}
		return val2;
	}

	internal static Sprite CreateIcon()
	{
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		Texture2D val = LoadTexture("AnimalFeedingTroughV3.Icon", "AFT V3 build icon");
		((Texture)val).wrapMode = (TextureWrapMode)1;
		return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), (float)((Texture)val).width);
	}
}
internal static class TroughFoodRules
{
	internal static readonly ConditionalWeakTable<Inventory, Container> Troughs = new ConditionalWeakTable<Inventory, Container>();

	private static readonly HashSet<string> Foods = new HashSet<string>(StringComparer.Ordinal);

	private static float _nextRefresh;

	private static float _nextMessage;

	[ThreadStatic]
	internal static int Loading;

	internal static bool IsFood(ItemData item)
	{
		if (item == null || item.m_shared == null)
		{
			return false;
		}
		if (Time.time >= _nextRefresh || Foods.Count == 0)
		{
			_nextRefresh = Time.time + 10f;
			Foods.Clear();
			if (Object.op_Implicit((Object)(object)ZNetScene.instance))
			{
				foreach (GameObject prefab in ZNetScene.instance.m_prefabs)
				{
					if (!Object.op_Implicit((Object)(object)prefab) || !Object.op_Implicit((Object)(object)prefab.GetComponent<Tameable>()))
					{
						continue;
					}
					MonsterAI component = prefab.GetComponent<MonsterAI>();
					if (!Object.op_Implicit((Object)(object)component) || component.m_consumeItems == null)
					{
						continue;
					}
					foreach (ItemDrop consumeItem in component.m_consumeItems)
					{
						if (Object.op_Implicit((Object)(object)consumeItem) && consumeItem.m_itemData != null && consumeItem.m_itemData.m_shared != null)
						{
							Foods.Add(consumeItem.m_itemData.m_shared.m_name);
						}
					}
				}
			}
		}
		return Foods.Contains(item.m_shared.m_name);
	}

	internal static bool Accept(Inventory inventory, ItemData item, bool notify)
	{
		if (Loading > 0 || !Troughs.TryGetValue(inventory, out var value) || !Object.op_Implicit((Object)(object)value) || IsFood(item))
		{
			return true;
		}
		if (notify && Object.op_Implicit((Object)(object)Player.m_localPlayer) && Time.time >= _nextMessage)
		{
			_nextMessage = Time.time + 1.5f;
			((Character)Player.m_localPlayer).Message((MessageType)2, LocalizationManager.Instance.TryTranslate("$xneliox_trough_food_only"), 0, (Sprite)null, false);
		}
		return false;
	}
}
[HarmonyPatch(typeof(Container), "GetInventory")]
internal static class RegisterTroughInventory
{
	private static void Postfix(Container __instance, Inventory __result)
	{
		if (__result != null && Object.op_Implicit((Object)(object)((Component)__instance).GetComponent<TroughFeeder>()) && !TroughFoodRules.Troughs.TryGetValue(__result, out var _))
		{
			TroughFoodRules.Troughs.Add(__result, __instance);
		}
	}
}
[HarmonyPatch]
internal static class FilterTroughInsertion
{
	private static IEnumerable<MethodBase> TargetMethods()
	{
		try
		{
			MethodInfo[] methods = typeof(Inventory).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (MethodInfo method in methods)
			{
				ParameterInfo[] args = method.GetParameters();
				if ((method.Name == "AddItem" || method.Name == "CanAddItem") && method.ReturnType == typeof(bool) && args.Length > 0 && args[0].ParameterType == typeof(ItemData))
				{
					yield return method;
				}
			}
		}
		finally
		{
		}
	}

	private static bool Prefix(Inventory __instance, ItemData __0, MethodBase __originalMethod, ref bool __result)
	{
		if (TroughFoodRules.Accept(__instance, __0, __originalMethod.Name == "AddItem"))
		{
			return true;
		}
		__result = false;
		return false;
	}
}
[HarmonyPatch]
internal static class PreserveSavedTroughContents
{
	private static IEnumerable<MethodBase> TargetMethods()
	{
		try
		{
			MethodInfo[] methods = typeof(Inventory).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (MethodInfo method in methods)
			{
				if (method.Name == "Load")
				{
					yield return method;
				}
			}
		}
		finally
		{
		}
	}

	private static void Prefix()
	{
		TroughFoodRules.Loading++;
	}

	private static Exception Finalizer(Exception __exception)
	{
		TroughFoodRules.Loading--;
		return __exception;
	}
}
internal static class TroughServingProtection
{
	internal const string Marker = "xneliox_trough_serving";

	private static readonly FieldInfo Instances = AccessTools.Field(typeof(ItemDrop), "s_instances");

	private static readonly MethodInfo CloneShared = AccessTools.Method(typeof(object), "MemberwiseClone", (Type[])null, (Type[])null);

	private static readonly ConditionalWeakTable<ItemDrop, object> Protected = new ConditionalWeakTable<ItemDrop, object>();

	internal static void ApplyLocalProtection(ItemDrop item)
	{
		//IL_0052: Unknown result type (might be due to invalid IL or missing references)
		//IL_005c: Expected O, but got Unknown
		//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0108: Unknown result type (might be due to invalid IL or missing references)
		if (!Object.op_Implicit((Object)(object)item))
		{
			return;
		}
		item.m_autoPickup = false;
		if (!Protected.TryGetValue(item, out var _) && item.m_itemData != null && item.m_itemData.m_shared != null)
		{
			item.m_itemData.m_shared = (SharedData)CloneShared.Invoke(item.m_itemData.m_shared, null);
			item.m_itemData.m_shared.m_autoStack = false;
			Renderer[] componentsInChildren = ((Component)item).GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val in componentsInChildren)
			{
				val.enabled = false;
			}
			ParticleSystem[] componentsInChildren2 = ((Component)item).GetComponentsInChildren<ParticleSystem>(true);
			foreach (ParticleSystem val2 in componentsInChildren2)
			{
				val2.Stop(true, (ParticleSystemStopBehavior)0);
			}
			Light[] componentsInChildren3 = ((Component)item).GetComponentsInChildren<Light>(true);
			foreach (Light val3 in componentsInChildren3)
			{
				((Behaviour)val3).enabled = false;
			}
			Rigidbody component = ((Component)item).GetComponent<Rigidbody>();
			if (Object.op_Implicit((Object)(object)component))
			{
				component.linearVelocity = Vector3.zero;
				component.angularVelocity = Vector3.zero;
				component.useGravity = false;
				component.constraints = (RigidbodyConstraints)126;
			}
			Protected.Add(item, new object());
		}
	}

	internal static bool IsServing(ItemDrop item)
	{
		if (!Object.op_Implicit((Object)(object)item))
		{
			return false;
		}
		if (((Object)((Component)item).gameObject).name.StartsWith("TroughServing_"))
		{
			return true;
		}
		ZNetView component = ((Component)item).GetComponent<ZNetView>();
		if (Object.op_Implicit((Object)(object)component) && component.IsValid())
		{
			return component.GetZDO().GetBool("xneliox_trough_serving", false);
		}
		return false;
	}

	internal static void DisableAttraction()
	{
		if (!(Instances.GetValue(null) is List<ItemDrop> list))
		{
			return;
		}
		foreach (ItemDrop item in list)
		{
			if (IsServing(item))
			{
				ApplyLocalProtection(item);
			}
		}
	}

	internal static IEnumerable<ItemDrop> GetServings()
	{
		if (!(Instances.GetValue(null) is List<ItemDrop> items))
		{
			yield break;
		}
		foreach (ItemDrop item in items)
		{
			if (IsServing(item))
			{
				yield return item;
			}
		}
	}
}
[HarmonyPatch(typeof(ItemDrop), "SlowUpdate")]
internal static class RestoreServingProtection
{
	private static void Prefix(ItemDrop __instance)
	{
		if (TroughServingProtection.IsServing(__instance))
		{
			TroughServingProtection.ApplyLocalProtection(__instance);
		}
	}
}
[HarmonyPatch(typeof(ItemDrop), "AutoStackItems")]
internal static class PreventServingStackMerge
{
	private static bool Prefix(ItemDrop __instance)
	{
		TroughServingProtection.DisableAttraction();
		return !TroughServingProtection.IsServing(__instance);
	}
}
[HarmonyPatch(typeof(Player), "AutoPickup")]
internal static class NoTroughServingAttraction
{
	private static void Prefix()
	{
		TroughServingProtection.DisableAttraction();
	}
}
[HarmonyPatch(typeof(Humanoid), "Pickup", new Type[]
{
	typeof(GameObject),
	typeof(bool),
	typeof(bool)
})]
internal static class NoPlayerServingPickup
{
	private static bool Prefix(Humanoid __instance, GameObject __0, ref bool __result)
	{
		if (!((Character)__instance).IsPlayer() || !Object.op_Implicit((Object)(object)__0) || !TroughServingProtection.IsServing(__0.GetComponent<ItemDrop>()))
		{
			return true;
		}
		__result = false;
		return false;
	}
}
[HarmonyPatch(typeof(ItemDrop), "Pickup", new Type[] { typeof(Humanoid) })]
internal static class NoManualServingPickup
{
	private static bool Prefix(ItemDrop __instance, Humanoid __0)
	{
		if (Object.op_Implicit((Object)(object)__0) && ((Character)__0).IsPlayer())
		{
			return !TroughServingProtection.IsServing(__instance);
		}
		return true;
	}
}
[HarmonyPatch(typeof(WearNTear), "Damage", new Type[] { typeof(HitData) })]
internal static class PreventTameableAnimalTroughDamage
{
	private static bool Prefix(WearNTear __instance, HitData hit)
	{
		if (!Object.op_Implicit((Object)(object)__instance) || hit == null || !Object.op_Implicit((Object)(object)((Component)__instance).GetComponentInParent<TroughFeeder>()))
		{
			return true;
		}
		Character attacker = hit.GetAttacker();
		if (Object.op_Implicit((Object)(object)attacker))
		{
			return !Object.op_Implicit((Object)(object)((Component)attacker).GetComponent<Tameable>());
		}
		return true;
	}
}
internal static class TroughTranslations
{
	internal static void Register()
	{
		CustomLocalization localization = LocalizationManager.Instance.GetLocalization();
		string text = "English";
		localization.AddTranslation(ref text, new Dictionary<string, string>
		{
			{ "xneliox_trough_name", "Feeding Trough" },
			{ "xneliox_trough_description", "A long trough for feeding tamed and tameable animals. Only suitable animal food can be stored here." },
			{ "xneliox_trough_food_only", "Only food eaten by tameable animals can be placed in this trough." }
		});
		string text2 = "German";
		localization.AddTranslation(ref text2, new Dictionary<string, string>
		{
			{ "xneliox_trough_name", "Futtertrog" },
			{ "xneliox_trough_description", "Ein langer Futtertrog für gezähmte und zähmbare Tiere. Hier kann nur geeignetes Tierfutter gelagert werden." },
			{ "xneliox_trough_food_only", "In diesen Trog kann nur Futter gelegt werden, das von zähmbaren Tieren gefressen wird." }
		});
		string text3 = "Russian";
		localization.AddTranslation(ref text3, new Dictionary<string, string>
		{
			{ "xneliox_trough_name", "Кормушка" },
			{ "xneliox_trough_description", "Длинная кормушка для приручённых и приручаемых животных. Сюда можно класть только подходящий для них корм." },
			{ "xneliox_trough_food_only", "В эту кормушку можно класть только корм, который едят приручаемые животные." }
		});
		string text4 = "Ukrainian";
		localization.AddTranslation(ref text4, new Dictionary<string, string>
		{
			{ "xneliox_trough_name", "Годівниця" },
			{ "xneliox_trough_description", "Довга годівниця для приручених тварин і тварин, яких можна приручити. Сюди можна класти лише придатний для них корм." },
			{ "xneliox_trough_food_only", "У цю годівницю можна класти лише корм, який їдять тварини, яких можна приручити." }
		});
		string text5 = "Japanese";
		localization.AddTranslation(ref text5, new Dictionary<string, string>
		{
			{ "xneliox_trough_name", "飼い葉桶" },
			{ "xneliox_trough_description", "飼いならした動物や、これから飼いならす動物に餌を与えるための長い飼い葉桶。飼いならせる動物が食べる餌だけを入れられます。" },
			{ "xneliox_trough_food_only", "この桶には、飼いならせる動物が食べる餌だけを入れられます。" }
		});
	}
}