Decompiled source of Magic Supremacy v2.1.9

plugins/Magic_Supremacy.dll

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

[assembly: AssemblyFileVersion("2.1.9")]
[assembly: Guid("4358610B-F3F4-4843-B7AF-98B7BC60DCDE")]
[assembly: ComVisible(false)]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCopyright("Copyright ©  2021")]
[assembly: AssemblyProduct("Magic_Supremacy")]
[assembly: AssemblyCompany("Dreanegade")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyTitle("Magic_Supremacy")]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: CompilationRelaxations(8)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("2.1.9.0")]
[module: UnverifiableCode]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[<58040e1a-0c6a-4780-8472-5838ad4d2d68>Embedded]
	internal sealed class <58040e1a-0c6a-4780-8472-5838ad4d2d68>EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	[<58040e1a-0c6a-4780-8472-5838ad4d2d68>Embedded]
	internal sealed class <839beae5-12ea-4eaa-8a82-47e46d9c3654>NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public <839beae5-12ea-4eaa-8a82-47e46d9c3654>NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public <839beae5-12ea-4eaa-8a82-47e46d9c3654>NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	[<58040e1a-0c6a-4780-8472-5838ad4d2d68>Embedded]
	internal sealed class <44d44cce-7ad9-4445-90b1-2eb839d16508>NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public <44d44cce-7ad9-4445-90b1-2eb839d16508>NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
}
[<44d44cce-7ad9-4445-90b1-2eb839d16508>NullableContext(1)]
[<839beae5-12ea-4eaa-8a82-47e46d9c3654>Nullable(0)]
internal sealed class ConfigurationManagerAttributes
{
	[<44d44cce-7ad9-4445-90b1-2eb839d16508>NullableContext(0)]
	public delegate void CustomHotkeyDrawerFunc(ConfigEntryBase setting, ref bool isCurrentlyAcceptingInput);

	public bool? ShowRangeAsPercent;

	public Action<ConfigEntryBase> CustomDrawer;

	public CustomHotkeyDrawerFunc CustomHotkeyDrawer;

	public bool? Browsable;

	public string Category;

	public object DefaultValue;

	public bool? HideDefaultButton;

	public bool? HideSettingName;

	public string Description;

	public string DispName;

	public int? Order;

	public bool? ReadOnly;

	public bool? IsAdvanced;

	public Func<object, string> ObjToStr;

	public Func<string, object> StrToObj;
}
[<44d44cce-7ad9-4445-90b1-2eb839d16508>NullableContext(1)]
[<839beae5-12ea-4eaa-8a82-47e46d9c3654>Nullable(0)]
public static class ExtraStats
{
	[<44d44cce-7ad9-4445-90b1-2eb839d16508>NullableContext(0)]
	private static class DevLog
	{
		public const bool Enabled = false;

		public const bool AttackSpeed = false;

		public const bool WetImmune = false;

		public const bool Tooltips = false;

		public const bool FoodStats = false;
	}

	[<44d44cce-7ad9-4445-90b1-2eb839d16508>NullableContext(0)]
	public enum ExtraStatType
	{
		Health,
		Stamina,
		Eitr,
		AttackSpeed,
		WetImmune
	}

	[<44d44cce-7ad9-4445-90b1-2eb839d16508>NullableContext(0)]
	public enum ExtraSourceType
	{
		ItemDrop,
		StatusEffect
	}

	[<839beae5-12ea-4eaa-8a82-47e46d9c3654>Nullable(0)]
	public class ExtraStatEntry
	{
		public string PrefabName;

		public ExtraStatType StatType;

		public float Value;

		public float? DisplayValue;

		public ExtraSourceType SourceType;

		public ExtraStatEntry(string prefab, ExtraStatType stat, float value, ExtraSourceType source)
		{
			PrefabName = prefab;
			StatType = stat;
			Value = value;
			DisplayValue = null;
			SourceType = source;
		}

		public ExtraStatEntry(string prefab, ExtraStatType stat, float value, float? displayValue, ExtraSourceType source)
		{
			PrefabName = prefab;
			StatType = stat;
			Value = value;
			DisplayValue = displayValue;
			SourceType = source;
		}
	}

	[HarmonyPatch(typeof(Player), "GetTotalFoodValue")]
	[<44d44cce-7ad9-4445-90b1-2eb839d16508>NullableContext(0)]
	public static class Player_GetTotalFoodValue_ExtraStatsPatch
	{
		[<44d44cce-7ad9-4445-90b1-2eb839d16508>NullableContext(1)]
		private static void Postfix(Player __instance, ref float hp, ref float stamina, ref float eitr)
		{
			if ((Object)(object)__instance == (Object)null)
			{
				return;
			}
			float num = 0f;
			float num2 = 0f;
			float num3 = 0f;
			try
			{
				Inventory inventory = ((Humanoid)__instance).GetInventory();
				if (inventory != null)
				{
					foreach (ItemData equippedItem in inventory.GetEquippedItems())
					{
						if (equippedItem != null && !((Object)(object)equippedItem.m_dropPrefab == (Object)null))
						{
							string name = ((Object)equippedItem.m_dropPrefab).name;
							GetItemDropBonusesForPrefab(name, out var extraHp, out var extraStamina, out var extraEitr, out var _, out var _);
							if (extraHp != 0f || extraStamina != 0f || extraEitr != 0f)
							{
								num += extraHp;
								num2 += extraStamina;
								num3 += extraEitr;
								DLogFood($"ItemDrop matched for food stats: {name} → +HP {extraHp}, +Stamina {extraStamina}, +Eitr {extraEitr}");
							}
						}
					}
				}
				if (((Character)__instance).m_seman != null && ((Character)__instance).m_seman.m_statusEffects != null)
				{
					foreach (StatusEffect statusEffect in ((Character)__instance).m_seman.m_statusEffects)
					{
						if (!((Object)(object)statusEffect == (Object)null))
						{
							string name2 = ((Object)statusEffect).name;
							GetStatusEffectBonuses(name2, out var extraHp2, out var extraStamina2, out var extraEitr2, out var _, out var _);
							if (extraHp2 != 0f || extraStamina2 != 0f || extraEitr2 != 0f)
							{
								num += extraHp2;
								num2 += extraStamina2;
								num3 += extraEitr2;
								string prefabName = Utils.GetPrefabName(name2);
								DLogFood($"StatusEffect matched for food stats: {name2} (clean={prefabName}) → +HP {extraHp2}, +Stamina {extraStamina2}, +Eitr {extraEitr2}");
							}
						}
					}
				}
			}
			catch (Exception ex)
			{
				LogError("Exception in ExtraStats Player.GetTotalFoodValue Postfix: " + ex);
			}
			if (num != 0f || num2 != 0f || num3 != 0f)
			{
				DLogFood($"Total food bonuses applied to player: +HP {num}, +Stamina {num2}, +Eitr {num3}");
				hp += num;
				stamina += num2;
				eitr += num3;
			}
		}
	}

	[<839beae5-12ea-4eaa-8a82-47e46d9c3654>Nullable(0)]
	[HarmonyPatch]
	public static class ItemData_StaticGetTooltip_ExtraStatsPatch
	{
		private static MethodBase TargetMethod()
		{
			return AccessTools.Method(typeof(ItemData), "GetTooltip", new Type[5]
			{
				typeof(ItemData),
				typeof(int),
				typeof(bool),
				typeof(float),
				typeof(int)
			}, (Type[])null);
		}

		private static void Postfix(ItemData item, int qualityLevel, bool crafting, float worldLevel, int stackOverride, ref string __result)
		{
			try
			{
				if (item == null || (Object)(object)item.m_dropPrefab == (Object)null)
				{
					return;
				}
				string name = ((Object)item.m_dropPrefab).name;
				DLogTooltip($"Static GetTooltip Postfix called for {name}, q={qualityLevel}, crafting={crafting}, worldLevel={worldLevel}, stackOverride={stackOverride}");
				GetItemDropBonusesForPrefab(name, out var extraHp, out var extraStamina, out var extraEitr, out var _, out var displayAttackSpeedPercent, out var wetImmune);
				if (extraHp != 0f || extraStamina != 0f || extraEitr != 0f || displayAttackSpeedPercent != 0f || wetImmune)
				{
					string text = BuildExtraStatsTooltipBlock(extraHp, extraStamina, extraEitr, displayAttackSpeedPercent, wetImmune);
					if (!string.IsNullOrEmpty(text))
					{
						DLogTooltip($"Appending extras for {name}: HP {extraHp}, Stamina {extraStamina}, Eitr {extraEitr}, AttackSpeed(Display)% {displayAttackSpeedPercent}, WetImmune {wetImmune}");
						__result += text;
					}
				}
			}
			catch (Exception ex)
			{
				LogError("Exception in ItemData_StaticGetTooltip_ExtraStatsPatch: " + ex);
			}
		}
	}

	[<44d44cce-7ad9-4445-90b1-2eb839d16508>NullableContext(0)]
	[HarmonyPatch(typeof(SE_Stats), "GetTooltipString")]
	public static class SE_Stats_GetTooltipString_ExtraStatsPatch
	{
		[<44d44cce-7ad9-4445-90b1-2eb839d16508>NullableContext(1)]
		private static void Postfix(SE_Stats __instance, ref string __result)
		{
			try
			{
				if ((Object)(object)__instance == (Object)null)
				{
					return;
				}
				string name = ((Object)__instance).name;
				string prefabName = Utils.GetPrefabName(name);
				DLogTooltip("SE GetTooltipString for " + name + " (clean=" + prefabName + ")");
				GetStatusEffectBonuses(name, out var extraHp, out var extraStamina, out var extraEitr, out var _, out var displayAttackSpeedPercent, out var wetImmune);
				if (extraHp != 0f || extraStamina != 0f || extraEitr != 0f || displayAttackSpeedPercent != 0f || wetImmune)
				{
					string text = BuildExtraStatsTooltipBlock(extraHp, extraStamina, extraEitr, displayAttackSpeedPercent, wetImmune);
					if (!string.IsNullOrEmpty(text))
					{
						DLogTooltip($"Appending SE extras for {name} (clean={prefabName}): HP {extraHp}, Stamina {extraStamina}, Eitr {extraEitr}, AttackSpeed(Display)% {displayAttackSpeedPercent}, WetImmune {wetImmune}");
						__result += text;
					}
				}
			}
			catch (Exception ex)
			{
				LogError("Exception in SE_Stats_GetTooltipString_ExtraStatsPatch: " + ex);
			}
		}
	}

	[<44d44cce-7ad9-4445-90b1-2eb839d16508>NullableContext(0)]
	private sealed class HumanoidState
	{
		public float DesiredSpeed = 1f;

		public float LastAppliedSpeed = 1f;

		public bool HasDesiredSpeed;

		public bool WasInAttack;

		public int ActiveAttackDepth;

		public float ActiveAttackMul = 1f;
	}

	[<44d44cce-7ad9-4445-90b1-2eb839d16508>NullableContext(0)]
	[HarmonyPatch(typeof(Humanoid), "StartAttack", new Type[]
	{
		typeof(Character),
		typeof(bool)
	})]
	public static class Humanoid_StartAttack_AttackSpeedPatch
	{
		[HarmonyPostfix]
		[<44d44cce-7ad9-4445-90b1-2eb839d16508>NullableContext(1)]
		private static void Postfix(Humanoid __instance, Character target, bool secondaryAttack, ref bool __result)
		{
			EnsureAttackInit();
			if (!__result)
			{
				return;
			}
			HumanoidState attackState = GetAttackState(__instance);
			float num = ComputeTotalAttackSpeedPercentForHumanoid(__instance);
			if (num == 0f)
			{
				attackState.DesiredSpeed = 1f;
				attackState.HasDesiredSpeed = false;
				ApplyAnimSpeed(__instance, attackState, 1f);
				attackState.ActiveAttackDepth = 0;
				attackState.ActiveAttackMul = 1f;
				return;
			}
			float num2 = 1f + num / 100f;
			if (num2 <= 0f || float.IsNaN(num2) || float.IsInfinity(num2))
			{
				attackState.DesiredSpeed = 1f;
				attackState.HasDesiredSpeed = false;
				ApplyAnimSpeed(__instance, attackState, 1f);
				attackState.ActiveAttackDepth = 0;
				attackState.ActiveAttackMul = 1f;
			}
			else
			{
				attackState.DesiredSpeed = num2;
				attackState.HasDesiredSpeed = true;
				ApplyAnimSpeed(__instance, attackState, num2);
				attackState.ActiveAttackDepth++;
				attackState.ActiveAttackMul = num2;
				DLogAttackSpeed($"StartAttack: total AttackSpeed%={num} → mul={num2} (activeDepth={attackState.ActiveAttackDepth})");
			}
		}
	}

