Decompiled source of ValBallCompatibility v0.1.2

plugins/ValBallCompatibility/ValBallCompatibility.dll

Decompiled 5 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security.Cryptography;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using ConditionalConfigSync;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("ValBallCompatibility")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: AssemblyInformationalVersion("0.1.0")]
[assembly: AssemblyProduct("ValBallCompatibility")]
[assembly: AssemblyTitle("ValBallCompatibility")]
[assembly: AssemblyVersion("0.1.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace ValBallCompatibility
{
	internal static class Cargo
	{
		private sealed class Cached
		{
			internal string Data;

			internal Inventory Inventory;

			internal bool Failed;
		}

		[ThreadStatic]
		private static int weightDepth;

		private static readonly ConditionalWeakTable<ItemData, Cached> cache = new ConditionalWeakTable<ItemData, Cached>();

		private static Type portalType;

		private static PropertyInfo portalSynced;

		private static FieldInfo portalAllowed;

		private static bool portalVerified;

		private static Inventory Get(ItemData item, string data)
		{
			Cached orCreateValue = cache.GetOrCreateValue(item);
			if (orCreateValue.Data != data)
			{
				orCreateValue.Data = data;
				orCreateValue.Inventory = null;
				orCreateValue.Failed = true;
				orCreateValue.Inventory = Load(data);
				orCreateValue.Failed = false;
			}
			if (orCreateValue.Failed || orCreateValue.Inventory == null)
			{
				throw new InvalidOperationException("Invalid cached horse cargo.");
			}
			return orCreateValue.Inventory;
		}

		internal static Inventory Load(string text)
		{
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Expected O, but got Unknown
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Expected O, but got Unknown
			if (text.Length > 2097152)
			{
				throw new InvalidOperationException("Cargo size exceeds limit.");
			}
			byte[] array = Convert.FromBase64String(text);
			if (array.Length > 1048576)
			{
				throw new InvalidOperationException("Cargo size exceeds limit.");
			}
			int num;
			using (BinaryReader binaryReader = new BinaryReader(new MemoryStream(array)))
			{
				num = ((binaryReader.ReadInt32() >= 108) ? binaryReader.ReadUInt16() : binaryReader.ReadInt32());
			}
			if (num < 0 || num > 256)
			{
				throw new InvalidOperationException("Cargo item count exceeds limit.");
			}
			Inventory val = new Inventory("Transport saddlebags", (Sprite)null, 16, 16);
			val.Load(new ZPackage(array));
			if (val.GetAllItems().Count != num)
			{
				throw new InvalidOperationException("Cargo contains missing or unreadable items.");
			}
			return val;
		}

		internal static bool Has(ItemData item, out string data)
		{
			data = null;
			if (item?.m_customData != null && item.m_customData.ContainsKey("valball.prefab") && item.m_customData.TryGetValue("vercadi.valball.cargo", out data))
			{
				return !string.IsNullOrEmpty(data);
			}
			return false;
		}

		internal static void Weight(ItemData __instance, ref float __result)
		{
			if (!Has(__instance, out var data))
			{
				return;
			}
			if (++weightDepth > 4)
			{
				weightDepth--;
				__result = 100000f;
				return;
			}
			try
			{
				__result += Get(__instance, data).GetTotalWeight();
			}
			catch
			{
				__result = 100000f;
			}
			finally
			{
				weightDepth--;
			}
		}

		internal static void Teleportable(Inventory __instance, bool __0, ref bool __result)
		{
			if (!__result)
			{
				return;
			}
			bool all = __0 || (Object.op_Implicit((Object)(object)ZoneSystem.instance) && ZoneSystem.instance.GetGlobalKey((GlobalKeys)35));
			try
			{
				foreach (ItemData allItem in __instance.GetAllItems())
				{
					if (Has(allItem, out var data) && !ContentsPortable(Get(allItem, data), all, 0))
					{
						__result = false;
						break;
					}
				}
			}
			catch
			{
				__result = false;
			}
		}

		private static bool ContentsPortable(Inventory inv, bool all, int depth)
		{
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Expected O, but got Unknown
			if (depth > 4)
			{
				return false;
			}
			foreach (ItemData allItem in inv.GetAllItems())
			{
				if (allItem?.m_shared == null || allItem.m_shared.m_toolTier >= 1000)
				{
					return false;
				}
				if (!all && !allItem.m_shared.m_teleportable && !ServerAllows(allItem))
				{
					return false;
				}
				if (Has(allItem, out var data) && !ContentsPortable(Get(allItem, data), all, depth + 1))
				{
					return false;
				}
				if (!Chainloader.PluginInfos.TryGetValue("vapok.mods.adventurebackpacks", out var value))
				{
					continue;
				}
				Type type = ((object)value.Instance).GetType().Assembly.GetType("AdventureBackpacks.API.ABAPI", throwOnError: true);
				MethodInfo methodInfo = AccessTools.Method(type, "IsBackpack", new Type[1] { typeof(ItemData) }, (Type[])null);
				if (methodInfo != null && (bool)methodInfo.Invoke(null, new object[1] { allItem }))
				{
					Inventory val = (Inventory)AccessTools.Method(type, "GetBackpackInventory", new Type[1] { typeof(ItemData) }, (Type[])null).Invoke(null, new object[1] { allItem });
					if (val == null || !ContentsPortable(val, all, depth + 1))
					{
						return false;
					}
				}
			}
			return true;
		}

		private static bool ServerAllows(ItemData item)
		{
			if (!Object.op_Implicit((Object)(object)item.m_dropPrefab) || !Chainloader.PluginInfos.TryGetValue("vercadi.AdventureBackpackCompatibility", out var value))
			{
				return false;
			}
			Type type = ((object)value.Instance).GetType();
			if (portalType != type)
			{
				portalType = type;
				portalVerified = false;
				Native.Verify(type.Assembly, "87929803694672352059BCE6595CEE4CF7DE424FB5776F067F23529C1896AF4A");
				portalSynced = AccessTools.Property(type, "Synced");
				portalAllowed = AccessTools.Field(type, "allowed");
				portalVerified = portalSynced != null && portalAllowed != null;
			}
			if (!portalVerified || !(bool)portalSynced.GetValue(value.Instance, null))
			{
				return false;
			}
			return ((HashSet<string>)portalAllowed.GetValue(value.Instance)).Contains(Rules.Name(((Object)item.m_dropPrefab).name));
		}
	}
	internal sealed class Journal
	{
		internal readonly string PathName;

		private readonly string snapshot;

		internal Journal(string operation, ItemData ball, string animalId)
		{
			//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_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Expected O, but got Unknown
			string text = Path.Combine(Paths.BepInExRootPath, "ValBallRecovery");
			Directory.CreateDirectory(text);
			Inventory val = new Inventory("Recovery", (Sprite)null, 1, 1);
			if (!val.AddItem(ball.Clone()))
			{
				throw new InvalidOperationException("Cannot stage recovery item.");
			}
			ZPackage val2 = new ZPackage();
			val.Save(val2);
			snapshot = "ValBallCompatibility 0.1.0\nOperation=" + operation + "\nAnimal=" + animalId + "\nInventory=" + val2.GetBase64() + "\n";
			PathName = Path.Combine(text, DateTime.UtcNow.ToString("yyyyMMddTHHmmssfff") + "-" + Guid.NewGuid().ToString("N") + ".txt");
			Phase("prepared");
		}

		internal void Phase(string phase)
		{
			byte[] bytes = Encoding.UTF8.GetBytes(snapshot + "Phase=" + phase + "\n");
			using FileStream fileStream = new FileStream(PathName, FileMode.Create, FileAccess.Write, FileShare.Read);
			fileStream.Write(bytes, 0, bytes.Length);
			fileStream.Flush(flushToDisk: true);
		}

		internal void Complete()
		{
			File.Delete(PathName);
		}
	}
	internal sealed class Native
	{
		internal const string Hash = "0D81F59CD0B57FD038460F679DEA164B9C077A0B6E6111A641AE9D57222B3AF0";

		internal readonly Type Projectile;

		internal readonly Type Capture;

		internal readonly Type Captured;

		internal readonly Type Plugin;

		internal readonly BaseUnityPlugin Mod;

		internal readonly SkillType Skill;

		internal Native()
		{
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			Mod = Chainloader.PluginInfos["gokbe.valball"].Instance;
			Verify(((object)Mod).GetType().Assembly, "0D81F59CD0B57FD038460F679DEA164B9C077A0B6E6111A641AE9D57222B3AF0");
			Assembly assembly = ((object)Mod).GetType().Assembly;
			Projectile = assembly.GetType("ValBall.ValBallProjectile", throwOnError: true);
			Capture = assembly.GetType("ValBall.CaptureRules", throwOnError: true);
			Captured = assembly.GetType("ValBall.CapturedCreature", throwOnError: true);
			Plugin = assembly.GetType("ValBall.ValBallPlugin", throwOnError: true);
			Skill = (SkillType)AccessTools.Field(Plugin, "ValMasterSkill").GetValue(null);
			string[] array = new string[3] { "Capture", "Release", "OnHit" };
			foreach (string text in array)
			{
				if (AccessTools.Method(Projectile, text, (Type[])null, (Type[])null) == null)
				{
					throw new MissingMethodException(text);
				}
			}
		}

		internal static void Verify(Assembly a, string expected)
		{
			using FileStream inputStream = File.OpenRead(a.Location);
			using SHA256 sHA = SHA256.Create();
			if (BitConverter.ToString(sHA.ComputeHash(inputStream)).Replace("-", "") != expected)
			{
				throw new NotSupportedException("Unreviewed " + a.GetName().Name + " binary.");
			}
		}

		internal static object Field(object o, string name)
		{
			return AccessTools.Field(o.GetType(), name).GetValue(o);
		}

		internal static T Read<T>(object o, string name)
		{
			return (T)Field(o, name);
		}

		internal static object Call(Type t, string name, object o, params object[] args)
		{
			return AccessTools.Method(t, name, (Type[])null, (Type[])null).Invoke(o, args);
		}

		internal ItemData Item(string prefab)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			return (ItemData)Call(Plugin, "NewItem", null, prefab);
		}

		internal object Snapshot(Character c)
		{
			return Call(Captured, "FromCharacter", null, c);
		}

		internal void Write(object snapshot, ItemData item)
		{
			Call(Captured, "Write", snapshot, item);
		}

		internal void Timers(object snapshot, ZDO zdo)
		{
			Call(Captured, "ApplyTimers", snapshot, zdo);
		}

		internal void Xp(Player p, float amount)
		{
			Call(Capture, "AwardXp", null, p, amount);
		}

		internal T Config<T>(string section, string key)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			return ((ConfigEntry<T>)(object)Mod.Config[new ConfigDefinition(section, key)]).Value;
		}

		internal object Tier(object projectile)
		{
			return Field(projectile, "m_tier");
		}

		internal ItemData Empty(object projectile)
		{
			return Item(Read<string>(Tier(projectile), "EmptyPrefab"));
		}

		internal ItemData Full(object projectile)
		{
			return Item(Read<string>(Tier(projectile), "FullPrefab"));
		}

		internal float Multiplier(object projectile)
		{
			return Read<ConfigEntry<float>>(Tier(projectile), "Multiplier").Value;
		}
	}
	internal static class ExtraState
	{
		private static readonly CultureInfo Invariant = CultureInfo.InvariantCulture;

		internal const string HorseId = "rae_OdinHorse";

		internal static readonly string[] AiBools = new string[3] { "huntplayer", "spawnday", "spawnnight" };

		internal static readonly FieldInfo HorseCache = FindHorseCache();

		private static FieldInfo FindHorseCache()
		{
			foreach (PluginInfo value in Chainloader.PluginInfos.Values)
			{
				if (!((Object)(object)value.Instance == (Object)null))
				{
					Type type = ((object)value.Instance).GetType().Assembly.GetType("OdinHorse.HorseSaddlebags");
					if (type != null)
					{
						Native.Verify(type.Assembly, "424B2406AC4C4F024E57C349277E3A4DA03AB95802C23A955247167B3751A99D");
						return AccessTools.Field(type, "s_containerCache") ?? throw new MissingFieldException("Horse cache");
					}
				}
			}
			return null;
		}

		internal static Container CachedHorseBag(Character c)
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			ZNetView component = ((Component)c).GetComponent<ZNetView>();
			if (HorseCache?.GetValue(null) is IDictionary dictionary && Object.op_Implicit((Object)(object)component) && component.IsValid() && dictionary.Contains(component.GetZDO().m_uid))
			{
				object? obj = dictionary[component.GetZDO().m_uid];
				return (Container)((obj is Container) ? obj : null);
			}
			return null;
		}

		internal static string Guard(Character c)
		{
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Expected O, but got Unknown
			Tameable component = ((Component)c).GetComponent<Tameable>();
			if (Object.op_Implicit((Object)(object)component) && (component.m_unsummonDistance > 0f || component.m_unsummonOnOwnerLogoutSeconds > 0f))
			{
				return "Summoned creatures cannot be transported.";
			}
			if (Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)component.m_saddle) && component.m_saddle.HaveValidUser())
			{
				return "Dismount before capturing this animal.";
			}
			foreach (Vagon item in (IEnumerable)AccessTools.Field(typeof(Vagon), "m_instances").GetValue(null))
			{
				Vagon val = item;
				if (Object.op_Implicit((Object)(object)val) && val.IsAttached(c))
				{
					return "Detach the cart before capturing this animal.";
				}
			}
			Container[] componentsInChildren = ((Component)c).GetComponentsInChildren<Container>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				if (componentsInChildren[i].IsInUse())
				{
					return "Close the animal's storage first.";
				}
			}
			Container val2 = CachedHorseBag(c);
			if (Object.op_Implicit((Object)(object)val2) && val2.IsInUse())
			{
				return "Close the horse's saddlebags first.";
			}
			return null;
		}

		internal static void Save(Character c, ItemData item)
		{
			//IL_0243: Unknown result type (might be due to invalid IL or missing references)
			//IL_024a: Expected O, but got Unknown
			ZDO zDO = ((Component)c).GetComponent<ZNetView>().GetZDO();
			Dictionary<string, string> customData = item.m_customData;
			customData["vercadi.valball.version"] = "1";
			customData["vercadi.valball.maxHealth"] = c.GetMaxHealth().ToString("R", Invariant);
			customData["vercadi.valball.bred"] = (zDO.GetBool("vercadi.valball.bred", false) ? "1" : "0");
			customData["vercadi.valball.oceanDuration"] = zDO.GetFloat("vercadi.valball.oceanDuration", 0f).ToString("R", Invariant);
			Tameable component = ((Component)c).GetComponent<Tameable>();
			if (Object.op_Implicit((Object)(object)component))
			{
				customData["vercadi.valball.tameRemaining"] = zDO.GetFloat(ZDOVars.s_tameTimeLeft, component.m_tamingTime).ToString("R", Invariant);
			}
			BaseAI component2 = ((Component)c).GetComponent<BaseAI>();
			if (Object.op_Implicit((Object)(object)component2))
			{
				string[] array = new string[2] { "m_despawnInDay", "m_eventCreature" };
				foreach (string text in array)
				{
					FieldInfo fieldInfo = AccessTools.Field(((object)component2).GetType(), text);
					if (fieldInfo != null && fieldInfo.FieldType == typeof(bool))
					{
						customData["vercadi.valball." + text] = (((bool)fieldInfo.GetValue(component2)) ? "1" : "0");
					}
				}
			}
			string text2 = Rules.Name(((Object)((Component)c).gameObject).name);
			if (!(text2 == "rae_OdinHorse") && !(text2 == "rae_Offspring_Normal"))
			{
				return;
			}
			if (HorseCache == null)
			{
				throw new NotSupportedException("Reviewed OdinHorse adapter is unavailable.");
			}
			customData["vercadi.valball.coat"] = zDO.GetInt("HorseMaterial", -1).ToString(Invariant);
			customData["vercadi.valball.armor"] = (zDO.GetBool("HaveArmor", false) ? "1" : "0");
			customData["vercadi.valball.waiting"] = (zDO.GetBool("IsWaiting", false) ? "1" : "0");
			Container val = CachedHorseBag(c);
			if (Object.op_Implicit((Object)(object)val))
			{
				ZPackage val2 = new ZPackage();
				val.GetInventory().Save(val2);
				if (val2.GetBase64() != zDO.GetString("rae_saddlebags", "") && val.GetInventory().NrOfItems() > 0)
				{
					throw new InvalidOperationException("Saddlebag cache differs from network state. Rejoin before capturing this horse.");
				}
			}
			string text3 = zDO.GetString("rae_saddlebags", "");
			if (text3.Length > 2097152)
			{
				throw new InvalidDataException("Horse cargo exceeds transport bound.");
			}
			if (text3.Length > 0)
			{
				Cargo.Load(text3);
			}
			customData["vercadi.valball.cargo"] = text3;
		}

		internal static void Restore(Character c, ItemData item)
		{
			Dictionary<string, string> customData = item.m_customData;
			ZNetView component = ((Component)c).GetComponent<ZNetView>();
			ZDO zDO = component.GetZDO();
			if (!customData.ContainsKey("vercadi.valball.version"))
			{
				return;
			}
			zDO.Set("vercadi.valball.bred", customData.TryGetValue("vercadi.valball.bred", out var value) && value == "1");
			zDO.Set("vercadi.valball.oceanDuration", Rules.Number(customData, "vercadi.valball.oceanDuration"));
			if (customData.ContainsKey("vercadi.valball.tameRemaining"))
			{
				zDO.Set(ZDOVars.s_tameTimeLeft, Math.Max(0f, Rules.Number(customData, "vercadi.valball.tameRemaining")));
			}
			BaseAI component2 = ((Component)c).GetComponent<BaseAI>();
			if (Object.op_Implicit((Object)(object)component2))
			{
				string[] array = new string[2] { "m_despawnInDay", "m_eventCreature" };
				foreach (string text in array)
				{
					FieldInfo fieldInfo = AccessTools.Field(((object)component2).GetType(), text);
					if (!(fieldInfo != null) || !customData.TryGetValue("vercadi.valball." + text, out var value2))
					{
						continue;
					}
					MonsterAI val = (MonsterAI)(object)((component2 is MonsterAI) ? component2 : null);
					if (val != null)
					{
						if (text == "m_eventCreature")
						{
							val.SetEventCreature(value2 == "1");
						}
						else
						{
							val.SetDespawnInDay(value2 == "1");
						}
					}
					else
					{
						fieldInfo.SetValue(component2, value2 == "1");
					}
				}
			}
			if (customData.TryGetValue("vercadi.valball.coat", out var value3))
			{
				zDO.Set("HorseMaterial", int.Parse(value3, Invariant));
				zDO.Set("rae_saddlebags", customData.TryGetValue("vercadi.valball.cargo", out var value4) ? value4 : "");
				string value5;
				bool flag = customData.TryGetValue("vercadi.valball.armor", out value5) && value5 == "1";
				string value6;
				bool flag2 = customData.TryGetValue("vercadi.valball.waiting", out value6) && value6 == "1";
				zDO.Set("HaveArmor", flag);
				zDO.Set("IsWaiting", flag2);
				if (Rules.Name(((Object)((Component)c).gameObject).name) == "rae_OdinHorse")
				{
					component.InvokeRPC(ZNetView.Everybody, "SetArmor", new object[1] { flag });
					component.InvokeRPC(ZNetView.Everybody, "SetWait", new object[1] { flag2 });
				}
			}
			float num = Rules.Number(customData, "vercadi.valball.maxHealth");
			if (num > 0f && num < 10000000f)
			{
				c.SetMaxHealth(num);
			}
		}
	}
	[BepInPlugin("vercadi.ValBallCompatibility", "ValBall Compatibility", "0.1.0")]
	[BepInDependency("gokbe.valball", "1.6.0")]
	[BepInDependency("_shudnal.ConditionalConfigSync", "1.0.9")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string Id = "vercadi.ValBallCompatibility";

		public const string Version = "0.1.0";

		private static Plugin instance;

		private Native native;

		private Harmony harmony;

		private ConfigSync sync;

		private ConfigEntry<string> progression;

		private Dictionary<string, Species> species = new Dictionary<string, Species>();

		private bool ready;

		private bool faulted;

		[ThreadStatic]
		private static int breeding;

		private bool Synced
		{
			get
			{
				if (Object.op_Implicit((Object)(object)ZNet.instance))
				{
					if (!ZNet.instance.IsServer())
					{
						if (((ConditionalConfigSync)sync).InitialSyncDone)
						{
							return !((ConditionalConfigSync)sync).IsSourceOfTruth;
						}
						return false;
					}
					return true;
				}
				return false;
			}
		}

		private void Awake()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: 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_0073: Expected O, but got Unknown
			//IL_02ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0316: Unknown result type (might be due to invalid IL or missing references)
			//IL_0321: Expected O, but got Unknown
			//IL_0321: Expected O, but got Unknown
			//IL_035c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0369: Expected O, but got Unknown
			//IL_03a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_03bd: Expected O, but got Unknown
			instance = this;
			harmony = new Harmony("vercadi.ValBallCompatibility");
			progression = ((BaseUnityPlugin)this).Config.Bind<string>("Capture", "Species progression", Rules.DefaultProgression, "Exact reviewed prefab:ValMasterLevel:worldBossKey entries separated by semicolons. Omit a species to disable new capture. Already-filled balls remain releasable. Already-tamed supported pets bypass skill and boss gates.");
			sync = new ConfigSync("vercadi.ValBallCompatibility")
			{
				DisplayName = "ValBall Compatibility",
				CurrentVersion = "0.1.0",
				MinimumRequiredVersion = "0.1.0",
				ModRequired = true
			};
			((ConditionalConfigSync)sync).AddLockingConfigEntry<bool>(((BaseUnityPlugin)this).Config.Bind<bool>("General", "Lock server settings", true, "Enforce this helper and ValBall gameplay settings from the server. Map/UI preferences remain local."));
			((ConditionalConfigSync)sync).AddConfigEntry<string>(progression, (ConfigSyncMode)0);
			progression.SettingChanged += delegate
			{
				ReadRules();
			};
			ReadRules();
			try
			{
				Type type = ((object)Chainloader.PluginInfos["gokbe.valball"].Instance).GetType().Assembly.GetType("ValBall.ValBallProjectile", throwOnError: true);
				Patch(type, "OnHit", "OnHitGuard");
				native = new Native();
				foreach (KeyValuePair<ConfigDefinition, ConfigEntryBase> item in native.Mod.Config)
				{
					if (!(item.Key.Section == "Map") && !(item.Key.Section == "Debug") && !(item.Key.Key == "ShowChanceLabel"))
					{
						typeof(ConfigSync).GetMethods().Single((MethodInfo m) => m.Name == "AddConfigEntry" && m.IsGenericMethodDefinition && m.GetParameters().Length == 2 && m.GetParameters()[1].ParameterType == typeof(ConfigSyncMode)).MakeGenericMethod(item.Value.SettingType)
							.Invoke(sync, new object[2]
							{
								item.Value,
								(object)(ConfigSyncMode)0
							});
					}
				}
				Patch(native.Projectile, "Capture", "Capture");
				Patch(native.Projectile, "Release", "Release");
				Patch(native.Capture, "GetLabel", "Label");
				Patch(typeof(Tameable), "TamingUpdate", "Taming");
				Patch(typeof(Character), "Awake", null, "Spawned");
				Tuple<Type, string>[] array = new Tuple<Type, string>[2]
				{
					Tuple.Create(typeof(Procreation), "Procreate"),
					Tuple.Create(typeof(Growup), "GrowUpdate")
				};
				foreach (Tuple<Type, string> tuple in array)
				{
					harmony.Patch((MethodBase)AccessTools.Method(tuple.Item1, tuple.Item2, (Type[])null, (Type[])null), new HarmonyMethod(typeof(Plugin), "BreedingStart", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(Plugin), "BreedingEnd", (Type[])null), (HarmonyMethod)null);
				}
				harmony.Patch((MethodBase)AccessTools.Method(typeof(ItemData), "GetWeight", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(Cargo), "Weight", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				harmony.Patch((MethodBase)AccessTools.Method(typeof(Inventory), "IsTeleportable", new Type[1] { typeof(bool) }, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(Cargo), "Teleportable", (Type[])null)
				{
					priority = 0
				}, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				ready = true;
				((BaseUnityPlugin)this).Logger.LogInfo((object)"ACTIVE: reviewed ValBall 1.6.0 capture rules, animal state, horse cargo and aquatic release guards. Multiplayer gameplay validation pending.");
			}
			catch (Exception ex)
			{
				ready = false;
				((BaseUnityPlugin)this).Logger.LogError((object)("Capture helper initialization failed. Do not throw ValBalls until this is resolved. " + ex));
			}
		}

		private void Patch(Type type, string method, string prefix = null, string postfix = null)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			harmony.Patch((MethodBase)(AccessTools.Method(type, method, (Type[])null, (Type[])null) ?? throw new MissingMethodException(type.FullName, method)), (prefix == null) ? ((HarmonyMethod)null) : new HarmonyMethod(typeof(Plugin), prefix, (Type[])null), (postfix == null) ? ((HarmonyMethod)null) : new HarmonyMethod(typeof(Plugin), postfix, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}

		private void ReadRules()
		{
			try
			{
				species = Rules.Parse(progression.Value);
			}
			catch (Exception ex)
			{
				species.Clear();
				((BaseUnityPlugin)this).Logger.LogError((object)("Capture rules rejected; new captures disabled. " + ex.Message));
			}
		}

		private Species SpeciesFor(Character target)
		{
			string text = Rules.Name(((Object)((Component)target).gameObject).name);
			if (species.TryGetValue(text, out var value))
			{
				return value;
			}
			Growup component = ((Component)target).GetComponent<Growup>();
			if (Object.op_Implicit((Object)(object)component))
			{
				object? value2 = AccessTools.Field(typeof(Growup), "m_grownPrefab").GetValue(component);
				GameObject val = (GameObject)((value2 is GameObject) ? value2 : null);
				if (Object.op_Implicit((Object)(object)val) && species.TryGetValue(Rules.Name(((Object)val).name), out var value3) && !value3.Hostile && value3.WaterDepth == 0f)
				{
					return new Species(text, value3.Level, value3.Boss, hostile: false, value3.Xp, 0f, 0.6f, 0f, young: true);
				}
			}
			return null;
		}

		private Decision Evaluate(Character target, Player player, float multiplier)
		{
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			if (!ready || faulted || !Synced)
			{
				return new Decision
				{
					Refusal = "Capture is waiting for matching server settings or requires log review."
				};
			}
			if (!Object.op_Implicit((Object)(object)target) || target.IsPlayer() || target.IsDead() || target.IsBoss())
			{
				return new Decision
				{
					Refusal = "This target cannot be captured."
				};
			}
			Species species = SpeciesFor(target);
			if (species == null)
			{
				return new Decision
				{
					Refusal = "This creature is not supported for capture."
				};
			}
			ZNetView component = ((Component)target).GetComponent<ZNetView>();
			if (!Object.op_Implicit((Object)(object)component) || !component.IsValid())
			{
				return new Decision
				{
					Refusal = "Creature network state is unavailable."
				};
			}
			string text = ExtraState.Guard(target);
			if (text != null)
			{
				return new Decision
				{
					Refusal = text
				};
			}
			ZDO zDO = component.GetZDO();
			return Rules.Evaluate(species, target.IsTamed(), zDO.GetBool("valball_bonded", false) || zDO.GetBool("vercadi.valball.seen", false), zDO.GetBool("vercadi.valball.bred", false), Object.op_Implicit((Object)(object)player) ? ((Character)player).GetSkills().GetSkillLevel(native.Skill) : 0f, species.Boss.Length == 0 || (Object.op_Implicit((Object)(object)ZoneSystem.instance) && ZoneSystem.instance.GetGlobalKey(species.Boss)), target.GetHealthPercentage(), target.GetLevel() - 1, multiplier, native.Config<float>("Val Master", "XpMultiplier"), native.Config<int>("Val Master", "TameableXpFactor"));
		}

		private static bool Label(Character __0, Player __1, float __2, ref string __result)
		{
			try
			{
				Decision decision = instance.Evaluate(__0, __1, __2);
				__result = (decision.Allowed ? ("Capture: " + Mathf.RoundToInt(decision.Chance * 100f) + "%") : decision.Refusal);
			}
			catch
			{
				__result = "Capture unavailable; check the compatibility log.";
			}
			return false;
		}

		private static bool OnHitGuard(object __instance, Collider __0, Vector3 __1, bool __2)
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Expected O, but got Unknown
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Expected O, but got Unknown
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			if (instance.ready && !instance.faulted && instance.Synced)
			{
				return true;
			}
			if (Native.Read<bool>(__instance, "m_resolved"))
			{
				return false;
			}
			Component val = (Component)__instance;
			ZNetView component = val.GetComponent<ZNetView>();
			if (!Object.op_Implicit((Object)(object)component) || !component.IsValid() || !component.IsOwner())
			{
				return false;
			}
			AccessTools.Field(__instance.GetType(), "m_resolved").SetValue(__instance, true);
			Projectile component2 = val.GetComponent<Projectile>();
			ItemData val2 = (ItemData)AccessTools.Field(typeof(Projectile), "m_weapon").GetValue(component2);
			object? value = AccessTools.Field(typeof(Projectile), "m_owner").GetValue(component2);
			Player player = (Player)((value is Player) ? value : null);
			try
			{
				Deliver(val2.Clone(), __1, player);
				Tell(player, "ValBall transport is unavailable. Check server sync and the compatibility log.");
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)instance).Logger.LogError((object)("Could not refund blocked throw: " + ex));
			}
			return false;
		}

		private static void BreedingStart()
		{
			breeding++;
		}

		private static Exception BreedingEnd(Exception __exception)
		{
			breeding = Math.Max(0, breeding - 1);
			return __exception;
		}

		private static void Spawned(Character __instance)
		{
			if (breeding > 0)
			{
				ZNetView component = ((Component)__instance).GetComponent<ZNetView>();
				if (Object.op_Implicit((Object)(object)component) && component.IsValid() && component.IsOwner())
				{
					component.GetZDO().Set("vercadi.valball.bred", true);
				}
			}
		}

		private static bool Taming(Tameable __instance)
		{
			if (!Object.op_Implicit((Object)(object)instance) || !instance.ready)
			{
				return true;
			}
			string key = Rules.Name(((Object)((Component)__instance).gameObject).name);
			if (!Rules.Catalog.TryGetValue(key, out var value) || value.WaterDepth <= 0f)
			{
				return true;
			}
			if (instance.species.TryGetValue(key, out var value2))
			{
				value = value2;
			}
			if (!instance.Synced)
			{
				return false;
			}
			ZNetView component = ((Component)__instance).GetComponent<ZNetView>();
			Character component2 = ((Component)__instance).GetComponent<Character>();
			if (!Object.op_Implicit((Object)(object)component) || !component.IsValid() || !component.IsOwner() || !Object.op_Implicit((Object)(object)component2) || component2.IsTamed())
			{
				return true;
			}
			ZDO zDO = component.GetZDO();
			float num = zDO.GetFloat("vercadi.valball.oceanDuration", 0f);
			if (num != value.TamingSeconds)
			{
				float num2 = zDO.GetFloat(ZDOVars.s_tameTimeLeft, __instance.m_tamingTime);
				float num3 = ((num > 0f) ? num : Math.Max(1f, __instance.m_tamingTime));
				zDO.Set(ZDOVars.s_tameTimeLeft, value.TamingSeconds * Mathf.Clamp01(num2 / num3));
				zDO.Set("vercadi.valball.oceanDuration", value.TamingSeconds);
			}
			__instance.m_tamingTime = value.TamingSeconds;
			if (value.Boss.Length != 0)
			{
				if (Object.op_Implicit((Object)(object)ZoneSystem.instance))
				{
					return ZoneSystem.instance.GetGlobalKey(value.Boss);
				}
				return false;
			}
			return true;
		}

		private static void Tell(Player player, string text)
		{
			try
			{
				if (Object.op_Implicit((Object)(object)player))
				{
					((Character)player).Message((MessageType)2, text, 0, (Sprite)null, false);
				}
			}
			catch
			{
			}
		}

		private void OnDestroy()
		{
			ready = false;
			Harmony obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
			if ((Object)(object)instance == (Object)(object)this)
			{
				instance = null;
			}
		}

		private static bool Capture(object __instance, Collider __0, Vector3 __1, Player __2)
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0336: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			Plugin plugin = instance;
			Journal journal = null;
			bool flag = false;
			bool flag2 = false;
			ItemData val = null;
			try
			{
				val = plugin.native.Empty(__instance);
				Character val2 = (Object.op_Implicit((Object)(object)__0) ? ((Component)__0).GetComponentInParent<Character>() : null);
				Decision decision = plugin.Evaluate(val2, __2, plugin.native.Multiplier(__instance));
				if (!decision.Allowed)
				{
					flag2 = true;
					Deliver(val, __1, __2);
					Tell(__2, decision.Refusal);
					return false;
				}
				ZNetView component = ((Component)val2).GetComponent<ZNetView>();
				component.ClaimOwnership();
				if (!component.IsOwner())
				{
					flag2 = true;
					Deliver(val, __1, __2);
					Tell(__2, "Creature ownership is busy. Try again when it has settled.");
					return false;
				}
				string text = ExtraState.Guard(val2);
				if (text != null)
				{
					flag2 = true;
					Deliver(val, __1, __2);
					Tell(__2, text);
					return false;
				}
				if (Random.value > decision.Chance)
				{
					if (!plugin.native.Config<bool>("Capture", "BreakOnFail"))
					{
						flag2 = true;
						Deliver(val, __1, __2);
					}
					Tell(__2, "The creature broke free.");
					return false;
				}
				object snapshot = plugin.native.Snapshot(val2);
				ItemData val3 = plugin.native.Full(__instance);
				val3.m_stack = 1;
				plugin.native.Write(snapshot, val3);
				ExtraState.Save(val2, val3);
				val3.m_customData["vercadi.valball.transaction"] = Guid.NewGuid().ToString("N");
				if (!Object.op_Implicit((Object)(object)ZNetScene.instance.GetPrefab(val3.m_customData["valball.prefab"])))
				{
					throw new InvalidOperationException("Creature prefab cannot be released.");
				}
				journal = new Journal("capture", val3, ((object)Unsafe.As<ZDOID, ZDOID>(ref component.GetZDO().m_uid)/*cast due to .constrained prefix*/).ToString());
				journal.Phase("before-destroy");
				flag = true;
				ZNetScene.instance.Destroy(((Component)val2).gameObject);
				journal.Phase("creature-destroyed");
				Deliver(val3, __1, __2);
				journal.Phase("filled-ball-delivered");
				journal.Complete();
				journal = null;
				try
				{
					plugin.native.Xp(__2, decision.Xp);
				}
				catch (Exception ex)
				{
					((BaseUnityPlugin)plugin).Logger.LogWarning((object)("Captured successfully; XP callback failed: " + ex.Message));
				}
				((BaseUnityPlugin)plugin).Logger.LogInfo((object)("CAPTURE COMMITTED: " + val3.m_customData["valball.prefab"] + "; cargo/state saved; xp=" + decision.Xp));
				Tell(__2, "Captured " + Localization.instance.Localize(Object.op_Implicit((Object)(object)val2) ? val2.m_name : val3.m_customData["valball.display"]) + ".");
			}
			catch (Exception ex2)
			{
				if (flag || flag2)
				{
					plugin.faulted = true;
					((BaseUnityPlugin)plugin).Logger.LogError((object)("Capture stopped after an uncertain world/inventory operation. Do not retry or restore automatically. Recovery record: " + journal?.PathName + "\n" + ex2));
					Tell(__2, "Capture stopped. Keep the session unchanged and review the recovery log.");
				}
				else
				{
					((BaseUnityPlugin)plugin).Logger.LogError((object)("Capture refused before creature removal: " + ex2));
					try
					{
						if (val != null)
						{
							flag2 = true;
							Deliver(val, __1, __2);
						}
						journal?.Complete();
					}
					catch (Exception ex3)
					{
						plugin.faulted = true;
						((BaseUnityPlugin)plugin).Logger.LogError((object)("Refund uncertain; no retry: " + ex3));
					}
					Tell(__2, "Capture refused; animal was not removed. Check the log.");
				}
			}
			return false;
		}

		private unsafe static bool Release(object __instance, object __0, ItemData __1, Vector3 __2, Player __3)
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0506: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0415: Unknown result type (might be due to invalid IL or missing references)
			Plugin plugin = instance;
			GameObject val = null;
			Journal journal = null;
			bool flag = false;
			bool flag2 = false;
			try
			{
				string text = Native.Read<string>(__0, "Prefab");
				GameObject prefab = ZNetScene.instance.GetPrefab(text);
				if (!Object.op_Implicit((Object)(object)prefab) || !Object.op_Implicit((Object)(object)prefab.GetComponent<Character>()))
				{
					flag2 = true;
					Deliver(Single(__1), __2, __3);
					Tell(__3, "Creature mod is missing. Filled ball returned.");
					return false;
				}
				Rules.Catalog.TryGetValue(text, out var value);
				Vector3 position = __2 + Vector3.up * 0.2f;
				if (value != null && value.WaterDepth > 0f && !WaterPosition(__2, value, out position, out var why))
				{
					flag2 = true;
					Deliver(Single(__1), __2, __3);
					Tell(__3, why);
					return false;
				}
				if (__1.m_customData.TryGetValue("vercadi.valball.cargo", out var value2) && value2.Length > 0)
				{
					Cargo.Load(value2);
				}
				if (__1.m_customData.ContainsKey("vercadi.valball.coat") && ExtraState.HorseCache == null)
				{
					throw new InvalidOperationException("OdinHorse state adapter missing.");
				}
				journal = new Journal("release", Single(__1), "not-spawned");
				Vector3 val2 = (Object.op_Implicit((Object)(object)__3) ? ((Component)__3).transform.forward : Vector3.forward);
				val2.y = 0f;
				val = Object.Instantiate<GameObject>(prefab, position, (((Vector3)(ref val2)).sqrMagnitude > 0.01f) ? Quaternion.LookRotation(val2) : Quaternion.identity);
				Character component = val.GetComponent<Character>();
				ZNetView component2 = val.GetComponent<ZNetView>();
				if (!Object.op_Implicit((Object)(object)component) || !Object.op_Implicit((Object)(object)component2) || !component2.IsValid() || !component2.IsOwner())
				{
					throw new InvalidOperationException("Released creature has no owned network state.");
				}
				ZDO zDO = component2.GetZDO();
				Journal journal2 = journal;
				ZDOID uid = zDO.m_uid;
				journal2.Phase("spawned-" + ((object)(*(ZDOID*)(&uid))/*cast due to .constrained prefix*/).ToString());
				component.SetLevel(Native.Read<int>(__0, "Level"));
				zDO.Set("valball_bonded", true);
				zDO.Set("vercadi.valball.seen", true);
				if (Object.op_Implicit((Object)(object)__3))
				{
					zDO.Set("valball_owner", __3.GetPlayerID());
				}
				bool flag3 = Native.Read<bool>(__0, "Tamed");
				if (flag3)
				{
					MonsterAI component3 = val.GetComponent<MonsterAI>();
					if (Object.op_Implicit((Object)(object)component3))
					{
						component3.MakeTame();
					}
					else
					{
						component.SetTamed(true);
					}
				}
				else
				{
					component.SetTamed(false);
				}
				plugin.native.Timers(__0, zDO);
				ExtraState.Restore(component, __1);
				float num = Native.Read<float>(__0, "HealthPct");
				component.SetHealth(Mathf.Max(1f, component.GetMaxHealth() * Mathf.Clamp(num, 0.01f, 1f)));
				zDO.Set(ZDOVars.s_tamedName, Native.Read<string>(__0, "TamedName") ?? "");
				zDO.Set(ZDOVars.s_tamedNameAuthor, Native.Read<string>(__0, "TamedNameAuthor") ?? "");
				Type type = plugin.native.Plugin.Assembly.GetType("ValBall.Growth", throwOnError: true);
				Type type2 = plugin.native.Plugin.Assembly.GetType("ValBall.Breeding", throwOnError: true);
				zDO.Set((int)AccessTools.Field(type, "GrowthHash").GetValue(null), Native.Read<float>(__0, "GrowthPoints"));
				zDO.Set((int)AccessTools.Field(type, "KillsHash").GetValue(null), Native.Read<int>(__0, "Kills"), false);
				zDO.Set((int)AccessTools.Field(type2, "BirthsHash").GetValue(null), Native.Read<int>(__0, "Births"), false);
				Tameable component4 = val.GetComponent<Tameable>();
				if (flag3 && Native.Read<bool>(__0, "Saddle") && Object.op_Implicit((Object)(object)component4) && Object.op_Implicit((Object)(object)component4.m_saddle))
				{
					component2.InvokeRPC("AddSaddle", Array.Empty<object>());
				}
				journal.Phase("creature-state-restored");
				flag = true;
				Deliver(plugin.native.Empty(__instance), __2, __3);
				journal.Phase("empty-ball-delivered");
				journal.Complete();
				journal = null;
				((BaseUnityPlugin)plugin).Logger.LogInfo((object)("RELEASE COMMITTED: " + text + "; tame=" + flag3 + "; one creature restored."));
				Tell(__3, "Released " + Localization.instance.Localize(component.m_name) + ".");
			}
			catch (Exception ex)
			{
				if (!flag && !flag2)
				{
					try
					{
						if (Object.op_Implicit((Object)(object)val))
						{
							ZNetView component5 = val.GetComponent<ZNetView>();
							if (!Object.op_Implicit((Object)(object)component5) || !component5.IsValid() || !component5.IsOwner())
							{
								throw new InvalidOperationException("Cannot confirm rollback ownership.");
							}
							ZNetScene.instance.Destroy(val);
							if (component5.IsValid())
							{
								throw new InvalidOperationException("Rollback did not remove creature network state.");
							}
						}
						flag2 = true;
						Deliver(Single(__1), __2, __3);
						journal?.Complete();
						((BaseUnityPlugin)plugin).Logger.LogError((object)("Release rolled back; filled ball returned. " + ex));
						Tell(__3, "Release failed; filled ball returned. Check the log before retrying.");
						return false;
					}
					catch (Exception ex2)
					{
						((BaseUnityPlugin)plugin).Logger.LogError((object)("Release rollback uncertain: " + ex2));
					}
				}
				plugin.faulted = true;
				((BaseUnityPlugin)plugin).Logger.LogError((object)("Release stopped after an uncertain operation; no automatic replay/refund. Recovery record: " + journal?.PathName + "\n" + ex));
				Tell(__3, "Release stopped. Review the recovery log before continuing.");
			}
			return false;
		}

		private static ItemData Single(ItemData item)
		{
			ItemData obj = item.Clone();
			obj.m_stack = 1;
			return obj;
		}

		private static void Deliver(ItemData ball, Vector3 hitPoint, Player player)
		{
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: 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)
			if (ball == null)
			{
				throw new InvalidOperationException("No return item.");
			}
			ball.m_stack = 1;
			if (Object.op_Implicit((Object)(object)player) && !((Character)player).IsDead() && ((Character)player).IsOwner() && (instance.native == null || instance.native.Config<bool>("General", "ReturnToInventory")))
			{
				Inventory inventory = ((Humanoid)player).GetInventory();
				if (inventory.CanAddItem(ball, 1) && inventory.AddItem(ball))
				{
					return;
				}
			}
			ItemDrop val = ItemDrop.DropItem(ball, 1, hitPoint + Vector3.up * 0.3f, Quaternion.identity);
			if (!Object.op_Implicit((Object)(object)val) || val.m_itemData == null)
			{
				throw new InvalidOperationException("Item delivery did not produce an item drop.");
			}
		}

		private static bool WaterPosition(Vector3 hit, Species s, out Vector3 position, out string why)
		{
			//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_000e: 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_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			position = hit;
			why = "Release this animal in deeper, unobstructed water.";
			float liquidLevel = Floating.GetLiquidLevel(hit, 1f, (LiquidType)0);
			if (float.IsNaN(liquidLevel) || float.IsInfinity(liquidLevel))
			{
				return false;
			}
			int mask = LayerMask.GetMask(new string[6] { "terrain", "Default", "static_solid", "piece", "Default_small", "vehicle" });
			Vector3[] array = (Vector3[])(object)new Vector3[5]
			{
				Vector3.zero,
				Vector3.right * s.Radius,
				Vector3.left * s.Radius,
				Vector3.forward * s.Radius,
				Vector3.back * s.Radius
			};
			RaycastHit val2 = default(RaycastHit);
			foreach (Vector3 val in array)
			{
				if (!Physics.Raycast(new Vector3(hit.x + val.x, liquidLevel + 1f, hit.z + val.z), Vector3.down, ref val2, 1000f, mask, (QueryTriggerInteraction)1) || liquidLevel - ((RaycastHit)(ref val2)).point.y < s.WaterDepth)
				{
					return false;
				}
			}
			position.y = liquidLevel - Math.Min(s.WaterDepth * 0.5f, s.Radius);
			if (Physics.OverlapSphere(position, s.Radius, mask, (QueryTriggerInteraction)1).Any((Collider c) => Object.op_Implicit((Object)(object)c) && !c.isTrigger))
			{
				return false;
			}
			return true;
		}
	}
	internal sealed class Species
	{
		internal string Name;

		internal string Boss;

		internal int Level;

		internal int Xp;

		internal bool Hostile;

		internal bool Young;

		internal float WaterDepth;

		internal float Radius;

		internal float TamingSeconds;

		internal Species(string name, int level, string boss, bool hostile, int xp = 20, float waterDepth = 0f, float radius = 0.6f, float taming = 0f, bool young = false)
		{
			Name = name;
			Level = level;
			Boss = boss;
			Hostile = hostile;
			Xp = xp;
			WaterDepth = waterDepth;
			Radius = radius;
			TamingSeconds = taming;
			Young = young;
		}
	}
	internal sealed class Decision
	{
		internal string Refusal;

		internal float Chance;

		internal float Xp;

		internal bool Allowed => Refusal == null;
	}
	internal static class Rules
	{
		internal const string Prefix = "vercadi.valball.";

		internal const int MaxInventoryBytes = 1048576;

		internal static readonly Dictionary<string, Species> Catalog = Build();

		internal static string DefaultProgression => string.Join(";", Catalog.Values.Select((Species s) => s.Name + ":" + s.Level + ":" + s.Boss));

		private static Dictionary<string, Species> Build()
		{
			Dictionary<string, Species> d = new Dictionary<string, Species>(StringComparer.Ordinal);
			string[] array = new string[5] { "Boar", "Deer", "Sheep_TW", "rae_OdinHorse", "Hen" };
			for (int i = 0; i < array.Length; i++)
			{
				Add(new Species(array[i], 0, "", hostile: false));
			}
			array = new string[3] { "Piggy", "rae_Offspring_Normal", "Chicken" };
			for (int i = 0; i < array.Length; i++)
			{
				Add(new Species(array[i], 0, "", hostile: false, 20, 0f, 0.6f, 0f, young: true));
			}
			array = new string[5] { "Brown", "DarkGrey", "Exotic", "Native", "White" };
			foreach (string text in array)
			{
				Add(new Species("BOH_Hare_" + text, 0, "", hostile: false));
				Add(new Species("BOH_Hare_" + text + "Kitten", 0, "", hostile: false, 20, 0f, 0.6f, 0f, young: true));
			}
			Add(new Species("Hare", 0, "defeated_goblinking", hostile: false, 96));
			Add(new Species("BOH_Hare_Kitten", 0, "defeated_goblinking", hostile: false, 96, 0f, 0.6f, 0f, young: true));
			Add(new Species("Greyling", 10, "", hostile: true));
			Add(new Species("Neck", 10, "", hostile: true));
			Add(new Species("Greydwarf", 25, "defeated_eikthyr", hostile: true, 36));
			Add(new Species("Skeleton", 25, "defeated_eikthyr", hostile: true, 36));
			Add(new Species("Greydwarf_Elite", 35, "defeated_gdking", hostile: true, 36));
			Add(new Species("Greydwarf_Shaman", 35, "defeated_gdking", hostile: true, 36));
			Add(new Species("Bjorn", 40, "defeated_gdking", hostile: true, 50));
			Add(new Species("Wolf", 40, "defeated_bonemass", hostile: true, 64));
			Add(new Species("Draugr", 45, "defeated_gdking", hostile: true, 50));
			Add(new Species("Lox", 50, "defeated_dragon", hostile: true, 80, 0f, 2f));
			Add(new Species("Troll", 55, "defeated_gdking", hostile: true, 50, 0f, 1.8f));
			Add(new Species("Fenring", 60, "defeated_bonemass", hostile: true, 64));
			Add(new Species("Fenring_Cultist", 60, "defeated_bonemass", hostile: true, 64));
			Add(new Species("StoneGolem", 65, "defeated_dragon", hostile: true, 80, 0f, 1.5f));
			Add(new Species("Unbjorn", 70, "defeated_goblinking", hostile: true, 96));
			Add(new Species("Animal_Dolphin_RtD", 25, "defeated_gdking", hostile: false, 36, 2f, 1.2f, 300f));
			Add(new Species("Monster_Orca_RtD", 45, "defeated_bonemass", hostile: false, 64, 5f, 3f, 900f));
			Add(new Species("Mirmaid_RtD", 65, "defeated_goblinking", hostile: false, 96, 2f, 1f, 1200f));
			return d;
			void Add(Species s)
			{
				d.Add(s.Name, s);
			}
		}

		internal static Dictionary<string, Species> Parse(string text)
		{
			Dictionary<string, Species> dictionary = new Dictionary<string, Species>(StringComparer.Ordinal);
			string[] array = (text ?? "").Split(new char[1] { ';' });
			foreach (string text2 in array)
			{
				if (!string.IsNullOrWhiteSpace(text2))
				{
					string[] array2 = text2.Trim().Split(new char[1] { ':' });
					if (array2.Length != 3 || !Catalog.TryGetValue(array2[0], out var value) || !int.TryParse(array2[1], out var result) || result < 0 || result > 100 || array2[2].Any((char c) => !char.IsLetterOrDigit(c) && c != '_') || dictionary.ContainsKey(array2[0]))
					{
						throw new FormatException("Invalid or unreviewed capture species rule: " + text2);
					}
					dictionary.Add(value.Name, new Species(value.Name, result, array2[2], value.Hostile, value.Xp, value.WaterDepth, value.Radius, value.TamingSeconds, value.Young));
				}
			}
			return dictionary;
		}

		internal static Decision Evaluate(Species s, bool tamed, bool seenBefore, bool bred, float skill, bool bossUnlocked, float health, int stars, float ball, float xpMultiplier, float tameXpPercent)
		{
			if (s == null)
			{
				return new Decision
				{
					Refusal = "This creature is not supported for capture."
				};
			}
			if (tamed)
			{
				return new Decision
				{
					Chance = 1f,
					Xp = 0f
				};
			}
			if (!bossUnlocked)
			{
				return new Decision
				{
					Refusal = "World boss requirement: " + s.Boss
				};
			}
			if (skill < (float)s.Level)
			{
				return new Decision
				{
					Refusal = "Requires Val Master " + s.Level + "."
				};
			}
			if (s.Hostile && health > 0.50001f)
			{
				return new Decision
				{
					Refusal = "Weaken this wild creature to 50% health first."
				};
			}
			double num = (s.Hostile ? Math.Min(0.9, 0.6 * Math.Pow(0.75, Math.Max(0, stars)) * (1.0 + (double)Math.Max(0f, skill - (float)s.Level) * 0.01) * (double)Math.Max(0f, ball)) : 1.0);
			return new Decision
			{
				Chance = (float)num,
				Xp = ((seenBefore || bred || s.Young) ? 0f : ((float)(s.Xp * (1 + Math.Max(0, stars))) * Math.Max(0f, xpMultiplier) * (s.Hostile ? 1f : (Math.Max(0f, tameXpPercent) / 100f))))
			};
		}

		internal static string Name(string name)
		{
			string text;
			if (name == null || !name.EndsWith("(Clone)", StringComparison.Ordinal))
			{
				text = name;
				if (text == null)
				{
					return "";
				}
			}
			else
			{
				text = name.Substring(0, name.Length - 7);
			}
			return text;
		}

		internal static float Number(IDictionary<string, string> data, string key, float fallback = 0f)
		{
			if (!data.TryGetValue(key, out var value) || !float.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out var result) || float.IsNaN(result) || float.IsInfinity(result))
			{
				return fallback;
			}
			return result;
		}
	}
}