Decompiled source of FeedLikeGrandma v1.1.8

FeedLikeGrandma.dll

Decompiled 3 days ago
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Cryptography;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using FeedLikeGrandma;
using HarmonyLib;
using JetBrains.Annotations;
using LocalizationManager;
using Microsoft.CodeAnalysis;
using ServerSync;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
using YamlDotNet.Core;
using YamlDotNet.Core.Events;
using YamlDotNet.Core.ObjectPool;
using YamlDotNet.Core.Tokens;
using YamlDotNet.Helpers;
using YamlDotNet.RepresentationModel;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.BufferedDeserialization;
using YamlDotNet.Serialization.BufferedDeserialization.TypeDiscriminators;
using YamlDotNet.Serialization.Callbacks;
using YamlDotNet.Serialization.Converters;
using YamlDotNet.Serialization.EventEmitters;
using YamlDotNet.Serialization.NamingConventions;
using YamlDotNet.Serialization.NodeDeserializers;
using YamlDotNet.Serialization.NodeTypeResolvers;
using YamlDotNet.Serialization.ObjectFactories;
using YamlDotNet.Serialization.ObjectGraphTraversalStrategies;
using YamlDotNet.Serialization.ObjectGraphVisitors;
using YamlDotNet.Serialization.Schemas;
using YamlDotNet.Serialization.TypeInspectors;
using YamlDotNet.Serialization.TypeResolvers;
using YamlDotNet.Serialization.Utilities;
using YamlDotNet.Serialization.ValueDeserializers;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("FeedLikeGrandma")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("sighsorry")]
[assembly: AssemblyProduct("FeedLikeGrandma")]
[assembly: AssemblyCopyright("Copyright © 2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("4358610B-F3F4-4843-B7AF-98B7BC60DCDE")]
[assembly: AssemblyFileVersion("1.1.8")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.1.8.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.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = 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 LocalizationManager
{
	[PublicAPI]
	public class Localizer
	{
		private static readonly Dictionary<string, Dictionary<string, Func<string>>> PlaceholderProcessors;

		private static readonly Dictionary<string, Dictionary<string, string>> loadedTexts;

		private static readonly ConditionalWeakTable<Localization, string> localizationLanguage;

		private static readonly List<WeakReference<Localization>> localizationObjects;

		private static BaseUnityPlugin? _plugin;

		private static readonly List<string> fileExtensions;

		private static BaseUnityPlugin plugin
		{
			get
			{
				//IL_009b: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a5: Expected O, but got Unknown
				if (_plugin == null)
				{
					IEnumerable<TypeInfo> source;
					try
					{
						source = Assembly.GetExecutingAssembly().DefinedTypes.ToList();
					}
					catch (ReflectionTypeLoadException ex)
					{
						source = from t in ex.Types
							where t != null
							select t.GetTypeInfo();
					}
					_plugin = (BaseUnityPlugin)Chainloader.ManagerObject.GetComponent((Type)source.First((TypeInfo t) => t.IsClass && typeof(BaseUnityPlugin).IsAssignableFrom(t)));
				}
				return _plugin;
			}
		}

		public static event Action? OnLocalizationComplete;

		private static void UpdatePlaceholderText(Localization localization, string key)
		{
			localizationLanguage.TryGetValue(localization, out string value);
			string text = loadedTexts[value][key];
			if (PlaceholderProcessors.TryGetValue(key, out Dictionary<string, Func<string>> value2))
			{
				text = value2.Aggregate(text, (string current, KeyValuePair<string, Func<string>> kv) => current.Replace("{" + kv.Key + "}", kv.Value()));
			}
			localization.AddWord(key, text);
		}

		public static void AddPlaceholder<T>(string key, string placeholder, ConfigEntry<T> config, Func<T, string>? convertConfigValue = null) where T : notnull
		{
			if (convertConfigValue == null)
			{
				convertConfigValue = (T val) => val.ToString();
			}
			if (!PlaceholderProcessors.ContainsKey(key))
			{
				PlaceholderProcessors[key] = new Dictionary<string, Func<string>>();
			}
			config.SettingChanged += delegate
			{
				UpdatePlaceholder();
			};
			if (loadedTexts.ContainsKey(Localization.instance.GetSelectedLanguage()))
			{
				UpdatePlaceholder();
			}
			void UpdatePlaceholder()
			{
				PlaceholderProcessors[key][placeholder] = () => convertConfigValue(config.Value);
				UpdatePlaceholderText(Localization.instance, key);
			}
		}

		public static void AddText(string key, string text)
		{
			List<WeakReference<Localization>> list = new List<WeakReference<Localization>>();
			foreach (WeakReference<Localization> localizationObject in localizationObjects)
			{
				if (localizationObject.TryGetTarget(out var target))
				{
					Dictionary<string, string> dictionary = loadedTexts[localizationLanguage.GetOrCreateValue(target)];
					if (!target.Translations().ContainsKey(key))
					{
						dictionary[key] = text;
						target.AddWord(key, text);
					}
				}
				else
				{
					list.Add(localizationObject);
				}
			}
			foreach (WeakReference<Localization> item in list)
			{
				localizationObjects.Remove(item);
			}
		}

		public static void Load()
		{
			_ = plugin;
		}

		public static void LoadLocalizationLater(Localization __instance)
		{
			LoadLocalization(Localization.instance, __instance.GetSelectedLanguage());
		}

		private static void LoadStartupLocalization()
		{
			LoadLocalizationLater(Localization.instance);
		}

		public static void SafeCallLocalizeComplete()
		{
			Localizer.OnLocalizationComplete?.Invoke();
		}

		private static void LoadLocalization(Localization __instance, string language)
		{
			if (!localizationLanguage.Remove(__instance))
			{
				localizationObjects.Add(new WeakReference<Localization>(__instance));
			}
			localizationLanguage.Add(__instance, language);
			Dictionary<string, string> dictionary = new Dictionary<string, string>();
			foreach (string item in from f in Directory.GetFiles(Path.GetDirectoryName(Paths.PluginPath), plugin.Info.Metadata.Name + ".*", SearchOption.AllDirectories)
				where fileExtensions.IndexOf(Path.GetExtension(f)) >= 0
				select f)
			{
				string[] array = Path.GetFileNameWithoutExtension(item).Split(new char[1] { '.' });
				if (array.Length >= 2)
				{
					string text = array[1];
					if (dictionary.ContainsKey(text))
					{
						Debug.LogWarning((object)("Duplicate key " + text + " found for " + plugin.Info.Metadata.Name + ". The duplicate file found at " + item + " will be skipped."));
					}
					else
					{
						dictionary[text] = item;
					}
				}
			}
			byte[] array2 = LoadTranslationFromAssembly("English");
			if (array2 == null)
			{
				throw new Exception("Found no English localizations in mod " + plugin.Info.Metadata.Name + ". Expected an embedded resource translations/English.json or translations/English.yml.");
			}
			Dictionary<string, string> dictionary2 = new DeserializerBuilder().IgnoreFields().Build().Deserialize<Dictionary<string, string>>(Encoding.UTF8.GetString(array2));
			if (dictionary2 == null)
			{
				throw new Exception("Localization for mod " + plugin.Info.Metadata.Name + " failed: Localization file was empty.");
			}
			string text2 = null;
			if (language != "English")
			{
				if (dictionary.TryGetValue(language, out var value))
				{
					text2 = File.ReadAllText(value);
				}
				else
				{
					byte[] array3 = LoadTranslationFromAssembly(language);
					if (array3 != null)
					{
						text2 = Encoding.UTF8.GetString(array3);
					}
				}
			}
			if (text2 == null && dictionary.TryGetValue("English", out var value2))
			{
				text2 = File.ReadAllText(value2);
			}
			if (text2 != null)
			{
				foreach (KeyValuePair<string, string> item2 in new DeserializerBuilder().IgnoreFields().Build().Deserialize<Dictionary<string, string>>(text2) ?? new Dictionary<string, string>())
				{
					dictionary2[item2.Key] = item2.Value;
				}
			}
			loadedTexts[language] = dictionary2;
			foreach (KeyValuePair<string, string> item3 in dictionary2)
			{
				UpdatePlaceholderText(__instance, item3.Key);
			}
		}

		static Localizer()
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Expected O, but got Unknown
			//IL_008f: 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_00ca: Expected O, but got Unknown
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Expected O, but got Unknown
			PlaceholderProcessors = new Dictionary<string, Dictionary<string, Func<string>>>();
			loadedTexts = new Dictionary<string, Dictionary<string, string>>();
			localizationLanguage = new ConditionalWeakTable<Localization, string>();
			localizationObjects = new List<WeakReference<Localization>>();
			fileExtensions = new List<string>(2) { ".json", ".yml" };
			Harmony val = new Harmony("org.bepinex.helpers.LocalizationManager");
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Localization), "SetupLanguage", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Localizer), "LoadLocalization", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(FejdStartup), "SetupGui", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Localizer), "LoadStartupLocalization", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(FejdStartup), "Start", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Localizer), "SafeCallLocalizeComplete", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}

		private static byte[]? LoadTranslationFromAssembly(string language)
		{
			foreach (string fileExtension in fileExtensions)
			{
				byte[] array = ReadEmbeddedFileBytes("translations." + language + fileExtension);
				if (array != null)
				{
					return array;
				}
			}
			return null;
		}

		public static byte[]? ReadEmbeddedFileBytes(string resourceFileName, Assembly? containingAssembly = null)
		{
			using MemoryStream memoryStream = new MemoryStream();
			if ((object)containingAssembly == null)
			{
				containingAssembly = Assembly.GetCallingAssembly();
			}
			string text = containingAssembly.GetManifestResourceNames().FirstOrDefault((string str) => str.EndsWith(resourceFileName, StringComparison.Ordinal));
			if (text != null)
			{
				containingAssembly.GetManifestResourceStream(text)?.CopyTo(memoryStream);
			}
			return (memoryStream.Length == 0L) ? null : memoryStream.ToArray();
		}
	}
	public static class LocalizationManagerVersion
	{
		public const string Version = "1.4.1";
	}
}
namespace System.Runtime.CompilerServices
{
	internal static class IsExternalInit
	{
	}
}
namespace FeedLikeGrandma
{
	internal static class FeedConsoleCommands
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static ConsoleEvent <0>__WriteReference;