	[<44d44cce-7ad9-4445-90b1-2eb839d16508>NullableContext(0)]
	[HarmonyPatch(typeof(Attack), "Stop")]
	public static class Attack_Stop_AttackSpeedResetPatch
	{
		[<44d44cce-7ad9-4445-90b1-2eb839d16508>NullableContext(1)]
		[HarmonyPostfix]
		private static void Postfix(Attack __instance)
		{
			try
			{
				EnsureAttackInit();
				if (__instance != null)
				{
					Humanoid character = __instance.m_character;
					if (!((Object)(object)character == (Object)null))
					{
						ResetForHumanoid(character);
						DLogAttackSpeed("Attack.Stop: ResetForHumanoid");
					}
				}
			}
			catch (Exception)
			{
			}
		}
	}

	[<44d44cce-7ad9-4445-90b1-2eb839d16508>NullableContext(0)]
	[HarmonyPatch(typeof(Humanoid), "UpdateAttack")]
	public static class Humanoid_UpdateAttack_AttackSpeedDtPatch
	{
		[HarmonyPrefix]
		[<44d44cce-7ad9-4445-90b1-2eb839d16508>NullableContext(1)]
		private static void Prefix(Humanoid __instance, ref float dt)
		{
			try
			{
				EnsureAttackInit();
				if ((Object)(object)__instance == (Object)null)
				{
					return;
				}
				HumanoidState attackState = GetAttackState(__instance);
				if (attackState.ActiveAttackDepth > 0)
				{
					float activeAttackMul = attackState.ActiveAttackMul;
					if (!(activeAttackMul <= 0f) && !float.IsNaN(activeAttackMul) && !float.IsInfinity(activeAttackMul))
					{
						dt *= activeAttackMul;
					}
				}
			}
			catch (Exception ex)
			{
				LogError("Exception in Humanoid_UpdateAttack_AttackSpeedDtPatch: " + ex);
			}
		}
	}

	[<44d44cce-7ad9-4445-90b1-2eb839d16508>NullableContext(0)]
	[HarmonyPatch(typeof(Humanoid), "CustomFixedUpdate")]
	public static class Humanoid_CustomFixedUpdate_AttackSpeedPatch
	{
		[HarmonyPostfix]
		[<44d44cce-7ad9-4445-90b1-2eb839d16508>NullableContext(1)]
		private static void Postfix(Humanoid __instance, float fixedDeltaTime)
		{
			EnsureAttackInit();
			HumanoidState attackState = GetAttackState(__instance);
			bool flag = ((Character)__instance).InAttack();
			if (flag)
			{
				if (attackState.HasDesiredSpeed)
				{
					ApplyAnimSpeed(__instance, attackState, attackState.DesiredSpeed);
				}
				else
				{
					ApplyAnimSpeed(__instance, attackState, 1f);
				}
			}
			else if (attackState.WasInAttack)
			{
				ApplyAnimSpeed(__instance, attackState, 1f);
				attackState.HasDesiredSpeed = false;
				attackState.DesiredSpeed = 1f;
			}
			attackState.WasInAttack = flag;
		}
	}

	[<44d44cce-7ad9-4445-90b1-2eb839d16508>NullableContext(0)]
	[HarmonyPatch(typeof(Character), "RPC_Stagger")]
	public static class Character_RPC_Stagger_AttackSpeedResetPatch
	{
		[<44d44cce-7ad9-4445-90b1-2eb839d16508>NullableContext(1)]
		[HarmonyPostfix]
		private static void Postfix(Character __instance, long sender, Vector3 forceDirection)
		{
			try
			{
				EnsureAttackInit();
				Humanoid val = (Humanoid)(object)((__instance is Humanoid) ? __instance : null);
				if (!((Object)(object)val == (Object)null))
				{
					ResetForHumanoid(val);
				}
			}
			catch (Exception)
			{
			}
		}
	}

	[<44d44cce-7ad9-4445-90b1-2eb839d16508>NullableContext(0)]
	[HarmonyPatch(typeof(Character), "OnDeath")]
	public static class Character_OnDeath_AttackSpeedResetPatch
	{
		[HarmonyPostfix]
		[<44d44cce-7ad9-4445-90b1-2eb839d16508>NullableContext(1)]
		private static void Postfix(Character __instance)
		{
			try
			{
				EnsureAttackInit();
				Humanoid val = (Humanoid)(object)((__instance is Humanoid) ? __instance : null);
				if (!((Object)(object)val == (Object)null))
				{
					ResetForHumanoid(val);
				}
			}
			catch (Exception)
			{
			}
		}
	}

	[HarmonyPatch(typeof(Character), "FreezeFrame")]
	[<44d44cce-7ad9-4445-90b1-2eb839d16508>NullableContext(0)]
	public static class Character_FreezeFrame_AttackSpeedScalePatch
	{
		[HarmonyPrefix]
		[<44d44cce-7ad9-4445-90b1-2eb839d16508>NullableContext(1)]
		private static void Prefix(Character __instance, ref float duration)
		{
			try
			{
				EnsureAttackInit();
				if ((Object)(object)__instance == (Object)null || Mathf.Abs(duration - 0.15f) > 0.01f)
				{
					return;
				}
				Humanoid val = (Humanoid)(object)((__instance is Humanoid) ? __instance : null);
				if ((Object)(object)val == (Object)null)
				{
					return;
				}
				HumanoidState attackState = GetAttackState(val);
				if (!attackState.HasDesiredSpeed)
				{
					return;
				}
				float desiredSpeed = attackState.DesiredSpeed;
				if (!(desiredSpeed <= 1.001f) && !float.IsNaN(desiredSpeed) && !float.IsInfinity(desiredSpeed))
				{
					float num = duration / desiredSpeed;
					if (num < 0.03f)
					{
						num = 0.03f;
					}
					DLogAttackSpeed($"FreezeFrame scale: {duration:F3} -> {num:F3} (mul={desiredSpeed:F3})");
					duration = num;
				}
			}
			catch (Exception ex)
			{
				LogError("Exception in Character_FreezeFrame_AttackSpeedScalePatch: " + ex);
			}
		}
	}

	[<44d44cce-7ad9-4445-90b1-2eb839d16508>NullableContext(0)]
	[HarmonyPatch(typeof(CharacterAnimEvent), "UpdateFreezeFrame")]
	public static class CharacterAnimEvent_UpdateFreezeFrame_ReapplySpeedPatch
	{
		[<44d44cce-7ad9-4445-90b1-2eb839d16508>NullableContext(1)]
		[HarmonyPostfix]
		private static void Postfix(CharacterAnimEvent __instance, float dt)
		{
			try
			{
				EnsureAttackInit();
				if ((Object)(object)__instance == (Object)null)
				{
					return;
				}
				Character componentInParent = ((Component)__instance).GetComponentInParent<Character>();
				Humanoid val = (Humanoid)(object)((componentInParent is Humanoid) ? componentInParent : null);
				if (!((Object)(object)val == (Object)null))
				{
					HumanoidState attackState = GetAttackState(val);
					if (attackState.HasDesiredSpeed && (attackState.ActiveAttackDepth > 0 || ((Character)val).InAttack()))
					{
						ApplyAnimSpeed(val, attackState, attackState.DesiredSpeed);
					}
					else
					{
						ApplyAnimSpeed(val, attackState, 1f);
					}
				}
			}
			catch (Exception ex)
			{
				LogError("Exception in CharacterAnimEvent_UpdateFreezeFrame_ReapplySpeedPatch: " + ex);
			}
		}
	}

	[HarmonyPatch(typeof(SEMan), "AddStatusEffect", new Type[]
	{
		typeof(int),
		typeof(bool),
		typeof(int),
		typeof(float)
	})]
	[<44d44cce-7ad9-4445-90b1-2eb839d16508>NullableContext(0)]
	public static class SEMan_AddStatusEffect_ByHash_WetImmunePatch
	{
		[<44d44cce-7ad9-4445-90b1-2eb839d16508>NullableContext(1)]
		[HarmonyPrefix]
		private static bool Prefix(SEMan __instance, int nameHash, bool resetTime, int itemLevel, float skillLevel)
		{
			try
			{
				EnsureWetInit();
				if (nameHash != SEMan.s_statusEffectWet)
				{
					return true;
				}
				Character val = null;
				try
				{
					val = _semanCharacterRef.Invoke(__instance);
				}
				catch (Exception)
				{
					val = null;
				}
				if ((Object)(object)val != (Object)null && HasWetImmune(val))
				{
					DLogWet("Blocked Wet (AddStatusEffect by hash) due to WetImmune");
					return false;
				}
			}
			catch (Exception ex2)
			{
				LogError("Exception in SEMan_AddStatusEffect_ByHash_WetImmunePatch: " + ex2);
			}
			return true;
		}
	}

	[<44d44cce-7ad9-4445-90b1-2eb839d16508>NullableContext(0)]
	[HarmonyPatch(typeof(SEMan), "AddStatusEffect", new Type[]
	{
		typeof(StatusEffect),
		typeof(bool),
		typeof(int),
		typeof(float)
	})]
	public static class SEMan_AddStatusEffect_BySE_WetImmunePatch
	{
		[<44d44cce-7ad9-4445-90b1-2eb839d16508>NullableContext(1)]
		[HarmonyPrefix]
		private static bool Prefix(SEMan __instance, StatusEffect statusEffect, bool resetTime, int itemLevel, float skillLevel, ref StatusEffect __result)
		{
			try
			{
				if ((Object)(object)statusEffect == (Object)null)
				{
					return true;
				}
				if (statusEffect.NameHash() != SEMan.s_statusEffectWet)
				{
					return true;
				}
				Character character = statusEffect.m_character;
				if ((Object)(object)character != (Object)null && HasWetImmune(character))
				{
					DLogWet("Blocked Wet (AddStatusEffect by SE) due to WetImmune");
					__result = null;
					return false;
				}
			}
			catch (Exception ex)
			{
				LogError("Exception in SEMan_AddStatusEffect_BySE_WetImmunePatch: " + ex);
			}
			return true;
		}
	}

	public static bool DEBUG = false;

	public static readonly List<ExtraStatEntry> ExtraStatsConfig = new List<ExtraStatEntry>
	{
		new ExtraStatEntry("SE_LightcallerArmor_DO", ExtraStatType.Eitr, 5f, ExtraSourceType.StatusEffect),
		new ExtraStatEntry("SE_DeathcallerArmor_DO", ExtraStatType.Eitr, 10f, ExtraSourceType.StatusEffect),
		new ExtraStatEntry("SE_FrostcallerArmor_DO", ExtraStatType.Eitr, 15f, ExtraSourceType.StatusEffect),
		new ExtraStatEntry("SE_FirecallerArmor_DO", ExtraStatType.Eitr, 20f, ExtraSourceType.StatusEffect),
		new ExtraStatEntry("SE_StormcallerArmor_DO", ExtraStatType.Eitr, 25f, ExtraSourceType.StatusEffect),
		new ExtraStatEntry("SE_LightcallerBelt_DO", ExtraStatType.Eitr, 10f, ExtraSourceType.StatusEffect),
		new ExtraStatEntry("SE_DeathcallerBelt_DO", ExtraStatType.Eitr, 15f, ExtraSourceType.StatusEffect),
		new ExtraStatEntry("SE_FrostcallerBelt_DO", ExtraStatType.Eitr, 20f, ExtraSourceType.StatusEffect),
		new ExtraStatEntry("SE_FirecallerBelt_DO", ExtraStatType.Eitr, 20f, ExtraSourceType.StatusEffect),
		new ExtraStatEntry("SE_StormcallerBelt_DO", ExtraStatType.Eitr, 25f, ExtraSourceType.StatusEffect),
		new ExtraStatEntry("SE_TotemcallerBelt_DO", ExtraStatType.Health, 10f, ExtraSourceType.StatusEffect),
		new ExtraStatEntry("SE_WindcallerBelt_DO", ExtraStatType.Stamina, 10f, ExtraSourceType.StatusEffect),
		new ExtraStatEntry("SE_BloodcallerArmor_DO", ExtraStatType.Health, 50f, ExtraSourceType.StatusEffect),
		new ExtraStatEntry("ArmorBloodcallerCapeDO", ExtraStatType.Health, 30f, ExtraSourceType.ItemDrop)
	};

