Decompiled source of PackBeasts v1.1.8

plugins/PackBeasts.dll

Decompiled an hour ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("PackBeasts")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("PackBeasts")]
[assembly: AssemblyTitle("PackBeasts")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace PackBeasts;

[BepInPlugin("anwo.PackBeasts", "PackBeasts", "1.1.8")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
public class PackBeastsPlugin : BaseUnityPlugin
{
	internal sealed class AnimalLook
	{
		internal ConfigEntry<float> Size;

		internal ConfigEntry<float> Out;

		internal ConfigEntry<float> Up;

		internal ConfigEntry<float> Back;
	}

	public const string Guid = "anwo.PackBeasts";

	public const string Name = "PackBeasts";

	public const string Version = "1.1.8";

	internal const string BagItemPrefab = "anwo_Saddlebags";

	internal const string DefaultCreatures = "Rideable, Lox, Asksvin, Moose, Moose_spiritcaller, rae_OdinHorse";

	internal static GameObject BagItem;

	internal static string BagItemName;

	internal static PackBeastsPlugin Instance;

	internal static ManualLogSource Log;

	internal const string RideableWord = "Rideable";

	internal static ConfigEntry<string> Creatures;

	internal static ConfigEntry<bool> NeedBagItem;

	internal static ConfigEntry<string> BagRecipe;

	internal static ConfigEntry<KeyboardShortcut> RemoveKey;

	internal static ConfigEntry<bool> ShowBags;

	internal static ConfigEntry<float> BagSideOffset;

	internal static ConfigEntry<float> BagUpOffset;

	internal static ConfigEntry<float> BagBackOffset;

	internal static ConfigEntry<float> BagScale;

	internal static readonly Dictionary<string, AnimalLook> Looks = new Dictionary<string, AnimalLook>(StringComparer.OrdinalIgnoreCase);

	internal static ConfigEntry<int> Width;

	internal static ConfigEntry<int> Height;

	internal static ConfigEntry<bool> RequireSaddle;

	internal static ConfigEntry<KeyboardShortcut> OpenKey;

	internal static ConfigEntry<string> BagName;

	internal static ConfigEntry<float> Reach;

	internal static Func<Tameable, bool> HaveSaddle;

	internal static Action<Container> DropAllItems;

	private Harmony _harmony;

	private const string PortablePalsGuid = "meldurson.valheim.PortablePals";

	private static readonly string[] PalstoneKeys = new string[2] { "anwo_pb_bags", "items" };

	private static readonly Dictionary<string, float[]> AnimalDefaults = new Dictionary<string, float[]>(StringComparer.OrdinalIgnoreCase)
	{
		{
			"Lox",
			new float[4] { 2f, -0.2f, 0f, 0f }
		},
		{
			"Moose",
			new float[4] { 2.6f, -0.08f, 0f, 0f }
		},
		{
			"Moose_spiritcaller",
			new float[4] { 2.6f, -0.08f, 0f, 0f }
		},
		{
			"Asksvin",
			new float[4] { 1.8f, -0.05f, 0f, 0f }
		},
		{
			"rae_OdinHorse",
			new float[4] { 2f, -0.05f, 0f, 0f }
		}
	};

	private FileSystemWatcher _watcher;

	private volatile bool _fileChanged;

	private float _reloadAt;

	private static Character s_lastTakeOff;

	private static float s_lastTakeOffTime = -10f;

	private void Start()
	{
		//IL_0041: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Expected O, but got Unknown
		try
		{
			if (!Chainloader.PluginInfos.TryGetValue("meldurson.valheim.PortablePals", out var value) || (Object)(object)value.Instance == (Object)null)
			{
				return;
			}
			ConfigEntry<string> val = default(ConfigEntry<string>);
			if (!value.Instance.Config.TryGetEntry<string>(new ConfigDefinition("6: Mod Compatibility", "Mod ZDOs"), ref val))
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("PortablePals found, but not its \"Mod ZDOs\" setting: palstones may not keep saddlebags. Add " + string.Join(",", PalstoneKeys) + " to it."));
				return;
			}
			List<string> names = (from n in (val.Value ?? "").Split(',')
				select n.Trim() into n
				where n.Length > 0
				select n).ToList();
			List<string> list = PalstoneKeys.Where((string k) => !names.Contains(k)).ToList();
			if (list.Count != 0)
			{
				names.AddRange(list);
				val.Value = string.Join(",", names);
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Added " + string.Join(",", list) + " to PortablePals' Mod ZDOs, so palstones keep saddlebags and their contents."));
			}
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)("Couldn't set up PortablePals to keep saddlebags: " + ex.Message));
		}
	}

	private void Awake()
	{
		//IL_0054: Unknown result type (might be due to invalid IL or missing references)
		//IL_0059: Unknown result type (might be due to invalid IL or missing references)
		//IL_0061: Expected O, but got Unknown
		//IL_0061: Unknown result type (might be due to invalid IL or missing references)
		//IL_006b: Expected O, but got Unknown
		//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
		//IL_0135: Unknown result type (might be due to invalid IL or missing references)
		//IL_013f: Expected O, but got Unknown
		//IL_0166: Unknown result type (might be due to invalid IL or missing references)
		//IL_0170: Expected O, but got Unknown
		//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d1: Expected O, but got Unknown
		//IL_0224: Unknown result type (might be due to invalid IL or missing references)
		//IL_022e: Expected O, but got Unknown
		//IL_0261: Unknown result type (might be due to invalid IL or missing references)
		//IL_026b: Expected O, but got Unknown
		//IL_029e: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a8: Expected O, but got Unknown
		//IL_02db: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e5: Expected O, but got Unknown
		//IL_0411: Unknown result type (might be due to invalid IL or missing references)
		//IL_041b: Expected O, but got Unknown
		//IL_045b: Unknown result type (might be due to invalid IL or missing references)
		Instance = this;
		Log = ((BaseUnityPlugin)this).Logger;
		Creatures = ((BaseUnityPlugin)this).Config.Bind<string>("1 - General", "Creatures", "Rideable, Lox, Asksvin, Moose, Moose_spiritcaller, rae_OdinHorse", "Comma-separated prefab names of tameable creatures that can carry saddlebags. \"Rideable\" means every creature that can wear a saddle, including mounts from mods you add later. The named ones are the rideable creatures in the game and the mod pack today (Lox, Asksvin, Moose, the spirit caller's moose, OdinHorse's horse), so they keep their bags even without \"Rideable\". Needs a game restart.");
		NeedBagItem = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - General", "Bags must be crafted", true, new ConfigDescription("Animals only carry saddlebags after you put a crafted Saddlebags item on them: put it on your hotbar and use it while looking at the animal, like a saddle. Bags that already held items when this was added stay on. Turn off to give every listed animal bags without crafting (the 1.0 behaviour).", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
		{
			IsAdminOnly = true
		} }));
		BagRecipe = ((BaseUnityPlugin)this).Config.Bind<string>("1 - General", "Saddlebags recipe", "LeatherScraps:8,DeerHide:4,BronzeNails:10", "Cost of one Saddlebags item, made at a workbench, as Item:Amount pairs separated by commas. Needs a game restart.");
		RequireSaddle = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - General", "Require saddle", true, "Animals that can wear a saddle only carry bags while saddled. Animals that can't wear one (if any) only need to be tamed.");
		OpenKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("1 - General", "Open key", new KeyboardShortcut((KeyCode)103, Array.Empty<KeyCode>()), "Opens the saddlebags of the animal you're looking at or riding.");
		RemoveKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("1 - General", "Take off key", new KeyboardShortcut((KeyCode)103, (KeyCode[])(object)new KeyCode[1] { (KeyCode)304 }), "Takes the (empty) saddlebags off the animal you're looking at, so you get the Saddlebags item back.");
		Width = ((BaseUnityPlugin)this).Config.Bind<int>("2 - Bags", "Columns", 4, new ConfigDescription("Bag size: columns. Needs a game restart. If you make the bags smaller, a bag with items in the removed slots keeps those slots until they're emptied.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(2, 8), Array.Empty<object>()));
		Height = ((BaseUnityPlugin)this).Config.Bind<int>("2 - Bags", "Rows", 2, new ConfigDescription("Bag size: rows. Needs a game restart. If you make the bags smaller, a bag with items in the removed slots keeps those slots until they're emptied.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 6), Array.Empty<object>()));
		BagName = ((BaseUnityPlugin)this).Config.Bind<string>("2 - Bags", "Name", "Saddlebags", "Title shown on the bag window and in the animal's hover text.");
		Reach = ((BaseUnityPlugin)this).Config.Bind<float>("2 - Bags", "Window close distance", 10f, new ConfigDescription("The bag window closes when the animal is further away than this, in metres. Chests use 4, which is too short for a big animal.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(4f, 30f), Array.Empty<object>()));
		ShowBags = ((BaseUnityPlugin)this).Config.Bind<bool>("3 - Look", "Show bags on the animal", true, "Show a leather bag hanging on each side of the saddle while an animal carries saddlebags.");
		BagSideOffset = ((BaseUnityPlugin)this).Config.Bind<float>("3 - Look", "Bag offset sideways", 0f, new ConfigDescription("Moves the bags out (+) or in (-), in metres, for every animal. Each animal also has its own setting under 4 - Bag look per animal.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-3f, 3f), Array.Empty<object>()));
		BagUpOffset = ((BaseUnityPlugin)this).Config.Bind<float>("3 - Look", "Bag offset up", 0f, new ConfigDescription("Moves the bags up (+) or down (-), in metres, for every animal.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-3f, 3f), Array.Empty<object>()));
		BagBackOffset = ((BaseUnityPlugin)this).Config.Bind<float>("3 - Look", "Bag offset back", 0f, new ConfigDescription("Moves the bags towards the tail (+) or the head (-), in metres, for every animal.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-3f, 3f), Array.Empty<object>()));
		BagScale = ((BaseUnityPlugin)this).Config.Bind<float>("3 - Look", "Bag size", 1f, new ConfigDescription("Size of the bags, for every animal (1 = sized from the saddle, 2 = twice as big).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.2f, 5f), Array.Empty<object>()));
		ShowBags.SettingChanged += delegate
		{
			BagsState.RebuildAll();
		};
		BagSideOffset.SettingChanged += delegate
		{
			BagsState.RebuildAll();
		};
		BagUpOffset.SettingChanged += delegate
		{
			BagsState.RebuildAll();
		};
		BagBackOffset.SettingChanged += delegate
		{
			BagsState.RebuildAll();
		};
		BagScale.SettingChanged += delegate
		{
			BagsState.RebuildAll();
		};
		BindAnimalLooks();
		WatchConfigFile();
		HaveSaddle = AccessTools.MethodDelegate<Func<Tameable, bool>>(AccessTools.Method(typeof(Tameable), "HaveSaddle", (Type[])null, (Type[])null), (object)null, true);
		DropAllItems = AccessTools.MethodDelegate<Action<Container>>(AccessTools.Method(typeof(Container), "DropAllItems", Type.EmptyTypes, (Type[])null), (object)null, true);
		_harmony = new Harmony("anwo.PackBeasts");
		_harmony.PatchAll(typeof(Patches));
		PrefabManager.OnVanillaPrefabsAvailable += AddBagItem;
		((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("{0} {1} loaded. Open key: {2}", "PackBeasts", "1.1.8", OpenKey.Value));
	}

	private void BindAnimalLooks()
	{
		//IL_010e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0118: Expected O, but got Unknown
		//IL_015e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0168: Expected O, but got Unknown
		//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b8: Expected O, but got Unknown
		//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_0208: Expected O, but got Unknown
		List<string> list = new List<string>();
		foreach (string item in (from s in "Rideable, Lox, Asksvin, Moose, Moose_spiritcaller, rae_OdinHorse".Split(',')
			select s.Trim()).Concat(CreatureNames()))
		{
			if (item.Length > 0 && !item.Equals("Rideable", StringComparison.OrdinalIgnoreCase) && !list.Contains<string>(item, StringComparer.OrdinalIgnoreCase))
			{
				list.Add(item);
			}
		}
		foreach (string item2 in list)
		{
			AnimalDefaults.TryGetValue(item2, out var value);
			if (value == null)
			{
				value = new float[4] { 1f, 0f, 0f, 0f };
			}
			AnimalLook animalLook = new AnimalLook
			{
				Size = ((BaseUnityPlugin)this).Config.Bind<float>("4 - Bag look per animal", item2 + " size", value[0], new ConfigDescription("Size of the bags on a " + item2 + ", times Bag size (1 = sized from its saddle).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.2f, 5f), Array.Empty<object>())),
				Out = ((BaseUnityPlugin)this).Config.Bind<float>("4 - Bag look per animal", item2 + " out", value[1], new ConfigDescription("Moves the bags on a " + item2 + " out (+) or in (-), in metres.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-3f, 3f), Array.Empty<object>())),
				Up = ((BaseUnityPlugin)this).Config.Bind<float>("4 - Bag look per animal", item2 + " up", value[2], new ConfigDescription("Moves the bags on a " + item2 + " up (+) or down (-), in metres.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-3f, 3f), Array.Empty<object>())),
				Back = ((BaseUnityPlugin)this).Config.Bind<float>("4 - Bag look per animal", item2 + " back", value[3], new ConfigDescription("Moves the bags on a " + item2 + " towards the tail (+) or the head (-), in metres.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-3f, 3f), Array.Empty<object>()))
			};
			ConfigEntry<float>[] array = new ConfigEntry<float>[4] { animalLook.Size, animalLook.Out, animalLook.Up, animalLook.Back };
			for (int num = 0; num < array.Length; num++)
			{
				array[num].SettingChanged += delegate
				{
					BagsState.RebuildAll();
				};
			}
			Looks[item2] = animalLook;
		}
	}

	internal static AnimalLook LookFor(string prefab)
	{
		if (string.IsNullOrEmpty(prefab))
		{
			return null;
		}
		if (Looks.TryGetValue(prefab, out var value))
		{
			return value;
		}
		string text = null;
		foreach (string key in Looks.Keys)
		{
			if (prefab.StartsWith(key, StringComparison.OrdinalIgnoreCase) && prefab.Length > key.Length && prefab[key.Length] == '_' && (text == null || key.Length > text.Length))
			{
				text = key;
			}
		}
		if (text == null)
		{
			return null;
		}
		return Looks[text];
	}

	private void WatchConfigFile()
	{
		try
		{
			string configFilePath = ((BaseUnityPlugin)this).Config.ConfigFilePath;
			_watcher = new FileSystemWatcher(Path.GetDirectoryName(configFilePath), Path.GetFileName(configFilePath));
			_watcher.NotifyFilter = NotifyFilters.Size | NotifyFilters.LastWrite;
			_watcher.Changed += delegate
			{
				_fileChanged = true;
			};
			_watcher.EnableRaisingEvents = true;
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogDebug((object)("Could not watch the config file: " + ex.Message));
		}
	}

	private void ReloadIfChanged()
	{
		if (_fileChanged)
		{
			_fileChanged = false;
			_reloadAt = Time.realtimeSinceStartup + 0.5f;
		}
		if (_reloadAt <= 0f || Time.realtimeSinceStartup < _reloadAt)
		{
			return;
		}
		_reloadAt = 0f;
		bool saveOnConfigSet = ((BaseUnityPlugin)this).Config.SaveOnConfigSet;
		try
		{
			((BaseUnityPlugin)this).Config.SaveOnConfigSet = false;
			((BaseUnityPlugin)this).Config.Reload();
			BagsState.RebuildAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Settings reloaded from the file.");
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogDebug((object)("Reloading the settings failed: " + ex.Message));
		}
		finally
		{
			((BaseUnityPlugin)this).Config.SaveOnConfigSet = saveOnConfigSet;
			_fileChanged = false;
		}
	}

	private void AddBagItem()
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Expected O, but got Unknown
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d9: Expected O, but got Unknown
		try
		{
			ItemConfig val = new ItemConfig();
			val.Name = "Saddlebags";
			val.Description = "Leather bags that hang from a saddle. Put them on your hotbar and use them while looking at a tamed, saddled animal (lox, asksvin, moose, horse) to put them on. " + ((object)OpenKey.Value/*cast due to .constrained prefix*/).ToString() + " opens them, " + ((object)RemoveKey.Value/*cast due to .constrained prefix*/).ToString() + " takes them off again when they're empty.";
			val.CraftingStation = CraftingStations.Workbench;
			val.MinStationLevel = 1;
			val.Requirements = ParseRecipe(BagRecipe.Value);
			val.Weight = 4f;
			val.StackSize = 1;
			Sprite val2 = LoadIcon();
			if ((Object)(object)val2 != (Object)null)
			{
				val.Icons = (Sprite[])(object)new Sprite[1] { val2 };
			}
			CustomItem val3 = new CustomItem("anwo_Saddlebags", "SaddleLox", val);
			if ((Object)(object)val3.ItemPrefab == (Object)null || (Object)(object)val3.ItemDrop == (Object)null)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"Could not make the Saddlebags item (no SaddleLox to copy).");
				return;
			}
			ItemManager.Instance.AddItem(val3);
			BagItem = val3.ItemPrefab;
			BagItemName = val3.ItemDrop.m_itemData.m_shared.m_name;
			val3.ItemDrop.m_itemData.m_shared.m_teleportable = true;
			((BaseUnityPlugin)this).Logger.LogInfo((object)("Saddlebags item added (" + BagRecipe.Value + ")."));
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("Adding the Saddlebags item failed: " + ex));
		}
		finally
		{
			PrefabManager.OnVanillaPrefabsAvailable -= AddBagItem;
		}
	}

	internal static bool IsBagItem(ItemData item)
	{
		if (item != null && item.m_shared != null && BagItemName != null)
		{
			return item.m_shared.m_name == BagItemName;
		}
		return false;
	}

	private static RequirementConfig[] ParseRecipe(string recipe)
	{
		//IL_008f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0094: Unknown result type (might be due to invalid IL or missing references)
		//IL_009f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b2: Expected O, but got Unknown
		//IL_0055: Unknown result type (might be due to invalid IL or missing references)
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0068: 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_007c: Expected O, but got Unknown
		List<RequirementConfig> list = new List<RequirementConfig>();
		string[] array = (recipe ?? "").Split(',');
		for (int i = 0; i < array.Length; i++)
		{
			string[] array2 = array[i].Split(':');
			if (array2.Length == 2 && int.TryParse(array2[1].Trim(), out var result) && result > 0 && array2[0].Trim().Length != 0)
			{
				list.Add(new RequirementConfig
				{
					Item = array2[0].Trim(),
					Amount = result,
					Recover = true
				});
			}
		}
		if (list.Count == 0)
		{
			list.Add(new RequirementConfig
			{
				Item = "LeatherScraps",
				Amount = 8,
				Recover = true
			});
		}
		return list.ToArray();
	}

	private static Sprite LoadIcon()
	{
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0055: Expected O, but got Unknown
		//IL_0081: Unknown result type (might be due to invalid IL or missing references)
		//IL_0090: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("PackBeasts.saddlebags.png");
			if (stream == null)
			{
				return null;
			}
			byte[] array = new byte[stream.Length];
			int num;
			for (int i = 0; i < array.Length; i += num)
			{
				num = stream.Read(array, i, array.Length - i);
				if (num <= 0)
				{
					break;
				}
			}
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
			ImageConversion.LoadImage(val, array);
			((Object)val).name = "anwo_saddlebags_icon";
			return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f));
		}
		catch (Exception ex)
		{
			Log.LogWarning((object)("Could not load the Saddlebags icon: " + ex.Message));
			return null;
		}
	}

	private void OnDestroy()
	{
		Harmony harmony = _harmony;
		if (harmony != null)
		{
			harmony.UnpatchSelf();
		}
		if (_watcher != null)
		{
			_watcher.Dispose();
		}
	}

	internal static HashSet<string> CreatureNames()
	{
		return new HashSet<string>(from s in Creatures.Value.Split(',')
			select s.Trim() into s
			where s.Length > 0
			select s, StringComparer.OrdinalIgnoreCase);
	}

	internal static bool CanUseBags(Character c, out Container bags, out string reason)
	{
		bags = null;
		reason = null;
		if ((Object)(object)c == (Object)null)
		{
			return false;
		}
		bags = ((Component)c).GetComponent<Container>();
		Tameable component = ((Component)c).GetComponent<Tameable>();
		if ((Object)(object)bags == (Object)null || (Object)(object)component == (Object)null)
		{
			return false;
		}
		if (!c.IsTamed())
		{
			reason = "Only tamed animals carry saddlebags";
			return false;
		}
		BagsState component2 = ((Component)c).GetComponent<BagsState>();
		if ((Object)(object)component2 != (Object)null && !component2.HasBags)
		{
			reason = "It has no saddlebags. Craft Saddlebags at a workbench and use them on it";
			return false;
		}
		if (RequireSaddle.Value && (Object)(object)component.m_saddle != (Object)null && !HaveSaddle(component))
		{
			reason = "Put a saddle on it first";
			return false;
		}
		return true;
	}

	internal static bool TryPutOn(Character c, Humanoid user, ItemData item)
	{
		//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)
		Player val = (Player)(object)((user is Player) ? user : null);
		BagsState bagsState = (((Object)(object)c != (Object)null) ? ((Component)c).GetComponent<BagsState>() : null);
		Tameable val2 = (((Object)(object)c != (Object)null) ? ((Component)c).GetComponent<Tameable>() : null);
		string text = null;
		if ((Object)(object)bagsState == (Object)null || (Object)(object)val2 == (Object)null)
		{
			text = "Saddlebags don't fit this animal";
		}
		else if (!c.IsTamed())
		{
			text = "Only tamed animals carry saddlebags";
		}
		else if (bagsState.Attached)
		{
			text = "It already carries saddlebags";
		}
		else if (!NeedBagItem.Value)
		{
			text = "Saddlebags don't need to be put on here: every animal already has them";
		}
		else if (RequireSaddle.Value && (Object)(object)val2.m_saddle != (Object)null && !HaveSaddle(val2))
		{
			text = "Put a saddle on it first";
		}
		if (text != null)
		{
			if ((Object)(object)val != (Object)null)
			{
				((Character)val).Message((MessageType)2, text, 0, (Sprite)null, false);
			}
			return true;
		}
		bagsState.RequestSet(on: true);
		user.GetInventory().RemoveOneItem(item);
		if ((Object)(object)val != (Object)null)
		{
			((Character)val).Message((MessageType)2, "Saddlebags on. " + ((object)OpenKey.Value/*cast due to .constrained prefix*/).ToString() + " opens them.", 0, (Sprite)null, false);
		}
		return true;
	}

	private void Update()
	{
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0055: Unknown result type (might be due to invalid IL or missing references)
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		ReloadIfChanged();
		try
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || ((Character)localPlayer).IsDead() || IsTyping() || InventoryGui.IsVisible())
			{
				return;
			}
			KeyboardShortcut value = RemoveKey.Value;
			if (((KeyboardShortcut)(ref value)).IsDown())
			{
				TakeOff(localPlayer);
				return;
			}
			value = OpenKey.Value;
			if (!((KeyboardShortcut)(ref value)).IsDown())
			{
				return;
			}
			Character val = null;
			if (((Character)localPlayer).IsRiding())
			{
				IDoodadController doodadController = localPlayer.GetDoodadController();
				Sadle val2 = (Sadle)(object)((doodadController is Sadle) ? doodadController : null);
				if (val2 != null)
				{
					val = val2.GetCharacter();
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				val = localPlayer.GetHoverCreature();
			}
			if ((Object)(object)val == (Object)null || (Object)(object)((Component)val).GetComponent<Container>() == (Object)null)
			{
				return;
			}
			if (!CanUseBags(val, out var bags, out var reason))
			{
				if (reason != null)
				{
					((Character)localPlayer).Message((MessageType)2, reason, 0, (Sprite)null, false);
				}
			}
			else
			{
				bags.Interact((Humanoid)(object)localPlayer, false, false);
			}
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogDebug((object)("Open failed: " + ex.Message));
		}
	}

	private static void TakeOff(Player p)
	{
		Character hoverCreature = p.GetHoverCreature();
		BagsState bagsState = (((Object)(object)hoverCreature != (Object)null) ? ((Component)hoverCreature).GetComponent<BagsState>() : null);
		if (!((Object)(object)bagsState == (Object)null) && NeedBagItem.Value && hoverCreature.IsTamed() && (!((Object)(object)hoverCreature == (Object)(object)s_lastTakeOff) || !(Time.time - s_lastTakeOffTime < 1.5f)))
		{
			if (!bagsState.Attached && bagsState.ItemCount == 0)
			{
				((Character)p).Message((MessageType)2, "It carries no saddlebags", 0, (Sprite)null, false);
				return;
			}
			if (bagsState.ItemCount > 0)
			{
				((Character)p).Message((MessageType)2, "Empty the saddlebags first", 0, (Sprite)null, false);
				return;
			}
			if (((Character)p).IsRiding())
			{
				((Character)p).Message((MessageType)2, "Get off first", 0, (Sprite)null, false);
				return;
			}
			bagsState.RequestSet(on: false);
			s_lastTakeOff = hoverCreature;
			s_lastTakeOffTime = Time.time;
			bagsState.RefreshSoon();
			((Character)p).Message((MessageType)2, "Saddlebags taken off", 0, (Sprite)null, false);
		}
	}

	private static bool IsTyping()
	{
		try
		{
			if (Console.IsVisible() || TextInput.IsVisible() || Menu.IsVisible() || Minimap.InTextInput())
			{
				return true;
			}
			Chat instance = Chat.instance;
			return (Object)(object)instance != (Object)null && instance.HasFocus();
		}
		catch
		{
			return false;
		}
	}
}
internal static class Patches
{
	private static readonly HashSet<GameObject> Modified = new HashSet<GameObject>();

	private static readonly FieldRef<ZNetScene, Dictionary<int, GameObject>> NamedPrefabs = MakeNamedPrefabs();

	private static readonly FieldRef<InventoryGui, Container> CurrentContainer = AccessTools.FieldRefAccess<InventoryGui, Container>("m_currentContainer");

	internal const int WidestBag = 8;

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

	private static FieldRef<ZNetScene, Dictionary<int, GameObject>> MakeNamedPrefabs()
	{
		try
		{
			return AccessTools.FieldRefAccess<ZNetScene, Dictionary<int, GameObject>>("m_namedPrefabs");
		}
		catch
		{
			return null;
		}
	}

	internal static bool IsRideable(GameObject prefab)
	{
		if ((Object)(object)prefab == (Object)null)
		{
			return false;
		}
		Tameable component = prefab.GetComponent<Tameable>();
		if ((Object)(object)component == (Object)null || (Object)(object)prefab.GetComponent<Character>() == (Object)null)
		{
			return false;
		}
		if (!((Object)(object)component.m_saddle != (Object)null))
		{
			return (Object)(object)prefab.GetComponentInChildren<Sadle>(true) != (Object)null;
		}
		return true;
	}

	private static IEnumerable<GameObject> RideablePrefabs(ZNetScene scene)
	{
		HashSet<GameObject> seen = new HashSet<GameObject>();
		IEnumerable<GameObject> enumerable = scene.m_prefabs ?? new List<GameObject>();
		Dictionary<int, GameObject> dictionary = null;
		try
		{
			dictionary = ((NamedPrefabs != null) ? NamedPrefabs.Invoke(scene) : null);
		}
		catch
		{
		}
		if (dictionary != null)
		{
			enumerable = enumerable.Concat(dictionary.Values);
		}
		foreach (GameObject item in enumerable)
		{
			if (!((Object)(object)item == (Object)null) && seen.Add(item))
			{
				bool flag = false;
				try
				{
					flag = IsRideable(item);
				}
				catch
				{
				}
				if (flag)
				{
					yield return item;
				}
			}
		}
	}

	[HarmonyPostfix]
	[HarmonyPriority(0)]
	[HarmonyPatch(typeof(ZNetScene), "Awake")]
	private static void AddBags(ZNetScene __instance)
	{
		Apply(__instance, late: false);
	}

	[HarmonyPostfix]
	[HarmonyPatch(typeof(Game), "Start")]
	private static void LateBags()
	{
		if ((Object)(object)ZNetScene.instance != (Object)null)
		{
			Apply(ZNetScene.instance, late: true);
		}
	}

	private static void Apply(ZNetScene __instance, bool late)
	{
		//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
		//IL_0206: Unknown result type (might be due to invalid IL or missing references)
		//IL_0216: Expected O, but got Unknown
		try
		{
			GameObject prefab = __instance.GetPrefab("piece_chest_wood");
			Container val = ((prefab != null) ? prefab.GetComponent<Container>() : null);
			List<KeyValuePair<string, GameObject>> list = new List<KeyValuePair<string, GameObject>>();
			HashSet<string> names = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
			foreach (string item in PackBeastsPlugin.CreatureNames())
			{
				if (string.Equals(item, "Rideable", StringComparison.OrdinalIgnoreCase))
				{
					foreach (GameObject item2 in RideablePrefabs(__instance))
					{
						if (names.Add(((Object)item2).name))
						{
							list.Add(new KeyValuePair<string, GameObject>(((Object)item2).name, item2));
						}
					}
				}
				else if (names.Add(item))
				{
					list.Add(new KeyValuePair<string, GameObject>(item, __instance.GetPrefab(item)));
				}
			}
			foreach (KeyValuePair<string, GameObject> item3 in list)
			{
				string key = item3.Key;
				GameObject value = item3.Value;
				if ((Object)(object)value == (Object)null)
				{
					if (!late)
					{
						PackBeastsPlugin.Log.LogWarning((object)("No creature called '" + key + "'; skipped."));
					}
				}
				else
				{
					if (Modified.Contains(value))
					{
						continue;
					}
					if ((Object)(object)value.GetComponent<Container>() != (Object)null)
					{
						if (!late)
						{
							PackBeastsPlugin.Log.LogWarning((object)("'" + key + "' already has storage from another mod; skipped."));
						}
						continue;
					}
					Container val2 = value.AddComponent<Container>();
					val2.m_name = PackBeastsPlugin.BagName.Value;
					val2.m_width = PackBeastsPlugin.Width.Value;
					val2.m_height = PackBeastsPlugin.Height.Value;
					val2.m_privacy = (PrivacySetting)2;
					val2.m_checkGuardStone = false;
					val2.m_autoDestroyEmpty = false;
					val2.m_defaultItems = new DropTable
					{
						m_drops = new List<DropData>(),
						m_dropMin = 0,
						m_dropMax = 0,
						m_dropChance = 0f
					};
					if ((Object)(object)val != (Object)null)
					{
						val2.m_bkg = val.m_bkg;
						val2.m_openEffects = val.m_openEffects;
						val2.m_closeEffects = val.m_closeEffects;
					}
					value.AddComponent<BagsState>();
					Modified.Add(value);
					PackBeastsPlugin.Log.LogInfo((object)$"Saddlebags added to {key} ({val2.m_width}x{val2.m_height}).");
				}
			}
			List<string> list2 = (from r in RideablePrefabs(__instance)
				select ((Object)r).name into n
				where !names.Contains(n)
				select n).ToList();
			if (list2.Count > 0 && !late)
			{
				PackBeastsPlugin.Log.LogInfo((object)("Rideable creatures without saddlebags (add them to Creatures if you want): " + string.Join(", ", list2)));
			}
		}
		catch (Exception ex)
		{
			PackBeastsPlugin.Log.LogError((object)("Adding saddlebags failed: " + ex));
		}
	}

	[HarmonyPostfix]
	[HarmonyPatch(typeof(Tameable), "GetHoverText")]
	private static void Hover(Tameable __instance, ref string __result)
	{
		//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_0126: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			Character component = ((Component)__instance).GetComponent<Character>();
			if (!PackBeastsPlugin.CanUseBags(component, out var bags, out var _))
			{
				BagsState bagsState = (((Object)(object)component != (Object)null) ? ((Component)component).GetComponent<BagsState>() : null);
				Player localPlayer = Player.m_localPlayer;
				if ((Object)(object)bagsState != (Object)null && component.IsTamed() && !bagsState.HasBags && (Object)(object)localPlayer != (Object)null && PackBeastsPlugin.BagItemName != null && ((Humanoid)localPlayer).GetInventory().GetAllItems().Any(PackBeastsPlugin.IsBagItem))
				{
					__result += "\n<color=#c0c0c0>Use your Saddlebags from the hotbar to put them on</color>";
				}
				return;
			}
			Inventory inventory = bags.GetInventory();
			int num = ((inventory != null) ? inventory.NrOfItems() : 0);
			__result = __result + $"\n[<color=yellow><b>{PackBeastsPlugin.OpenKey.Value}</b></color>] {PackBeastsPlugin.BagName.Value}" + ((num > 0) ? string.Format(" ({0} {1})", num, (num == 1) ? "item" : "items") : " (empty)");
			if (num == 0 && PackBeastsPlugin.NeedBagItem.Value)
			{
				BagsState component2 = ((Component)component).GetComponent<BagsState>();
				if (component2 != null && component2.Attached)
				{
					__result += $"  [<color=yellow><b>{PackBeastsPlugin.RemoveKey.Value}</b></color>] Take off";
				}
			}
		}
		catch
		{
		}
	}

	[HarmonyPrefix]
	[HarmonyPatch(typeof(Tameable), "UseItem")]
	private static bool TameableUseItem(Tameable __instance, Humanoid user, ItemData item, ref bool __result)
	{
		try
		{
			if (!PackBeastsPlugin.IsBagItem(item))
			{
				return true;
			}
			__result = PackBeastsPlugin.TryPutOn(((Component)__instance).GetComponent<Character>(), user, item);
			return false;
		}
		catch (Exception ex)
		{
			PackBeastsPlugin.Log.LogWarning((object)("Putting on saddlebags failed: " + ex.Message));
			return true;
		}
	}

	[HarmonyPrefix]
	[HarmonyPatch(typeof(Sadle), "UseItem")]
	private static bool SaddleUseItem(Sadle __instance, Humanoid user, ItemData item, ref bool __result)
	{
		try
		{
			if (!PackBeastsPlugin.IsBagItem(item))
			{
				return true;
			}
			__result = PackBeastsPlugin.TryPutOn(__instance.GetCharacter(), user, item);
			return false;
		}
		catch (Exception ex)
		{
			PackBeastsPlugin.Log.LogWarning((object)("Putting on saddlebags failed: " + ex.Message));
			return true;
		}
	}

	[HarmonyPrefix]
	[HarmonyPatch(typeof(Character), "OnDeath")]
	private static void OnDeath(Character __instance)
	{
		try
		{
			Container component = ((Component)__instance).GetComponent<Container>();
			if (!((Object)(object)component == (Object)null) && component.IsOwner())
			{
				BagsState component2 = ((Component)__instance).GetComponent<BagsState>();
				if ((Object)(object)component2 != (Object)null && component2.Attached)
				{
					component2.DropBagItem();
				}
				Inventory inventory = component.GetInventory();
				if (inventory != null && inventory.NrOfItems() != 0)
				{
					PackBeastsPlugin.DropAllItems(component);
					PackBeastsPlugin.Log.LogInfo((object)(Utils.GetPrefabName(((Component)__instance).gameObject) + " died; dropped its saddlebags."));
				}
			}
		}
		catch (Exception ex)
		{
			PackBeastsPlugin.Log.LogError((object)("Dropping saddlebags on death failed: " + ex));
		}
	}

	[HarmonyPrefix]
	[HarmonyPatch(typeof(InventoryGui), "UpdateContainer")]
	private static void ReachPrefix(InventoryGui __instance, out float __state)
	{
		__state = -1f;
		try
		{
			Container val = CurrentContainer.Invoke(__instance);
			if (!((Object)(object)val == (Object)null) && !((Object)(object)((Component)val).GetComponent<Character>() == (Object)null))
			{
				__state = __instance.m_autoCloseDistance;
				__instance.m_autoCloseDistance = Mathf.Max(__state, PackBeastsPlugin.Reach.Value);
			}
		}
		catch
		{
		}
	}

	[HarmonyFinalizer]
	[HarmonyPatch(typeof(InventoryGui), "UpdateContainer")]
	private static Exception ReachFinalizer(InventoryGui __instance, Exception __exception, float __state)
	{
		if (__state >= 0f)
		{
			__instance.m_autoCloseDistance = __state;
		}
		return __exception;
	}

	[HarmonyPrefix]
	[HarmonyPatch(typeof(Container), "Load")]
	private static void LoadPrefix(Container __instance)
	{
		try
		{
			if (!((Object)(object)((Component)__instance).GetComponent<Character>() == (Object)null))
			{
				Inventory inventory = __instance.GetInventory();
				if (inventory != null)
				{
					InventoryWidth.Invoke(inventory) = Mathf.Max(8, __instance.m_width);
				}
			}
		}
		catch
		{
		}
	}

	[HarmonyFinalizer]
	[HarmonyPatch(typeof(Container), "Load")]
	private static Exception LoadFinalizer(Container __instance, Exception __exception)
	{
		try
		{
			if ((Object)(object)((Component)__instance).GetComponent<Character>() != (Object)null)
			{
				Inventory inventory = __instance.GetInventory();
				if (inventory != null)
				{
					int num = __instance.m_width;
					foreach (ItemData allItem in inventory.GetAllItems())
					{
						if (allItem != null)
						{
							num = Mathf.Max(num, allItem.m_gridPos.x + 1);
						}
					}
					InventoryWidth.Invoke(inventory) = num;
				}
			}
		}
		catch
		{
		}
		return __exception;
	}

	[HarmonyPrefix]
	[HarmonyPatch(typeof(Sadle), "Interact")]
	private static bool SaddleInteract(Sadle __instance, Humanoid character, bool alt, ref bool __result)
	{
		try
		{
			if (!alt)
			{
				return true;
			}
			Character character2 = __instance.GetCharacter();
			Container val = (((Object)(object)character2 != (Object)null) ? ((Component)character2).GetComponent<Container>() : null);
			if (!((Object)(object)val == (Object)null))
			{
				Inventory inventory = val.GetInventory();
				if (inventory != null && inventory.NrOfItems() != 0)
				{
					Player val2 = (Player)(object)((character is Player) ? character : null);
					if (val2 != null && (Object)(object)val2 == (Object)(object)Player.m_localPlayer)
					{
						((Character)val2).Message((MessageType)2, "Empty the saddlebags before taking the saddle off", 0, (Sprite)null, false);
					}
					__result = false;
					return false;
				}
			}
			return true;
		}
		catch
		{
			return true;
		}
	}

	[HarmonyPostfix]
	[HarmonyPatch(typeof(Tameable), "DropSaddle")]
	private static void DropSaddlePostfix(Tameable __instance, bool __result)
	{
		try
		{
			if (__result && PackBeastsPlugin.RequireSaddle.Value && PackBeastsPlugin.NeedBagItem.Value)
			{
				BagsState component = ((Component)__instance).GetComponent<BagsState>();
				if (!((Object)(object)component == (Object)null) && component.IsOwner && component.Attached && component.ItemCount <= 0)
				{
					component.DropBagItem();
					component.RefreshSoon();
					PackBeastsPlugin.Log.LogInfo((object)(Utils.GetPrefabName(((Component)__instance).gameObject) + "'s saddle came off; its saddlebags came off with it."));
				}
			}
		}
		catch (Exception ex)
		{
			PackBeastsPlugin.Log.LogWarning((object)("Dropping saddlebags with the saddle failed: " + ex.Message));
		}
	}

	[HarmonyPrefix]
	[HarmonyPatch(typeof(Tameable), "DropSaddle")]
	private static bool DropSaddle(Tameable __instance, ref bool __result)
	{
		try
		{
			Character component = ((Component)__instance).GetComponent<Character>();
			if ((Object)(object)component == (Object)null || component.IsDead() || component.GetHealth() <= 0f)
			{
				return true;
			}
			Container component2 = ((Component)__instance).GetComponent<Container>();
			if (!((Object)(object)component2 == (Object)null))
			{
				Inventory inventory = component2.GetInventory();
				if (inventory != null && inventory.NrOfItems() != 0)
				{
					__result = false;
					return false;
				}
			}
			return true;
		}
		catch
		{
			return true;
		}
	}
}
public class BagsState : MonoBehaviour
{
	private sealed class FollowCheck
	{
		public SkinnedMeshRenderer Saddle;

		public bool FullMatrix;

		public int[] Index;

		public Vector3[] Start;

		public Transform[] Bones;

		public Matrix4x4[] BoneStart;

		public GameObject Frame;

		public Transform Bone;

		public Matrix4x4 FrameStart;

		public int Tries;

		public int Informative;
	}

	internal const string KeyBags = "anwo_pb_bags";

	internal const string RpcSetBags = "anwo_pb_setbags";

	private static readonly List<BagsState> All = new List<BagsState>();

	private ZNetView m_nview;

	private Container m_container;

	private float m_next;

	private GameObject m_visual;

	private readonly List<GameObject> m_parts = new List<GameObject>();

	private bool m_visualFailed;

	private static readonly HashSet<string> s_logged = new HashSet<string>();

	private static string s_measure = "";

	private FollowCheck m_follow;

	private static Mesh s_bakeMesh;

	private static readonly string[] TackWords = new string[9] { "rein", "bridle", "halter", "head", "jaw", "mouth", "tongue", "stirrup", "bit" };

	private static readonly string[] MovingWords = new string[28]
	{
		"rein", "bridle", "halter", "head", "jaw", "mouth", "tongue", "stirrup", "bit", "neck",
		"tail", "leg", "foot", "feet", "hoof", "hand", "finger", "toe", "thigh", "calf",
		"knee", "shin", "arm", "ear", "eye", "wing", "horn", "antler"
	};

	internal bool Attached
	{
		get
		{
			if ((Object)(object)m_nview != (Object)null && m_nview.IsValid())
			{
				return m_nview.GetZDO().GetBool("anwo_pb_bags", false);
			}
			return false;
		}
	}

	internal int ItemCount
	{
		get
		{
			if (!((Object)(object)m_container != (Object)null))
			{
				return 0;
			}
			Inventory inventory = m_container.GetInventory();
			if (inventory == null)
			{
				return 0;
			}
			return inventory.NrOfItems();
		}
	}

	internal bool HasBags
	{
		get
		{
			if (PackBeastsPlugin.NeedBagItem.Value && !Attached)
			{
				return ItemCount > 0;
			}
			return true;
		}
	}

	internal bool IsOwner
	{
		get
		{
			if ((Object)(object)m_nview != (Object)null && m_nview.IsValid())
			{
				return m_nview.IsOwner();
			}
			return false;
		}
	}

	private void Awake()
	{
		m_nview = ((Component)this).GetComponent<ZNetView>();
		m_container = ((Component)this).GetComponent<Container>();
		if ((Object)(object)m_nview == (Object)null || m_nview.GetZDO() == null)
		{
			((Behaviour)this).enabled = false;
			return;
		}
		m_nview.Register<bool>("anwo_pb_setbags", (Action<long, bool>)RPC_SetBags);
		m_next = Time.time + Random.Range(0.5f, 1.5f);
		All.Add(this);
	}

	private void OnDestroy()
	{
		All.Remove(this);
	}

	internal void RefreshSoon()
	{
		m_next = 0f;
	}

	internal void RequestSet(bool on)
	{
		if ((Object)(object)m_nview != (Object)null && m_nview.IsValid())
		{
			m_nview.InvokeRPC("anwo_pb_setbags", new object[1] { on });
		}
	}

	private void RPC_SetBags(long sender, bool on)
	{
		try
		{
			if ((Object)(object)m_nview == (Object)null || !m_nview.IsValid() || !m_nview.IsOwner())
			{
				return;
			}
			ZDO zDO = m_nview.GetZDO();
			if (on)
			{
				if (!zDO.GetBool("anwo_pb_bags", false))
				{
					zDO.Set("anwo_pb_bags", true);
				}
			}
			else if (zDO.GetBool("anwo_pb_bags", false) && ItemCount <= 0)
			{
				zDO.Set("anwo_pb_bags", false);
				DropBagItem();
			}
		}
		catch (Exception ex)
		{
			PackBeastsPlugin.Log.LogWarning((object)("Saddlebags change failed: " + ex.Message));
		}
	}

	internal void DropBagItem()
	{
		//IL_0016: 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_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: 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)
		//IL_0049: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_004c: 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_0071: Unknown result type (might be due to invalid IL or missing references)
		//IL_0076: Unknown result type (might be due to invalid IL or missing references)
		//IL_0080: Unknown result type (might be due to invalid IL or missing references)
		GameObject bagItem = PackBeastsPlugin.BagItem;
		if (!((Object)(object)bagItem == (Object)null))
		{
			Vector3 val = ((Component)this).transform.position + Vector3.up * 1.2f + ((Component)this).transform.right * 1.2f;
			Rigidbody component = Object.Instantiate<GameObject>(bagItem, val, Quaternion.identity).GetComponent<Rigidbody>();
			if ((Object)(object)component != (Object)null)
			{
				component.AddForce((((Component)this).transform.right + Vector3.up) * 2f, (ForceMode)2);
			}
			if ((Object)(object)m_nview != (Object)null && m_nview.IsValid())
			{
				m_nview.GetZDO().Set("anwo_pb_bags", false);
			}
		}
	}

	private void Update()
	{
		if (Time.time < m_next)
		{
			return;
		}
		m_next = Time.time + 1f;
		try
		{
			if ((Object)(object)m_nview == (Object)null || !m_nview.IsValid())
			{
				return;
			}
			if (PackBeastsPlugin.NeedBagItem.Value && m_nview.IsOwner() && !Attached && ItemCount > 0)
			{
				m_nview.GetZDO().Set("anwo_pb_bags", true);
				PackBeastsPlugin.Log.LogInfo((object)(Utils.GetPrefabName(((Component)this).gameObject) + " already had items in its saddlebags, so it keeps them."));
			}
			if (PackBeastsPlugin.NeedBagItem.Value && PackBeastsPlugin.RequireSaddle.Value && m_nview.IsOwner() && Attached && ItemCount == 0)
			{
				Tameable component = ((Component)this).GetComponent<Tameable>();
				Character component2 = ((Component)this).GetComponent<Character>();
				if ((Object)(object)component != (Object)null && (Object)(object)component.m_saddle != (Object)null && (Object)(object)component2 != (Object)null && !component2.IsDead() && !PackBeastsPlugin.HaveSaddle(component))
				{
					DropBagItem();
					PackBeastsPlugin.Log.LogInfo((object)(Utils.GetPrefabName(((Component)this).gameObject) + " has no saddle; its empty saddlebags fell off."));
				}
			}
			UpdateVisual();
			CheckFollow();
		}
		catch (Exception ex)
		{
			PackBeastsPlugin.Log.LogDebug((object)("Saddlebags update failed: " + ex.Message));
		}
	}

	internal static void RebuildAll()
	{
		s_logged.Clear();
		foreach (BagsState item in All)
		{
			if (!((Object)(object)item == (Object)null))
			{
				item.DestroyVisual();
				item.m_visualFailed = false;
				item.m_next = 0f;
			}
		}
	}

	private void DestroyVisual()
	{
		m_follow = null;
		foreach (GameObject part in m_parts)
		{
			if ((Object)(object)part != (Object)null)
			{
				Object.Destroy((Object)(object)part);
			}
		}
		m_parts.Clear();
		if ((Object)(object)m_visual != (Object)null)
		{
			Object.Destroy((Object)(object)m_visual);
		}
		m_visual = null;
	}

	private void UpdateVisual()
	{
		Tameable component = ((Component)this).GetComponent<Tameable>();
		Sadle val = (((Object)(object)component != (Object)null) ? component.m_saddle : null);
		if ((Object)(object)val == (Object)null)
		{
			return;
		}
		Character component2 = ((Component)this).GetComponent<Character>();
		bool flag = PackBeastsPlugin.ShowBags.Value && (Object)(object)component2 != (Object)null && component2.IsTamed() && HasBags;
		if (flag && (Object)(object)m_visual == (Object)null && !m_visualFailed && ((Component)val).gameObject.activeInHierarchy)
		{
			try
			{
				m_visual = Build(val, component2);
			}
			catch (Exception ex)
			{
				PackBeastsPlugin.Log.LogDebug((object)("Saddlebag look failed on " + ((Object)this).name + ": " + ex.Message));
			}
			if ((Object)(object)m_visual == (Object)null)
			{
				m_visualFailed = true;
			}
		}
		bool flag2 = flag && ((Component)val).gameObject.activeInHierarchy;
		if ((Object)(object)m_visual != (Object)null && m_visual.activeSelf != flag2)
		{
			m_visual.SetActive(flag2);
		}
		foreach (GameObject part in m_parts)
		{
			if ((Object)(object)part != (Object)null && part.activeSelf != flag2)
			{
				part.SetActive(flag2);
			}
		}
	}

	private GameObject Build(Sadle saddle, Character character)
	{
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: 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_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_01db: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
		//IL_0204: Unknown result type (might be due to invalid IL or missing references)
		//IL_0208: Unknown result type (might be due to invalid IL or missing references)
		//IL_020a: 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_0211: Unknown result type (might be due to invalid IL or missing references)
		//IL_0212: Unknown result type (might be due to invalid IL or missing references)
		//IL_0214: Unknown result type (might be due to invalid IL or missing references)
		//IL_0219: Unknown result type (might be due to invalid IL or missing references)
		//IL_021a: Unknown result type (might be due to invalid IL or missing references)
		//IL_021b: Unknown result type (might be due to invalid IL or missing references)
		//IL_021d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0222: Unknown result type (might be due to invalid IL or missing references)
		//IL_023e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0244: Unknown result type (might be due to invalid IL or missing references)
		//IL_0251: 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_025d: Unknown result type (might be due to invalid IL or missing references)
		//IL_026b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0271: Unknown result type (might be due to invalid IL or missing references)
		//IL_0277: Unknown result type (might be due to invalid IL or missing references)
		//IL_0291: Unknown result type (might be due to invalid IL or missing references)
		//IL_0293: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_02fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_02de: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_0301: Unknown result type (might be due to invalid IL or missing references)
		//IL_0303: Unknown result type (might be due to invalid IL or missing references)
		//IL_0304: Unknown result type (might be due to invalid IL or missing references)
		//IL_0306: Unknown result type (might be due to invalid IL or missing references)
		//IL_030b: Unknown result type (might be due to invalid IL or missing references)
		//IL_031b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0320: Unknown result type (might be due to invalid IL or missing references)
		//IL_0321: Unknown result type (might be due to invalid IL or missing references)
		//IL_0326: Unknown result type (might be due to invalid IL or missing references)
		//IL_0334: Unknown result type (might be due to invalid IL or missing references)
		//IL_0339: Unknown result type (might be due to invalid IL or missing references)
		//IL_033d: Unknown result type (might be due to invalid IL or missing references)
		//IL_033f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0344: Unknown result type (might be due to invalid IL or missing references)
		//IL_0348: Unknown result type (might be due to invalid IL or missing references)
		//IL_034f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0350: Unknown result type (might be due to invalid IL or missing references)
		//IL_0352: Unknown result type (might be due to invalid IL or missing references)
		//IL_0357: Unknown result type (might be due to invalid IL or missing references)
		//IL_0358: Unknown result type (might be due to invalid IL or missing references)
		//IL_0359: Unknown result type (might be due to invalid IL or missing references)
		//IL_035b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0360: Unknown result type (might be due to invalid IL or missing references)
		//IL_0387: Unknown result type (might be due to invalid IL or missing references)
		//IL_0388: Unknown result type (might be due to invalid IL or missing references)
		//IL_0389: Unknown result type (might be due to invalid IL or missing references)
		//IL_038e: Unknown result type (might be due to invalid IL or missing references)
		//IL_03b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_03bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_03be: Unknown result type (might be due to invalid IL or missing references)
		//IL_03c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_039e: Unknown result type (might be due to invalid IL or missing references)
		//IL_039f: Unknown result type (might be due to invalid IL or missing references)
		//IL_03a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_03a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_04a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_04aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_04ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_04b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_04b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_04b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_04b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_04be: Unknown result type (might be due to invalid IL or missing references)
		//IL_04c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_041a: Unknown result type (might be due to invalid IL or missing references)
		//IL_041f: Unknown result type (might be due to invalid IL or missing references)
		//IL_042a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0431: Unknown result type (might be due to invalid IL or missing references)
		//IL_0567: Unknown result type (might be due to invalid IL or missing references)
		//IL_059c: Unknown result type (might be due to invalid IL or missing references)
		//IL_05ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_05c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_05d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_0692: Unknown result type (might be due to invalid IL or missing references)
		//IL_0697: Unknown result type (might be due to invalid IL or missing references)
		//IL_0699: Unknown result type (might be due to invalid IL or missing references)
		//IL_069e: Unknown result type (might be due to invalid IL or missing references)
		//IL_06aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_06af: Unknown result type (might be due to invalid IL or missing references)
		//IL_06b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_06b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0457: Unknown result type (might be due to invalid IL or missing references)
		//IL_045c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0461: Unknown result type (might be due to invalid IL or missing references)
		//IL_0466: Unknown result type (might be due to invalid IL or missing references)
		//IL_046b: Unknown result type (might be due to invalid IL or missing references)
		//IL_046d: Unknown result type (might be due to invalid IL or missing references)
		//IL_046e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0470: Unknown result type (might be due to invalid IL or missing references)
		//IL_0475: Unknown result type (might be due to invalid IL or missing references)
		//IL_0476: Unknown result type (might be due to invalid IL or missing references)
		//IL_0477: Unknown result type (might be due to invalid IL or missing references)
		//IL_0479: Unknown result type (might be due to invalid IL or missing references)
		//IL_047e: Unknown result type (might be due to invalid IL or missing references)
		//IL_06c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_06ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_06cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_06ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_06d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_06d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_06d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_06d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_06db: Unknown result type (might be due to invalid IL or missing references)
		//IL_06e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_0726: Unknown result type (might be due to invalid IL or missing references)
		//IL_0653: Unknown result type (might be due to invalid IL or missing references)
		//IL_0658: Unknown result type (might be due to invalid IL or missing references)
		//IL_065e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0660: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a39: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a40: Expected O, but got Unknown
		//IL_0a60: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a67: Expected O, but got Unknown
		//IL_0891: Unknown result type (might be due to invalid IL or missing references)
		//IL_08a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_08af: Unknown result type (might be due to invalid IL or missing references)
		//IL_0944: Unknown result type (might be due to invalid IL or missing references)
		//IL_078c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0bca: Unknown result type (might be due to invalid IL or missing references)
		//IL_0bcf: Unknown result type (might be due to invalid IL or missing references)
		//IL_0bd1: Unknown result type (might be due to invalid IL or missing references)
		//IL_0bd6: Unknown result type (might be due to invalid IL or missing references)
		//IL_09a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_09b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_09c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_09cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_09db: Unknown result type (might be due to invalid IL or missing references)
		//IL_09e2: Unknown result type (might be due to invalid IL or missing references)
		//IL_09f1: Unknown result type (might be due to invalid IL or missing references)
		//IL_09f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a07: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a0e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0cd1: Unknown result type (might be due to invalid IL or missing references)
		//IL_0cd7: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a9c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0ac5: Unknown result type (might be due to invalid IL or missing references)
		//IL_0ac7: Unknown result type (might be due to invalid IL or missing references)
		//IL_0c0a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0c0f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0c22: Unknown result type (might be due to invalid IL or missing references)
		//IL_0c35: Unknown result type (might be due to invalid IL or missing references)
		//IL_0c69: Unknown result type (might be due to invalid IL or missing references)
		//IL_0c79: Unknown result type (might be due to invalid IL or missing references)
		//IL_0c7e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0c83: Unknown result type (might be due to invalid IL or missing references)
		//IL_0c91: Unknown result type (might be due to invalid IL or missing references)
		//IL_0ca1: Unknown result type (might be due to invalid IL or missing references)
		//IL_0ca6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0cab: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b04: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b34: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b38: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b4e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b50: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b62: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b69: Unknown result type (might be due to invalid IL or missing references)
		Transform transform = ((Component)this).transform;
		Matrix4x4 val = Matrix4x4.TRS(transform.position, transform.rotation, Vector3.one);
		Matrix4x4 inverse = ((Matrix4x4)(ref val)).inverse;
		Vector3 val2 = Vector3.positiveInfinity;
		Vector3 val3 = Vector3.negativeInfinity;
		Material val4 = null;
		int num = 0;
		List<Vector3> list = new List<Vector3>();
		List<Transform> list2 = new List<Transform>();
		List<Renderer> list3 = new List<Renderer>();
		Renderer[] componentsInChildren = ((Component)saddle).GetComponentsInChildren<Renderer>();
		foreach (Renderer val5 in componentsInChildren)
		{
			if (!((Object)(object)val5 == (Object)null) && val5.enabled && (val5 is MeshRenderer || val5 is SkinnedMeshRenderer) && !((Object)(object)((Component)val5).GetComponentInParent<BagLook>() != (Object)null))
			{
				list3.Add(val5);
			}
		}
		int num2 = 0;
		if (list3.Any((Renderer r) => !IsTack(((Object)r).name)))
		{
			num2 += list3.RemoveAll((Renderer r) => IsTack(((Object)r).name));
		}
		foreach (Renderer item in list3)
		{
			if ((Object)(object)val4 == (Object)null)
			{
				val4 = item.sharedMaterial;
			}
			bool[] keep = null;
			SkinnedMeshRenderer val6 = (SkinnedMeshRenderer)(object)((item is SkinnedMeshRenderer) ? item : null);
			if (val6 != null && val6.bones != null)
			{
				Transform[] bones = val6.bones;
				foreach (Transform val7 in bones)
				{
					if ((Object)(object)val7 != (Object)null)
					{
						list2.Add(val7);
					}
				}
				keep = SaddleVertices(val6, out var dropped);
				num2 += dropped;
			}
			else
			{
				list2.Add(((Component)item).transform);
			}
			list.AddRange(SurfacePoints(item, 600, keep));
		}
		if (list.Count == 0)
		{
			return null;
		}
		Matrix4x4 val8 = Matrix4x4.TRS(transform.position, transform.rotation, Vector3.one);
		foreach (Vector3 item2 in list)
		{
			Vector3 val9 = ((Matrix4x4)(ref inverse)).MultiplyPoint3x4(item2);
			val2 = Vector3.Min(val2, val9);
			val3 = Vector3.Max(val3, val9);
		}
		Vector3 val10 = default(Vector3);
		((Vector3)(ref val10))..ctor((val2.x + val3.x) * 0.5f, val2.y + (val3.y - val2.y) * 0.55f, val2.z + (val3.z - val2.z) * 0.2f);
		string how;
		bool known;
		Transform val11 = SaddleBone(saddle, list3, list2, ((Matrix4x4)(ref val8)).MultiplyPoint3x4(val10), out how, out known);
		Matrix4x4 val12 = (((Object)(object)val11 != (Object)null) ? val11.localToWorldMatrix : val8);
		string note = "no pose correction";
		if ((Object)(object)val11 != (Object)null && RestPose(((Component)this).transform, val11, out var rest, out note))
		{
			val12 = rest;
		}
		Matrix4x4 val13 = (((Object)(object)val11 != (Object)null) ? (val12 * val11.worldToLocalMatrix) : Matrix4x4.identity);
		Matrix4x4 val14 = inverse * val13;
		List<Vector3> list4 = new List<Vector3>(list.Count);
		val2 = Vector3.positiveInfinity;
		val3 = Vector3.negativeInfinity;
		foreach (Vector3 item3 in list)
		{
			Vector3 val15 = ((Matrix4x4)(ref val14)).MultiplyPoint3x4(item3);
			list4.Add(val15);
			val2 = Vector3.Min(val2, val15);
			val3 = Vector3.Max(val3, val15);
			num++;
		}
		string text = s_measure;
		Vector3 val16 = val3 - val2;
		if (!(((Vector3)(ref val16)).magnitude < 0.25f))
		{
			val16 = val3 - val2;
			if (!(((Vector3)(ref val16)).magnitude > 8f))
			{
				goto IL_04a9;
			}
		}
		val2 = Vector3.positiveInfinity;
		val3 = Vector3.negativeInfinity;
		componentsInChildren = ((Component)saddle).GetComponentsInChildren<Renderer>();
		foreach (Renderer val17 in componentsInChildren)
		{
			if (!((Object)(object)val17 == (Object)null) && val17.enabled && (val17 is MeshRenderer || val17 is SkinnedMeshRenderer) && !((Object)(object)((Component)val17).GetComponentInParent<BagLook>() != (Object)null))
			{
				Bounds bounds = val17.bounds;
				for (int num3 = 0; num3 < 8; num3++)
				{
					Vector3 val18 = ((Matrix4x4)(ref val14)).MultiplyPoint3x4(((Bounds)(ref bounds)).center + Vector3.Scale(((Bounds)(ref bounds)).extents, new Vector3((float)(((num3 & 1) != 0) ? 1 : (-1)), (float)(((num3 & 2) != 0) ? 1 : (-1)), (float)(((num3 & 4) != 0) ? 1 : (-1)))));
					val2 = Vector3.Min(val2, val18);
					val3 = Vector3.Max(val3, val18);
				}
			}
		}
		text += ", used the renderer boxes";
		goto IL_04a9;
		IL_04a9:
		Vector3 val19 = val3 - val2;
		Vector3 val20 = (val3 + val2) * 0.5f;
		PackBeastsPlugin.AnimalLook animalLook = PackBeastsPlugin.LookFor(Utils.GetPrefabName(((Component)this).gameObject));
		float num4 = PackBeastsPlugin.BagScale.Value * (animalLook?.Size.Value ?? 1f);
		float num5 = PackBeastsPlugin.BagSideOffset.Value + (animalLook?.Out.Value ?? 0f);
		float num6 = PackBeastsPlugin.BagUpOffset.Value + (animalLook?.Up.Value ?? 0f);
		float num7 = PackBeastsPlugin.BagBackOffset.Value + (animalLook?.Back.Value ?? 0f);
		float num8 = Mathf.Clamp(val19.z * 0.36f, 0.28f, 0.5f) * num4;
		float num9 = num8 * 0.78f;
		float num10 = num8 * 0.36f;
		float num11 = val19.x * 0.5f * 0.92f + num10 * 0.5f;
		float num12 = val2.y + val19.y * 0.55f + num6;
		float num13 = val2.z + num8 * 0.35f - num7;
		List<Vector3> list5 = new List<Vector3>();
		SkinnedMeshRenderer[] componentsInChildren2 = ((Component)this).GetComponentsInChildren<SkinnedMeshRenderer>();
		foreach (SkinnedMeshRenderer val21 in componentsInChildren2)
		{
			if ((Object)(object)val21 == (Object)null || !((Renderer)val21).enabled || ((Component)val21).transform.IsChildOf(((Component)saddle).transform) || (Object)(object)((Component)val21).GetComponentInParent<BagLook>() != (Object)null)
			{
				continue;
			}
			foreach (Vector3 item4 in SurfacePoints((Renderer)(object)val21, 6000))
			{
				list5.Add(((Matrix4x4)(ref val14)).MultiplyPoint3x4(item4));
			}
		}
		Vector3 val22 = Vector3.zero;
		Vector3 val23 = Vector3.zero;
		if (list5.Count > 0)
		{
			val22 = Vector3.positiveInfinity;
			val23 = Vector3.negativeInfinity;
			foreach (Vector3 item5 in list5)
			{
				val22 = Vector3.Min(val22, item5);
				val23 = Vector3.Max(val23, item5);
			}
		}
		float[] array = new float[2];
		float[] array2 = new float[2];
		for (int num14 = 0; num14 < 2; num14++)
		{
			array2[num14] = Flank(list5, (num14 == 0) ? (-1f) : 1f, val20.x, num12 - num9, num12, num13 - num8 * 0.5f, num13 + num8 * 0.5f);
		}
		if (array2[0] <= 0f && array2[1] <= 0f)
		{
			for (int num15 = 0; num15 < 2; num15++)
			{
				array2[num15] = Flank(list5, (num15 == 0) ? (-1f) : 1f, val20.x, num12 - num9 * 2f, num12 + num9 * 0.5f, num13 - num8, num13 + num8);
			}
		}
		float num16 = ((array2[0] > 0f && array2[1] > 0f) ? Mathf.Min(array2[0], array2[1]) : Mathf.Max(array2[0], array2[1]));
		for (int num17 = 0; num17 < 2; num17++)
		{
			float num18 = ((num16 > 0f) ? Mathf.Max(num16 + num10 * 0.45f, Mathf.Min(num11, num16 + num10)) : num11);
			array[num17] = num18 + num5;
			array[num17] = Mathf.Max(array[num17], num10 * 0.6f);
		}
		string prefabName = Utils.GetPrefabName(((Component)this).gameObject);
		if (s_logged.Add(prefabName))
		{
			PackBeastsPlugin.Log.LogInfo((object)($"Saddlebag look for {prefabName}: saddle {val19.x:0.00} wide, {val19.y:0.00} tall, {val19.z:0.00} long ({num} points; {text}); " + $"body {array2[0]:0.00} / {array2[1]:0.00} m out at the bags ({list5.Count} points); bags {num8:0.00} x {num9:0.00} x {num10:0.00} m, " + $"{array[0]:0.00} / {array[1]:0.00} m out, top {num12 - val2.y:0.00} m above the saddle's lowest point; " + string.Format("hung on {0} ({1}; {2}); left out {3} reins/stirrup parts; ", ((Object)(object)val11 != (Object)null) ? ((Object)val11).name : "the saddle", how, note, num2) + $"body spans x {val22.x:0.00}..{val23.x:0.00}, y {val22.y - val2.y:0.00}..{val23.y - val2.y:0.00}, z {val22.z - val2.z:0.00}..{val23.z - val2.z:0.00} m from the saddle's back bottom."));
		}
		Materials materials = Materials.For(val4);
		GameObject val24 = new GameObject("anwo_saddlebags");
		val24.AddComponent<BagLook>();
		val24.transform.SetParent(((Component)saddle).transform, false);
		GameObject val25 = new GameObject("anwo_saddlebags_frame");
		val25.AddComponent<BagLook>();
		Vector3 val27 = default(Vector3);
		Vector3 val28 = default(Vector3);
		for (int num19 = 0; num19 < 2; num19++)
		{
			float num20 = ((num19 == 0) ? (-1f) : 1f);
			GameObject val26 = MakeBag(num8, num9, num10, num20, materials);
			((Vector3)(ref val27))..ctor(val20.x + num20 * array[num19], num12 - num9 * 0.5f, num13);
			val26.transform.SetPositionAndRotation(val27, Quaternion.identity);
			int num21 = 0;
			float[] array3 = new float[2]
			{
				(0f - num8) * 0.3f,
				num8 * 0.3f
			};
			foreach (float num22 in array3)
			{
				((Vector3)(ref val28))..ctor(val20.x + num20 * (array[num19] - num10 * 0.3f), num12 - num9 * 0.08f, num13 + num22);
				if (FindAnchor(list4, val28, num20, val20.x, num8, num9, out var anchor))
				{
					Strap(val26, val28, anchor, num8 * 0.09f, num10 * 0.1f, Vector3.right * num20, materials.Dark);
					num21++;
				}
			}
			if (num21 == 0)
			{
				AddHangers(val26, num8, num9, num10, num20, materials);
			}
			val26.transform.SetParent(val25.transform, true);
		}
		Matrix4x4 val29 = ((Matrix4x4)(ref val12)).inverse * val8;
		if ((Object)(object)val11 != (Object)null && ((Matrix4x4)(ref val29)).ValidTRS())
		{
			val25.transform.SetParent(val11, false);
			val25.transform.localPosition = Vector4.op_Implicit(((Matrix4x4)(ref val29)).GetColumn(3));
			val25.transform.localRotation = ((Matrix4x4)(ref val29)).rotation;
			val25.transform.localScale = ((Matrix4x4)(ref val29)).lossyScale;
			m_parts.Add(val25);
			if (!known)
			{
				StartFollowCheck(list3, val25, val11, (Vector3[])(object)new Vector3[2]
				{
					val25.transform.TransformPoint(new Vector3(val20.x - array[0], num12, num13)),
					val25.transform.TransformPoint(new Vector3(val20.x + array[1], num12, num13))
				}, Mathf.Max(0.4f, num8 * 1.5f));
			}
		}
		else
		{
			val25.transform.SetPositionAndRotation(transform.position, transform.rotation);
			val25.transform.SetParent(val24.transform, true);
		}
		return val24;
	}

	private void StartFollowCheck(List<Renderer> renderers, GameObject frame, Transform bone, Vector3[] anchors, float radius)
	{
		//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c7: 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_00dc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_010c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0111: Unknown result type (might be due to invalid IL or missing references)
		//IL_0116: Unknown result type (might be due to invalid IL or missing references)
		//IL_0118: Unknown result type (might be due to invalid IL or missing references)
		//IL_011d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0122: Unknown result type (might be due to invalid IL or missing references)
		//IL_0127: Unknown result type (might be due to invalid IL or missing references)
		//IL_0130: Unknown result type (might be due to invalid IL or missing references)
		//IL_0135: Unknown result type (might be due to invalid IL or missing references)
		//IL_013a: Unknown result type (might be due to invalid IL or missing references)
		//IL_013f: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f3: Unknown result type (might be due to invalid IL or missing references)
		m_follow = null;
		try
		{
			SkinnedMeshRenderer val = null;
			foreach (Renderer renderer in renderers)
			{
				SkinnedMeshRenderer val2 = (SkinnedMeshRenderer)(object)((renderer is SkinnedMeshRenderer) ? renderer : null);
				if (val2 != null && (Object)(object)val2.sharedMesh != (Object)null && val2.bones != null && ((Object)(object)val == (Object)null || val2.sharedMesh.vertexCount > val.sharedMesh.vertexCount))
				{
					val = val2;
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			bool full;
			Vector3[] v = Bake(val, out full, null);
			if (v == null || v.Length == 0)
			{
				return;
			}
			Matrix4x4 m = (full ? ((Component)val).transform.localToWorldMatrix : Matrix4x4.TRS(((Component)val).transform.position, ((Component)val).transform.rotation, Vector3.one));
			List<KeyValuePair<float, int>> list = new List<KeyValuePair<float, int>>();
			for (int i = 0; i < v.Length; i++)
			{
				Vector3 val3 = ((Matrix4x4)(ref m)).MultiplyPoint3x4(v[i]);
				Vector3 val4 = val3 - anchors[0];
				float sqrMagnitude = ((Vector3)(ref val4)).sqrMagnitude;
				val4 = val3 - anchors[1];
				float key = Mathf.Min(sqrMagnitude, ((Vector3)(ref val4)).sqrMagnitude);
				list.Add(new KeyValuePair<float, int>(key, i));
			}
			list.Sort((KeyValuePair<float, int> a, KeyValuePair<float, int> b) => a.Key.CompareTo(b.Key));
			List<int> list2 = new List<int>();
			foreach (KeyValuePair<float, int> item in list)
			{
				if (list2.Count < 160 && (list2.Count < 24 || !(item.Key > radius * radius)))
				{
					list2.Add(item.Value);
					continue;
				}
				break;
			}
			List<Transform> list3 = val.bones.Where((Transform b) => (Object)(object)b != (Object)null && !IsMovingPart(((Object)b).name)).Distinct().ToList();
			if ((Object)(object)bone != (Object)null && !list3.Contains(bone))
			{
				list3.Add(bone);
			}
			if (list3.Count >= 2)
			{
				FollowCheck follow = new FollowCheck
				{
					Saddle = val,
					FullMatrix = full,
					Index = list2.ToArray(),
					Start = list2.Select((int num) => ((Matrix4x4)(ref m)).MultiplyPoint3x4(v[num])).ToArray(),
					Bones = list3.ToArray(),
					BoneStart = list3.Select((Transform b) => b.localToWorldMatrix).ToArray(),
					Frame = frame,
					Bone = bone,
					FrameStart = frame.transform.localToWorldMatrix
				};
				m_follow = follow;
			}
		}
		catch (Exception ex)
		{
			PackBeastsPlugin.Log.LogDebug((object)("Saddlebag follow check failed to start: " + ex.Message));
		}
	}

	private void CheckFollow()
	{
		//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_012d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0132: Unknown result type (might be due to invalid IL or missing references)
		//IL_0137: Unknown result type (might be due to invalid IL or missing references)
		//IL_018b: Unknown result type (might be due to invalid IL or missing references)
		//IL_019d: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_02bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_02fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_0303: Unknown result type (might be due to invalid IL or missing references)
		//IL_031a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0331: Unknown result type (might be due to invalid IL or missing references)
		FollowCheck follow = m_follow;
		if (follow == null)
		{
			return;
		}
		try
		{
			if ((Object)(object)follow.Saddle == (Object)null || (Object)(object)follow.Frame == (Object)null || (Object)(object)follow.Bone == (Object)null || !((Component)follow.Saddle).gameObject.activeInHierarchy)
			{
				m_follow = null;
				return;
			}
			if (++follow.Tries > 300 || follow.Informative >= 6)
			{
				m_follow = null;
				return;
			}
			bool full;
			Vector3[] array = Bake(follow.Saddle, out full, follow.FullMatrix);
			if (array == null)
			{
				m_follow = null;
				return;
			}
			Matrix4x4 val = (follow.FullMatrix ? ((Component)follow.Saddle).transform.localToWorldMatrix : Matrix4x4.TRS(((Component)follow.Saddle).transform.position, ((Component)follow.Saddle).transform.rotation, Vector3.one));
			Vector3[] array2 = (Vector3[])(object)new Vector3[follow.Index.Length];
			for (int i = 0; i < follow.Index.Length; i++)
			{
				if (follow.Index[i] >= array.Length)
				{
					m_follow = null;
					return;
				}
				array2[i] = ((Matrix4x4)(ref val)).MultiplyPoint3x4(array[follow.Index[i]]);
			}
			float num = float.MaxValue;
			float num2 = float.MaxValue;
			float num3 = 0f;
			int num4 = -1;
			for (int j = 0; j < follow.Bones.Length; j++)
			{
				if (!((Object)(object)follow.Bones[j] == (Object)null))
				{
					Matrix4x4 val2 = follow.Bones[j].localToWorldMatrix * ((Matrix4x4)(ref follow.BoneStart[j])).inverse;
					float num5 = 0f;
					for (int k = 0; k < array2.Length; k++)
					{
						float num6 = num5;
						Vector3 val3 = ((Matrix4x4)(ref val2)).MultiplyPoint3x4(follow.Start[k]) - array2[k];
						num5 = num6 + ((Vector3)(ref val3)).sqrMagnitude;
					}
					num5 /= (float)Mathf.Max(1, array2.Length);
					if (num5 < num)
					{
						num = num5;
						num4 = j;
					}
					if ((Object)(object)follow.Bones[j] == (Object)(object)follow.Bone)
					{
						num2 = num5;
					}
					num3 = Mathf.Max(num3, num5);
				}
			}
			if (num3 < 0.0009f)
			{
				return;
			}
			follow.Informative++;
			if (num4 >= 0 && !((Object)(object)follow.Bones[num4] == (Object)(object)follow.Bone) && !(num2 < 0.0009f) && !(num * 4f > num2))
			{
				Transform val4 = follow.Bones[num4];
				Matrix4x4 val5 = ((Matrix4x4)(ref follow.BoneStart[num4])).inverse * follow.FrameStart;
				if (!((Matrix4x4)(ref val5)).ValidTRS())
				{
					m_follow = null;
					return;
				}
				follow.Frame.transform.SetParent(val4, false);
				follow.Frame.transform.localPosition = Vector4.op_Implicit(((Matrix4x4)(ref val5)).GetColumn(3));
				follow.Frame.transform.localRotation = ((Matrix4x4)(ref val5)).rotation;
				follow.Frame.transform.localScale = ((Matrix4x4)(ref val5)).lossyScale;
				PackBeastsPlugin.Log.LogInfo((object)("Saddlebags on " + Utils.GetPrefabName(((Component)this).gameObject) + " moved from " + ((Object)follow.Bone).name + " to " + ((Object)val4).name + ", which the saddle follows " + $"(off by {Mathf.Sqrt(num2) * 100f:0} cm on {((Object)follow.Bone).name}, {Mathf.Sqrt(num) * 100f:0} cm on {((Object)val4).name})."));
				m_follow = null;
			}
		}
		catch (Exception ex)
		{
			PackBeastsPlugin.Log.LogDebug((object)("Saddlebag follow check failed: " + ex.Message));
			m_follow = null;
		}
	}

	private static Vector3[] Bake(SkinnedMeshRenderer smr, out bool full, bool? useFull)
	{
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: Expected O, but got Unknown
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_0062: Unknown result type (might be due to invalid IL or missing references)
		//IL_0067: Unknown result type (might be due to invalid IL or missing references)
		//IL_006c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0071: Unknown result type (might be due to invalid IL or missing references)
		//IL_0078: Unknown result type (might be due to invalid IL or missing references)
		//IL_007d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0081: Unknown result type (might be due to invalid IL or missing references)
		//IL_0086: Unknown result type (might be due to invalid IL or missing references)
		//IL_0096: Unknown result type (might be due to invalid IL or missing references)
		//IL_009f: Unknown result type (might be due to invalid IL or missing references)
		full = true;
		if ((Object)(object)s_bakeMesh == (Object)null)
		{
			s_bakeMesh = new Mesh();
		}
		smr.BakeMesh(s_bakeMesh, true);
		Vector3[] vertices = s_bakeMesh.vertices;
		if (useFull.HasValue)
		{
			full = useFull.Value;
			return vertices;
		}
		Matrix4x4 localToWorldMatrix = ((Component)smr).transform.localToWorldMatrix;
		Matrix4x4 m = Matrix4x4.TRS(((Component)smr).transform.position, ((Component)smr).transform.rotation, Vector3.one);
		Bounds bounds = ((Renderer)smr).bounds;
		Vector3 size = ((Bounds)(ref bounds)).size;
		float num = Mathf.Max(0.01f, ((Vector3)(ref size)).magnitude);
		float num2 = Extent(vertices, localToWorldMatrix);
		float num3 = Extent(vertices, m);
		full = Mathf.Abs(Mathf.Log(Mathf.Max(0.0001f, num2) / num)) <= Mathf.Abs(Mathf.Log(Mathf.Max(0.0001f, num3) / num));
		return vertices;
	}

	private static bool FindAnchor(List<Vector3> saddle, Vector3 start, float s, float centerX, float length, float height, out Vector3 anchor)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0003: Unknown result type (might be due to invalid IL or missing references)
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_0047: 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_0063: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_0065: Unknown result type (might be due to invalid IL or missing references)
		//IL_006a: Unknown result type (might be due to invalid IL or missing references)
		//IL_007c: Unknown result type (might be due to invalid IL or missing references)
		//IL_007d: Unknown result type (might be due to invalid IL or missing references)
		anchor = start;
		float num = float.MaxValue;
		foreach (Vector3 item in saddle)
		{
			if (!((item.x - centerX) * s <= 0f) && !(item.y < start.y + height * 0.08f) && !(Mathf.Abs(item.z - start.z) > length * 0.25f))
			{
				Vector3 val = item - start;
				float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude;
				if (sqrMagnitude < num)
				{
					num = sqrMagnitude;
					anchor = item;
				}
			}
		}
		return num < height * height * 9f;
	}

	private static bool RestPose(Transform animal, Transform bone, out Matrix4x4 rest, out string note)
	{
		//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_00b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00da: Unknown result type (might be due to invalid IL or missing references)
		//IL_00df: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
		//IL_0103: Unknown result type (might be due to invalid IL or missing references)
		//IL_0112: Unknown result type (might be due to invalid IL or missing references)
		//IL_0117: Unknown result type (might be due to invalid IL or missing references)
		//IL_011d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0122: Unknown result type (might be due to invalid IL or missing references)
		//IL_0127: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
		rest = bone.localToWorldMatrix;
		note = "no bind pose for " + ((Object)bone).name;
		try
		{
			SkinnedMeshRenderer[] componentsInChildren = ((Component)animal).GetComponentsInChildren<SkinnedMeshRenderer>(true);
			Transform val = bone;
			while ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)animal.parent)
			{
				SkinnedMeshRenderer[] array = componentsInChildren;
				foreach (SkinnedMeshRenderer val2 in array)
				{
					if ((Object)(object)val2 == (Object)null || val2.bones == null || (Object)(object)val2.sharedMesh == (Object)null || (Object)(object)((Component)val2).GetComponentInParent<BagLook>() != (Object)null)
					{
						continue;
					}
					int num = Array.IndexOf(val2.bones, val);
					if (num < 0)
					{
						continue;
					}
					Matrix4x4[] bindposes = val2.sharedMesh.bindposes;
					if (bindposes == null || num >= bindposes.Length)
					{
						continue;
					}
					Matrix4x4 val3 = ((Component)val2).transform.localToWorldMatrix * ((Matrix4x4)(ref bindposes[num])).inverse * (val.worldToLocalMatrix * bone.localToWorldMatrix);
					if (!((Matrix4x4)(ref val3)).ValidTRS())
					{
						note = "bind pose not usable";
						continue;
					}
					float num2 = Quaternion.Angle(((Matrix4x4)(ref val3)).rotation, bone.rotation);
					Vector3 val4 = Vector4.op_Implicit(((Matrix4x4)(ref val3)).GetColumn(3)) - bone.position;
					float magnitude = ((Vector3)(ref val4)).magnitude;
					string arg = (((Object)(object)val == (Object)(object)bone) ? "" : (" via " + ((Object)val).name));
					note = $"pose corrected {num2:0} deg, {magnitude:0.00} m{arg}";
					if (num2 > 50f || magnitude > 1.5f)
					{
						note = $"pose correction skipped ({num2:0} deg, {magnitude:0.00} m{arg})";
						return false;
					}
					rest = val3;
					return true;
				}
				val = val.parent;
			}
		}
		catch (Exception ex)
		{
			note = "bind pose unreadable: " + ex.Message;
		}
		return false;
	}

	private static Transform SaddleBone(Sadle saddle, List<Renderer> renderers, List<Transform> bones, Vector3 point, out string how, out bool known)
	{
		//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_02a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_0312: Unknown result type (might be due to invalid IL or missing references)
		Dictionary<Transform, float> dictionary = new Dictionary<Transform, float>();
		float total = 0f;
		foreach (Renderer renderer in renderers)
		{
			SkinnedMeshRenderer val = (SkinnedMeshRenderer)(object)((renderer is SkinnedMeshRenderer) ? renderer : null);
			if (val != null)
			{
				if (((Renderer)val).enabled && val.bones != null && !((Object)(object)val.sharedMesh == (Object)null) && val.sharedMesh.isReadable)
				{
					Transform[] bones2 = val.bones;
					BoneWeight[] boneWeights = val.sharedMesh.boneWeights;
					for (int i = 0; i < boneWeights.Length; i++)
					{
						BoneWeight val2 = boneWeights[i];
						AddWeight(dictionary, bones2, ((BoneWeight)(ref val2)).boneIndex0, ((BoneWeight)(ref val2)).weight0);
						AddWeight(dictionary, bones2, ((BoneWeight)(ref val2)).boneIndex1, ((BoneWeight)(ref val2)).weight1);
						AddWeight(dictionary, bones2, ((BoneWeight)(ref val2)).boneIndex2, ((BoneWeight)(ref val2)).weight2);
						AddWeight(dictionary, bones2, ((BoneWeight)(ref val2)).boneIndex3, ((BoneWeight)(ref val2)).weight3);
						total += ((BoneWeight)(ref val2)).weight0 + ((BoneWeight)(ref val2)).weight1 + ((BoneWeight)(ref val2)).weight2 + ((BoneWeight)(ref val2)).weight3;
					}
				}
			}
			else if (renderer is MeshRenderer)
			{
				MeshFilter component = ((Component)renderer).GetComponent<MeshFilter>();
				int num = (((Object)(object)component != (Object)null && (Object)(object)component.sharedMesh != (Object)null) ? component.sharedMesh.vertexCount : 8);
				dictionary.TryGetValue(((Component)renderer).transform, out var value);
				dictionary[((Component)renderer).transform] = value + (float)num;
				total += num;
			}
		}
		List<Transform> list = new List<Transform>();
		foreach (KeyValuePair<Transform, float> item in dictionary)
		{
			if (item.Value >= total * 0.05f)
			{
				list.Add(item.Key);
			}
		}
		List<Transform> list2 = list.Where((Transform b) => !IsMovingPart(((Object)b).name)).ToList();
		string text = string.Join(", ", from p in dictionary.OrderByDescending((KeyValuePair<Transform, float> p) => p.Value).Take(5)
			select ((Object)p.Key).name + " " + ((total > 0f) ? (p.Value / total * 100f) : 0f).ToString("0") + "%");
		if (list2.Count > 0)
		{
			how = "carried by: " + text;
			known = true;
			return Nearest(list2, point);
		}
		known = false;
		List<Transform> list3 = bones.Where((Transform b) => (Object)(object)b != (Object)null && !IsMovingPart(((Object)b).name)).ToList();
		how = ((list.Count > 0) ? ("only head/leg bones carry the saddle (" + text + "), so the nearest back bone") : "nearest the saddle's middle");
		return Nearest((list3.Count > 0) ? list3 : bones, point);
	}

	private static bool[] SaddleVertices(SkinnedMeshRenderer sk, out int dropped)
	{
		dropped = 0;
		try
		{
			Mesh sharedMesh = sk.sharedMesh;
			if ((Object)(object)sharedMesh == (Object)null || !sharedMesh.isReadable)
			{
				return null;
			}
			BoneWeight[] boneWeights = sharedMesh.boneWeights;
			Transform[] bones = sk.bones;
			if (boneWeights == null || boneWeights.Length == 0 || boneWeights.Length != sharedMesh.vertexCount || bones == null)
			{
				return null;
			}
			bool[] array = new bool[bones.Length];
			for (int i = 0; i < bones.Length; i++)
			{
				array[i] = (Object)(object)bones[i] != (Object)null && IsTack(((Object)bones[i]).name);
			}
			bool[] array2 = new bool[boneWeights.Length];
			int num = 0;
			for (int j = 0; j < boneWeights.Length; j++)
			{
				int num2 = ((BoneWeight)(ref boneWeights[j])).boneIndex0;
				float num3 = ((BoneWeight)(ref boneWeights[j])).weight0;
				if (((BoneWeight)(ref boneWeights[j])).weight1 > num3)
				{
					num3 = ((BoneWeight)(ref boneWeights[j])).weight1;
					num2 = ((BoneWeight)(ref boneWeights[j])).boneIndex1;
				}
				if (((BoneWeight)(ref boneWeights[j])).weight2 > num3)
				{
					num3 = ((BoneWeight)(ref boneWeights[j])).weight2;
					num2 = ((BoneWeight)(ref boneWeights[j])).boneIndex2;
				}
				if (((BoneWeight)(ref boneWeights[j])).weight3 > num3)
				{
					num2 = ((BoneWeight)(ref boneWeights[j])).boneIndex3;
				}
				array2[j] = num2 < 0 || num2 >= array.Length || !array[num2];
				if (array2[j])
				{
					num++;
				}
			}
			if (num < 30 || num < boneWeights.Length / 5)
			{
				return null;
			}
			dropped = boneWeights.Length - num;
			return (dropped > 0) ? array2 : null;
		}
		catch
		{
			return null;
		}
	}

	internal static bool IsTack(string name)
	{
		return NameHasWord(name, TackWords);
	}

	internal static bool IsMovingPart(string name)
	{
		return NameHasWord(name, MovingWords);
	}

	internal static bool NameHasWord(string name, string[] words)
	{
		if (string.IsNullOrEmpty(name))
		{
			return false;
		}
		List<string> list = new List<string>();
		StringBuilder stringBuilder = new StringBuilder();
		for (int i = 0; i < name.Length; i++)
		{
			char c = name[i];
			if ((!char.IsLetter(c) || (char.IsUpper(c) && i > 0 && char.IsLower(name[i - 1]))) && stringBuilder.Length > 0)
			{
				list.Add(stringBuilder.ToString());
				stringBuilder.Length = 0;
			}
			if (char.IsLetter(c))
			{
				stringBuilder.Append(char.ToLowerInvariant(c));
			}
		}
		if (stringBuilder.Length > 0)
		{
			list.Add(stringBuilder.ToString());
		}
		foreach (string item in list)
		{
			int num = 0;
			while (num < words.Length)
			{
				string text = words[num];
				bool num2;
				if (text.Length > 3)
				{
					num2 = item.StartsWith(text);
				}
				else
				{
					if (item == text)
					{
						goto IL_00f9;
					}
					num2 = item == text + "s";
				}
				if (!num2)
				{
					num++;
					continue;
				}
				goto IL_00f9;
				IL_00f9:
				return true;
			}
		}
		return false;
	}

	private static void AddWeight(Dictionary<Transform, float> weights, Transform[] bones, int index, float weight)
	{
		if (!(weight <= 0f) && index >= 0 && index < bones.Length && !((Object)(object)bones[index] == (Object)null))
		{
			weights.TryGetValue(bones[index], out var value);
			weights[bones[index]] = value + weight;
		}
	}

	private static Transform Nearest(List<Transform> candidates, Vector3 point)
	{
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		//IL_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)
		Transform result = null;
		float num = float.MaxValue;
		foreach (Transform candidate in candidates)
		{
			if (!((Object)(object)candidate == (Object)null))
			{
				Vector3 val = candidate.position - point;
				float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude;
				if (sqrMagnitude < num)
				{
					num = sqrMagnitude;
					result = candidate;
				}
			}
		}
		return result;
	}

	private static void Strap(GameObject parent, Vector3 from, Vector3 to, float width, float thickness, Vector3 outward, Material material)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0041: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0072: Unknown result type (might be due to invalid IL or missing references)
		Vector3 val = to - from;
		float magnitude = ((Vector3)(ref val)).magnitude;
		if (!(magnitude < 0.01f))
		{
			GameObject val2 = new GameObject("strap");
			val2.transform.SetPositionAndR