			public static ConsoleOptionsFetcher <1>__GetEmptyOptions;
		}

		private static readonly List<string> EmptyOptions = new List<string>();

		private static bool Registered;

		internal static void Register()
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Expected O, but got Unknown
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Expected O, but got Unknown
			if (!Registered)
			{
				Registered = true;
				object obj = <>O.<0>__WriteReference;
				if (obj == null)
				{
					ConsoleEvent val = WriteReference;
					<>O.<0>__WriteReference = val;
					obj = (object)val;
				}
				object obj2 = <>O.<1>__GetEmptyOptions;
				if (obj2 == null)
				{
					ConsoleOptionsFetcher val2 = GetEmptyOptions;
					<>O.<1>__GetEmptyOptions = val2;
					obj2 = (object)val2;
				}
				new ConsoleCommand("flg:reference", "Write generated FeedLikeGrandma reference YAML. Usage: flg:reference", (ConsoleEvent)obj, false, false, false, false, false, false, (ConsoleOptionsFetcher)obj2, false, false, false);
			}
		}

		private static List<string> GetEmptyOptions()
		{
			return EmptyOptions;
		}

		private static void WriteReference(ConsoleEventArgs args)
		{
			if (FeedLikeGrandmaPlugin.TryWriteReferenceConfigurationFile(out string path, out string error))
			{
				Terminal context = args.Context;
				if (context != null)
				{
					context.AddString("Wrote FeedLikeGrandma reference to " + path);
				}
			}
			else
			{
				Terminal context2 = args.Context;
				if (context2 != null)
				{
					context2.AddString(error);
				}
			}
		}
	}
	internal static class GameAccess
	{
		private static readonly FieldRef<BaseAI, Tameable> BaseAITameable = AccessTools.FieldRefAccess<BaseAI, Tameable>("m_tamable");

		private static readonly FieldRef<Character, ZNetView> CharacterNetworkView = AccessTools.FieldRefAccess<Character, ZNetView>("m_nview");

		private static readonly FieldRef<Character, float> CharacterWaterLevel = AccessTools.FieldRefAccess<Character, float>("m_waterLevel");

		private static readonly FieldRef<Character, float> CharacterTarLevel = AccessTools.FieldRefAccess<Character, float>("m_tarLevel");

		private static readonly FieldRef<Container, ZNetView> ContainerNetworkView = AccessTools.FieldRefAccess<Container, ZNetView>("m_nview");

		private static readonly FieldRef<Container, Piece> ContainerContainerPiece = AccessTools.FieldRefAccess<Container, Piece>("m_piece");

		private static readonly FieldRef<EggGrow, ZNetView> EggGrowNetworkView = AccessTools.FieldRefAccess<EggGrow, ZNetView>("m_nview");

		private static readonly FieldRef<EggGrow, ItemDrop> EggGrowEggItem = AccessTools.FieldRefAccess<EggGrow, ItemDrop>("m_item");

		private static readonly FieldRef<Growup, ZNetView> GrowupNetworkView = AccessTools.FieldRefAccess<Growup, ZNetView>("m_nview");

		private static readonly FieldRef<Procreation, ZNetView> ProcreationNetworkView = AccessTools.FieldRefAccess<Procreation, ZNetView>("m_nview");

		private static readonly FieldRef<Procreation, GameObject> ProcreationOwnPrefab = AccessTools.FieldRefAccess<Procreation, GameObject>("m_myPrefab");

		private static readonly FieldRef<Procreation, GameObject> ProcreationOffspringPrefab = AccessTools.FieldRefAccess<Procreation, GameObject>("m_offspringPrefab");

		private static readonly FieldRef<Procreation, Tameable> ProcreationTameableComponent = AccessTools.FieldRefAccess<Procreation, Tameable>("m_tameable");

		private static readonly FieldRef<Sadle, ZNetView> SadleNetworkView = AccessTools.FieldRefAccess<Sadle, ZNetView>("m_nview");

		private static readonly FieldRef<Sadle, int> SadleRidingSpeed = AccessTools.FieldRefAccess<Sadle, int>("m_speed");

		private static readonly FieldRef<BaseAI, ZSyncAnimation> BaseAISyncedAnimator = AccessTools.FieldRefAccess<BaseAI, ZSyncAnimation>("m_animator");

		private static readonly FieldRef<ZSyncAnimation, Animator> ZSyncAnimationUnityAnimator = AccessTools.FieldRefAccess<ZSyncAnimation, Animator>("m_animator");

		private static readonly FieldRef<Humanoid, float> HumanoidAttackDrawTime = AccessTools.FieldRefAccess<Humanoid, float>("m_attackDrawTime");

		private static readonly FieldRef<Inventory, int> InventoryInventoryWidth = AccessTools.FieldRefAccess<Inventory, int>("m_width");

		private static readonly FieldRef<Inventory, int> InventoryInventoryHeight = AccessTools.FieldRefAccess<Inventory, int>("m_height");

		private static readonly FieldRef<ObjectDB, Dictionary<int, GameObject>> ObjectDBItemHashes = AccessTools.FieldRefAccess<ObjectDB, Dictionary<int, GameObject>>("m_itemByHash");

		private static readonly FieldRef<ObjectDB, Dictionary<SharedData, GameObject>> ObjectDBItemDataPrefabs = AccessTools.FieldRefAccess<ObjectDB, Dictionary<SharedData, GameObject>>("m_itemByData");

		private static readonly FieldRef<ZNetScene, Dictionary<int, GameObject>> ZNetSceneNamedPrefabs = AccessTools.FieldRefAccess<ZNetScene, Dictionary<int, GameObject>>("m_namedPrefabs");

		private static readonly FieldRef<ZNetScene, Dictionary<ZDO, ZNetView>> ZNetSceneInstances = AccessTools.FieldRefAccess<ZNetScene, Dictionary<ZDO, ZNetView>>("m_instances");

		private static readonly FieldRef<ZNetView, IDictionary> ZNetViewRpcHandlers = AccessTools.FieldRefAccess<ZNetView, IDictionary>("m_functions");

		private static readonly FieldRef<ZRoutedRpc, IDictionary> ZRoutedRpcRpcHandlers = AccessTools.FieldRefAccess<ZRoutedRpc, IDictionary>("m_functions");

		private static readonly FieldRef<ZRoutedRpc, long> ZRoutedRpcPeerId = AccessTools.FieldRefAccess<ZRoutedRpc, long>("m_id");

		private static readonly FieldRef<GameCamera, Camera> GameCameraGameCameraComponent = AccessTools.FieldRefAccess<GameCamera, Camera>("m_camera");

		private static readonly FieldRef<Localization, Dictionary<string, string>> LocalizationTranslations = AccessTools.FieldRefAccess<Localization, Dictionary<string, string>>("m_translations");

		private static readonly FieldRef<HotkeyBar, List<ItemData>> HotkeyBarHotbarItems = AccessTools.FieldRefAccess<HotkeyBar, List<ItemData>>("m_items");

		private static readonly FieldRef<HotkeyBar, IList> HotkeyBarHotbarElements = AccessTools.FieldRefAccess<HotkeyBar, IList>("m_elements");

		private static readonly Func<BaseAI, Vector3, bool> BaseAIHavePath = AccessTools.MethodDelegate<Func<BaseAI, Vector3, bool>>(AccessTools.DeclaredMethod(typeof(BaseAI), "HavePath", new Type[1] { typeof(Vector3) }, (Type[])null), (object)null, true);

		private static readonly Action<Container> ContainerSave = AccessTools.MethodDelegate<Action<Container>>(AccessTools.DeclaredMethod(typeof(Container), "Save", new Type[0], (Type[])null), (object)null, true);

		private static readonly Func<Growup, GameObject> GrowupGetPrefab = AccessTools.MethodDelegate<Func<Growup, GameObject>>(AccessTools.DeclaredMethod(typeof(Growup), "GetPrefab", new Type[0], (Type[])null), (object)null, true);

		private static readonly Action<Humanoid, PieceTable> HumanoidSetPlaceMode = AccessTools.MethodDelegate<Action<Humanoid, PieceTable>>(AccessTools.DeclaredMethod(typeof(Humanoid), "SetPlaceMode", new Type[1] { typeof(PieceTable) }, (Type[])null), (object)null, true);

		private static readonly Action<Inventory, bool, bool> InventoryChanged = AccessTools.MethodDelegate<Action<Inventory, bool, bool>>(AccessTools.DeclaredMethod(typeof(Inventory), "Changed", new Type[2]
		{
			typeof(bool),
			typeof(bool)
		}, (Type[])null), (object)null, true);

		private static readonly Func<Procreation, bool> ProcreationIsPregnant = AccessTools.MethodDelegate<Func<Procreation, bool>>(AccessTools.DeclaredMethod(typeof(Procreation), "IsPregnant", new Type[0], (Type[])null), (object)null, true);

		private static readonly Func<Sadle, bool> SadleIsLocalUser = AccessTools.MethodDelegate<Func<Sadle, bool>>(AccessTools.DeclaredMethod(typeof(Sadle), "IsLocalUser", new Type[0], (Type[])null), (object)null, true);

		private static readonly Action<Sadle, float> SadleSetStamina = AccessTools.MethodDelegate<Action<Sadle, float>>(AccessTools.DeclaredMethod(typeof(Sadle), "SetStamina", new Type[1] { typeof(float) }, (Type[])null), (object)null, true);

		private static readonly Action<Sadle, float> SadleUseStamina = AccessTools.MethodDelegate<Action<Sadle, float>>(AccessTools.DeclaredMethod(typeof(Sadle), "UseStamina", new Type[1] { typeof(float) }, (Type[])null), (object)null, true);

		private static readonly Func<Tameable, bool> TameableHaveSaddle = AccessTools.MethodDelegate<Func<Tameable, bool>>(AccessTools.DeclaredMethod(typeof(Tameable), "HaveSaddle", new Type[0], (Type[])null), (object)null, true);

		private static readonly Func<Tameable, float> TameableGetRemainingTime = AccessTools.MethodDelegate<Func<Tameable, float>>(AccessTools.DeclaredMethod(typeof(Tameable), "GetRemainingTime", new Type[0], (Type[])null), (object)null, true);

		private static readonly Action<Tameable, long, string, string> TameableRPC_SetName = AccessTools.MethodDelegate<Action<Tameable, long, string, string>>(AccessTools.DeclaredMethod(typeof(Tameable), "RPC_SetName", new Type[3]
		{
			typeof(long),
			typeof(string),
			typeof(string)
		}, (Type[])null), (object)null, true);

		private static readonly Action<Tameable, bool> TameableSetSaddle = AccessTools.MethodDelegate<Action<Tameable, bool>>(AccessTools.DeclaredMethod(typeof(Tameable), "SetSaddle", new Type[1] { typeof(bool) }, (Type[])null), (object)null, true);

		private static readonly Action<Tameable> TameableTame = AccessTools.MethodDelegate<Action<Tameable>>(AccessTools.DeclaredMethod(typeof(Tameable), "Tame", new Type[0], (Type[])null), (object)null, true);

		private static readonly Func<ZRoutedRpc, long> ZRoutedRpcGetServerPeerID = AccessTools.MethodDelegate<Func<ZRoutedRpc, long>>(AccessTools.DeclaredMethod(typeof(ZRoutedRpc), "GetServerPeerID", new Type[0], (Type[])null), (object)null, true);

		private static readonly Action<Localization, string, string> LocalizationAddWord = AccessTools.MethodDelegate<Action<Localization, string, string>>(AccessTools.DeclaredMethod(typeof(Localization), "AddWord", new Type[2]
		{
			typeof(string),
			typeof(string)
		}, (Type[])null), (object)null, true);

		internal static ref Tameable TameableComponent(this BaseAI instance)
		{
			return ref BaseAITameable.Invoke(instance);
		}

		internal static ref ZNetView NetworkView(this Character instance)
		{
			return ref CharacterNetworkView.Invoke(instance);
		}

		internal static ref float WaterLevel(this Character instance)
		{
			return ref CharacterWaterLevel.Invoke(instance);
		}

		internal static ref float TarLevel(this Character instance)
		{
			return ref CharacterTarLevel.Invoke(instance);
		}

		internal static ref ZNetView NetworkView(this Container instance)
		{
			return ref ContainerNetworkView.Invoke(instance);
		}

		internal static ref Piece ContainerPiece(this Container instance)
		{
			return ref ContainerContainerPiece.Invoke(instance);
		}

		internal static ref ZNetView NetworkView(this EggGrow instance)
		{
			return ref EggGrowNetworkView.Invoke(instance);
		}

		internal static ref ItemDrop EggItem(this EggGrow instance)
		{
			return ref EggGrowEggItem.Invoke(instance);
		}

		internal static ref ZNetView NetworkView(this Growup instance)
		{
			return ref GrowupNetworkView.Invoke(instance);
		}

		internal static ref ZNetView NetworkView(this Procreation instance)
		{
			return ref ProcreationNetworkView.Invoke(instance);
		}

		internal static ref GameObject OwnPrefab(this Procreation instance)
		{
			return ref ProcreationOwnPrefab.Invoke(instance);
		}

		internal static ref GameObject OffspringPrefab(this Procreation instance)
		{
			return ref ProcreationOffspringPrefab.Invoke(instance);
		}

		internal static ref Tameable TameableComponent(this Procreation instance)
		{
			return ref ProcreationTameableComponent.Invoke(instance);
		}

		internal static ref ZNetView NetworkView(this Sadle instance)
		{
			return ref SadleNetworkView.Invoke(instance);
		}

		internal static ref int RidingSpeed(this Sadle instance)
		{
			return ref SadleRidingSpeed.Invoke(instance);
		}

		internal static ref ZSyncAnimation SyncedAnimator(this BaseAI instance)
		{
			return ref BaseAISyncedAnimator.Invoke(instance);
		}

		internal static ref Animator UnityAnimator(this ZSyncAnimation instance)
		{
			return ref ZSyncAnimationUnityAnimator.Invoke(instance);
		}

		internal static ref float AttackDrawTime(this Humanoid instance)
		{
			return ref HumanoidAttackDrawTime.Invoke(instance);
		}

		internal static ref int InventoryWidth(this Inventory instance)
		{
			return ref InventoryInventoryWidth.Invoke(instance);
		}

		internal static ref int InventoryHeight(this Inventory instance)
		{
			return ref InventoryInventoryHeight.Invoke(instance);
		}

		internal static ref Dictionary<int, GameObject> ItemHashes(this ObjectDB instance)
		{
			return ref ObjectDBItemHashes.Invoke(instance);
		}

		internal static ref Dictionary<SharedData, GameObject> ItemDataPrefabs(this ObjectDB instance)
		{
			return ref ObjectDBItemDataPrefabs.Invoke(instance);
		}

		internal static ref Dictionary<int, GameObject> NamedPrefabs(this ZNetScene instance)
		{
			return ref ZNetSceneNamedPrefabs.Invoke(instance);
		}

		internal static ref Dictionary<ZDO, ZNetView> Instances(this ZNetScene instance)
		{
			return ref ZNetSceneInstances.Invoke(instance);
		}

		internal static ref IDictionary RpcHandlers(this ZNetView instance)
		{
			return ref ZNetViewRpcHandlers.Invoke(instance);
		}

		internal static ref IDictionary RpcHandlers(this ZRoutedRpc instance)
		{
			return ref ZRoutedRpcRpcHandlers.Invoke(instance);
		}

		internal static ref long PeerId(this ZRoutedRpc instance)
		{
			return ref ZRoutedRpcPeerId.Invoke(instance);
		}

		internal static ref Camera GameCameraComponent(this GameCamera instance)
		{
			return ref GameCameraGameCameraComponent.Invoke(instance);
		}

		internal static ref Dictionary<string, string> Translations(this Localization instance)
		{
			return ref LocalizationTranslations.Invoke(instance);
		}

		internal static ref List<ItemData> HotbarItems(this HotkeyBar instance)
		{
			return ref HotkeyBarHotbarItems.Invoke(instance);
		}

		internal static ref IList HotbarElements(this HotkeyBar instance)
		{
			return ref HotkeyBarHotbarElements.Invoke(instance);
		}

		internal static bool HavePath(this BaseAI instance, Vector3 target)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			return BaseAIHavePath(instance, target);
		}

		internal static void Save(this Container instance)
		{
			ContainerSave(instance);
		}

		internal static GameObject GetPrefab(this Growup instance)
		{
			return GrowupGetPrefab(instance);
		}

		internal static void SetPlaceMode(this Humanoid instance, PieceTable buildPieces)
		{
			HumanoidSetPlaceMode(instance, buildPieces);
		}

		internal static void Changed(this Inventory instance, bool success = false, bool cheatedStateChanged = false)
		{
			InventoryChanged(instance, success, cheatedStateChanged);
		}

		internal static bool IsPregnant(this Procreation instance)
		{
			return ProcreationIsPregnant(instance);
		}

		internal static bool IsLocalUser(this Sadle instance)
		{
			return SadleIsLocalUser(instance);
		}

		internal static void SetStamina(this Sadle instance, float stamina)
		{
			SadleSetStamina(instance, stamina);
		}

		internal static void UseStamina(this Sadle instance, float v)
		{
			SadleUseStamina(instance, v);
		}

		internal static bool HaveSaddle(this Tameable instance)
		{
			return TameableHaveSaddle(instance);
		}

		internal static float GetRemainingTime(this Tameable instance)
		{
			return TameableGetRemainingTime(instance);
		}

		internal static void RPC_SetName(this Tameable instance, long sender, string name, string authorId)
		{
			TameableRPC_SetName(instance, sender, name, authorId);
		}

		internal static void SetSaddle(this Tameable instance, bool enabled)
		{
			TameableSetSaddle(instance, enabled);
		}

		internal static void Tame(this Tameable instance)
		{
			TameableTame(instance);
		}

		internal static long GetServerPeerID(this ZRoutedRpc instance)
		{
			return ZRoutedRpcGetServerPeerID(instance);
		}

		internal static void AddWord(this Localization instance, string key, string text)
		{
			LocalizationAddWord(instance, key, text);
		}
	}
	internal static class FeedAutoFeedSystem
	{
		private const float ContainerCleanupInterval = 5f;

		private const float DropSurfaceHeightTolerance = 1f;

		private const float MinimumDropSurfaceNormalY = 0.5f;

		private static readonly float[] DropPointAngles = new float[8] { 0f, 45f, -45f, 90f, -90f, 135f, -135f, 180f };

		private static readonly List<Container> RegisteredFeedContainers = new List<Container>();

		private static float _nextContainerCleanupTime;

		private static int _dropSurfaceMask;

		internal static void Shutdown()
		{
			RegisteredFeedContainers.Clear();
			_nextContainerCleanupTime = 0f;
		}

		internal static void RegisterContainer(Container? container)
		{
			if (IsContainerAlive(container) && FeedBarrelSystem.IsFeedBarrel(container))
			{
				FeedBarrelSystem.ApplyConfiguredContainerSize(container);
				if (!RegisteredFeedContainers.Contains(container))
				{
					RegisteredFeedContainers.Add(container);
				}
			}
		}

		internal static void DeregisterContainer(Container? container)
		{
			if (!((Object)(object)container == (Object)null))
			{
				RegisteredFeedContainers.Remove(container);
			}
		}

		internal static void RefreshRegisteredContainerSizes()
		{
			CleanupContainers();
			foreach (Container registeredFeedContainer in RegisteredFeedContainers)
			{
				FeedBarrelSystem.ApplyConfiguredContainerSize(registeredFeedContainer);
			}
		}

		internal static bool TryFindClosestConsumableFromFeedBarrel(MonsterAI monsterAI, float maxRange, out ItemDrop? consumable)
		{
			//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_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_015b: 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_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			consumable = null;
			if (!FeedBarrelSystem.IsEnabled)
			{
				return false;
			}
			if ((Object)(object)monsterAI == (Object)null || maxRange <= 0f)
			{
				return false;
			}
			if (monsterAI.m_consumeItems == null || monsterAI.m_consumeItems.Count == 0)
			{
				return false;
			}
			CleanupContainersThrottled();
			if (RegisteredFeedContainers.Count == 0)
			{
				return false;
			}
			GameObject gameObject = ((Component)monsterAI).gameObject;
			if (!FeedSystem.HasRuleFor(gameObject))
			{
				return false;
			}
			ZNetView component = gameObject.GetComponent<ZNetView>();
			Tameable component2 = gameObject.GetComponent<Tameable>();
			if ((Object)(object)component == (Object)null || !component.IsValid() || !component.IsOwner() || (Object)(object)component2 == (Object)null || !component2.IsHungry() || ((BaseAI)monsterAI).IsAlerted())
			{
				return false;
			}
			Vector3 position = ((Component)monsterAI).transform.position;
			float sqrRange = maxRange * maxRange;
			Container val = null;
			ItemData val2 = null;
			Vector3 dropPosition = Vector3.zero;
			float num = float.PositiveInfinity;
			foreach (Container registeredFeedContainer in RegisteredFeedContainers)
			{
				if (IsEligibleContainer(registeredFeedContainer, position, sqrRange))
				{
					Vector3 val3 = GetContainerCenter(registeredFeedContainer) - position;
					float sqrMagnitude = ((Vector3)(ref val3)).sqrMagnitude;
					if (!(sqrMagnitude >= num) && TrySelectFood(monsterAI, registeredFeedContainer, out ItemData item) && item != null && TryGetReachableDropPoint(monsterAI, registeredFeedContainer, position, maxRange, out var dropPosition2))
					{
						val = registeredFeedContainer;
						val2 = item;
						dropPosition = dropPosition2;
						num = sqrMagnitude;
					}
				}
			}
			if ((Object)(object)val != (Object)null && val2 != null && TryRemoveAndDrop(val, val2, dropPosition, out consumable) && (Object)(object)consumable != (Object)null)
			{
				return true;
			}
			return false;
		}

		private static bool TrySelectFood(MonsterAI monsterAI, Container container, out ItemData? item)
		{
			item = null;
			Inventory inventory = container.GetInventory();
			if (inventory == null)
			{
				return false;
			}
			if (!FeedSystem.TrySelectAutoFeedItem(monsterAI, inventory.GetAllItems(), out item) || item == null)
			{
				return false;
			}
			return EnsureDropPrefab(item);
		}

		private static bool TryRemoveAndDrop(Container container, ItemData item, Vector3 dropPosition, out ItemDrop? droppedItem)
		{
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			droppedItem = null;
			Inventory inventory = container.GetInventory();
			ZNetView val = container.NetworkView();
			if (inventory == null || (Object)(object)val == (Object)null || !val.IsValid())
			{
				return false;
			}
			if (!val.IsOwner())
			{
				val.ClaimOwnership();
			}
			if (!val.IsOwner())
			{
				return false;
			}
			ItemData val2 = item.Clone();
			val2.m_dropPrefab = item.m_dropPrefab;
			if (!inventory.RemoveOneItem(item))
			{
				return false;
			}
			container.Save();
			droppedItem = ItemDrop.DropItem(val2, 1, dropPosition, ((Component)container).transform.rotation);
			return (Object)(object)droppedItem != (Object)null;
		}

		private static bool TryGetReachableDropPoint(MonsterAI monsterAI, Container container, Vector3 animalPosition, float maxRange, out Vector3 dropPosition)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: 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_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: 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_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: 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_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: 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_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: 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_00ce: 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_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: 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)
			Vector3 containerCenter = GetContainerCenter(container);
			Vector3 val = (((Object)(object)container.ContainerPiece() != (Object)null) ? ((StaticTarget)container.ContainerPiece()).FindClosestPoint(animalPosition) : containerCenter);
			Vector3 val2 = HorizontalNormalized(animalPosition - val);
			if (((Vector3)(ref val2)).sqrMagnitude <= 0f)
			{
				val2 = -((Component)container).transform.forward;
			}
			float num = Mathf.Max(1.25f, monsterAI.m_consumeRange * 0.75f);
			if (TryUseDropPoint(monsterAI, container, animalPosition, val + val2 * num, maxRange, out dropPosition))
			{
				return true;
			}
			float num2 = Mathf.Max(1.5f, monsterAI.m_consumeRange + 0.5f);
			float[] dropPointAngles = DropPointAngles;
			foreach (float num3 in dropPointAngles)
			{
				Vector3 val3 = Quaternion.Euler(0f, num3, 0f) * val2;
				if (TryUseDropPoint(monsterAI, container, animalPosition, containerCenter + val3 * num2, maxRange, out dropPosition))
				{
					return true;
				}
			}
			dropPosition = Vector3.zero;
			return false;
		}

		private static bool TryUseDropPoint(MonsterAI monsterAI, Container container, Vector3 animalPosition, Vector3 point, float maxRange, out Vector3 dropPosition)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: 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_000e: 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_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			dropPosition = Vector3.zero;
			if (!TryGetDropSurface(container, animalPosition, point, out point))
			{
				return false;
			}
			Vector3 val = point - animalPosition;
			if (((Vector3)(ref val)).sqrMagnitude > maxRange * maxRange || !((BaseAI)(object)monsterAI).HavePath(point))
			{
				return false;
			}
			dropPosition = point + Vector3.up * 0.25f;
			return true;
		}

		private static Vector3 GetContainerCenter(Container container)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)container.ContainerPiece() != (Object)null)
			{
				return ((StaticTarget)container.ContainerPiece()).GetCenter();
			}
			return ((Component)container).transform.position;
		}

		private static Vector3 HorizontalNormalized(Vector3 vector)
		{
			//IL_0022: 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)
			vector.y = 0f;
			if (!(((Vector3)(ref vector)).sqrMagnitude > 0.0001f))
			{
				return Vector3.zero;
			}
			return ((Vector3)(ref vector)).normalized;
		}

		private static bool TryGetDropSurface(Container container, Vector3 animalPosition, Vector3 point, out Vector3 surfacePoint)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: 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_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: 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)
			surfacePoint = Vector3.zero;
			if (_dropSurfaceMask == 0)
			{
				_dropSurfaceMask = LayerMask.GetMask(new string[5] { "Default", "static_solid", "Default_small", "piece", "terrain" });
			}
			point.y = animalPosition.y + 1f;
			RaycastHit val = default(RaycastHit);
			if (!Physics.Raycast(point, Vector3.down, ref val, 2f, _dropSurfaceMask, (QueryTriggerInteraction)1) || (Object)(object)((RaycastHit)(ref val)).collider == (Object)null || (Object)(object)((RaycastHit)(ref val)).collider.attachedRigidbody != (Object)null || ((Component)((RaycastHit)(ref val)).collider).transform.IsChildOf(((Component)container).transform) || ((RaycastHit)(ref val)).normal.y < 0.5f)
			{
				return false;
			}
			surfacePoint = ((RaycastHit)(ref val)).point;
			return true;
		}

		private static bool IsEligibleContainer(Container container, Vector3 animalPosition, float sqrRange)
		{
			//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_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			if (!IsContainerObjectValid(container))
			{
				return false;
			}
			Inventory inventory = container.GetInventory();
			if (inventory == null || inventory.NrOfItems() <= 0 || container.IsInUse())
			{
				return false;
			}
			if (!FeedBarrelSystem.IsEnabled || !FeedBarrelSystem.IsFeedBarrel(container))
			{
				return false;
			}
			Vector3 val = GetContainerCenter(container) - animalPosition;
			return ((Vector3)(ref val)).sqrMagnitude <= sqrRange;
		}

		private static bool IsContainerAlive(Container? container)
		{
			return (Object)(object)container != (Object)null;
		}

		private static bool IsContainerObjectValid(Container? container)
		{
			if (!IsContainerAlive(container))
			{
				return false;
			}
			ZNetView val = container.NetworkView();
			if ((Object)(object)val == (Object)null || !val.IsValid() || container.GetInventory() == null)
			{
				return false;
			}
			return val.GetZDO().GetLong(ZDOVars.s_creator, 0L) != 0;
		}

		private static bool EnsureDropPrefab(ItemData item)
		{
			if ((Object)(object)item.m_dropPrefab != (Object)null)
			{
				return true;
			}
			GameObject dropPrefab = default(GameObject);
			if (ObjectDB.instance == null || !ObjectDB.instance.TryGetItemPrefab(item.m_shared, ref dropPrefab))
			{
				return false;
			}
			item.m_dropPrefab = dropPrefab;
			return true;
		}

		private static void CleanupContainersThrottled()
		{
			if (RegisteredFeedContainers.Count != 0 && !(Time.time < _nextContainerCleanupTime))
			{
				_nextContainerCleanupTime = Time.time + 5f;
				CleanupContainers();
			}
		}

		private static void CleanupContainers()
		{
			RegisteredFeedContainers.RemoveAll((Container container) => !IsContainerAlive(container) || !FeedBarrelSystem.IsFeedBarrel(container));
		}
	}
	internal static class FeedBarrelSystem
	{
		private sealed class RendererMaterialSnapshot
		{
			public Renderer Renderer { get; }

			public Material[] Materials { get; }

			public RendererMaterialSnapshot(Renderer renderer, Material[] materials)
			{
				Renderer = renderer;
				Materials = materials;
			}
		}

		internal const string PrefabName = "FLG_FeedBarrel";

		private const string SourcePrefabName = "piece_chest_barrel";

		private const string EctoplasmMaterialName = "ectoplasm_mat";

		private const int DefaultColumns = 6;

		private const int DefaultRows = 2;

		private const int MinColumns = 6;

		private const int MaxColumns = 8;

		private const int MinRows = 2;

		private const int MaxRows = 100;

		private const int IconSize = 128;

		private const int IconLayer = 30;

		private static GameObject? _prefab;

		private static GameObject? _prefabContainer;

		private static readonly Dictionary<string, Material> MaterialLookupCache = new Dictionary<string, Material>(StringComparer.OrdinalIgnoreCase);

		private static readonly HashSet<string> MaterialLookupMissCache = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

		private static List<RendererMaterialSnapshot>? _originalMaterials;

		private static Sprite? _originalIcon;

		private static Sprite? _ectoplasmIcon;

		private static bool _materialLookupCacheBuilt;

		internal static bool IsEnabled => !string.IsNullOrWhiteSpace(FeedLikeGrandmaPlugin.FeedBarrelRecipe.Value);

		internal static void OnGameDataChanged()
		{
			MaterialLookupCache.Clear();
			MaterialLookupMissCache.Clear();
			_materialLookupCacheBuilt = false;
		}

		internal static void RegisterPrefabsAndPieces(ObjectDB? objectDb = null)
		{
			if (objectDb == null)
			{
				objectDb = ObjectDB.instance;
			}
			GameObject val = RegisterPersistentPrefabCore(objectDb, configureBuildRequirements: true);
			if (val != null)
			{
				RegisterWithHammer(objectDb, val);
			}
		}

		internal static void RegisterPersistentPrefab(ObjectDB? objectDb = null)
		{
			RegisterPersistentPrefabCore(objectDb ?? ObjectDB.instance, configureBuildRequirements: false);
		}

		private static GameObject? RegisterPersistentPrefabCore(ObjectDB? objectDb, bool configureBuildRequirements)
		{
			GameObject val = EnsurePrefab();
			if (val == null)
			{
				return null;
			}
			ConfigurePrefab(val, objectDb, configureBuildRequirements);
			if (ZNetScene.instance != null)
			{
				RegisterWithZNetScene(ZNetScene.instance, val);
			}
			FeedAutoFeedSystem.RefreshRegisteredContainerSizes();
			return val;
		}

		internal static bool IsFeedBarrel(Container? container)
		{
			if ((Object)(object)container == (Object)null)
			{
				return false;
			}
			return IsFeedBarrel(((Component)container).gameObject);
		}

		internal static bool IsFeedBarrel(GameObject? gameObject)
		{
			if ((Object)(object)gameObject == (Object)null)
			{
				return false;
			}
			return string.Equals(Utils.GetPrefabName(gameObject), "FLG_FeedBarrel", StringComparison.Ordinal);
		}

		private static GameObject? EnsurePrefab()
		{
			if (_prefab != null)
			{
				return _prefab;
			}
			GameObject val = FindScenePrefab("FLG_FeedBarrel");
			if (val != null)
			{
				_prefab = val;
				return _prefab;
			}
			GameObject val2 = FindScenePrefab("piece_chest_barrel");
			if (val2 == null)
			{
				return null;
			}
			GameObject val3 = Object.Instantiate<GameObject>(val2, EnsurePrefabContainer().transform);
			((Object)val3).name = "FLG_FeedBarrel";
			if (val3.GetComponent<Piece>() == null || val3.GetComponent<Container>() == null || val3.GetComponent<ZNetView>() == null)
			{
				FeedLikeGrandmaPlugin.Log.LogWarning((object)"Could not create FLG_FeedBarrel: piece_chest_barrel did not have the expected Piece, Container, and ZNetView components.");
				Object.Destroy((Object)(object)val3);
				return null;
			}
			_prefab = val3;
			return _prefab;
		}

		private static void ConfigurePrefab(GameObject prefab, ObjectDB? objectDb, bool configureBuildRequirements)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			Piece component = prefab.GetComponent<Piece>();
			if (component != null)
			{
				bool isEnabled = IsEnabled;
				component.m_name = "$flg_feed_barrel";
				component.m_description = "$flg_feed_barrel_description";
				component.m_enabled = isEnabled;
				component.m_category = (PieceCategory)0;
				StoreOriginalIcon(component);
				StoreOriginalMaterials(prefab);
				ApplyConfiguredMaterial(prefab, component);
				if (configureBuildRequirements && objectDb != null)
				{
					component.m_resources = (isEnabled ? BuildRequirements(objectDb, FeedLikeGrandmaPlugin.FeedBarrelRecipe.Value).ToArray() : Array.Empty<Requirement>());
				}
			}
			Container component2 = prefab.GetComponent<Container>();
			if (component2 != null)
			{
				component2.m_name = "$flg_feed_barrel";
				ApplyConfiguredContainerSize(component2);
			}
		}

		internal static void ApplyConfiguredContainerSize(Container? container)
		{
			if (container != null && IsFeedBarrel(container))
			{
				GetConfiguredContainerSize(out var columns, out var rows);
				container.m_width = columns;
				container.m_height = rows;
				Inventory inventory = container.GetInventory();
				if (inventory != null)
				{
					inventory.InventoryWidth() = columns;
					inventory.InventoryHeight() = rows;
				}
			}
		}

		private static void ApplyConfiguredMaterial(GameObject prefab, Piece piece)
		{
			RestoreOriginalMaterials();
			piece.m_icon = _originalIcon;
			if (FeedLikeGrandmaPlugin.FeedBarrelMaterialStyle.Value != FeedLikeGrandmaPlugin.FeedBarrelMaterial.Ectoplasm)
			{
				return;
			}
			Material val = ResolveMaterial("ectoplasm_mat");
			if (val == null)
			{
				FeedLikeGrandmaPlugin.Log.LogWarning((object)"FLG_FeedBarrel material 'ectoplasm_mat' was not found. Using default barrel material.");
				return;
			}
			ApplyMaterialOverride(prefab, val);
			if (_ectoplasmIcon == null)
			{
				_ectoplasmIcon = RenderPieceIcon(prefab);
			}
			if (_ectoplasmIcon != null)
			{
				piece.m_icon = _ectoplasmIcon;
			}
		}

		private static void GetConfiguredContainerSize(out int columns, out int rows)
		{
			columns = ((FeedLikeGrandmaPlugin.FeedBarrelContainerColumns != null) ? FeedLikeGrandmaPlugin.FeedBarrelContainerColumns.Value : 6);
			rows = ((FeedLikeGrandmaPlugin.FeedBarrelContainerRows != null) ? FeedLikeGrandmaPlugin.FeedBarrelContainerRows.Value : 2);
			columns = Mathf.Clamp(columns, 6, 8);
			rows = Mathf.Clamp(rows, 2, 100);
		}

		private static void RegisterWithZNetScene(ZNetScene zNetScene, GameObject prefab)
		{
			int stableHashCode = StringExtensionMethods.GetStableHashCode("FLG_FeedBarrel");
			if ((Object)(object)prefab.GetComponent<ZNetView>() != (Object)null)
			{
				if (zNetScene.m_prefabs.All((GameObject existing) => (Object)(object)existing == (Object)null || ((Object)existing).name != "FLG_FeedBarrel"))
				{
					zNetScene.m_prefabs.Add(prefab);
				}
			}
			else if (zNetScene.m_nonNetViewPrefabs.All((GameObject existing) => (Object)(object)existing == (Object)null || ((Object)existing).name != "FLG_FeedBarrel"))
			{
				zNetScene.m_nonNetViewPrefabs.Add(prefab);
			}
			if (!zNetScene.NamedPrefabs().ContainsKey(stableHashCode))
			{
				zNetScene.NamedPrefabs().Add(stableHashCode, prefab);
			}
			else if ((Object)(object)zNetScene.NamedPrefabs()[stableHashCode] == (Object)null || ((Object)zNetScene.NamedPrefabs()[stableHashCode]).name == "FLG_FeedBarrel")
			{
				zNetScene.NamedPrefabs()[stableHashCode] = prefab;
			}
		}

		private static void RegisterWithHammer(ObjectDB? objectDb, GameObject prefab)
		{
			if (objectDb == null)
			{
				return;
			}
			GameObject itemPrefab = objectDb.GetItemPrefab("Hammer");
			PieceTable val = (((Object)(object)itemPrefab == (Object)null) ? null : itemPrefab.GetComponent<ItemDrop>())?.m_itemData.m_shared.m_buildPieces;
			if (val != null)
			{
				val.m_pieces.RemoveAll((GameObject existing) => (Object)(object)existing == (Object)null || ((Object)existing).name == "FLG_FeedBarrel");
				if (!IsEnabled)
				{
					RefreshLocalBuildTable(val);
					return;
				}
				val.m_pieces.Add(prefab);
				RefreshLocalBuildTable(val);
			}
		}

		private static void RefreshLocalBuildTable(PieceTable pieceTable)
		{
			if (Player.m_localPlayer != null && Player.m_localPlayer.GetBuildTool() != null && (Object)(object)Player.m_localPlayer.GetBuildTool() == (Object)(object)pieceTable)
			{
				((Humanoid)(object)Player.m_localPlayer).SetPlaceMode(pieceTable);
			}
		}

		private static IEnumerable<Requirement> BuildRequirements(ObjectDB objectDb, string recipeText)
		{
			if (string.IsNullOrWhiteSpace(recipeText))
			{
				yield break;
			}
			string[] array = recipeText.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries);
			for (int i = 0; i < array.Length; i++)
			{
				string[] array2 = array[i].Trim().Split(new char[1] { ':' }, StringSplitOptions.RemoveEmptyEntries);
				if (array2.Length != 0)
				{
					string text = array2[0].Trim();
					int result = 1;
					if (array2.Length > 1)
					{
						int.TryParse(array2[1].Trim(), NumberStyles.Integer, CultureInfo.InvariantCulture, out result);
						result = Mathf.Max(1, result);
					}
					GameObject val = FindItemPrefab(objectDb, text);
					ItemDrop val2 = (((Object)(object)val == (Object)null) ? null : val.GetComponent<ItemDrop>());
					if (val2 == null)
					{
						FeedLikeGrandmaPlugin.Log.LogWarning((object)("FLG_FeedBarrel build ingredient '" + text + "' was not found."));
						continue;
					}
					yield return new Requirement
					{
						m_resItem = val2,
						m_amount = result,
						m_amountPerLevel = 0,
						m_recover = true
					};
				}
			}
		}

		private static GameObject? FindItemPrefab(ObjectDB objectDb, string itemName)
		{
			GameObject itemPrefab = objectDb.GetItemPrefab(itemName);
			if (itemPrefab != null)
			{
				return itemPrefab;
			}
			int stableHashCode = StringExtensionMethods.GetStableHashCode(itemName);
			if (!objectDb.ItemHashes().TryGetValue(stableHashCode, out GameObject value))
			{
				return null;
			}
			return value;
		}

		private static GameObject? FindScenePrefab(string prefabName)
		{
			if (ZNetScene.instance == null)
			{
				return null;
			}
			GameObject prefab = ZNetScene.instance.GetPrefab(prefabName);
			if (prefab != null)
			{
				return prefab;
			}
			int stableHashCode = StringExtensionMethods.GetStableHashCode(prefabName);
			if (!ZNetScene.instance.NamedPrefabs().TryGetValue(stableHashCode, out GameObject value))
			{
				return null;
			}
			return value;
		}

		private static void StoreOriginalIcon(Piece piece)
		{
			if (_originalIcon == null)
			{
				_originalIcon = piece.m_icon;
			}
		}

		private static void StoreOriginalMaterials(GameObject prefab)
		{
			if (_originalMaterials == null)
			{
				_originalMaterials = (from renderer in GetVisualRenderers(prefab)
					select new RendererMaterialSnapshot(renderer, renderer.sharedMaterials.ToArray())).ToList();
			}
		}

		private static void RestoreOriginalMaterials()
		{
			if (_originalMaterials == null)
			{
				return;
			}
			foreach (RendererMaterialSnapshot originalMaterial in _originalMaterials)
			{
				if (originalMaterial.Renderer != null)
				{
					originalMaterial.Renderer.sharedMaterials = originalMaterial.Materials.ToArray();
				}
			}
		}

		private static void ApplyMaterialOverride(GameObject prefab, Material material)
		{
			foreach (Renderer visualRenderer in GetVisualRenderers(prefab))
			{
				Material[] sharedMaterials = visualRenderer.sharedMaterials;
				if (sharedMaterials.Length != 0)
				{
					Material[] array = (Material[])(object)new Material[sharedMaterials.Length];
					for (int i = 0; i < array.Length; i++)
					{
						array[i] = material;
					}
					visualRenderer.sharedMaterials = array;
				}
			}
		}

		private static Material? ResolveMaterial(string materialName)
		{
			string text = NormalizeMaterialName(materialName);
			if (text.Length == 0 || MaterialLookupMissCache.Contains(text))
			{
				return null;
			}
			EnsureMaterialLookupCache(force: false);
			if (TryResolveCachedMaterial(materialName, text, out Material material))
			{
				return material;
			}
			EnsureMaterialLookupCache(force: true);
			if (TryResolveCachedMaterial(materialName, text, out material))
			{
				return material;
			}
			MaterialLookupMissCache.Add(text);
			return null;
		}

		private static bool TryResolveCachedMaterial(string materialName, string normalizedName, out Material? material)
		{
			if (MaterialLookupCache.TryGetValue(materialName, out Material value) && value != null)
			{
				material = value;
				return true;
			}
			if (MaterialLookupCache.TryGetValue(normalizedName, out Material value2) && value2 != null)
			{
				material = value2;
				return true;
			}
			material = null;
			return false;
		}

		private static void EnsureMaterialLookupCache(bool force)
		{
			if (_materialLookupCacheBuilt && !force)
			{
				return;
			}
			MaterialLookupCache.Clear();
			MaterialLookupMissCache.Clear();
			Material[] array = Resources.FindObjectsOfTypeAll<Material>();
			foreach (Material val in array)
			{
				if (val != null && !string.IsNullOrWhiteSpace(((Object)val).name))
				{
					if (!MaterialLookupCache.ContainsKey(((Object)val).name))
					{
						MaterialLookupCache[((Object)val).name] = val;
					}
					string text = NormalizeMaterialName(((Object)val).name);
					if (text.Length > 0 && !MaterialLookupCache.ContainsKey(text))
					{
						MaterialLookupCache[text] = val;
					}
				}
			}
			_materialLookupCacheBuilt = true;
		}

		private static string NormalizeMaterialName(string name)
		{
			return (name ?? string.Empty).Replace(" (Instance)", string.Empty).Trim();
		}

		private static Sprite? RenderPieceIcon(GameObject sourcePrefab)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Invalid comparison between Unknown and I4
			//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_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: 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_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: 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_018e: 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_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: 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_023b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0257: Unknown result type (might be due to invalid IL or missing references)
			//IL_025c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0269: Expected O, but got Unknown
			//IL_0286: 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_02a4: Unknown result type (might be due to invalid IL or missing references)
			if ((int)SystemInfo.graphicsDeviceType == 4)
			{
				return null;
			}
			GameObject val = null;
			Camera val2 = null;
			Light val3 = null;
			RenderTexture val4 = null;
			RenderTexture active = RenderTexture.active;
			try
			{
				val = SpawnIconRenderClone(sourcePrefab, out List<Renderer> renderers);
				if (val == null || renderers.Count == 0)
				{
					return null;
				}
				Bounds bounds = renderers[0].bounds;
				foreach (Renderer item in renderers.Skip(1))
				{
					((Bounds)(ref bounds)).Encapsulate(item.bounds);
				}
				Vector3 size = ((Bounds)(ref bounds)).size;
				Transform transform = val.transform;
				transform.position -= ((Bounds)(ref bounds)).center;
				val2 = new GameObject("FeedLikeGrandma Feed Barrel Icon Camera", new Type[1] { typeof(Camera) }).GetComponent<Camera>();
				val2.backgroundColor = Color.clear;
				val2.clearFlags = (CameraClearFlags)2;
				val2.fieldOfView = 0.5f;
				val2.farClipPlane = 10000000f;
				val2.cullingMask = 1073741824;
				((Component)val2).transform.rotation = Quaternion.Euler(0f, 180f, 0f);
				val3 = new GameObject("FeedLikeGrandma Feed Barrel Icon Light", new Type[1] { typeof(Light) }).GetComponent<Light>();
				((Component)val3).transform.position = Vector3.zero;
				((Component)val3).transform.rotation = Quaternion.Euler(5f, 180f, 5f);
				val3.type = (LightType)1;
				val3.cullingMask = 1073741824;
				val3.intensity = 1.3f;
				float num = (Mathf.Max(size.x, size.y) + 0.1f) / Mathf.Tan(val2.fieldOfView * ((float)Math.PI / 180f));
				if (float.IsNaN(num) || float.IsInfinity(num) || num <= 0f)
				{
					num = Mathf.Max(size.x, Mathf.Max(size.y, size.z)) + 1f;
				}
				((Component)val2).transform.position = new Vector3(0f, 0f, num);
				val4 = (RenderTexture.active = (val2.targetTexture = RenderTexture.GetTemporary(128, 128, 24, (RenderTextureFormat)0)));
				GL.Clear(true, true, Color.clear);
				val2.Render();
				Texture2D val6 = new Texture2D(128, 128, (TextureFormat)4, false)
				{
					name = "FLG_FeedBarrel_Icon"
				};
				Rect val7 = default(Rect);
				((Rect)(ref val7))..ctor(0f, 0f, 128f, 128f);
				val6.ReadPixels(val7, 0, 0);
				val6.Apply();
				Sprite obj = Sprite.Create(val6, val7, new Vector2(0.5f, 0.5f), 100f);
				((Object)obj).name = ((Object)val6).name;
				return obj;
			}
			catch (Exception ex)
			{
				FeedLikeGrandmaPlugin.Log.LogWarning((object)("FLG_FeedBarrel icon render failed: " + ex.Message));
				return null;
			}
			finally
			{
				RenderTexture.active = active;
				if (val2 != null)
				{
					val2.targetTexture = null;
					DestroyTemporaryObject(((Component)val2).gameObject);
				}
				if (val3 != null)
				{
					DestroyTemporaryObject(((Component)val3).gameObject);
				}
				if ((Object)(object)val4 != (Object)null)
				{
					RenderTexture.ReleaseTemporary(val4);
				}
				if (val != null)
				{
					DestroyTemporaryObject(val);
				}
			}
		}

		private static GameObject? SpawnIconRenderClone(GameObject sourcePrefab, out List<Renderer> renderers)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Expected O, but got Unknown
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			renderers = new List<Renderer>();
			GameObject val = null;
			try
			{
				val = new GameObject("FLG_FeedBarrel_IconRoot");
				val.SetActive(false);
				GameObject val2 = Object.Instantiate<GameObject>(sourcePrefab, val.transform, false);
				((Object)val2).name = "FLG_FeedBarrel_IconRender";
				StripIconRenderClone(val2);
				val2.transform.SetParent((Transform)null, false);
				Object.DestroyImmediate((Object)(object)val);
				val = null;
				val2.transform.position = Vector3.zero;
				val2.transform.rotation = Quaternion.Euler(23f, 51f, 25.8f);
				SetLayerRecursive(val2, 30);
				val2.SetActive(true);
				renderers = (from renderer in GetVisualRenderers(val2)
					where ((Component)renderer).gameObject.activeInHierarchy
					select renderer).ToList();
				if (renderers.Count == 0)
				{
					DestroyTemporaryObject(val2);
					return null;
				}
				HashSet<Renderer> hashSet = new HashSet<Renderer>(renderers);
				Renderer[] componentsInChildren = val2.GetComponentsInChildren<Renderer>(true);
				foreach (Renderer val3 in componentsInChildren)
				{
					if (val3 != null && !hashSet.Contains(val3))
					{
						val3.enabled = false;
					}
				}
				return val2;
			}
			catch
			{
				if (val != null)
				{
					Object.DestroyImmediate((Object)(object)val);
				}
				throw;
			}
		}

		private static void StripIconRenderClone(GameObject renderObject)
		{
			Transform[] componentsInChildren = renderObject.GetComponentsInChildren<Transform>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Component[] components = ((Component)componentsInChildren[i]).GetComponents<Component>();
				for (int num = components.Length - 1; num >= 0; num--)
				{
					Component val = components[num];
					if (!((Object)(object)val == (Object)null) && !(val is Transform) && !(val is MeshFilter) && !(val is MeshRenderer) && !(val is SkinnedMeshRenderer))
					{
						try
						{
							Object.DestroyImmediate((Object)(object)val);
						}
						catch (Exception ex)
						{
							FeedLikeGrandmaPlugin.Log.LogDebug((object)("Could not strip icon render component '" + ((object)val).GetType().Name + "' from '" + ((Object)renderObject).name + "': " + ex.Message));
						}
					}
				}
			}
		}

		private static List<Renderer> GetVisualRenderers(GameObject prefab)
		{
			return (from renderer in prefab.GetComponentsInChildren<Renderer>(true)
				where (Object)(object)renderer != (Object)null && renderer.enabled && !((object)renderer).GetType().Name.Equals("ParticleSystemRenderer", StringComparison.Ordinal)
				select renderer).ToList();
		}

		private static void SetLayerRecursive(GameObject gameObject, int layer)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			gameObject.layer = layer;
			foreach (Transform item in gameObject.transform)
			{
				SetLayerRecursive(((Component)item).gameObject, layer);
			}
		}

		private static void DestroyTemporaryObject(GameObject? gameObject)
		{
			if (gameObject == null)
			{
				return;
			}
			try
			{
				gameObject.SetActive(false);
				Object.DestroyImmediate((Object)(object)gameObject);
			}
			catch (Exception ex)
			{
				FeedLikeGrandmaPlugin.Log.LogDebug((object)("Could not immediately destroy icon render object '" + ((Object)gameObject).name + "': " + ex.Message));
				Object.Destroy((Object)(object)gameObject);
			}
		}

		private static GameObject EnsurePrefabContainer()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			if (_prefabContainer != null)
			{
				return _prefabContainer;
			}
			_prefabContainer = new GameObject("FeedLikeGrandma Feed Barrel Prefabs");
			_prefabContainer.SetActive(false);
			Object.DontDestroyOnLoad((Object)(object)_prefabContainer);
			return _prefabContainer;
		}
	}
	internal static class FeedBetterRidingCompatibility
	{
		private const string BetterRidingPluginTypeName = "BetterRiding.BetterRidingPlugin";

		private const string MountStaminaSystemTypeName = "BetterRiding.Behaviour.MountStaminaSystem";

		private const string MountAttackControllerTypeName = "BetterRiding.Behaviour.MountAttackController";

		private const string BetterRidingBlockFlyingDismountPatchTypeName = "BetterRiding.Behaviour.BlockFlyingDismountPatch";

		private const string DragonRidersBlockFlyingDismountPatchTypeName = "DragonRiders.Patches.MountController.BlockFlyingDismountPatch";

		private const float AttackRecordCleanupInterval = 60f;

		private const float AttackRecordTtl = 1800f;

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

		private static readonly Dictionary<string, ConfigEntry<bool>?> BetterRidingBoolConfigEntries = new Dictionary<string, ConfigEntry<bool>>(StringComparer.Ordinal);

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

		private static float _nextAttackRecordCleanupTime;

		private static bool _betterRidingPluginTypeSearched;

		private static Type? _betterRidingPluginType;

		private static bool _mountStaminaSystemTypeSearched;

		private static Type? _mountStaminaSystemType;

		private static bool _mountStaminaSaddleFieldSearched;

		private static FieldInfo? _mountStaminaSaddleField;

		private static int _mountAttackSafetySaddleId;

		private static int _mountAttackSafetyCharacterId;

		private static int _mountAttackSafetyFrame;

		private static bool _mountAttackSafetyAllowed = true;

		private static Type? BetterRidingPluginType
		{
			get
			{
				if (!_betterRidingPluginTypeSearched)
				{
					_betterRidingPluginType = FindType("BetterRiding.BetterRidingPlugin");
					_betterRidingPluginTypeSearched = true;
				}
				return _betterRidingPluginType;
			}
		}

		private static Type? MountStaminaSystemType
		{
			get
			{
				if (!_mountStaminaSystemTypeSearched)
				{
					_mountStaminaSystemType = FindType("BetterRiding.Behaviour.MountStaminaSystem");
					_mountStaminaSystemTypeSearched = true;
				}
				return _mountStaminaSystemType;
			}
		}

		internal static bool HasBetterRiding => BetterRidingPluginType != null;

		internal static void Shutdown()
		{
			LastAttackTimes.Clear();
			BetterRidingBoolConfigEntries.Clear();
			ExpiredAttackKeys.Clear();
			_nextAttackRecordCleanupTime = 0f;
			_mountAttackSafetySaddleId = 0;
			_mountAttackSafetyCharacterId = 0;
			_mountAttackSafetyFrame = 0;
			_mountAttackSafetyAllowed = true;
			_betterRidingPluginTypeSearched = false;
			_betterRidingPluginType = null;
			_mountStaminaSystemTypeSearched = false;
			_mountStaminaSystemType = null;
			_mountStaminaSaddleFieldSearched = false;
			_mountStaminaSaddleField = null;
		}

		private static Type? FindType(string typeName)
		{
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			for (int i = 0; i < assemblies.Length; i++)
			{
				Type type = assemblies[i].GetType(typeName, throwOnError: false);
				if (type != null)
				{
					return type;
				}
			}
			return null;
		}

		internal static MethodBase? GetMountStaminaSystemMethod(string methodName)
		{
			Type mountStaminaSystemType = MountStaminaSystemType;
			if (!(mountStaminaSystemType == null))
			{
				return AccessTools.Method(mountStaminaSystemType, methodName, (Type[])null, (Type[])null);
			}
			return null;
		}

		internal static MethodBase? GetMountAttackUpdate()
		{
			Type type = FindType("BetterRiding.Behaviour.MountAttackController");
			if (!(type == null))
			{
				return AccessTools.Method(type, "Update", (Type[])null, (Type[])null);
			}
			return null;
		}

		internal static MethodBase? GetBetterRidingBlockFlyingDismountPrefix()
		{
			Type type = FindType("BetterRiding.Behaviour.BlockFlyingDismountPatch");
			if (!(type == null))
			{
				return AccessTools.Method(type, "Prefix", (Type[])null, (Type[])null);
			}
			return null;
		}

		internal static MethodBase? GetDragonRidersBlockFlyingDismountPrefix()
		{
			Type type = FindType("DragonRiders.Patches.MountController.BlockFlyingDismountPatch");
			if (!(type == null))
			{
				return AccessTools.Method(type, "Prefix", (Type[])null, (Type[])null);
			}
			return null;
		}

		internal static bool HandleMountedAttack(Humanoid humanoid, ref bool result)
		{
			if (!TryFindAttackSaddle(humanoid, out Sadle saddle) || !TryGetMountStamina(saddle, out ResolvedMountStaminaValues mountStamina) || mountStamina == null)
			{
				return true;
			}
			float time = Time.time;
			CleanupAttackRecords(time);
			int mountKey = GetMountKey(saddle);
			if (mountKey != 0 && LastAttackTimes.TryGetValue(mountKey, out var value) && time - value < mountStamina.AttackCooldown)
			{
				result = false;
				return false;
			}
			if (!CanUseAttackStamina(saddle, mountStamina))
			{
				result = false;
				return false;
			}
			UseAttackStamina(saddle, mountStamina);
			if (mountKey != 0)
			{
				LastAttackTimes[mountKey] = time;
			}
			result = true;
			return false;
		}

		private static void CleanupAttackRecords(float now)
		{
			if (LastAttackTimes.Count == 0 || now < _nextAttackRecordCleanupTime)
			{
				return;
			}
			_nextAttackRecordCleanupTime = now + 60f;
			ExpiredAttackKeys.Clear();
			foreach (KeyValuePair<int, float> lastAttackTime in LastAttackTimes)
			{
				if (now - lastAttackTime.Value > 1800f)
				{
					ExpiredAttackKeys.Add(lastAttackTime.Key);
				}
			}
			foreach (int expiredAttackKey in ExpiredAttackKeys)
			{
				LastAttackTimes.Remove(expiredAttackKey);
			}
			ExpiredAttackKeys.Clear();
		}

		internal static void SuppressPlayerAttackControlsWhileRiding(Player player, ref bool attack, ref bool attackHold, ref bool secondaryAttack, ref bool secondaryAttackHold)
		{
			if (player != null && ((Character)player).IsRiding())
			{
				attack = false;
				attackHold = false;
				secondaryAttack = false;
				secondaryAttackHold = false;
				ResetPlayerDrawAttack(player);
			}
		}

		internal static bool AllowPlayerAttackInput(Player player)
		{
			if (player == null || !((Character)player).IsRiding())
			{
				return true;
			}
			ResetPlayerDrawAttack(player);
			return false;
		}

		internal static bool CanAttack(object mountStaminaSystem, ref bool result)
		{
			if (!TryGetSystemSaddle(mountStaminaSystem, out Sadle saddle) || !TryGetMountStamina(saddle, out ResolvedMountStaminaValues mountStamina) || mountStamina == null)
			{
				return true;
			}
			result = CanUseAttackStamina(saddle, mountStamina);
			return false;
		}

		internal static bool CanJump(object mountStaminaSystem, ref bool result)
		{
			if (!TryGetSystemSaddle(mountStaminaSystem, out Sadle saddle) || !TryGetMountStamina(saddle, out ResolvedMountStaminaValues mountStamina) || mountStamina == null)
			{
				return true;
			}
			result = CanUseJumpStamina(saddle, mountStamina);
			return false;
		}

		internal static bool OnAttackStart(object mountStaminaSystem)
		{
			if (!TryGetSystemSaddle(mountStaminaSystem, out Sadle saddle) || !TryGetMountStamina(saddle, out ResolvedMountStaminaValues mountStamina) || mountStamina == null)
			{
				return true;
			}
			UseAttackStamina(saddle, mountStamina);
			return false;
		}

		internal static bool OnJumpStart(object mountStaminaSystem)
		{
			if (!TryGetSystemSaddle(mountStaminaSystem, out Sadle saddle) || !TryGetMountStamina(saddle, out ResolvedMountStaminaValues mountStamina) || mountStamina == null)
			{
				return true;
			}
			UseJumpStamina(saddle, mountStamina);
			return false;
		}

		internal static bool AllowMountAttackUpdate()
		{
			Player localPlayer = Player.m_localPlayer;
			if (localPlayer == null)
			{
				return true;
			}
			IDoodadController doodadController = localPlayer.GetDoodadController();
			Sadle val = (Sadle)(object)((doodadController is Sadle) ? doodadController : null);
			if (val == null)
			{
				return true;
			}
			int instanceID = ((Object)val).GetInstanceID();
			Character character = val.GetCharacter();
			if (character == null)
			{
				return true;
			}
			int instanceID2 = ((Object)character).GetInstanceID();
			if (instanceID == _mountAttackSafetySaddleId && instanceID2 == _mountAttackSafetyCharacterId && Time.frameCount - _mountAttackSafetyFrame <= (_mountAttackSafetyAllowed ? 30 : 5))
			{
				return _mountAttackSafetyAllowed;
			}
			bool num = IsMountAttackStateSafe(character);
			_mountAttackSafetySaddleId = instanceID;
			_mountAttackSafetyCharacterId = instanceID2;
			_mountAttackSafetyFrame = Time.frameCount;
			_mountAttackSafetyAllowed = num;
			return num;
		}

		internal static bool AllowBlockFlyingDismount(Player player, ref bool result)
		{
			if (!ShouldAllowWaterDismount(player))
			{
				return true;
			}
			result = true;
			return false;
		}

		private static bool IsMountAttackStateSafe(Character character)
		{
			Humanoid val = (Humanoid)(object)((character is Humanoid) ? character : null);
			if (val == null)
			{
				return true;
			}
			if (character.GetBaseAI() != null && val.m_defaultItems != null)
			{
				return val.m_defaultItems.Length >= 2;
			}
			return false;
		}

		private static bool ShouldAllowWaterDismount(Player player)
		{
			if (player == null || !((Character)player).IsRiding())
			{
				return false;
			}
			IDoodadController doodadController = player.GetDoodadController();
			IDoodadController obj = ((doodadController is Sadle) ? doodadController : null);
			Character character = ((obj != null) ? ((Sadle)obj).GetCharacter() : null);
			if (obj != null)
			{
				if (!IsInWater((Character?)(object)player))
				{
					return IsInWater(character);
				}
				return true;
			}
			return false;
		}

		private static bool IsInWater(Character? character)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			if (character == null)
			{
				return false;
			}
			if (!character.InWater())
			{
				if (character.WaterLevel() > character.TarLevel())
				{
					return character.WaterLevel() - ((Component)character).transform.position.y > 0.05f;
				}
				return false;
			}
			return true;
		}

		private static void ResetPlayerDrawAttack(Player player)
		{
			if (!(((Humanoid)(object)player).AttackDrawTime() <= 0f))
			{
				string text = ((Humanoid)player).GetCurrentWeapon()?.m_shared.m_attack.m_drawAnimationState;
				if (!string.IsNullOrEmpty(text))
				{
					((Character)player).GetZAnim().SetBool(text, false);
					((Character)player).GetZAnim().SetFloat("drawpercent", 0f);
				}
				((Humanoid)(object)player).AttackDrawTime() = 0f;
			}
		}

		private static bool CanUseAttackStamina(Sadle? saddle, ResolvedMountStaminaValues mountStamina)
		{
			if (GetBetterRidingBoolConfig("EnableAttackStaminaDrain", fallback: true))
			{
				return CanUseStamina(saddle, mountStamina.AttackStaminaCost);
			}
			return true;
		}

		private static bool CanUseJumpStamina(Sadle? saddle, ResolvedMountStaminaValues mountStamina)
		{
			if (GetBetterRidingBoolConfig("EnableJumpStaminaDrain", fallback: true))
			{
				return CanUseStamina(saddle, mountStamina.JumpStaminaCost);
			}
			return true;
		}

		private static void UseAttackStamina(Sadle? saddle, ResolvedMountStaminaValues mountStamina)
		{
			if (GetBetterRidingBoolConfig("EnableAttackStaminaDrain", fallback: true))
			{
				UseStaminaDirect(saddle, mountStamina.AttackStaminaCost);
			}
		}

		private static void UseJumpStamina(Sadle? saddle, ResolvedMountStaminaValues mountStamina)
		{
			if (GetBetterRidingBoolConfig("EnableJumpStaminaDrain", fallback: true))
			{
				UseStaminaDirect(saddle, mountStamina.JumpStaminaCost);
			}
		}

		private static bool CanUseStamina(Sadle? saddle, float amount)
		{
			if (saddle != null && saddle.NetworkView() != null && saddle.NetworkView().IsValid())
			{
				return saddle.GetStamina() >= amount;
			}
			return false;
		}

		private static void UseStaminaDirect(Sadle? saddle, float amount)
		{
			if (!(amount <= 0f) && saddle != null && saddle.NetworkView() != null && saddle.NetworkView().IsValid() && saddle.NetworkView().IsOwner())
			{
				float stamina = saddle.GetStamina();
				if (!(stamina < amount))
				{
					saddle.SetStamina(Mathf.Max(0f, stamina - amount));
				}
			}
		}

		private static bool TryGetSystemSaddle(object mountStaminaSystem, out Sadle? saddle)
		{
			saddle = null;
			if (mountStaminaSystem == null)
			{
				return false;
			}
			FieldInfo mountStaminaSaddleField = GetMountStaminaSaddleField();
			if (mountStaminaSaddleField == null)
			{
				return false;
			}
			object? value = mountStaminaSaddleField.GetValue(mountStaminaSystem);
			saddle = (Sadle?)((value is Sadle) ? value : null);
			return saddle != null;
		}

		private static bool TryFindAttackSaddle(Humanoid humanoid, out Sadle? saddle)
		{
			saddle = null;
			if (humanoid == null)
			{
				return false;
			}
			Player val = (Player)(object)((humanoid is Player) ? humanoid : null);
			if (val != null && ((Character)val).IsRiding())
			{
				IDoodadController doodadController = val.GetDoodadController();
				saddle = (Sadle?)(object)((doodadController is Sadle) ? doodadController : null);
				return saddle != null;
			}
			Player localPlayer = Player.m_localPlayer;
			if (localPlayer == null || !((Character)localPlayer).IsRiding())
			{
				return false;
			}
			IDoodadController doodadController2 = localPlayer.GetDoodadController();
			saddle = (Sadle?)(object)((doodadController2 is Sadle) ? doodadController2 : null);
			Sadle? obj = saddle;
			Character val2 = ((obj != null) ? obj.GetCharacter() : null);
			if (val2 == null || (object)val2 != humanoid)
			{
				saddle = null;
				return false;
			}
			return true;
		}

		private static bool TryGetMountStamina(Sadle? saddle, out ResolvedMountStaminaValues? mountStamina)
		{
			mountStamina = null;
			if (saddle == null)
			{
				return false;
			}
			Character character = saddle.GetCharacter();
			if (character != null)
			{
				return FeedSystem.TryGetMountStamina(character, out mountStamina);
			}
			return false;
		}

		private static int GetMountKey(Sadle? saddle)
		{
			if (saddle == null)
			{
				return 0;
			}
			Character character = saddle.GetCharacter();
			if (character != null)
			{
				return ((Object)((Component)character).gameObject).GetInstanceID();
			}
			return 0;
		}

		private static bool GetBetterRidingBoolConfig(string fieldName, bool fallback)
		{
			if (!BetterRidingBoolConfigEntries.TryGetValue(fieldName, out ConfigEntry<bool> value))
			{
				Type betterRidingPluginType = BetterRidingPluginType;
				value = ((betterRidingPluginType == null) ? null : AccessTools.Field(betterRidingPluginType, fieldName)?.GetValue(null)) as ConfigEntry<bool>;
				BetterRidingBoolConfigEntries[fieldName] = value;
			}
			return value?.Value ?? fallback;
		}

		private static FieldInfo? GetMountStaminaSaddleField()
		{
			if (!_mountStaminaSaddleFieldSearched)
			{
				Type mountStaminaSystemType = MountStaminaSystemType;
				_mountStaminaSaddleField = ((mountStaminaSystemType == null) ? null : AccessTools.Field(mountStaminaSystemType, "m_saddle"));
				_mountStaminaSaddleFieldSearched = true;
			}
			return _mountStaminaSaddleField;
		}
	}
	[HarmonyPatch(typeof(Player), "SetControls")]
	internal static class BetterRidingSuppressPlayerAttackHoldPatch
	{
		private static bool Prepare()
		{
			return FeedBetterRidingCompatibility.HasBetterRiding;
		}

		[HarmonyPriority(0)]
		[HarmonyAfter(new string[] { "Yggdrah.BetterRiding" })]
		private static void Prefix(Player __instance, ref bool attack, ref bool attackHold, ref bool secondaryAttack, ref bool secondaryAttackHold)
		{
			FeedBetterRidingCompatibility.SuppressPlayerAttackControlsWhileRiding(__instance, ref attack, ref attackHold, ref secondaryAttack, ref secondaryAttackHold);
		}
	}
	[HarmonyPatch(typeof(Player), "PlayerAttackInput")]
	internal static class BetterRidingSuppressPlayerAttackInputPatch
	{
		private static bool Prepare()
		{
			return FeedBetterRidingCompatibility.HasBetterRiding;
		}

		private static bool Prefix(Player __instance)
		{
			return FeedBetterRidingCompatibility.AllowPlayerAttackInput(__instance);
		}
	}
	[HarmonyPatch]
	internal static class BetterRidingHandleMountedAttackPatch
	{
		private static bool Prepare()
		{
			return FeedBetterRidingCompatibility.GetMountStaminaSystemMethod("HandleMountedAttack") != null;
		}

		private static MethodBase? TargetMethod()
		{
			return FeedBetterRidingCompatibility.GetMountStaminaSystemMethod("HandleMountedAttack");
		}

		private static bool Prefix(Humanoid instance, ref bool __result)
		{
			return FeedBetterRidingCompatibility.HandleMountedAttack(instance, ref __result);
		}
	}
	[HarmonyPatch]
	internal static class BetterRidingCanAttackPatch
	{
		private static bool Prepare()
		{
			return FeedBetterRidingCompatibility.GetMountStaminaSystemMethod("CanAttack") != null;
		}

		private static MethodBase? TargetMethod()
		{
			return FeedBetterRidingCompatibility.GetMountStaminaSystemMethod("CanAttack");
		}

		private static bool Prefix(object __instance, ref bool __result)
		{
			return FeedBetterRidingCompatibility.CanAttack(__instance, ref __result);
		}
	}
	[HarmonyPatch]
	internal static class BetterRidingCanJumpPatch
	{
		private static bool Prepare()
		{
			return FeedBetterRidingCompatibility.GetMountStaminaSystemMethod("CanJump") != null;
		}

		private static MethodBase? TargetMethod()
		{
			return FeedBetterRidingCompatibility.GetMountStaminaSystemMethod("CanJump");
		}

		private static bool Prefix(object __instance, ref bool __result)
		{
			return FeedBetterRidingCompatibility.CanJump(__instance, ref __result);
		}
	}
	[HarmonyPatch]
	internal static class BetterRidingOnAttackStartPatch
	{
		private static bool Prepare()
		{
			return FeedBetterRidingCompatibility.GetMountStaminaSystemMethod("OnAttackStart") != null;
		}

		private static MethodBase? TargetMethod()
		{
			return FeedBetterRidingCompatibility.GetMountStaminaSystemMethod("OnAttackStart");
		}

		private static bool Prefix(object __instance)
		{
			return FeedBetterRidingCompatibility.OnAttackStart(__instance);
		}
	}
	[HarmonyPatch]
	internal static class BetterRidingOnJumpStartPatch
	{
		private static bool Prepare()
		{
			return FeedBetterRidingCompatibility.GetMountStaminaSystemMethod("OnJumpStart") != null;
		}

		private static MethodBase? TargetMethod()
		{
			return FeedBetterRidingCompatibility.GetMountStaminaSystemMethod("OnJumpStart");
		}

		private static bool Prefix(object __instance)
		{
			return FeedBetterRidingCompatibility.OnJumpStart(__instance);
		}
	}
	[HarmonyPatch]
	internal static class BetterRidingMountAttackSafetyPatch
	{
		private static bool Prepare()
		{
			return FeedBetterRidingCompatibility.GetMountAttackUpdate() != null;
		}

		private static MethodBase? TargetMethod()
		{
			return FeedBetterRidingCompatibility.GetMountAttackUpdate();
		}

		private static bool Prefix()
		{
			return FeedBetterRidingCompatibility.AllowMountAttackUpdate();
		}
	}
	[HarmonyPatch]
	internal static class BetterRidingBlockFlyingDismountWaterPatch
	{
		private static bool Prepare()
		{
			return FeedBetterRidingCompatibility.GetBetterRidingBlockFlyingDismountPrefix() != null;
		}

		private static MethodBase? TargetMethod()
		{
			return FeedBetterRidingCompatibility.GetBetterRidingBlockFlyingDismountPrefix();
		}

		[HarmonyPriority(800)]
		private static bool Prefix(Player __0, ref bool __result)
		{
			return FeedBetterRidingCompatibility.AllowBlockFlyingDismount(__0, ref __result);
		}
	}
	[HarmonyPatch]
	internal static class DragonRidersBlockFlyingDismountWaterPatch
	{
		private static bool Prepare()
		{
			return FeedBetterRidingCompatibility.GetDragonRidersBlockFlyingDismountPrefix() != null;
		}

		private static MethodBase? TargetMethod()
		{
			return FeedBetterRidingCompatibility.GetDragonRidersBlockFlyingDismountPrefix();
		}

		[HarmonyPriority(800)]
		private static bool Prefix(Player __0, ref bool __result)
		{
			return FeedBetterRidingCompatibility.AllowBlockFlyingDismount(__0, ref __result);
		}
	}
	internal sealed class RawFeedConfig
	{
		public Dictionary<string, RawFeedingRule> Rules { get; } = new Dictionary<string, RawFeedingRule>(StringComparer.OrdinalIgnoreCase);

		public Dictionary<string, float> FoodNumbers { get; } = new Dictionary<string, float>(StringComparer.OrdinalIgnoreCase);

		public RawFeedValues Defaults { get; set; } = new RawFeedValues();
	}
	internal sealed class RawFoodEntry
	{
		public string PrefabName { get; init; } = string.Empty;

		public int? RequiredQuality { get; init; }

		public float? Value { get; init; }
	}
	internal sealed class RawFeedValues
	{
		public float LevelUpConstant { get; init; } = 1f;

		public float TamingConstant { get; init; } = 1f;

		public float GrowthConstant { get; init; } = 1f;

		public float HealConstant { get; init; } = 1f;

		public float FedConstant { get; init; } = 60f;
	}
	internal sealed class RawTameValues
	{
		public float FedDuration { get; init; }

		public float TamingTime { get; init; }

		public bool StartsTamed { get; init; }

		public bool Commandable { get; init; }
	}
	internal sealed class RawProcreationValues
	{
		public int MaxCreatures { get; init; }

		public float TotalCheckRange { get; init; }
	}
	internal sealed class RawGrowValues
	{
		public float GrowTime { get; init; }
	}
	internal sealed class RawEggGrowValues
	{
		public float GrowTime { get; init; }
	}
	internal sealed class RawMountStaminaValues
	{
		public float AttackStaminaCost { get; init; }

		public float JumpStaminaCost { get; init; }

		public float AttackCooldown { get; init; }
	}
	internal sealed class RawFeedingRule
	{
		public string PrefabName { get; init; } = string.Empty;

		public RawFeedValues? Feed { get; set; }

		public RawTameValues? Tame { get; set; }

		public RawProcreationValues? Procreation { get; set; }

		public RawGrowValues? Grow { get; set; }

		public RawEggGrowValues? EggGrow { get; set; }

		public RawMountStaminaValues? MountStamina { get; set; }

		public bool HasConsumeItemsOverride { get; set; }

		public bool HasRestrictedBiomeOverride { get; set; }

		public List<string> RestrictedBiomes { get; } = new List<string>();

		public List<RawFoodEntry> Foods { get; } = new List<RawFoodEntry>();

		public Dictionary<int, List<RawFoodEntry>> LevelUpItems { get; } = new Dictionary<int, List<RawFoodEntry>>();
	}
	internal sealed class ResolvedFoodEntry
	{
		public string PrefabName { get; init; } = string.Empty;

		public int? RequiredQuality { get; init; }

		public float Value { get; init; }

		public Sprite Icon { get; init; }
	}
	internal sealed class ResolvedFeedingRule
	{
		public GameObject Prefab { get; init; }

		public float LevelUpConstant { get; init; }

		public float TamingConstant { get; init; }

		public float GrowthConstant { get; init; }

		public float HealConstant { get; init; }

		public float FedConstant { get; init; }

		public List<ResolvedFoodEntry> Foods { get; init; } = new List<ResolvedFoodEntry>();

		public Dictionary<int, List<ResolvedFoodEntry>> LevelUpItems { get; init; } = new Dictionary<int, List<ResolvedFoodEntry>>();

		public ResolvedMountStaminaValues? MountStamina { get; init; }

		public bool HasRestrictedBiomeOverride { get; init; }

		public IReadOnlyList<string> RestrictedBiomes { get; init; } = Array.Empty<string>();
	}
	internal sealed class ResolvedMountStaminaValues
	{
		public float AttackStaminaCost { get; init; }

		public float JumpStaminaCost { get; init; }

		public float AttackCooldown { get; init; }
	}
	internal static class FeedingYamlParser
	{
		private sealed class Diagnostics
		{
			private readonly List<string> _warnings;

			private readonly List<string> _errors;

			internal Diagnostics(List<string> warnings, List<string> errors)
			{
				_warnings = warnings;
				_errors = errors;
			}

			internal void Warning(string message)
			{
				_warnings.Add(message);
			}

			internal void Error(string message)
			{
				_errors.Add(message);
			}
		}

		public static RawFeedConfig Parse(string yamlText, List<string> warnings, List<string> errors)
		{
			Diagnostics diagnostics = new Diagnostics(warnings, errors);
			RawFeedConfig rawFeedConfig = new RawFeedConfig();
			if (string.IsNullOrWhiteSpace(yamlText))
			{
				return rawFeedConfig;
			}
			YamlStream yamlStream = new YamlStream();
			yamlStream.Load(new StringReader(yamlText));
			if (yamlStream.Documents.Count == 0 || !(yamlStream.Documents[0].RootNode is YamlMappingNode yamlMappingNode))
			{
				diagnostics.Error("YAML root must be a mapping of defaults, foodNumbers, and prefab names.");
				return rawFeedConfig;
			}
			foreach (KeyValuePair<YamlNode, YamlNode> child in yamlMappingNode.Children)
			{
				string text = ReadScalar(child.Key).Trim();
				if (text.Length == 0)
				{
					diagnostics.Error(Location(child.Key) + ": top-level key cannot be empty.");
					continue;
				}
				if (text.Equals("defaults", StringComparison.OrdinalIgnoreCase))
				{
					ParseDefaults(rawFeedConfig, child.Value, diagnostics);
					continue;
				}
				if (text.Equals("foodNumbers", StringComparison.OrdinalIgnoreCase))
				{
					ParseFoodNumbers(rawFeedConfig.FoodNumbers, child.Value, "foodNumbers", diagnostics);
					continue;
				}
				RawFeedingRule value = ParseRule(text, child.Value, diagnostics);
				if (rawFeedConfig.Rules.ContainsKey(text))
				{
					diagnostics.Warning(Location(child.Key) + ": prefab '" + text + "' was defined more than once. The last definition won.");
				}
				rawFeedConfig.Rules[text] = value;
			}
			return rawFeedConfig;
		}

		private static void ParseDefaults(RawFeedConfig config, YamlNode node, Diagnostics diagnostics)
		{
			if (!(node is YamlMappingNode yamlMappingNode))
			{
				diagnostics.Error(Location(node) + ": defaults must be a mapping.");
				return;
			}
			foreach (KeyValuePair<YamlNode, YamlNode> child in yamlMappingNode.Children)
			{
				string text = ReadScalar(child.Key).Trim();
				if (text.Equals("feed", StringComparison.OrdinalIgnoreCase))
				{
					config.Defaults = ParseFeedValues(child.Value, "defaults.feed", diagnostics);
				}
				else
				{
					diagnostics.Error(Location(child.Key) + ": unknown defaults field '" + text + "'.");
				}
			}
		}

		private static RawFeedingRule ParseRule(string prefabName, YamlNode node, Diagnostics diagnostics)
		{
			RawFeedingRule rawFeedingRule = new RawFeedingRule
			{
				PrefabName = prefabName
			};
			if (!(node is YamlMappingNode yamlMappingNode))
			{
				diagnostics.Error(Location(node) + ": prefab '" + prefabName + "' must contain a mapping.");
				return rawFeedingRule;
			}
			foreach (KeyValuePair<YamlNode, YamlNode> child in yamlMappingNode.Children)
			{
				string text = ReadScalar(child.Key).Trim();
				switch (NormalizeField(text))
				{
				case "feed":
					rawFeedingRule.Feed = ParseFeedValues(child.Value, prefabName + ".feed", diagnostics);
					break;
				case "consumeitems":
					rawFeedingRule.HasConsumeItemsOverride = true;
					ParseConsumeItems(rawFeedingRule, child.Value, diagnostics);
					break;
				case "levelupitems":
					ParseLevelUpItems(rawFeedingRule, child.Value, prefabName + ".levelUpItems", diagnostics);
					break;
				case "tame":
					rawFeedingRule.Tame = ParseTameValues(child.Value, prefabName + ".tame", diagnostics);
					break;
				case "procreation":
					rawFeedingRule.Procreation = ParseProcreationValues(child.Value, prefabName + ".procreation", diagnostics);
					break;
				case "grow":
					rawFeedingRule.Grow = ParseGrowValues(child.Value, prefabName + ".grow", diagnostics);
					break;
				case "egggrow":
					rawFeedingRule.EggGrow = ParseEggGrowValues(child.Value, prefabName + ".eggGrow", diagnostics);
					break;
				case "mountstamina":
					rawFeedingRule.MountStamina = ParseMountStaminaValues(child.Value, prefabName + ".mountStamina", diagnostics);
					break;
				case "restrictedbiome":
				case "restrictedbiomes":
					rawFeedingRule.HasRestrictedBiomeOverride = true;
					rawFeedingRule.RestrictedBiomes.Clear();
					rawFeedingRule.RestrictedBiomes.AddRange((from value in ParseStringList(child.Value)
						select Unquote(value).Trim() into value
						where value.Length > 0
						select value).Distinct<string>(StringComparer.OrdinalIgnoreCase));
					break;
				default:
					diagnostics.Error(Location(child.Key) + ": unknown field '" + text + "' for prefab '" + prefabName + "'.");
					break;
				}
			}
			return rawFeedingRule;
		}

		private static void ParseConsumeItems(RawFeedingRule rule, YamlNode node, Diagnostics diagnostics)
		{
			ParseFoodEntries(rule.Foods, rule.PrefabName, node, diagnostics);
		}

		private static void ParseFoodEntries(List<RawFoodEntry> foods, string context, YamlNode node, Diagnostics diagnostics)
		{
			if (node is YamlSequenceNode yamlSequenceNode)
			{
				{
					foreach (YamlNode child in yamlSequenceNode.Children)
					{
						AddFoodEntry(foods, context, child, diagnostics);
					}
					return;
				}
			}
			foreach (string item in ParseStringList(node))
			{
				AddFoodEntry(foods, context, item, node, diagnostics);
			}
		}

		private static void AddFoodEntry(List<RawFoodEntry> foods, string context, YamlNode node, Diagnostics diagnostics)
		{
			if (node is YamlMappingNode yamlMappingNode && yamlMappingNode.Children.Count == 1)
			{
				KeyValuePair<YamlNode, YamlNode> keyValuePair = yamlMappingNode.Children.First();
				AddFoodEntry(foods, context, ReadScalar(keyValuePair.Key).Trim(), ReadScalar(keyValuePair.Value).Trim(), node, diagnostics);
				return;
			}
			if (node is YamlSequenceNode yamlSequenceNode)
			{
				List<string> list = yamlSequenceNode.Children.Select((YamlNode child) => ReadScalar(child).Trim()).ToList();
				if (list.Count >= 2)
				{
					AddFoodEntry(foods, context, list[0], list[1], node, diagnostics);
					return;
				}
			}
			AddFoodEntry(foods, context, ReadScalar(node).Trim(), node, diagnostics);
		}

		private static void AddFoodEntry(List<RawFoodEntry> foods, string context, string entryText, YamlNode node, Diagnostics diagnostics)
		{
			string valueText = null;
			string foodName;
			if (TrySplitCommaValue(entryText, out string key, out string value))
			{
				foodName = Unquote(key).Trim();
				valueText = value;
			}
			else
			{
				foodName = Unquote(entryText).Trim();
			}
			AddFoodEntry(foods, context, foodName, valueText, node, diagnostics);
		}

		private static void AddFoodEntry(List<RawFoodEntry> foods, string ruleName, string foodName, string? valueText, YamlNode node, Diagnostics diagnostics)
		{
			string prefabName;
			int? requiredQuality;
			if (string.IsNullOrWhiteSpace(foodName))
			{
				diagnostics.Error(Location(node) + ": food item name cannot be empty.");
			}
			else if (TryParseFoodToken(foodName, node, diagnostics, out prefabName, out requiredQuality))
			{
				float? value = null;
				if (!string.IsNullOrWhiteSpace(valueText))
				{
					value = Math.Max(0f, ParseFloat(valueText, ruleName + "." + FormatFoodKey(prefabName, requiredQuality), node, diagnostics));
				}
				int num = foods.FindIndex((RawFoodEntry entry) => entry.PrefabName.Equals(prefabName, StringComparison.OrdinalIgnoreCase) && entry.RequiredQuality == requiredQuality);
				if (num >= 0)
				{
					diagnostics.Warning(Location(node) + ": food '" + FormatFoodKey(prefabName, requiredQuality) + "' was defined more than once for '" + ruleName + "'. The last value won.");
					foods.RemoveAt(num);
				}
				foods.Add(new RawFoodEntry
				{
					PrefabName = prefabName,
					RequiredQuality = requiredQuality,
					Value = value
				});
			}
		}

		private static void ParseLevelUpItems(RawFeedingRule rule, YamlNode node, string context, Diagnostics diagnostics)
		{
			if (!(node is YamlMappingNode yamlMappingNode))
			{
				diagnostics.Error(Location(node) + ": " + context + " must be a mapping of current Character level to consumeItems.");
				return;
			}
			foreach (KeyValuePair<YamlNode, YamlNode> child in yamlMappingNode.Children)
			{
				int num = Math.Max(1, ParseInt(child.Key, context + ".level", diagnostics));
				List<RawFoodEntry> list = new List<RawFoodEntry>();
				ParseFoodEntries(list, $"{rule.PrefabName}.levelUpItems.{num}", child.Value, diagnostics);
				if (rule.LevelUpItems.ContainsKey(num))
				{
					diag