	private static readonly ConditionalWeakTable<Humanoid, HumanoidState> _attackState = new ConditionalWeakTable<Humanoid, HumanoidState>();

	private static FieldRef<Character, ZSyncAnimation> _zanimRef;

	private static bool _attackInit;

	private const float HitFreeze_Default = 0.15f;

	private const float HitFreeze_Epsilon = 0.01f;

	private const float HitFreeze_Min = 0.03f;

	private static FieldRef<SEMan, Character> _semanCharacterRef;

	private static bool _wetInit;

	private static void LogInfo(string msg)
	{
	}

	private static void LogError(string msg)
	{
	}

	private static void DLogAttackSpeed(string msg)
	{
	}

	private static void DLogWet(string msg)
	{
	}

	private static void DLogTooltip(string msg)
	{
	}

	private static void DLogFood(string msg)
	{
	}

	private static void GetItemDropBonusesForPrefab(string prefabName, out float extraHp, out float extraStamina, out float extraEitr, out float extraAttackSpeedPercent, out float displayAttackSpeedPercent, out bool wetImmune)
	{
		extraHp = 0f;
		extraStamina = 0f;
		extraEitr = 0f;
		extraAttackSpeedPercent = 0f;
		displayAttackSpeedPercent = 0f;
		wetImmune = false;
		if (string.IsNullOrEmpty(prefabName))
		{
			return;
		}
		for (int i = 0; i < ExtraStatsConfig.Count; i++)
		{
			ExtraStatEntry extraStatEntry = ExtraStatsConfig[i];
			if (extraStatEntry.SourceType == ExtraSourceType.ItemDrop && string.Equals(prefabName, extraStatEntry.PrefabName, StringComparison.OrdinalIgnoreCase))
			{
				switch (extraStatEntry.StatType)
				{
				case ExtraStatType.Health:
					extraHp += extraStatEntry.Value;
					break;
				case ExtraStatType.Stamina:
					extraStamina += extraStatEntry.Value;
					break;
				case ExtraStatType.Eitr:
					extraEitr += extraStatEntry.Value;
					break;
				case ExtraStatType.AttackSpeed:
					extraAttackSpeedPercent += extraStatEntry.Value;
					displayAttackSpeedPercent += (extraStatEntry.DisplayValue.HasValue ? extraStatEntry.DisplayValue.Value : extraStatEntry.Value);
					break;
				case ExtraStatType.WetImmune:
					wetImmune = true;
					break;
				}
			}
		}
	}

	private static void GetItemDropBonusesForPrefab(string prefabName, out float extraHp, out float extraStamina, out float extraEitr, out float extraAttackSpeedPercent, out bool wetImmune)
	{
		GetItemDropBonusesForPrefab(prefabName, out extraHp, out extraStamina, out extraEitr, out extraAttackSpeedPercent, out var _, out wetImmune);
	}

	private static void GetStatusEffectBonuses(string seRawName, out float extraHp, out float extraStamina, out float extraEitr, out float extraAttackSpeedPercent, out float displayAttackSpeedPercent, out bool wetImmune)
	{
		extraHp = 0f;
		extraStamina = 0f;
		extraEitr = 0f;
		extraAttackSpeedPercent = 0f;
		displayAttackSpeedPercent = 0f;
		wetImmune = false;
		if (string.IsNullOrEmpty(seRawName))
		{
			return;
		}
		string prefabName = Utils.GetPrefabName(seRawName);
		for (int i = 0; i < ExtraStatsConfig.Count; i++)
		{
			ExtraStatEntry extraStatEntry = ExtraStatsConfig[i];
			if (extraStatEntry.SourceType == ExtraSourceType.StatusEffect && string.Equals(prefabName, extraStatEntry.PrefabName, StringComparison.OrdinalIgnoreCase))
			{
				switch (extraStatEntry.StatType)
				{
				case ExtraStatType.Health:
					extraHp += extraStatEntry.Value;
					break;
				case ExtraStatType.Stamina:
					extraStamina += extraStatEntry.Value;
					break;
				case ExtraStatType.Eitr:
					extraEitr += extraStatEntry.Value;
					break;
				case ExtraStatType.AttackSpeed:
					extraAttackSpeedPercent += extraStatEntry.Value;
					displayAttackSpeedPercent += (extraStatEntry.DisplayValue.HasValue ? extraStatEntry.DisplayValue.Value : extraStatEntry.Value);
					break;
				case ExtraStatType.WetImmune:
					wetImmune = true;
					break;
				}
			}
		}
	}

	private static void GetStatusEffectBonuses(string seRawName, out float extraHp, out float extraStamina, out float extraEitr, out float extraAttackSpeedPercent, out bool wetImmune)
	{
		GetStatusEffectBonuses(seRawName, out extraHp, out extraStamina, out extraEitr, out extraAttackSpeedPercent, out var _, out wetImmune);
	}

	private static string BuildExtraStatsTooltipBlock(float extraHp, float extraStamina, float extraEitr, float displayAttackSpeedPercent, bool wetImmune)
	{
		if (extraHp == 0f && extraStamina == 0f && extraEitr == 0f && displayAttackSpeedPercent == 0f && !wetImmune)
		{
			return string.Empty;
		}
		StringBuilder stringBuilder = new StringBuilder();
		string text = "$extrastats_health_DO";
		string text2 = "$extrastats_stamina_DO";
		string text3 = "$extrastats_eitr_DO";
		string text4 = "$extrastats_attackspeed_DO";
		string text5 = "$extrastats_immune_DO";
		string text6 = "$extrastats_wet_DO";
		if (Localization.instance != null)
		{
			text = Localization.instance.Localize(text);
			text2 = Localization.instance.Localize(text2);
			text3 = Localization.instance.Localize(text3);
			text4 = Localization.instance.Localize(text4);
			text5 = Localization.instance.Localize(text5);
			text6 = Localization.instance.Localize(text6);
		}
		if (extraHp != 0f)
		{
			string arg = ((extraHp >= 0f) ? "+" : "");
			stringBuilder.Append($"\n{text}: <color=#f27979>{arg}{extraHp:F0}</color>");
		}
		if (extraStamina != 0f)
		{
			string arg2 = ((extraStamina >= 0f) ? "+" : "");
			stringBuilder.Append($"\n{text2}: <color=#ffff80>{arg2}{extraStamina:F0}</color>");
		}
		if (extraEitr != 0f)
		{
			string arg3 = ((extraEitr >= 0f) ? "+" : "");
			stringBuilder.Append($"\n{text3}: <color=#8686ee>{arg3}{extraEitr:F0}</color>");
		}
		if (displayAttackSpeedPercent != 0f)
		{
			int num = Mathf.RoundToInt(displayAttackSpeedPercent);
			string arg4 = ((num >= 0) ? "+" : "");
			stringBuilder.Append($"\n{text4}: <color=orange>{arg4}{num}%</color>");
		}
		if (wetImmune)
		{
			stringBuilder.Append("\n" + text5 + ": <color=orange>" + text6 + "</color>");
		}
		return stringBuilder.ToString();
	}

	private static bool HasWetImmune(Character c)
	{
		if ((Object)(object)c == (Object)null)
		{
			return false;
		}
		try
		{
			Player val = (Player)(object)((c is Player) ? c : null);
			if ((Object)(object)val != (Object)null)
			{
				Inventory inventory = ((Humanoid)val).GetInventory();
				if (inventory != null)
				{
					List<ItemData> equippedItems = inventory.GetEquippedItems();
					for (int i = 0; i < equippedItems.Count; i++)
					{
						ItemData val2 = equippedItems[i];
						if (val2 != null && !((Object)(object)val2.m_dropPrefab == (Object)null))
						{
							string name = ((Object)val2.m_dropPrefab).name;
							GetItemDropBonusesForPrefab(name, out var _, out var _, out var _, out var _, out var _, out var wetImmune);
							if (wetImmune)
							{
								DLogWet("WetImmune from ItemDrop: " + name);
								return true;
							}
						}
					}
				}
			}
			if (c.m_seman != null && c.m_seman.m_statusEffects != null)
			{
				List<StatusEffect> statusEffects = c.m_seman.m_statusEffects;
				for (int j = 0; j < statusEffects.Count; j++)
				{
					StatusEffect val3 = statusEffects[j];
					if (!((Object)(object)val3 == (Object)null))
					{
						string name2 = ((Object)val3).name;
						GetStatusEffectBonuses(name2, out var _, out var _, out var _, out var _, out var _, out var wetImmune2);
						if (wetImmune2)
						{
							string prefabName = Utils.GetPrefabName(name2);
							DLogWet("WetImmune from StatusEffect: " + name2 + " (clean=" + prefabName + ")");
							return true;
						}
					}
				}
			}
		}
		catch (Exception ex)
		{
			LogError("Exception in HasWetImmune: " + ex);
		}
		return false;
	}

	private static void EnsureAttackInit()
	{
		if (!_attackInit)
		{
			_attackInit = true;
			_zanimRef = AccessTools.FieldRefAccess<Character, ZSyncAnimation>("m_zanim");
		}
	}

	private static HumanoidState GetAttackState(Humanoid h)
	{
		return _attackState.GetValue(h, (Humanoid _) => new HumanoidState());
	}

	private static void ApplyAnimSpeed(Humanoid h, HumanoidState state, float speed)
	{
		ZSyncAnimation val = null;
		try
		{
			val = _zanimRef.Invoke((Character)(object)h);
		}
		catch (Exception)
		{
			return;
		}
		if (!((Object)(object)val == (Object)null) && !Mathf.Approximately(state.LastAppliedSpeed, speed))
		{
			val.SetSpeed(speed);
			state.LastAppliedSpeed = speed;
		}
	}

	private static void ResetForHumanoid(Humanoid h)
	{
		if (!((Object)(object)h == (Object)null))
		{
			EnsureAttackInit();
			HumanoidState attackState = GetAttackState(h);
			ApplyAnimSpeed(h, attackState, 1f);
			attackState.HasDesiredSpeed = false;
			attackState.DesiredSpeed = 1f;
			attackState.WasInAttack = false;
			attackState.ActiveAttackDepth = 0;
			attackState.ActiveAttackMul = 1f;
		}
	}

	private static float ComputeTotalAttackSpeedPercentForHumanoid(Humanoid h)
	{
		float num = 0f;
		if ((Object)(object)h == (Object)null)
		{
			return 0f;
		}
		try
		{
			Player val = (Player)(object)((h is Player) ? h : null);
			if ((Object)(object)val != (Object)null)
			{
				Inventory inventory = ((Humanoid)val).GetInventory();
				if (inventory != null)
				{
					List<ItemData> equippedItems = inventory.GetEquippedItems();
					for (int i = 0; i < equippedItems.Count; i++)
					{
						ItemData val2 = equippedItems[i];
						if (val2 != null && !((Object)(object)val2.m_dropPrefab == (Object)null))
						{
							string name = ((Object)val2.m_dropPrefab).name;
							GetItemDropBonusesForPrefab(name, out var _, out var _, out var _, out var extraAttackSpeedPercent, out var _, out var _);
							if (extraAttackSpeedPercent != 0f)
							{
								num += extraAttackSpeedPercent;
								DLogAttackSpeed($"AttackSpeed from ItemDrop: {name} → {extraAttackSpeedPercent}%");
							}
						}
					}
				}
			}
			if (((Character)h).m_seman != null && ((Character)h).m_seman.m_statusEffects != null)
			{
				List<StatusEffect> statusEffects = ((Character)h).m_seman.m_statusEffects;
				for (int j = 0; j < statusEffects.Count; j++)
				{
					StatusEffect val3 = statusEffects[j];
					if (!((Object)(object)val3 == (Object)null))
					{
						string name2 = ((Object)val3).name;
						GetStatusEffectBonuses(name2, out var _, out var _, out var _, out var extraAttackSpeedPercent2, out var _, out var _);
						if (extraAttackSpeedPercent2 != 0f)
						{
							num += extraAttackSpeedPercent2;
							string prefabName = Utils.GetPrefabName(name2);
							DLogAttackSpeed($"AttackSpeed from StatusEffect: {name2} (clean={prefabName}) → {extraAttackSpeedPercent2}%");
						}
					}
				}
			}
		}
		catch (Exception ex)
		{
			LogError("Exception in ComputeTotalAttackSpeedPercentForHumanoid: " + ex);
		}
		return num;
	}

	private static void EnsureWetInit()
	{
		if (!_wetInit)
		{
			_wetInit = true;
			_semanCharacterRef = AccessTools.FieldRefAccess<SEMan, Character>("m_character");
		}
	}
}
[<44d44cce-7ad9-4445-90b1-2eb839d16508>NullableContext(1)]
[<839beae5-12ea-4eaa-8a82-47e46d9c3654>Nullable(0)]
[HarmonyPatch]
public static class LivingContainerSpawner
{
	[<44d44cce-7ad9-4445-90b1-2eb839d16508>NullableContext(0)]
	private static class DevLog
	{
		public const bool Enabled = false;

		public const bool SpawnTimers = true;

		public const bool SpawnAttempts = true;

		public const bool Dedicated = true;

		public const bool Lifecycle = true;

		public const bool Perf = true;

		public const bool Watcher = true;

		public const bool WatcherVerbose = false;

		public const bool StateReset = true;
	}

	[<839beae5-12ea-4eaa-8a82-47e46d9c3654>Nullable(0)]
	private class LivingContainerDef
	{
		public string Prefab;

		public Biome Biomes;

		public float CheckInterval;

		public float SpawnChance;

		public int MaxInWorld;

		public float MinDistance;

		public float MaxDistance;

		public float MinAltitude;

		public float MaxAltitude;

		public bool AllowInWater;

		public int MaxSpawnAttempts;

		public float DestroyDelay;

		public string VfxPrefab;

		public string PinSprite;

		public string PinText;

		public bool PinAnimate;

		public bool PinDoubleSize;
	}

	[<44d44cce-7ad9-4445-90b1-2eb839d16508>NullableContext(0)]
	private struct ItemsCacheEntry
	{
		public int ItemsLen;

		public int QuickHash;

		public bool IsEmpty;

		public int DecodedCount;

		public float LastTouchTime;
	}

	[<44d44cce-7ad9-4445-90b1-2eb839d16508>NullableContext(0)]
	private struct PrefabContainerTuning
	{
		public int Width;

		public int Height;

		public int LootMin;

		public int LootMax;

		public bool Equals(PrefabContainerTuning other)
		{
			if (Width == other.Width && Height == other.Height && LootMin == other.LootMin)
			{
				return LootMax == other.LootMax;
			}
			return false;
		}
	}

	[<839beae5-12ea-4eaa-8a82-47e46d9c3654>Nullable(0)]
	private class LivingContainerRegistryComponent : MonoBehaviour
	{
		private ZNetView _nview;

		private ZDOID _uid;

		private string _prefab;

		private void Awake()
		{
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: 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)
			try
			{
				_nview = ((Component)this).GetComponent<ZNetView>();
				if ((Object)(object)_nview == (Object)null || !_nview.IsValid())
				{
					return;
				}
				_prefab = Utils.GetPrefabName(((Object)((Component)this).gameObject).name);
				BuildDefCache();
				if (DefByPrefab.ContainsKey(_prefab))
				{
					ZDO val = null;
					try
					{
						val = _nview.GetZDO();
					}
					catch
					{
					}
					if (val != null)
					{
						_uid = val.m_uid;
						RegisterLoadedRiko(_uid, _nview, _prefab);
					}
				}
			}
			catch
			{
			}
		}

		private void OnDestroy()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//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_0017: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (_uid != default(ZDOID))
				{
					UnregisterLoadedRiko(_uid);
				}
			}
			catch
			{
			}
		}
	}

	[<44d44cce-7ad9-4445-90b1-2eb839d16508>NullableContext(0)]
	private enum GroundFail
	{
		None,
		WorldGenNoHeight,
		RaycastNoHit,
		WrongBiome,
		InWater,
		WaterTooDeep,
		OceanDepth,
		Lava,
		Altitude,
		Overlap,
		MistlandsBlocked
	}

	[<839beae5-12ea-4eaa-8a82-47e46d9c3654>Nullable(0)]
	[HarmonyPatch(typeof(InventoryGui), "Hide")]
	private static class InventoryGui_Hide_Patch
	{
		private static void Prefix(InventoryGui __instance, out Container __state)
		{
			__state = (((Object)(object)__instance != (Object)null) ? __instance.m_currentContainer : null);
		}

		private static void Postfix(Container __state)
		{
			if ((Object)(object)__state != (Object)null)
			{
				HandleContainerClosed(__state);
			}
		}
	}

	[<839beae5-12ea-4eaa-8a82-47e46d9c3654>Nullable(0)]
	private class LivingContainerPinComponent : MonoBehaviour
	{
		public string PinSprite;

		public string PinText;

		public bool PinAnimate;

		public bool PinDoubleSize;

		private PinData _pin;

		private const float PinUpdateInterval_Seconds = 5f;

		private float _nextPinUpdateTime;

		private void Update()
		{
			//IL_006b: 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)
			if (!LivingContainerConfig.IsRikoEnabled())
			{
				if (_pin != null && (Object)(object)Minimap.instance != (Object)null)
				{
					Minimap.instance.RemovePin(_pin);
					_pin = null;
				}
				Object.Destroy((Object)(object)this);
				return;
			}
			float time = Time.time;
			if (_pin != null)
			{
				if (!(time < _nextPinUpdateTime))
				{
					_nextPinUpdateTime = time + 5f;
					_pin.m_pos = ((Component)this).transform.position;
				}
			}
			else
			{
				TryCreatePin();
			}
		}

		private void TryCreatePin()
		{
			//IL_004d: 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_006e: Unknown result type (might be due to invalid IL or missing references)
			if (!string.IsNullOrEmpty(PinSprite) && !((Object)(object)Minimap.instance == (Object)null) && Magic_SupremacyPlugin.PinSprites != null && Magic_SupremacyPlugin.PinSprites.TryGetValue(PinSprite, out var value) && !((Object)(object)value == (Object)null))
			{
				PinData val = Minimap.instance.AddPin(((Component)this).transform.position, (PinType)8, PinText ?? "", false, false, 0L, default(PlatformUserID));
				val.m_icon = value;
				val.m_animate = PinAnimate;
				val.m_doubleSize = PinDoubleSize;
				val.m_save = false;
				_pin = val;
				_nextPinUpdateTime = Time.time + 5f;
			}
		}

		private void OnDestroy()
		{
			if (_pin != null && (Object)(object)Minimap.instance != (Object)null)
			{
				Minimap.instance.RemovePin(_pin);
			}
		}
	}

	[<44d44cce-7ad9-4445-90b1-2eb839d16508>NullableContext(0)]
	private class RikoSpawnStabilizer : MonoBehaviour
	{
		private bool _started;

		public void Init()
		{
			if (!_started)
			{
				_started = true;
				((MonoBehaviour)this).StartCoroutine(StabilizeRoutine());
			}
		}

		[<44d44cce-7ad9-4445-90b1-2eb839d16508>NullableContext(1)]
		private IEnumerator StabilizeRoutine()
		{
			StabilizeOnce(((Component)this).gameObject);
			yield return null;
			StabilizeOnce(((Component)this).gameObject);
			yield return (object)new WaitForSeconds(0.35f);
			StabilizeOnce(((Component)this).gameObject);
		}
	}

	private static readonly LivingContainerDef[] Defs = new LivingContainerDef[6]
	{
		new LivingContainerDef
		{
			Prefab = "EncounterCreatureRikoBlackforestDO",
			Biomes = (Biome)8,
			CheckInterval = 360f,
			SpawnChance = 0.3f,
			MaxInWorld = 3,
			MinDistance = 18f,
			MaxDistance = 36f,
			MinAltitude = 0f,
			MaxAltitude = 2000f,
			AllowInWater = false,
			MaxSpawnAttempts = 15,
			DestroyDelay = 1f,
			VfxPrefab = "fx_riko_disappear_DO",
			PinSprite = "PinRikoDO",
			PinText = "",
			PinAnimate = false,
			PinDoubleSize = true
		},
		new LivingContainerDef
		{
			Prefab = "EncounterCreatureRikoSwampDO",
			Biomes = (Biome)2,
			CheckInterval = 360f,
			SpawnChance = 0.3f,
			MaxInWorld = 3,
			MinDistance = 18f,
			MaxDistance = 36f,
			MinAltitude = -1f,
			MaxAltitude = 2000f,
			AllowInWater = false,
			MaxSpawnAttempts = 18,
			DestroyDelay = 1f,
			VfxPrefab = "fx_riko_disappear_DO",
			PinSprite = "PinRikoDO",
			PinText = "",
			PinAnimate = false,
			PinDoubleSize = true
		},
		new LivingContainerDef
		{
			Prefab = "EncounterCreatureRikoMountainDO",
			Biomes = (Biome)4,
			CheckInterval = 360f,
			SpawnChance = 0.3f,
			MaxInWorld = 3,
			MinDistance = 18f,
			MaxDistance = 36f,
			MinAltitude = 10f,
			MaxAltitude = 2000f,
			AllowInWater = false,
			MaxSpawnAttempts = 15,
			DestroyDelay = 1f,
			VfxPrefab = "fx_riko_disappear_DO",
			PinSprite = "PinRikoDO",
			PinText = "",
			PinAnimate = false,
			PinDoubleSize = true
		},
		new LivingContainerDef
		{
			Prefab = "EncounterCreatureRikoPlainsDO",
			Biomes = (Biome)16,
			CheckInterval = 360f,
			SpawnChance = 0.3f,
			MaxInWorld = 3,
			MinDistance = 18f,
			MaxDistance = 36f,
			MinAltitude = 0f,
			MaxAltitude = 2000f,
			AllowInWater = false,
			MaxSpawnAttempts = 15,
			DestroyDelay = 1f,
			VfxPrefab = "fx_riko_disappear_DO",
			PinSprite = "PinRikoDO",
			PinText = "",
			PinAnimate = false,
			PinDoubleSize = true
		},
		new LivingContainerDef
		{
			Prefab = "EncounterCreatureRikoMistlandsDO",
			Biomes = (Biome)512,
			CheckInterval = 360f,
			SpawnChance = 0.3f,
			MaxInWorld = 3,
			MinDistance = 15f,
			MaxDistance = 40f,
			MinAltitude = 12f,
			MaxAltitude = 2000f,
			AllowInWater = false,
			MaxSpawnAttempts = 18,
			DestroyDelay = 1f,
			VfxPrefab = "fx_riko_disappear_DO",
			PinSprite = "PinRikoDO",
			PinText = "",
			PinAnimate = false,
			PinDoubleSize = true
		},
		new LivingContainerDef
		{
			Prefab = "EncounterCreatureRikoAshlandsDO",
			Biomes = (Biome)32,
			CheckInterval = 360f,
			SpawnChance = 0.3f,
			MaxInWorld = 3,
			MinDistance = 18f,
			MaxDistance = 36f,
			MinAltitude = 0f,
			MaxAltitude = 2000f,
			AllowInWater = false,
			MaxSpawnAttempts = 15,
			DestroyDelay = 1f,
			VfxPrefab = "fx_riko_disappear_DO",
			PinSprite = "PinRikoDO",
			PinText = "",
			PinAnimate = false,
			PinDoubleSize = true
		}
	};

	private const float Riko_SeenRadius_Meters = 120f;

	private const float Riko_SeenUpdateInterval_Seconds = 12f;

	private const float Riko_TTL_Minutes = 20f;

	private const float Riko_Grace_Minutes = 2f;

	private const float Riko_TtlScanInterval_Seconds = 45f;

	private const float Riko_DestroyScanInterval_Seconds = 20f;

	private const float Riko_LoadedDestroyCheckInterval_Seconds = 0.2f;

	private const float Riko_EmptyWatcherInterval_Seconds = 30f;

	private const float ConfigRefreshInterval_Seconds = 5f;

	private const int OriginMaxAttempts = 3;

	private const int OriginPickGuard = 16;

	private const int MaxCatchupChecksPerTick_PerDef = 2;

	private const float WorldCountRescanInterval_Seconds = 90f;

	private const float ServerStartupGrace_Seconds = 10f;

	private const float MaxAllowedWaterDepth_Center = 0.08f;

	private const float MaxAllowedWaterDepth_Side = 0.12f;

	private const float DryAreaProbeRadius = 0.9f;

	private const int DryAreaAllowedWetSideSamples = 1;

	private const float MistlandsHeadroomHeight = 2.2f;

	private const float MistlandsHeadroomRadius = 0.45f;

	private const float MistlandsCeilingCheckStart = 0.15f;

	private const float DedNoGroundLogInterval_Seconds = 15f;

	private const string ZdoKey_Killed = "MS_Riko_Killed";

	private const string ZdoKey_SpawnTime = "MS_Riko_SpawnTime";

	private const string ZdoKey_LastSeenTime = "MS_Riko_LastSeenTime";

	private const string ZdoKey_DestroyAt = "MS_Riko_DestroyAt";

	private const string ZdoKey_VfxPlayed = "MS_Riko_VfxPlayed";

	private const string ZdoKey_FinalDestroyCounted = "MS_Riko_FinalDestroyCounted";

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

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

	private static float[] WorldChecks;

	private static float LastWorldUpdate;

	private static float NextSeenUpdateTime;

	private static float NextDestroyScanTime;

	private static float NextLoadedDestroyCheckTime;

	private static float NextTtlScanTime;

	private static float NextConfigRefreshTime;

	private static float NextWorldCountRescanTime;

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

	private const float AuthoritativeCountRefreshInterval_Seconds = 20f;

	private static bool WorldCountCacheInitialized;

	private static readonly List<Vector3> OriginPositions = new List<Vector3>(32);

	private static readonly FieldInfo ZNetPeer_m_refPos_Field = AccessTools.Field(typeof(ZNetPeer), "m_refPos");

	private static readonly Dictionary<ZDOID, ZNetView> LoadedRikos = new Dictionary<ZDOID, ZNetView>(256);

	private static int LoadedRegistryInvalidSweeps;

	private static List<ZDOID> _registrySweepKeys;

	private static bool PurgeInProgress;

	private static int PurgePrefabIndex;

	private static int PurgeSectorIndex;

	private static readonly List<ZDO> PurgeZdos = new List<ZDO>(256);

	private static float ServerWorldEnterTime = -1f;

	private static bool ServerGraceLogged;

	private static float _dedNextNoGroundLogTime;

	private static int _dedLastPlayers = -999;

	private static int _dedLastPeers = -999;

	private static int _dedLastOriginPos = -999;

	private static float _dedNextHeartbeatTime;

	private static bool _emptyWatcherInProgress;

	private static int _emptyWatcherPrefabIndex;

	private static int _emptyWatcherSectorIndex;

	private static readonly List<ZDO> _emptyWatcherZdos = new List<ZDO>(256);

	private static float _emptyWatcherNextRunTime;

	private static int _hashInUse;

	private static int _hashItems;

	private static readonly Dictionary<ZDOID, ItemsCacheEntry> _itemsCache = new Dictionary<ZDOID, ItemsCacheEntry>(512);

	private static float _itemsCacheNextCleanupTime;

	private const float ItemsCacheCleanupInterval_Seconds = 60f;

	private const float ItemsCacheKeepSeconds = 600f;

	private const int ItemsCacheMaxSize = 4096;

	private static List<ZDOID> _itemsCacheKeysTmp;

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

	private static readonly int SolidMask = LayerMask.GetMask(new string[5] { "terrain", "static_solid", "Default", "piece", "vehicle" });

	private static readonly Vector2[] DryAreaProbeOffsets = (Vector2[])(object)new Vector2[5]
	{
		new Vector2(0f, 0f),
		new Vector2(1f, 0f),
		new Vector2(-1f, 0f),
		new Vector2(0f, 1f),
		new Vector2(0f, -1f)
	};

	private static void Log(string msg)
	{
	}

	private static void LogTimers(string msg)
	{
	}

	private static void LogSpawn(string msg)
	{
	}

	private static void LogDed(string msg)
	{
	}

	private static void LogLife(string msg)
	{
	}

	private static void LogPerf(string msg)
	{
	}

	private static void LogWatcher(string msg)
	{
	}

	private static void LogWatcherVerbose(string msg)
	{
	}

	private static void LogReset(string msg)
	{
	}

	private static void RegisterLoadedRiko(ZDOID uid, ZNetView nv, string prefab)
	{
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)nv == (Object)null))
		{
			LoadedRikos[uid] = nv;
			LogPerf($"registry ADD prefab={prefab} uid={uid} loaded={LoadedRikos.Count}");
		}
	}

	private static void UnregisterLoadedRiko(ZDOID uid)
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		if (LoadedRikos.Remove(uid))
		{
			LogPerf($"registry REMOVE uid={uid} loaded={LoadedRikos.Count}");
		}
	}

	private static void EnsureRegistryComponent(GameObject go)
	{
		if (!((Object)(object)go == (Object)null) && !((Object)(object)go.GetComponent<LivingContainerRegistryComponent>() != (Object)null))
		{
			go.AddComponent<LivingContainerRegistryComponent>();
		}
	}

	[HarmonyPatch(typeof(ZNet), "Awake")]
	[HarmonyPostfix]
	private static void ZNet_Awake_Postfix()
	{
		try
		{
			if (!((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer())
			{
				ResetRuntimeState_Server("ZNet.Awake");
			}
		}
		catch
		{
		}
	}

	private static void ResetRuntimeState_Server(string reason)
	{
		WorldChecks = null;
		LastWorldUpdate = 0f;
		WorldCounts.Clear();
		WorldCountCacheInitialized = false;
		NextWorldCountRescanTime = 0f;
		NextAuthoritativeCountCheckTime.Clear();
		LoadedRikos.Clear();
		LoadedRegistryInvalidSweeps = 0;
		NextSeenUpdateTime = 0f;
		NextDestroyScanTime = 0f;
		NextLoadedDestroyCheckTime = 0f;
		NextTtlScanTime = 0f;
		NextConfigRefreshTime = 0f;
		PurgeInProgress = false;
		PurgePrefabIndex = 0;
		PurgeSectorIndex = 0;
		PurgeZdos.Clear();
		_emptyWatcherInProgress = false;
		_emptyWatcherPrefabIndex = 0;
		_emptyWatcherSectorIndex = 0;
		_emptyWatcherZdos.Clear();
		_emptyWatcherNextRunTime = 0f;
		_itemsCache.Clear();
		_itemsCacheNextCleanupTime = 0f;
		ServerWorldEnterTime = Time.time;
		ServerGraceLogged = false;
		OriginPositions.Clear();
		_dedNextNoGroundLogTime = 0f;
		_dedLastPlayers = -999;
		_dedLastPeers = -999;
		_dedLastOriginPos = -999;
		_dedNextHeartbeatTime = 0f;
		LogReset($"server RuntimeState RESET reason={reason} time={ServerWorldEnterTime:0.00} session={ZDOMan.GetSessionID()}");
	}

	[HarmonyPostfix]
	[HarmonyPatch(typeof(ZoneSystem), "Update")]
	private static void ZoneSystem_Update_Postfix()
	{
		if (!LivingContainerConfig.IsRikoEnabled() || (Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer() || (Object)(object)ZNetScene.instance == (Object)null || ZDOMan.instance == null || (Object)(object)ObjectDB.instance == (Object)null)
		{
			return;
		}
		if (ServerWorldEnterTime < 0f)
		{
			ServerWorldEnterTime = Time.time;
		}
		float num = Time.time - ServerWorldEnterTime;
		bool flag = num < 10f;
		if (flag && !ServerGraceLogged)
		{
			ServerGraceLogged = true;
			LogTimers($"server StartupGrace ACTIVE seconds={10f:0.0} sinceEnter={num:0.00}");
		}
		BuildDefCache();
		if (Time.time >= NextConfigRefreshTime)
		{
			RefreshDefsFromConfig();
			NextConfigRefreshTime = Time.time + 5f;
		}
		List<Player> allPlayers = Player.GetAllPlayers();
		BuildOriginPositions(allPlayers);
		LogDedicatedStateIfNeeded(allPlayers);
		UpdateLastSeenForLoadedRikos();
		ProcessLoadedDestroyDueFast();
		ProcessScheduledDestroyForLoadedRikos();
		TryRunEmptyWatcher_Server();
		TryPurgeExpiredOrKilledRikoZDOs();
		if (OriginPositions.Count == 0)
		{
			return;
		}
		float time = Time.time;
		if (LastWorldUpdate <= 0f)
		{
			LastWorldUpdate = time;
			EnsureWorldChecksInitialized();
			EnsureWorldCounts_Cached(initial: true);
			LogTimers($"server WorldTimers INIT sinceEnter={num:0.00} note=FirstWorldTick");
			return;
		}
		float num2 = time - LastWorldUpdate;
		if (num2 < 5f)
		{
			return;
		}
		LastWorldUpdate = time;
		EnsureWorldChecksInitialized();
		EnsureWorldCounts_Cached(initial: false);
		LogTimers($"server WorldTick sinceEnter={num:0.00} delta={num2:0.00} origins={OriginPositions.Count}");
		for (int i = 0; i < Defs.Length; i++)
		{
			LivingContainerDef livingContainerDef = Defs[i];
			if (livingContainerDef == null)
			{
				continue;
			}
			float num3 = WorldChecks[i];
			WorldChecks[i] -= num2;
			float num4 = WorldChecks[i];
			if (num3 > 0f && (num3 < 5f || num4 <= 0f))
			{
				LogTimers($"server WorldTimer prefab={livingContainerDef.Prefab} before={num3:0.00} after={num4:0.00} delta={num2:0.00} interval={livingContainerDef.CheckInterval:0.0} grace={flag}");
			}
			if (WorldChecks[i] > 0f)
			{
				continue;
			}
			if (flag)
			{
				WorldChecks[i] = Mathf.Max(1f, livingContainerDef.CheckInterval);
				LogTimers($"server WorldTimer BLOCKED_BY_GRACE prefab={livingContainerDef.Prefab} setNext={WorldChecks[i]:0.00}");
				continue;
			}
			int num5 = 0;
			float num6 = Mathf.Max(1f, livingContainerDef.CheckInterval);
			while (WorldChecks[i] <= 0f && num5 < 2)
			{
				TrySpawnWithFallbackOrigins(OriginPositions, livingContainerDef, num, num5);
				WorldChecks[i] += num6;
				num5++;
			}
			if (WorldChecks[i] <= 0f)
			{
				WorldChecks[i] = Mathf.Min(1f, num6);
				LogTimers($"server WorldTimer STILL_OVERDUE prefab={livingContainerDef.Prefab} cappedNext={WorldChecks[i]:0.00}");
			}
			else
			{
				LogTimers($"server WorldTimer ADVANCED prefab={livingContainerDef.Prefab} nextIn={WorldChecks[i]:0.00} catchupUsed={num5}");
			}
		}
	}

	private static void EnsureWorldChecksInitialized()
	{
		if (WorldChecks == null || WorldChecks.Length != Defs.Length)
		{
			WorldChecks = new float[Defs.Length];
			for (int i = 0; i < WorldChecks.Length; i++)
			{
				LivingContainerDef livingContainerDef = Defs[i];
				float num = ((livingContainerDef != null) ? Mathf.Max(1f, livingContainerDef.CheckInterval) : 60f);
				float num2 = Mathf.Min(30f, num * 0.1f);
				WorldChecks[i] = num + Random.Range(0f, num2);
			}
			LogTimers($"server WorldChecks CREATED count={WorldChecks.Length}");
		}
	}

	private static void BuildOriginPositions(List<Player> players)
	{
		//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00da: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_0101: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_0121: 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_0141: Unknown result type (might be due to invalid IL or missing references)
		//IL_0152: Unknown result type (might be due to invalid IL or missing references)
		//IL_0157: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_008c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0091: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00be: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
		OriginPositions.Clear();
		if (players != null && players.Count > 0)
		{
			for (int i = 0; i < players.Count; i++)
			{
				Player val = players[i];
				if (!((Object)(object)val == (Object)null))
				{
					AddOriginPosition(((Component)val).transform.position);
				}
			}
		}
		else
		{
			if ((Object)(object)ZNet.instance == (Object)null)
			{
				return;
			}
			List<ZNetPeer> list = null;
			try
			{
				list = ZNet.instance.GetPeers();
			}
			catch
			{
			}
			if (list == null || list.Count == 0)
			{
				return;
			}
			for (int j = 0; j < list.Count; j++)
			{
				ZNetPeer val2 = list[j];
				if (val2 == null)
				{
					continue;
				}
				Vector3 val3 = Vector3.zero;
				try
				{
					if (ZNetPeer_m_refPos_Field != null)
					{
						object value = ZNetPeer_m_refPos_Field.GetValue(val2);
						if (value is Vector3)
						{
							Vector3 val4 = (Vector3)value;
							val3 = val4;
						}
					}
				}
				catch
				{
				}
				if (!(val3 == Vector3.zero))
				{
					AddOriginPosition(val3);
					AddOriginPosition(val3 + new Vector3(24f, 0f, 0f));
					AddOriginPosition(val3 + new Vector3(-24f, 0f, 0f));
					AddOriginPosition(val3 + new Vector3(0f, 0f, 24f));
					AddOriginPosition(val3 + new Vector3(0f, 0f, -24f));
				}
			}
		}
	}

	private static void AddOriginPosition(Vector3 pos)
	{
		//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_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_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_0049: Unknown result type (might be due to invalid IL or missing references)
		if (pos == Vector3.zero)
		{
			return;
		}
		for (int i = 0; i < OriginPositions.Count; i++)
		{
			Vector3 val = OriginPositions[i] - pos;
			if (((Vector3)(ref val)).sqrMagnitude < 1f)
			{
				return;
			}
		}
		OriginPositions.Add(pos);
	}

	private static void LogDedicatedStateIfNeeded(List<Player> players)
	{
	}

	private static bool SafeIsDedicated()
	{
		try
		{
			return (Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsDedicated();
		}
		catch
		{
			return false;
		}
	}

	private static bool TrySpawnWithFallbackOrigins(List<Vector3> origins, LivingContainerDef def, float sinceEnter, int catchup)
	{
		//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_00eb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
		//IL_0055: Unknown result type (might be due to invalid IL or missing references)
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		//IL_005c: Unknown result type (might be due to invalid IL or missing references)
		//IL_005e: Unknown result type (might be due to invalid IL or missing references)
		//IL_018d: Unknown result type (might be due to invalid IL or missing references)
		//IL_019c: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fe: 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_006e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0070: Unknown result type (might be due to invalid IL or missing references)
		//IL_0110: Unknown result type (might be due to invalid IL or missing references)
		//IL_011c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0128: Unknown result type (might be due to invalid IL or missing references)
		//IL_013e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0146: Unknown result type (might be due to invalid IL or missing references)
		//IL_0099: 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_00a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
		if (origins == null || origins.Count == 0 || def == null)
		{
			return false;
		}
		int num = 0;
		int num2 = -1;
		int num3 = -1;
		int num4 = -1;
		for (int i = 0; i < 3; i++)
		{
			int num5 = -1;
			Vector3 val = Vector3.zero;
			int num6 = 0;
			while (num5 < 0 && num6 < 16)
			{
				num6++;
				int num7 = Random.Range(0, origins.Count);
				if (num7 != num2 && num7 != num3 && num7 != num4)
				{
					Vector3 val2 = origins[num7];
					if (!(val2 == Vector3.zero))
					{
						num5 = num7;
						val = val2;
					}
				}
			}
			if (num5 < 0)
			{
				for (int j = 0; j < origins.Count; j++)
				{
					if (j != num2 && j != num3 && j != num4)
					{
						Vector3 val3 = origins[j];
						if (!(val3 == Vector3.zero))
						{
							num5 = j;
							val = val3;
							break;
						}
					}
				}
			}
			if (num5 < 0)
			{
				return false;
			}
			switch (num)
			{
			case 0:
				num2 = num5;
				break;
			case 1:
				num3 = num5;
				break;
			case 2:
				num4 = num5;
				break;
			}
			num++;
			Biome biomeSafe = GetBiomeSafe(val);
			if ((int)biomeSafe != 0 && (biomeSafe & def.Biomes) == 0)
			{
				LogSpawn("server TrySpawn SKIP originBiomeMismatch " + $"originPos=({val.x:0.0},{val.y:0.0},{val.z:0.0}) " + $"originBiome={biomeSafe} needed={def.Biomes} prefab={def.Prefab} " + $"originAttempt={i + 1}/{3}");
				continue;
			}
			LogSpawn($"server TrySpawn CALL originPos=({val.x:0.0},{val.y:0.0},{val.z:0.0}) prefab={def.Prefab} sinceEnter={sinceEnter:0.00} catchup={catchup} originAttempt={i + 1}/{3}");
			if (TrySpawnAtPosition(val, def))
			{
				return true;
			}
		}
		return false;
	}

	private static bool TrySpawnAtPosition(Vector3 origin, LivingContainerDef def)
	{
		//IL_037d: Unknown result type (might be due to invalid IL or missing references)
		//IL_038c: Unknown result type (might be due to invalid IL or missing references)
		//IL_039b: 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_00f1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_0201: Unknown result type (might be due to invalid IL or missing references)
		//IL_0206: Unknown result type (might be due to invalid IL or missing references)
		//IL_0209: Unknown result type (might be due to invalid IL or missing references)
		//IL_020b: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
		if (def == null)
		{
			return false;
		}
		float value = Random.value;
		if (value > def.SpawnChance)
		{
			LogSpawn($"server TrySpawn FAIL chance prefab={def.Prefab} rnd={value:0.000} chance={def.SpawnChance:0.000}");
			return false;
		}
		int authoritativeAliveCountForPrefab = GetAuthoritativeAliveCountForPrefab(def.Prefab);
		if (authoritativeAliveCountForPrefab >= def.MaxInWorld)
		{
			LogSpawn($"server TrySpawn FAIL maxInWorld prefab={def.Prefab} count={authoritativeAliveCountForPrefab} max={def.MaxInWorld}");
			return false;
		}
		GameObject prefab = ZNetScene.instance.GetPrefab(def.Prefab);
		if ((Object)(object)prefab == (Object)null)
		{
			LogSpawn("server TrySpawn FAIL missingPrefab prefab=" + def.Prefab);
			return false;
		}
		ApplyContainerConfigToPrefab(def, prefab);
		int num = Mathf.Max(1, def.MaxSpawnAttempts);
		int num2 = 0;
		int num3 = 0;
		int num4 = 0;
		int num5 = 0;
		int num6 = 0;
		int num7 = 0;
		int num8 = 0;
		int num9 = 0;
		int num10 = 0;
		int num11 = 0;
		for (int i = 0; i < num; i++)
		{
			Vector3 val = PickPoint(origin, def.MinDistance, def.MaxDistance);
			if (!TryGetRikoSpawnPoint(val, def, out var spawnPos, out var fail))
			{
				switch (fail)
				{
				case GroundFail.WorldGenNoHeight:
				case GroundFail.RaycastNoHit:
					num2++;
					break;
				case GroundFail.WrongBiome:
					num3++;
					break;
				case GroundFail.InWater:
					num4++;
					break;
				case GroundFail.WaterTooDeep:
					num5++;
					break;
				case GroundFail.OceanDepth:
					num6++;
					break;
				case GroundFail.Lava:
					num7++;
					break;
				case GroundFail.Altitude:
					num8++;
					break;
				case GroundFail.Overlap:
					num9++;
					break;
				case GroundFail.MistlandsBlocked:
					num10++;
					break;
				}
				LogSpawn($"server TrySpawn attempt={i + 1} FAIL prefab={def.Prefab} fail={fail} candidate=({val.x:0.0},{val.y:0.0},{val.z:0.0})");
				continue;
			}
			Quaternion val2 = Quaternion.Euler(0f, Random.Range(0f, 360f), 0f);
			GameObject val3 = Object.Instantiate<GameObject>(prefab, spawnPos, val2);
			if ((Object)(object)val3 == (Object)null)
			{
				num11++;
				LogSpawn($"server TrySpawn attempt={i + 1} FAIL instantiateNull prefab={def.Prefab}");
				continue;
			}
			EnsureRegistryComponent(val3);
			AttachPinComponent(val3, def);
			Container component = val3.GetComponent<Container>();
			if ((Object)(object)component != (Object)null)
			{
				component.m_autoDestroyEmpty = false;
			}
			FixSpawnInsideGeometry(val3);
			ZNetView val4 = null;
			ZDO val5 = null;
			try
			{
				val4 = val3.GetComponent<ZNetView>();
				if ((Object)(object)val4 != (Object)null && val4.IsValid())
				{
					val5 = val4.GetZDO();
				}
			}
			catch
			{
			}
			if (val5 != null)
			{
				try
				{
					EnsureServerOwnership(val4, val5, "SpawnInitZdo");
					long nowSeconds = GetNowSeconds();
					val5.Set("MS_Riko_SpawnTime", nowSeconds);
					val5.Set("MS_Riko_LastSeenTime", nowSeconds);
					val5.Set("MS_Riko_Killed", 0);
					val5.Set("MS_Riko_DestroyAt", 0L);
					val5.Set("MS_Riko_VfxPlayed", 0);
					val5.Set("MS_Riko_FinalDestroyCounted", 0);
				}
				catch
				{
				}
			}
			WorldCounts[def.Prefab] = ((!WorldCounts.TryGetValue(def.Prefab, out var value2)) ? 1 : (value2 + 1));
			string text = ((val5 != null) ? ((object)(ZDOID)(ref val5.m_uid)).ToString() : "null");
			LogSpawn($"server TrySpawn SUCCESS prefab={def.Prefab} uid={text} pos=({spawnPos.x:0.0},{spawnPos.y:0.0},{spawnPos.z:0.0}) attempt={i + 1} worldCount={WorldCounts[def.Prefab]}");
			LogSpawn($"server TrySpawn SUMMARY prefab={def.Prefab} attempts={num} " + $"groundFail={num2} biomeFail={num3} waterFail={num4} deepWaterFail={num5} oceanFail={num6} lavaFail={num7} altitudeFail={num8} overlapFail={num9} mistBlockedFail={num10} instFail={num11}");
			return true;
		}
		LogSpawn($"server TrySpawn SUMMARY prefab={def.Prefab} attempts={num} " + $"groundFail={num2} biomeFail={num3} waterFail={num4} deepWaterFail={num5} oceanFail={num6} lavaFail={num7} altitudeFail={num8} overlapFail={num9} mistBlockedFail={num10} instFail={num11}");
		return false;
	}

	private static bool TryGetRikoSpawnPoint(Vector3 candidate, LivingContainerDef def, out Vector3 spawnPos, out GroundFail fail)
	{
		//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_000a: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: 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_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Invalid comparison between Unknown and I4
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: 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_0069: 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_00c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_0086: 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_00da: Unknown result type (might be due to invalid IL or missing references)
		//IL_0106: Unknown result type (might be due to invalid IL or missing references)
		//IL_0110: 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_00e4: 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_00f3: 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_0142: Unknown result type (might be due to invalid IL or missing references)
		//IL_0144: Unknown result type (might be due to invalid IL or missing references)
		//IL_014e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0153: Unknown result type (might be due to invalid IL or missing references)
		//IL_0158: Unknown result type (might be due to invalid IL or missing references)
		//IL_0123: Unknown result type (might be due to invalid IL or missing references)
		//IL_011a: Unknown result type (might be due to invalid IL or missing references)
		spawnPos = candidate;
		fail = GroundFail.None;
		if (!TryGetGroundPoint(candidate, out var groundPoint, out var fail2))
		{
			fail = fail2;
			return false;
		}
		Biome biomeSafe = GetBiomeSafe(groundPoint);
		if ((biomeSafe & def.Biomes) == 0)
		{
			fail = GroundFail.WrongBiome;
			return false;
		}
		bool flag = (biomeSafe & 2) > 0;
		Heightmap val = Heightmap.FindHeightmap(groundPoint);
		if ((Object)(object)val != (Object)null && val.GetOceanDepth(groundPoint) > 0.5f)
		{
			fail = GroundFail.OceanDepth;
			return false;
		}
		if ((def.Biomes & 0x20) != 0)
		{
			bool flag2 = IsAshlandsLavaByWorldGen(groundPoint);
			if (!flag2 && (Object)(object)val != (Object)null)
			{
				flag2 = val.IsLava(groundPoint, 0.4f);
			}
			if (flag2)
			{
				fail = GroundFail.Lava;
				return false;
			}
		}
		if (!def.AllowInWater && !flag && IsAreaTooWetForRiko(groundPoint, out var _, out var _))
		{
			fail = GroundFail.WaterTooDeep;
			return false;
		}
		if (groundPoint.y < def.MinAltitude || groundPoint.y > def.MaxAltitude)
		{
			fail = GroundFail.Altitude;
			return false;
		}
		Vector3 ground = groundPoint;
		if (SafeIsDedicated())
		{
			TryFindSolidBelow(groundPoint + Vector3.up * 1f, 8f, out ground);
		}
		if ((def.Biomes & 0x200) != 0 && (SafeIsDedicated() ? IsMistlandsSpawnSpaceBlocked(ground) : IsMistlandsSpawnSpaceBlocked_Local(ground)))
		{
			fail = GroundFail.MistlandsBlocked;
			return false;
		}
		if (IsBodyOverlapping(ground))
		{
			fail = GroundFail.Overlap;
			return false;
		}
		spawnPos = ground + Vector3.up * 0.03f;
		return true;
	}

	private static bool TryGetGroundPoint(Vector3 candidate, out Vector3 groundPoint, out GroundFail fail)
	{
		//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_00c8: 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_00d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fe: 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_007e: Unknown result type (might be due to invalid IL or missing references)
		//IL_007f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0089: Unknown result type (might be due to invalid IL or missing references)
		//IL_008e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0093: 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_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_0042: 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_0051: Unknown result type (might be due to invalid IL or missing references)
		//IL_0056: Unknown result type (might be due to invalid IL or missing references)
		//IL_00be: 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)
		//IL_00b4: 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_0077: Unknown result type (might be due to invalid IL or missing references)
		groundPoint = candidate;
		fail = GroundFail.None;
		if (SafeIsDedicated())
		{
			if (TryGetWorldGeneratorHeight(candidate.x, candidate.z, out var y))
			{
				groundPoint = new Vector3(candidate.x, y, candidate.z);
				RaycastHit val = default(RaycastHit);
				if (Physics.Raycast(candidate + Vector3.up * 200f, Vector3.down, ref val, 500f, SolidMask, (QueryTriggerInteraction)1))
				{
					groundPoint = ((RaycastHit)(ref val)).point;
				}
				return true;
			}
			RaycastHit val2 = default(RaycastHit);
			if (Physics.Raycast(candidate + Vector3.up * 200f, Vector3.down, ref val2, 500f, SolidMask, (QueryTriggerInteraction)1))
			{
				groundPoint = ((RaycastHit)(ref val2)).point;
				return true;
			}
			fail = GroundFail.WorldGenNoHeight;
			ThrottledNoGroundLog(candidate, fail);
			return false;
		}
		RaycastHit val3 = default(RaycastHit);
		if (!Physics.Raycast(candidate + Vector3.up * 200f, Vector3.down, ref val3, 500f, SolidMask, (QueryTriggerInteraction)1))
		{
			fail = GroundFail.RaycastNoHit;
			return false;
		}
		groundPoint = ((RaycastHit)(ref val3)).point;
		return true;
	}

	private static bool TryGetWorldGeneratorHeight(float x, float z, out float y)
	{
		y = 0f;
		try
		{
			if (WorldGenerator.instance == null)
			{
				return false;
			}
			Color val = default(Color);
			float height = WorldGenerator.instance.GetHeight(x, z, ref val);
			if (float.IsNaN(height) || float.IsInfinity(height))
			{
				return false;
			}
			y = height;
			return true;
		}
		catch
		{
			return false;
		}
	}

	private static Biome GetBiomeSafe(Vector3 pos)
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: 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_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			if (WorldGenerator.instance != null)
			{
				return WorldGenerator.instance.GetBiome(pos);
			}
		}
		catch
		{
		}
		try
		{
			return Heightmap.FindBiome(pos);
		}
		catch
		{
		}
		return (Biome)0;
	}

	private static bool IsAshlandsLavaByWorldGen(Vector3 point, float lavaValue = 0.4f)
	{
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0018: Invalid comparison between Unknown and I4
		//IL_0025: 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_003a: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			if (WorldGenerator.instance == null)
			{
				return false;
			}
			if ((int)WorldGenerator.instance.GetBiome(point) != 32)
			{
				return false;
			}
			Color val = default(Color);
			WorldGenerator.instance.GetBiomeHeight((Biome)32, point.x, point.z, ref val, false);
			return val.a > lavaValue;
		}
		catch
		{
			return false;
		}
	}

	private static void ThrottledNoGroundLog(Vector3 candidate, GroundFail fail)
	{
	}

	private static bool IsAreaTooWetForRiko(Vector3 centerGround, out float centerDepth, out int wetSideSamples)
	{
		//IL_0017: 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_002d: 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_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_005e: Unknown result type (might be due to invalid IL or missing references)
		centerDepth = 0f;
		wetSideSamples = 0;
		for (int i = 0; i < DryAreaProbeOffsets.Length; i++)
		{
			Vector2 val = DryAreaProbeOffsets[i] * 0.9f;
			float num = centerGround.x + val.x;
			float num2 = centerGround.z + val.y;
			if (!TryGetWorldGeneratorHeight(num, num2, out var y))
			{
				if (i == 0)
				{
					centerDepth = 999f;
				}
				return true;
			}
			if (!TryGetWaterSurfaceY(new Vector3(num, y, num2), out var waterY))
			{
				continue;
			}
			float num3 = waterY - y;
			if (i == 0)
			{
				centerDepth = num3;
				if (num3 > 0.08f)
				{
					return true;
				}
			}
			else if (num3 > 0.12f)
			{
				wetSideSamples++;
			}
		}
		return wetSideSamples > 1;
	}

	private static bool TryGetWaterSurfaceY(Vector3 point, out float waterY)
	{
		//IL_0056: 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_005c: Unknown result type (might be due to invalid IL or missing references)
		//IL_005d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0062: Unknown result type (might be due to invalid IL or missing references)
		//IL_009b: Unknown result type (might be due to invalid IL or missing references)
		waterY = 0f;
		List<WaterVolume> instances = WaterVolume.Instances;
		if (instances == null || instances.Count == 0)
		{
			return false;
		}
		WaterVolume val = null;
		float num = float.MaxValue;
		for (int i = 0; i < instances.Count; i++)
		{
			WaterVolume val2 = instances[i];
			if ((Object)(object)val2 == (Object)null)
			{
				continue;
			}
			Collider val3 = null;
			try
			{
				val3 = ((Component)val2).GetComponent<Collider>();
			}
			catch
			{
			}
			if ((Object)(object)val3 == (Object)null)
			{
				continue;
			}
			Vector3 val4 = val3.ClosestPoint(point) - point;
			float sqrMagnitude = ((Vector3)(ref val4)).sqrMagnitude;
			if (sqrMagnitude < num)
			{
				num = sqrMagnitude;
				val = val2;
				if (num <= 1E-06f)
				{
					break;
				}
			}
		}
		if ((Object)(object)val == (Object)null)
		{
			return false;
		}
		try
		{
			waterY = val.GetWaterSurface(point, 1f);
			return true;
		}
		catch
		{
			return false;
		}
	}

	private static bool IsMistlandsSpawnSpaceBlocked(Vector3 groundPoint)
	{
		//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_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: 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_002b: 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_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_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_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_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_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_00c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_00e6: Unknown result type (might be due to invalid IL or missing references)
		Vector3 val = groundPoint + Vector3.up * 0.15f;
		Vector3 val2 = val + Vector3.up * 2.2f;
		if (!Physics.CheckCapsule(val, val2, 0.45f, SolidMask, (QueryTriggerInteraction)1))
		{
			return false;
		}
		Vector3[] array = (Vector3[])(object)new Vector3[5]
		{
			Vector3.zero,
			new Vector3(0.45f, 0f, 0f),
			new Vector3(-0.45f, 0f, 0f),
			new Vector3(0f, 0f, 0.45f),
			new Vector3(0f, 0f, -0.45f)
		};
		int num = 0;
		for (int i = 0; i < array.Length; i++)
		{
			Vector3 val3 = val + array[i];
			Vector3 val4 = val2 + array[i];
			if (Physics.CheckCapsule(val3, val4, 0.45f, SolidMask, (QueryTriggerInteraction)1))
			{
				num++;
			}
		}
		return num >= 3;
	}

	private static bool IsMistlandsSpawnSpaceBlocked_Local(Vector3 groundPoint)
	{
		//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_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: 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_002b: 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_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_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_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_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_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_00c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_00e6: Unknown result type (might be due to invalid IL or missing references)
		Vector3 val = groundPoint + Vector3.up * 0.2f;
		Vector3 val2 = val + Vector3.up * 1.85f;
		if (!Physics.CheckCapsule(val, val2, 0.3f, SolidMask, (QueryTriggerInteraction)1))
		{
			return false;
		}
		Vector3[] array = (Vector3[])(object)new Vector3[5]
		{
			Vector3.zero,
			new Vector3(0.3f, 0f, 0f),
			new Vector3(-0.3f, 0f, 0f),
			new Vector3(0f, 0f, 0.3f),
			new Vector3(0f, 0f, -0.3f)
		};
		int num = 0;
		for (int i = 0; i < array.Length; i++)
		{
			Vector3 val3 = val + array[i];
			Vector3 val4 = val2 + array[i];
			if (Physics.CheckCapsule(val3, val4, 0.3f, SolidMask, (QueryTriggerInteraction)1))
			{
				num++;
			}
		}
		return num >= 5;
	}

	private static bool HasAnyKnownRikoInWorld()
	{
		if (LoadedRikos.Count > 0)
		{
			return true;
		}
		foreach (KeyValuePair<string, int> worldCount in WorldCounts)
		{
			if (worldCount.Value > 0)
			{
				return true;
			}
		}
		return false;
	}

	private static void EnsureWorldCounts_Cached(bool initial)
	{
		float time = Time.time;
		if (!WorldCountCacheInitialized)
		{
			RescanWorldCounts_GlobalZdo("init");
			WorldCountCacheInitialized = true;
			NextWorldCountRescanTime = time + 90f;
		}
		else if (!initial && !(time < NextWorldCountRescanTime))
		{
			RescanWorldCounts_GlobalZdo("timer");
			NextWorldCountRescanTime = time + 90f;
		}
	}

	private static void RescanWorldCounts_GlobalZdo(string reason)
	{
		WorldCounts.Clear();
		if (ZDOMan.instance == null)
		{
			return;
		}
		int num = 0;
		int num2 = 0;
		for (int i = 0; i < Defs.Length; i++)
		{
			LivingContainerDef livingContainerDef = Defs[i];
			if (livingContainerDef == null || string.IsNullOrEmpty(livingContainerDef.Prefab))
			{
				continue;
			}
			int num3 = 0;
			PurgeZdos.Clear();
			bool flag = false;
			int num4 = 0;
			try
			{
				while (!flag && num4 < 10000)
				{
					flag = ZDOMan.instance.GetAllZDOsWithPrefabIterative(livingContainerDef.Prefab, PurgeZdos, ref num3);
					num4++;
				}
			}
			catch
			{
				EnsureWorldCounts_LoadedFallback();
				PurgeZdos.Clear();
				LogPerf("WorldCounts RESCAN_FALLBACK reason=" + reason + " note=iterativeFailed");
				return;
			}
			int num5 = 0;
			for (int j = 0; j < PurgeZdos.Count; j++)
			{
				ZDO val = PurgeZdos[j];
				if (val != null)
				{
					int num6 = 0;
					try
					{
						num6 = val.GetInt("MS_Riko_Killed", 0);
					}
					catch
					{
					}
					if (num6 != 1)
					{
						num5++;
					}
				}
			}
			WorldCounts[livingContainerDef.Prefab] = num5;
			num++;
			num2 += PurgeZdos.Count;
		}
		PurgeZdos.Clear();
		LogPerf($"WorldCounts RESCAN_OK reason={reason} prefabs={num} scannedZdos={num2}");
	}

	private static void EnsureWorldCounts_LoadedFallback()
	{
		WorldCounts.Clear();
		foreach (KeyValuePair<ZDOID, ZNetView> loadedRiko in LoadedRikos)
		{
			ZNetView value = loadedRiko.Value;
			if ((Object)(object)value == (Object)null || !value.IsValid())
			{
				continue;
			}
			string prefabName = Utils.GetPrefabName(((Object)((Component)value).gameObject).name);
			if (!DefByPrefab.ContainsKey(prefabName))
			{
				continue;
			}
			ZDO val = null;
			try
			{
				val = value.GetZDO();
			}
			catch
			{
			}
			if (val != null)
			{
				int num = 0;
				try
				{
					num = val.GetInt("MS_Riko_Killed", 0);
				}
				catch
				{
				}
				if (num == 1)
				{
					continue;
				}
			}
			WorldCounts[prefabName] = ((!WorldCounts.TryGetValue(prefabName, out var value2)) ? 1 : (value2 + 1));
		}
	}

	private static int GetAuthoritativeAliveCountForPrefab(string prefabName)
	{
		if (string.IsNullOrEmpty(prefabName))
		{
			return 0;
		}
		int value;
		int num = (WorldCounts.TryGetValue(prefabName, out value) ? value : 0);
		if (ZDOMan.instance == null)
		{
			return num;
		}
		float time = Time.time;
		if (NextAuthoritativeCountCheckTime.TryGetValue(prefabName, out var value2) && time < value2)
		{
			return num;
		}
		int num2 = 0;
		PurgeZdos.Clear();
		bool flag = false;
		int num3 = 0;
		try
		{
			while (!flag && num3 < 10000)
			{
				flag = ZDOMan.instance.GetAllZDOsWithPrefabIterative(prefabName, PurgeZdos, ref num2);
				num3++;
			}
		}
		catch
		{
			NextAuthoritativeCountCheckTime[prefabName] = time + 20f;
			int num4 = num;
			LogPerf($"WorldCounts AUTHORITATIVE_FALLBACK prefab={prefabName} cached={num4} note=iterativeFailed");
			PurgeZdos.Clear();
			return num4;
		}
		int num5 = 0;
		for (int i = 0; i < PurgeZdos.Count; i++)
		{
			ZDO val = PurgeZdos[i];
			if (val != null)
			{
				int num6 = 0;
				try
				{
					num6 = val.GetInt("MS_Riko_Killed", 0);
				}
				catch
				{
				}
				if (num6 != 1)
				{
					num5++;
				}
			}
		}
		PurgeZdos.Clear();
		WorldCounts[prefabName] = num5;
		NextAuthoritativeCountCheckTime[prefabName] = time + 20f;
		LogPerf($"WorldCounts AUTHORITATIVE prefab={prefabName} count={num5}");
		return num5;
	}

	private static void SweepRegistryInvalidEntriesIfNeeded()
	{
		//IL_007e: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
		LoadedRegistryInvalidSweeps++;
		if (LoadedRegistryInvalidSweeps < 10)
		{
			return;
		}
		LoadedRegistryInvalidSweeps = 0;
		if (LoadedRikos.Count == 0)
		{
			return;
		}
		if (_registrySweepKeys == null)
		{
			_registrySweepKeys = new List<ZDOID>(128);
		}
		_registrySweepKeys.Clear();
		foreach (KeyValuePair<ZDOID, ZNetView> loadedRiko in LoadedRikos)
		{
			ZNetView value = loadedRiko.Value;
			if ((Object)(object)value == (Object)null || !value.IsValid())
			{
				_registrySweepKeys.Add(loadedRiko.Key);
			}
		}
		for (int i = 0; i < _registrySweepKeys.Count; i++)
		{
			LoadedRikos.Remove(_registrySweepKeys[i]);
		}
		if (_registrySweepKeys.Count > 0)
		{
			LogPerf($"registry SWEEP removed={_registrySweepKeys.Count} remaining={LoadedRikos.Count}");
		}
	}

	private static void UpdateLastSeenForLoadedRikos()
	{
		//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fa: 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)
		float time = Time.time;
		if (time < NextSeenUpdateTime)
		{
			return;
		}
		NextSeenUpdateTime = time + 12f;
		if (LoadedRikos.Count == 0 || OriginPositions.Count == 0)
		{
			return;
		}
		float num = 14400f;
		long nowSeconds = GetNowSeconds();
		SweepRegistryInvalidEntriesIfNeeded();
		foreach (KeyValuePair<ZDOID, ZNetView> loadedRiko in LoadedRikos)
		{
			ZNetView value = loadedRiko.Value;
			if ((Object)(object)value == (Object)null || !value.IsValid())
			{
				continue;
			}
			string prefabName = Utils.GetPrefabName(((Object)((Component)value).gameObject).name);
			if (!DefByPrefab.ContainsKey(prefabName))
			{
				continue;
			}
			ZDO val = null;
			try
			{
				val = value.GetZDO();
			}
			catch
			{
			}
			if (val != null)
			{
				int num2 = 0;
				try
				{
					num2 = val.GetInt("MS_Riko_Killed", 0);
				}
				catch
				{
				}
				if (num2 == 1)
				{
					continue;
				}
			}
			Vector3 position = ((Component)value).transform.position;
			bool flag = false;
			for (int i = 0; i < OriginPositions.Count; i++)
			{
				Vector3 val2 = OriginPositions[i] - position;
				if (((Vector3)(ref val2)).sqrMagnitude <= num)
				{
					flag = true;
					break;
				}
			}
			if (!flag)
			{
				continue;
			}
			try
			{
				if (val != null)
				{
					val.Set("MS_Riko_LastSeenTime", nowSeconds);
				}
			}
			catch
			{
			}
		}
		LogPerf($"SeenUpdate tick interval={12f:0.0} loaded={LoadedRikos.Count} origins={OriginPositions.Count}");
	}

	private static void TryDestroyKilledRikoFromZdo(ZDO zdo, string prefabName, long nowS, string reason)
	{
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		if (zdo == null || string.IsNullOrEmpty(prefabName))
		{
			return;
		}
		long num = 0L;
		try
		{
			num = zdo.GetLong("MS_Riko_DestroyAt", 0L);
		}
		catch
		{
		}
		if (num <= 0)
		{
			num = nowS;
		}
		if (nowS < num)
		{
			return;
		}
		GameObject val = null;
		try
		{
			if ((Object)(object)ZNetScene.instance != (Object)null)
			{
				val = ZNetScene.instance.FindInstance(zdo.m_uid);
			}
		}
		catch
		{
			val = null;
		}
		if ((Object)(object)val != (Object)null)
		{
			ZNetView val2 = null;
			try
			{
				val2 = val.GetComponent<ZNetView>();
			}
			catch
			{
			}
			if ((Object)(object)val2 != (Object)null && val2.IsValid())
			{
				DestroyKilledLoadedRiko(val2, prefabName, reason, playFx: false);
				return;
			}
		}
		ForceDestroyZDO_AndEnqueue(zdo, prefabName, reason + " notLoaded");
	}

	private static void ProcessLoadedDestroyDueFast()
	{
		float time = Time.time;
		if (time < NextLoadedDestroyCheckTime)
		{
			return;
		}
		NextLoadedDestroyCheckTime = time + 0.2f;
		if (LoadedRikos.Count == 0)
		{
			return;
		}
		long nowSeconds = GetNowSeconds();
		SweepRegistryInvalidEntriesIfNeeded();
		foreach (KeyValuePair<ZDOID, ZNetView> loadedRiko in LoadedRikos)
		{
			ZNetView value = loadedRiko.Value;
			if ((Object)(object)value == (Object)null || !value.IsValid())
			{
				continue;
			}
			ZDO val = null;
			try
			{
				val = value.GetZDO();
			}
			catch
			{
			}
			if (val == null)
			{
				continue;
			}
			int num = 0;
			long num2 = 0L;
			try
			{
				num = val.GetInt("MS_Riko_Killed", 0);
			}
			catch
			{
			}
			if (num != 1)
			{
				continue;
			}
			try
			{
				num2 = val.GetLong("MS_Riko_DestroyAt", 0L);
			}
			catch
			{
			}
			if (num2 <= 0)
			{
				num2 = nowSeconds;
			}
			if (nowSeconds >= num2)
			{
				string prefabName = Utils.GetPrefabName(((Object)((Component)value).gameObject).name);
				if (DefByPrefab.ContainsKey(prefabName))
				{
					DestroyKilledLoadedRiko(value, prefabName, "LoadedFastDue", playFx: false);
				}
			}
		}
	}

	private static void ProcessScheduledDestroyForLoadedRikos()
	{
		float time = Time.time;
		if (time < NextDestroyScanTime)
		{
			return;
		}
		NextDestroyScanTime = time + 20f;
		if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer() || ZDOMan.instance == null || LoadedRikos.Count == 0)
		{
			return;
		}
		long nowSeconds = GetNowSeconds();
		int num = 0;
		int num2 = 0;
		int num3 = 0;
		for (int i = 0; i < Defs.Length; i++)
		{
			LivingContainerDef livingContainerDef = Defs[i];
			if (livingContainerDef == null || string.IsNullOrEmpty(livingContainerDef.Prefab))
			{
				continue;
			}
			int num4 = 0;
			PurgeZdos.Clear();
			bool flag = false;
			int num5 = 0;
			try
			{
				while (!flag && num5 < 10000)
				{
					flag = ZDOMan.instance.GetAllZDOsWithPrefabIterative(livingContainerDef.Prefab, PurgeZdos, ref num4);
					num5++;
				}
			}
			catch
			{
				PurgeZdos.Clear();
				continue;
			}
			num++;
			num2 += PurgeZdos.Count;
			for (int j = 0; j < PurgeZdos.Count; j++)
			{
				ZDO val = PurgeZdos[j];
				if (val == null)
				{
					continue;
				}
				int num6 = 0;
				try
				{
					num6 = val.GetInt("MS_Riko_Killed", 0);
				}
				catch
				{
				}
				if (num6 == 1)
				{
					long num7 = 0L;
					try
					{
						num7 = val.GetLong("MS_Riko_DestroyAt", 0L);
					}
					catch
					{
					}
					if (num7 <= 0)
					{
						num7 = nowSeconds;
					}
					if (nowSeconds >= num7)
					{
						num3++;
						TryDestroyKilledRikoFromZdo(val, livingContainerDef.Prefab, nowSeconds, "ScheduledDestroy due");
					}
				}
			}
			PurgeZdos.Clear();
		}
		LogPerf($"DestroyScan tick interval={20f:0.0} " + $"prefabs={num} scannedZdos={num2} dueKilled={num3}");
	}

	private static void TryRunEmptyWatcher_Server()
	{
		//IL_0213: Unknown result type (might be due to invalid IL or missing references)
		if (!LivingContainerConfig.IsRikoEnabled() || (Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer() || ZDOMan.instance == null || (!_emptyWatcherInProgress && !HasAnyKnownRikoInWorld()))
		{
			return;
		}
		float time = Time.time;
		if (!_emptyWatcherInProgress && time < _emptyWatcherNextRunTime)
		{
			return;
		}
		CleanupItemsCacheIfNeeded();
		EnsureZdoVarHashes();
		BuildDefCache();
		if (!_emptyWatcherInProgress)
		{
			_emptyWatcherInProgress = true;
			_emptyWatcherPrefabIndex = 0;
			_emptyWatcherSectorIndex = 0;
			_emptyWatcherZdos.Clear();
			_emptyWatcherNextRunTime = time + 30f;
		}
		string text = null;
		while (_emptyWatcherPrefabIndex < Defs.Length)
		{
			LivingContainerDef livingContainerDef = Defs[_emptyWatcherPrefabIndex];
			if (livingContainerDef != null && !string.IsNullOrEmpty(livingContainerDef.Prefab))
			{
				text = livingContainerDef.Prefab;
				break;
			}
			_emptyWatcherPrefabIndex++;
		}
		if (text == null)
		{
			_emptyWatcherInProgress = false;
			return;
		}
		bool allZDOsWithPrefabIterative;
		try
		{
			allZDOsWithPrefabIterative = ZDOMan.instance.GetAllZDOsWithPrefabIterative(text, _emptyWatcherZdos, ref _emptyWatcherSectorIndex);
		}
		catch
		{
			_emptyWatcherInProgress = false;
			_emptyWatcherZdos.Clear();
			return;
		}
		if (!allZDOsWithPrefabIterative)
		{
			return;
		}
		int num = 0;
		int num2 = 0;
		int num3 = 0;
		int num4 = 0;
		int num5 = 0;
		int num6 = 0;
		int num7 = 0;
		long nowSeconds = GetNowSeconds();
		LivingContainerDef value;
		bool flag = DefByPrefab.TryGetValue(text, out value);