Decompiled source of Magic Supremacy v3.1.1

plugins/Magic_Supremacy.dll

Decompiled a day 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 AzuEPI;
using AzuEPI.Core.Slots;
using AzuExtendedPlayerInventory;
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.Audio;
using UnityEngine.Events;
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("3.1.1")]
[assembly: Guid("4358610B-F3F4-4843-B7AF-98B7BC60DCDE")]
[assembly: ComVisible(false)]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCopyright("Copyright ©  2021")]
[assembly: AssemblyProduct("Magic_Supremacy")]
[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: AssemblyCompany("Dreanegade")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("3.1.1.0")]
[module: <381866ae-969f-47df-8883-468dae25f647>RefSafetyRules(11)]
[module: UnverifiableCode]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[<beb3d20d-b65b-4e5e-9dae-b5332544c623>Embedded]
	internal sealed class <beb3d20d-b65b-4e5e-9dae-b5332544c623>EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[<beb3d20d-b65b-4e5e-9dae-b5332544c623>Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class <5659c901-bae2-435e-a01b-19ba0d7edac2>NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public <5659c901-bae2-435e-a01b-19ba0d7edac2>NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public <5659c901-bae2-435e-a01b-19ba0d7edac2>NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[<beb3d20d-b65b-4e5e-9dae-b5332544c623>Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class <7ff4dd61-fbb9-4f30-85a4-9da04aa89218>NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public <7ff4dd61-fbb9-4f30-85a4-9da04aa89218>NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	[CompilerGenerated]
	[<beb3d20d-b65b-4e5e-9dae-b5332544c623>Embedded]
	internal sealed class <381866ae-969f-47df-8883-468dae25f647>RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public <381866ae-969f-47df-8883-468dae25f647>RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
[<7ff4dd61-fbb9-4f30-85a4-9da04aa89218>NullableContext(1)]
[<5659c901-bae2-435e-a01b-19ba0d7edac2>Nullable(0)]
public static class ExtraTooltip
{
	[<7ff4dd61-fbb9-4f30-85a4-9da04aa89218>NullableContext(0)]
	private static class DevLog
	{
		public const bool Enabled = false;
	}

	[<7ff4dd61-fbb9-4f30-85a4-9da04aa89218>NullableContext(0)]
	public enum TooltipAttackSlot
	{
		Main,
		Secondary
	}

	[<5659c901-bae2-435e-a01b-19ba0d7edac2>Nullable(0)]
	private class TooltipLinkDef
	{
		public readonly string ItemPrefabName;

		public readonly TooltipAttackSlot AttackSlot;

		public readonly List<TooltipEntry> Entries;

		public TooltipLinkDef(string itemPrefabName, TooltipAttackSlot attackSlot, string statusEffectPrefabName)
		{
			ItemPrefabName = itemPrefabName;
			AttackSlot = attackSlot;
			Entries = new List<TooltipEntry>
			{
				new TooltipSELine(statusEffectPrefabName)
			};
		}

		public TooltipLinkDef(string itemPrefabName, TooltipAttackSlot attackSlot, params TooltipEntry[] entries)
		{
			ItemPrefabName = itemPrefabName;
			AttackSlot = attackSlot;
			Entries = new List<TooltipEntry>(entries);
		}
	}

	[<7ff4dd61-fbb9-4f30-85a4-9da04aa89218>NullableContext(0)]
	private abstract class TooltipEntry
	{
		[<7ff4dd61-fbb9-4f30-85a4-9da04aa89218>NullableContext(1)]
		public abstract string Build(string itemPrefabName, int qualityLevel, float skillLevel);
	}

	[<5659c901-bae2-435e-a01b-19ba0d7edac2>Nullable(0)]
	private class TooltipSELine : TooltipEntry
	{
		private readonly string StatusEffectPrefabName;

		public TooltipSELine(string statusEffectPrefabName)
		{
			StatusEffectPrefabName = statusEffectPrefabName;
		}

		public override string Build(string itemPrefabName, int qualityLevel, float skillLevel)
		{
			StatusEffect val = FindStatusEffect(StatusEffectPrefabName);
			if ((Object)(object)val == (Object)null)
			{
				DLog("StatusEffect not found: " + StatusEffectPrefabName + " for item " + itemPrefabName + ".");
				return "";
			}
			string text = BuildVanillaStatusEffectTooltip(val, qualityLevel, skillLevel);
			if (string.IsNullOrEmpty(text))
			{
				DLog("Tooltip skipped for " + itemPrefabName + ": empty tooltip from " + StatusEffectPrefabName + ".");
				return "";
			}
			return text;
		}
	}

	[<5659c901-bae2-435e-a01b-19ba0d7edac2>Nullable(0)]
	private class TooltipTextLine : TooltipEntry
	{
		private readonly string TextKeyOrText;

		private readonly string Color;

		public TooltipTextLine(string textKeyOrText, string color = null)
		{
			TextKeyOrText = textKeyOrText;
			Color = color;
		}

		public override string Build(string itemPrefabName, int qualityLevel, float skillLevel)
		{
			return Colorize(Localize(TextKeyOrText), Color);
		}
	}

	[<5659c901-bae2-435e-a01b-19ba0d7edac2>Nullable(0)]
	private class TooltipInlineLine : TooltipEntry
	{
		private readonly List<TooltipInlinePart> Parts;

		public TooltipInlineLine(params TooltipInlinePart[] parts)
		{
			Parts = new List<TooltipInlinePart>(parts);
		}

		public override string Build(string itemPrefabName, int qualityLevel, float skillLevel)
		{
			StringBuilder stringBuilder = new StringBuilder();
			foreach (TooltipInlinePart part in Parts)
			{
				if (part != null)
				{
					stringBuilder.Append(part.Build());
				}
			}
			return stringBuilder.ToString();
		}
	}

	[<5659c901-bae2-435e-a01b-19ba0d7edac2>Nullable(0)]
	private class TooltipInlinePart
	{
		private readonly string TextKeyOrText;

		private readonly string Color;

		public TooltipInlinePart(string textKeyOrText, string color = null)
		{
			TextKeyOrText = textKeyOrText;
			Color = color;
		}

		public string Build()
		{
			return Colorize(Localize(TextKeyOrText), Color);
		}
	}

	[HarmonyPatch(typeof(ItemData), "GetTooltip", new Type[]
	{
		typeof(ItemData),
		typeof(int),
		typeof(bool),
		typeof(float),
		typeof(int),
		typeof(bool)
	})]
	[<7ff4dd61-fbb9-4f30-85a4-9da04aa89218>NullableContext(0)]
	private static class ItemData_GetTooltip_ExtraTooltipPatch
	{
		[<7ff4dd61-fbb9-4f30-85a4-9da04aa89218>NullableContext(1)]
		private static void Postfix(ItemData item, int qualityLevel, bool crafting, float worldLevel, int stackOverride, bool appending, ref string __result)
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (item == null || item.m_shared == null)
				{
					return;
				}
				string itemPrefabName = GetItemPrefabName(item);
				if (string.IsNullOrEmpty(itemPrefabName))
				{
					return;
				}
				List<TooltipLinkDef> defsForItem = GetDefsForItem(itemPrefabName);
				if (defsForItem.Count != 0)
				{
					float skillLevel = 0f;
					if ((Object)(object)Player.m_localPlayer != (Object)null)
					{
						skillLevel = ((Character)Player.m_localPlayer).GetSkillLevel(item.m_shared.m_skillType);
					}
					StringBuilder stringBuilder = new StringBuilder();
					AppendEntriesForSlot(stringBuilder, defsForItem, TooltipAttackSlot.Main, qualityLevel, skillLevel);
					AppendEntriesForSlot(stringBuilder, defsForItem, TooltipAttackSlot.Secondary, qualityLevel, skillLevel);
					if (stringBuilder.Length <= 0)
					{
						DLog("Tooltip skipped for " + itemPrefabName + ": no valid extra tooltip was generated.");
						return;
					}
					__result = __result + "\n\n" + stringBuilder.ToString().TrimEnd(Array.Empty<char>());
					DLog("Extra tooltip added for " + itemPrefabName + ".");
				}
			}
			catch (Exception arg)
			{
				DLog($"ERROR while adding extra tooltip: {arg}");
			}
		}
	}

	private const string MainAttackHeaderColor = "#FFC654";

	private const string SecondaryAttackHeaderColor = "#FFC654";

	private const string VanillaSENameColor = "orange";

	private const string HealValueColor = "#C8FF6A";

	private const string MainAttackKey = "$main_attack_DO";

	private const string SecondaryAttackKey = "$secondary_attack_DO";

	private static readonly List<TooltipLinkDef> Defs = new List<TooltipLinkDef>
	{
		new TooltipLinkDef("StaffTotemcallerTotem_DO", TooltipAttackSlot.Main, "SE_TotemcallerSlow_DO"),
		new TooltipLinkDef("StaffTotemcallerTotem_DO", TooltipAttackSlot.Secondary, "SE_TotemcallerBuff_DO"),
		new TooltipLinkDef("StaffTotemcallerBoomerang_DO", TooltipAttackSlot.Secondary, "SE_TotemcallerOrbit_DO"),
		new TooltipLinkDef("StaffMushroomcallerMushroom_DO", TooltipAttackSlot.Main, new TooltipTextLine("$aoe_trap_damage_DO"), new TooltipTextLine(" "), new TooltipSELine("SE_MushroomcallerSlow_DO")),
		new TooltipLinkDef("StaffMushroomcallerMushroom_DO", TooltipAttackSlot.Secondary, new TooltipTextLine("$aoe_area_light_DO")),
		new TooltipLinkDef("StaffDeathcallerBlaster_DO", TooltipAttackSlot.Secondary, "SE_DeathcallerDebuff_DO"),
		new TooltipLinkDef("BowFrostcallerIce_DO", TooltipAttackSlot.Secondary, new TooltipTextLine("$aoe_trap_damage_DO"), new TooltipTextLine("$aoe_area_debuff_DO"), new TooltipTextLine(" "), new TooltipSELine("SE_FrostcallerAura_DO")),
		new TooltipLinkDef("StaffFrostcallerShotgun_DO", TooltipAttackSlot.Secondary, new TooltipTextLine("$aoe_area_spawn_DO"), new TooltipTextLine("$aoe_area_obstacle_DO")),
		new TooltipLinkDef("StaffFirecallerRing_DO", TooltipAttackSlot.Secondary, "SE_FirecallerOrbit_DO"),
		new TooltipLinkDef("StaffStonecallerBurst_DO", TooltipAttackSlot.Secondary, new TooltipTextLine("$aoe_area_obstacle_DO")),
		new TooltipLinkDef("StaffWindcallerBuff_DO", TooltipAttackSlot.Main, "SE_WindcallerShield_DO"),
		new TooltipLinkDef("StaffWindcallerBuff_DO", TooltipAttackSlot.Secondary, "SE_WindcallerPetal_DO"),
		new TooltipLinkDef("StaffLightcallerHeal_DO", TooltipAttackSlot.Main, new TooltipTextLine("$aoe_trap_heal_DO"), new TooltipInlineLine(new TooltipInlinePart("$heal_DO"), new TooltipInlinePart(": "), new TooltipInlinePart("40", "orange"))),
		new TooltipLinkDef("StaffLightcallerHeal_DO", TooltipAttackSlot.Secondary, "SE_LightcallerHeal_DO"),
		new TooltipLinkDef("StaffLightcallerSphere_DO", TooltipAttackSlot.Secondary, new TooltipTextLine("$aoe_area_light_DO"), new TooltipTextLine("$aoe_area_damage_DO")),
		new TooltipLinkDef("StaffStormcallerSphere_DO", TooltipAttackSlot.Secondary, new TooltipTextLine("$aoe_trap_damage_DO")),
		new TooltipLinkDef("StaffStormcallerShocker_DO", TooltipAttackSlot.Secondary, "SE_StormcallerOrbit_DO"),
		new TooltipLinkDef("StaffBloodcallerHeal_DO", TooltipAttackSlot.Main, "SE_BloodcallerHeal_DO"),
		new TooltipLinkDef("StaffBloodcallerHeal_DO", TooltipAttackSlot.Secondary, "SE_BloodcallerBuff_DO"),
		new TooltipLinkDef("StaffBloodcallerShotgun_DO", TooltipAttackSlot.Secondary, new TooltipTextLine("$aoe_area_damage_DO"), new TooltipTextLine(" "), new TooltipTextLine("$aoe_area_debuff_DO"), new TooltipTextLine(" "), new TooltipSELine("SE_BloodcallerDebuff_DO"))
	};

	private static void AppendEntriesForSlot(StringBuilder sb, List<TooltipLinkDef> itemDefs, TooltipAttackSlot slot, int qualityLevel, float skillLevel)
	{
		bool flag = false;
		foreach (TooltipLinkDef itemDef in itemDefs)
		{
			if (itemDef.AttackSlot != slot)
			{
				continue;
			}
			string value = BuildDefTooltip(itemDef, qualityLevel, skillLevel);
			if (string.IsNullOrEmpty(value))
			{
				continue;
			}
			if (!flag)
			{
				if (sb.Length > 0)
				{
					sb.Append("\n\n");
				}
				sb.Append(GetAttackHeader(slot));
				sb.Append("\n");
				flag = true;
			}
			else
			{
				sb.Append("\n\n");
			}
			sb.Append(value);
		}
	}

	private static string BuildDefTooltip(TooltipLinkDef def, int qualityLevel, float skillLevel)
	{
		if (def == null || def.Entries == null || def.Entries.Count == 0)
		{
			return "";
		}
		StringBuilder stringBuilder = new StringBuilder();
		foreach (TooltipEntry entry in def.Entries)
		{
			if (entry == null)
			{
				continue;
			}
			string value = entry.Build(def.ItemPrefabName, qualityLevel, skillLevel);
			if (!string.IsNullOrEmpty(value))
			{
				if (stringBuilder.Length > 0)
				{
					stringBuilder.Append("\n");
				}
				stringBuilder.Append(value);
			}
		}
		return stringBuilder.ToString();
	}

	private static string BuildVanillaStatusEffectTooltip(StatusEffect statusEffect, int qualityLevel, float skillLevel)
	{
		if ((Object)(object)statusEffect == (Object)null)
		{
			return "";
		}
		statusEffect.SetLevel(qualityLevel, skillLevel);
		return "<color=orange>" + statusEffect.m_name + "</color>\n" + statusEffect.GetTooltipString();
	}

	private static string GetAttackHeader(TooltipAttackSlot slot)
	{
		return slot switch
		{
			TooltipAttackSlot.Main => Colorize(Localize("$main_attack_DO"), "#FFC654"), 
			TooltipAttackSlot.Secondary => Colorize(Localize("$secondary_attack_DO"), "#FFC654"), 
			_ => "", 
		};
	}

	private static string Colorize(string text, string color)
	{
		if (string.IsNullOrEmpty(text))
		{
			return "";
		}
		if (string.IsNullOrEmpty(color))
		{
			return text;
		}
		return "<color=" + color + ">" + text + "</color>";
	}

	private static string Localize(string keyOrText)
	{
		if (string.IsNullOrEmpty(keyOrText))
		{
			return "";
		}
		if (Localization.instance == null)
		{
			return keyOrText;
		}
		if (keyOrText.StartsWith("$"))
		{
			return Localization.instance.Localize(keyOrText);
		}
		return keyOrText;
	}

	private static List<TooltipLinkDef> GetDefsForItem(string itemPrefabName)
	{
		List<TooltipLinkDef> list = new List<TooltipLinkDef>();
		foreach (TooltipLinkDef def in Defs)
		{
			if (def.ItemPrefabName == itemPrefabName)
			{
				list.Add(def);
			}
		}
		return list;
	}

	private static StatusEffect FindStatusEffect(string statusEffectPrefabName)
	{
		if ((Object)(object)ObjectDB.instance == (Object)null)
		{
			return null;
		}
		foreach (StatusEffect statusEffect in ObjectDB.instance.m_StatusEffects)
		{
			if (!((Object)(object)statusEffect == (Object)null))
			{
				if (((Object)statusEffect).name == statusEffectPrefabName)
				{
					return statusEffect;
				}
				if (Utils.GetPrefabName(((Object)statusEffect).name) == statusEffectPrefabName)
				{
					return statusEffect;
				}
			}
		}
		return null;
	}

	private static string GetItemPrefabName(ItemData item)
	{
		if (item == null)
		{
			return "";
		}
		if ((Object)(object)item.m_dropPrefab != (Object)null)
		{
			return Utils.GetPrefabName(((Object)item.m_dropPrefab).name);
		}
		if (item.m_shared != null && !string.IsNullOrEmpty(item.m_shared.m_name))
		{
			GameObject val = (((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetItemPrefab(item.m_shared.m_name) : null);
			if ((Object)(object)val != (Object)null)
			{
				return Utils.GetPrefabName(((Object)val).name);
			}
		}
		return "";
	}

	private static void DLog(string message)
	{
	}
}
[<7ff4dd61-fbb9-4f30-85a4-9da04aa89218>NullableContext(1)]
[<5659c901-bae2-435e-a01b-19ba0d7edac2>Nullable(0)]
public static class TooltipColor
{
	[<5659c901-bae2-435e-a01b-19ba0d7edac2>Nullable(0)]
	private class StatusEffectTextColorDef
	{
		public readonly string StatusEffectPrefabName;

		public readonly string TooltipColor;

		public StatusEffectTextColorDef(string statusEffectPrefabName, string tooltipColor)
		{
			StatusEffectPrefabName = statusEffectPrefabName;
			TooltipColor = tooltipColor;
		}
	}

	[HarmonyPatch(typeof(SE_Stats), "GetTooltipString")]
	[<7ff4dd61-fbb9-4f30-85a4-9da04aa89218>NullableContext(0)]
	private static class SE_Stats_GetTooltipString_TooltipColorPatch
	{
		[<7ff4dd61-fbb9-4f30-85a4-9da04aa89218>NullableContext(1)]
		private static void Postfix(SE_Stats __instance, ref string __result)
		{
			try
			{
				if (!((Object)(object)__instance == (Object)null) && !string.IsNullOrEmpty(__result))
				{
					StatusEffectTextColorDef statusEffectTextColorDef = GetStatusEffectTextColorDef(Utils.GetPrefabName(((Object)__instance).name));
					if (statusEffectTextColorDef != null && !string.IsNullOrEmpty(statusEffectTextColorDef.TooltipColor))
					{
						ApplyTooltipDescriptionColor(__instance, statusEffectTextColorDef.TooltipColor, ref __result);
					}
				}
			}
			catch (Exception ex)
			{
				Debug.LogError((object)("[TooltipColor] ERROR: " + ex));
			}
		}
	}

	private static readonly List<StatusEffectTextColorDef> StatusEffectTextColorDefs = new List<StatusEffectTextColorDef>
	{
		new StatusEffectTextColorDef("SE_MushroomcallerArmor_DO", "#f0bdff"),
		new StatusEffectTextColorDef("SE_TotemcallerArmor_DO", "#f0bdff"),
		new StatusEffectTextColorDef("SE_DeathcallerArmor_DO", "#f0bdff"),
		new StatusEffectTextColorDef("SE_FrostcallerArmor_DO", "#f0bdff"),
		new StatusEffectTextColorDef("SE_FirecallerArmor_DO", "#f0bdff"),
		new StatusEffectTextColorDef("SE_StonecallerArmor_DO", "#f0bdff"),
		new StatusEffectTextColorDef("SE_WindcallerArmor_DO", "#f0bdff"),
		new StatusEffectTextColorDef("SE_LightcallerArmor_DO", "#f0bdff"),
		new StatusEffectTextColorDef("SE_StormcallerArmor_DO", "#f0bdff"),
		new StatusEffectTextColorDef("SE_BloodcallerArmor_DO", "#f0bdff")
	};

	private static void ApplyTooltipDescriptionColor(SE_Stats se, string color, ref string result)
	{
		if ((Object)(object)se == (Object)null || string.IsNullOrEmpty(color))
		{
			return;
		}
		string tooltip = ((StatusEffect)se).m_tooltip;
		if (!string.IsNullOrEmpty(tooltip))
		{
			if (result.StartsWith(tooltip + "\n\n"))
			{
				result = Colorize(tooltip, color) + result.Substring(tooltip.Length);
			}
			else if (result.StartsWith(tooltip + "\n"))
			{
				result = Colorize(tooltip, color) + result.Substring(tooltip.Length);
			}
			else if (result == tooltip)
			{
				result = Colorize(tooltip, color);
			}
		}
	}

	private static StatusEffectTextColorDef GetStatusEffectTextColorDef(string sePrefabName)
	{
		if (string.IsNullOrEmpty(sePrefabName))
		{
			return null;
		}
		foreach (StatusEffectTextColorDef statusEffectTextColorDef in StatusEffectTextColorDefs)
		{
			if (statusEffectTextColorDef != null && statusEffectTextColorDef.StatusEffectPrefabName == sePrefabName)
			{
				return statusEffectTextColorDef;
			}
		}
		return null;
	}

	private static string Colorize(string text, string color)
	{
		if (string.IsNullOrEmpty(text))
		{
			return "";
		}
		if (string.IsNullOrEmpty(color))
		{
			return text;
		}
		return "<color=" + color + ">" + text + "</color>";
	}
}
[<7ff4dd61-fbb9-4f30-85a4-9da04aa89218>NullableContext(1)]
[<5659c901-bae2-435e-a01b-19ba0d7edac2>Nullable(0)]
internal static class CraftingStationBaseLevel
{
	[<5659c901-bae2-435e-a01b-19ba0d7edac2>Nullable(0)]
	private sealed class StationDef
	{
		public readonly string PrefabName;

		public readonly int BaseLevel;

		public StationDef(string prefabName, int baseLevel)
		{
			PrefabName = prefabName;
			BaseLevel = baseLevel;
		}
	}

	[HarmonyPatch(typeof(CraftingStation), "GetLevel")]
	[<7ff4dd61-fbb9-4f30-85a4-9da04aa89218>NullableContext(0)]
	private static class CraftingStation_GetLevel_Patch
	{
		[<7ff4dd61-fbb9-4f30-85a4-9da04aa89218>NullableContext(1)]
		private static void Postfix(CraftingStation __instance, ref int __result)
		{
			EnsureInitialized();
			string prefabName = GetPrefabName(__instance);
			if (!string.IsNullOrEmpty(prefabName) && BaseLevels.TryGetValue(prefabName, out var value))
			{
				int extentionCount = __instance.GetExtentionCount(false);
				int val = value + extentionCount;
				int num = __result;
				__result = Math.Max(__result, val);
				if (__result != num)
				{
					Log("Level adjusted | prefab=" + prefabName + " | " + $"baseLevel={value} | " + $"extensions={extentionCount} | " + $"before={num} | " + $"after={__result}");
				}
			}
		}
	}

	private const bool LoggingEnabled = false;

	private static readonly StationDef[] Defs = new StationDef[1]
	{
		new StationDef("MagicWeaver_DO", 4)
	};

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

	private static bool _initialized;

	private static void EnsureInitialized()
	{
		if (_initialized)
		{
			return;
		}
		_initialized = true;
		StationDef[] defs = Defs;
		foreach (StationDef stationDef in defs)
		{
			if (stationDef != null && !string.IsNullOrEmpty(stationDef.PrefabName))
			{
				if (stationDef.BaseLevel < 1)
				{
					Log("Invalid def ignored | prefab=" + stationDef.PrefabName + " | " + $"baseLevel={stationDef.BaseLevel}");
					continue;
				}
				BaseLevels[stationDef.PrefabName] = stationDef.BaseLevel;
				Log("Registered | prefab=" + stationDef.PrefabName + " | " + $"baseLevel={stationDef.BaseLevel}");
			}
		}
	}

	private static string GetPrefabName(CraftingStation station)
	{
		if ((Object)(object)station == (Object)null || (Object)(object)((Component)station).gameObject == (Object)null)
		{
			return null;
		}
		string text = ((Object)((Component)station).gameObject).name;
		if (string.IsNullOrEmpty(text))
		{
			return null;
		}
		if (text.EndsWith("(Clone)", StringComparison.Ordinal))
		{
			text = text.Substring(0, text.Length - "(Clone)".Length);
		}
		return text;
	}

	private static void Log(string message)
	{
	}
}
[<7ff4dd61-fbb9-4f30-85a4-9da04aa89218>NullableContext(1)]
[<5659c901-bae2-435e-a01b-19ba0d7edac2>Nullable(0)]
internal sealed class ConfigurationManagerAttributes
{
	[<7ff4dd61-fbb9-4f30-85a4-9da04aa89218>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;
}
[<7ff4dd61-fbb9-4f30-85a4-9da04aa89218>NullableContext(1)]
[<5659c901-bae2-435e-a01b-19ba0d7edac2>Nullable(0)]
public static class ExtraStats
{
	[<7ff4dd61-fbb9-4f30-85a4-9da04aa89218>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;
	}

	[<7ff4dd61-fbb9-4f30-85a4-9da04aa89218>NullableContext(0)]
	public enum ExtraStatType
	{
		Health,
		Stamina,
		Eitr,
		AttackSpeed,
		WetImmune
	}

	[<7ff4dd61-fbb9-4f30-85a4-9da04aa89218>NullableContext(0)]
	public enum ExtraSourceType
	{
		ItemDrop,
		StatusEffect
	}

	[<5659c901-bae2-435e-a01b-19ba0d7edac2>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;
		}
	}

	[<7ff4dd61-fbb9-4f30-85a4-9da04aa89218>NullableContext(0)]
	[HarmonyPatch(typeof(Player), "GetTotalFoodValue")]
	public static class Player_GetTotalFoodValue_ExtraStatsPatch
	{
		[<7ff4dd61-fbb9-4f30-85a4-9da04aa89218>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;
			}
		}
	}

	[HarmonyPatch]
	[<5659c901-bae2-435e-a01b-19ba0d7edac2>Nullable(0)]
	public static class ItemData_StaticGetTooltip_ExtraStatsPatch
	{
		private static MethodBase TargetMethod()
		{
			return AccessTools.Method(typeof(ItemData), "GetTooltip", new Type[6]
			{
				typeof(ItemData),
				typeof(int),
				typeof(bool),
				typeof(float),
				typeof(int),
				typeof(bool)
			}, (Type[])null);
		}

		private static void Postfix(ItemData item, int qualityLevel, bool crafting, float worldLevel, int stackOverride, bool appending, ref string __result)
		{
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			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}, appending={appending}");
				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)
				{
					return;
				}
				string text = BuildExtraStatsTooltipBlock(extraHp, extraStamina, extraEitr, displayAttackSpeedPercent, wetImmune);
				if (string.IsNullOrEmpty(text))
				{
					return;
				}
				float num = 0f;
				if ((Object)(object)Player.m_localPlayer != (Object)null)
				{
					num = ((Character)Player.m_localPlayer).GetSkillLevel(item.m_shared.m_skillType);
				}
				string statusEffectTooltip = item.GetStatusEffectTooltip(qualityLevel, num);
				string chainTooltip = item.GetChainTooltip(qualityLevel, num);
				string setStatusEffectTooltip = item.GetSetStatusEffectTooltip(qualityLevel, num);
				int num2 = -1;
				if (!string.IsNullOrEmpty(statusEffectTooltip))
				{
					int num3 = __result.IndexOf(statusEffectTooltip, StringComparison.Ordinal);
					if (num3 >= 0)
					{
						num2 = ((num3 - 2 >= 0 && __result.Substring(num3 - 2, 2) == "\n\n") ? (num3 - 2) : num3);
					}
				}
				if (num2 < 0 && !string.IsNullOrEmpty(chainTooltip))
				{
					int num4 = __result.IndexOf(chainTooltip, StringComparison.Ordinal);
					if (num4 >= 0)
					{
						num2 = ((num4 - 2 >= 0 && __result.Substring(num4 - 2, 2) == "\n\n") ? (num4 - 2) : num4);
					}
				}
				if (num2 < 0)
				{
					int num5 = __result.IndexOf("\n$item_eitrregen_modifier:", StringComparison.Ordinal);
					if (num5 >= 0)
					{
						num2 = num5;
					}
				}
				if (num2 < 0 && !string.IsNullOrEmpty(setStatusEffectTooltip))
				{
					int num6 = __result.IndexOf("\n\n$item_seteffect", StringComparison.Ordinal);
					if (num6 >= 0)
					{
						num2 = num6;
					}
				}
				if (num2 < 0)
				{
					int num7 = __result.IndexOf("\n$item_fulladrenaline:", StringComparison.Ordinal);
					if (num7 >= 0)
					{
						num2 = num7;
					}
				}
				if (num2 >= 0)
				{
					DLogTooltip("Inserting ItemDrop extras before special/effect section for " + name);
					__result = __result.Insert(num2, text);
				}
				else
				{
					DLogTooltip("No special/effect section found, appending ItemDrop extras at end for " + name);
					__result += text;
				}
			}
			catch (Exception ex)
			{
				LogError("Exception in ItemData_StaticGetTooltip_ExtraStatsPatch: " + ex);
			}
		}
	}

	[<7ff4dd61-fbb9-4f30-85a4-9da04aa89218>NullableContext(0)]
	[HarmonyPatch(typeof(SE_Stats), "GetTooltipString")]
	public static class SE_Stats_GetTooltipString_ExtraStatsPatch
	{
		[<7ff4dd61-fbb9-4f30-85a4-9da04aa89218>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)
				{
					return;
				}
				string text = BuildExtraStatsTooltipBlock(extraHp, extraStamina, extraEitr, displayAttackSpeedPercent, wetImmune);
				if (!string.IsNullOrEmpty(text))
				{
					if (text.StartsWith("\n"))
					{
						text = text.Substring(1);
					}
					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);
			}
		}
	}

	[<7ff4dd61-fbb9-4f30-85a4-9da04aa89218>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;
	}

	[HarmonyPatch(typeof(Humanoid), "StartAttack", new Type[]
	{
		typeof(Character),
		typeof(bool)
	})]
	[<7ff4dd61-fbb9-4f30-85a4-9da04aa89218>NullableContext(0)]
	public static class Humanoid_StartAttack_AttackSpeedPatch
	{
		[HarmonyPostfix]
		[<7ff4dd61-fbb9-4f30-85a4-9da04aa89218>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})");
			}
		}
	}

	[<7ff4dd61-fbb9-4f30-85a4-9da04aa89218>NullableContext(0)]
	[HarmonyPatch(typeof(Attack), "Stop")]
	public static class Attack_Stop_AttackSpeedResetPatch
	{
		[HarmonyPostfix]
		[<7ff4dd61-fbb9-4f30-85a4-9da04aa89218>NullableContext(1)]
		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)
			{
			}
		}
	}

	[<7ff4dd61-fbb9-4f30-85a4-9da04aa89218>NullableContext(0)]
	[HarmonyPatch(typeof(Humanoid), "UpdateAttack")]
	public static class Humanoid_UpdateAttack_AttackSpeedDtPatch
	{
		[HarmonyPrefix]
		[<7ff4dd61-fbb9-4f30-85a4-9da04aa89218>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);
			}
		}
	}

	[HarmonyPatch(typeof(Humanoid), "CustomFixedUpdate")]
	[<7ff4dd61-fbb9-4f30-85a4-9da04aa89218>NullableContext(0)]
	public static class Humanoid_CustomFixedUpdate_AttackSpeedPatch
	{
		[<7ff4dd61-fbb9-4f30-85a4-9da04aa89218>NullableContext(1)]
		[HarmonyPostfix]
		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;
		}
	}

	[HarmonyPatch(typeof(Character), "RPC_Stagger")]
	[<7ff4dd61-fbb9-4f30-85a4-9da04aa89218>NullableContext(0)]
	public static class Character_RPC_Stagger_AttackSpeedResetPatch
	{
		[<7ff4dd61-fbb9-4f30-85a4-9da04aa89218>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)
			{
			}
		}
	}

	[<7ff4dd61-fbb9-4f30-85a4-9da04aa89218>NullableContext(0)]
	[HarmonyPatch(typeof(Character), "OnDeath")]
	public static class Character_OnDeath_AttackSpeedResetPatch
	{
		[HarmonyPostfix]
		[<7ff4dd61-fbb9-4f30-85a4-9da04aa89218>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)
			{
			}
		}
	}

	[<7ff4dd61-fbb9-4f30-85a4-9da04aa89218>NullableContext(0)]
	[HarmonyPatch(typeof(Character), "FreezeFrame")]
	public static class Character_FreezeFrame_AttackSpeedScalePatch
	{
		[<7ff4dd61-fbb9-4f30-85a4-9da04aa89218>NullableContext(1)]
		[HarmonyPrefix]
		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);
			}
		}
	}

	[HarmonyPatch(typeof(CharacterAnimEvent), "UpdateFreezeFrame")]
	[<7ff4dd61-fbb9-4f30-85a4-9da04aa89218>NullableContext(0)]
	public static class CharacterAnimEvent_UpdateFreezeFrame_ReapplySpeedPatch
	{
		[HarmonyPostfix]
		[<7ff4dd61-fbb9-4f30-85a4-9da04aa89218>NullableContext(1)]
		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);
			}
		}
	}

	[<7ff4dd61-fbb9-4f30-85a4-9da04aa89218>NullableContext(0)]
	[HarmonyPatch(typeof(SEMan), "AddStatusEffect", new Type[]
	{
		typeof(int),
		typeof(bool),
		typeof(int),
		typeof(float),
		typeof(short)
	})]
	public static class SEMan_AddStatusEffect_ByHash_WetImmunePatch
	{
		[<7ff4dd61-fbb9-4f30-85a4-9da04aa89218>NullableContext(1)]
		[HarmonyPrefix]
		private static bool Prefix(SEMan __instance, int nameHash, bool resetTime, int itemLevel, float skillLevel, short variant)
		{
			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 | variant={variant}");
					return false;
				}
			}
			catch (Exception ex2)
			{
				LogError("Exception in SEMan_AddStatusEffect_ByHash_WetImmunePatch: " + ex2);
			}
			return true;
		}
	}

	[HarmonyPatch(typeof(SEMan), "AddStatusEffect", new Type[]
	{
		typeof(StatusEffect),
		typeof(bool),
		typeof(int),
		typeof(float),
		typeof(short)
	})]
	[<7ff4dd61-fbb9-4f30-85a4-9da04aa89218>NullableContext(0)]
	public static class SEMan_AddStatusEffect_BySE_WetImmunePatch
	{
		[<7ff4dd61-fbb9-4f30-85a4-9da04aa89218>NullableContext(1)]
		[HarmonyPrefix]
		private static bool Prefix(SEMan __instance, StatusEffect statusEffect, bool resetTime, int itemLevel, float skillLevel, short variant, 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 | variant={variant}");
					__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("ArmorInspirationTrinketPlains_DO", ExtraStatType.Eitr, 10f, ExtraSourceType.ItemDrop),
		new ExtraStatEntry("ArmorInspirationTrinketMistlands_DO", ExtraStatType.Eitr, 10f, ExtraSourceType.ItemDrop),
		new ExtraStatEntry("ArmorInspirationTrinketAshlands_DO", ExtraStatType.Eitr, 10f, ExtraSourceType.ItemDrop),
		new ExtraStatEntry("ArmorBloodcallerTrinket_DO", ExtraStatType.Health, 5f, ExtraSourceType.ItemDrop),
		new ExtraStatEntry("ArmorMushroomcallerLegs_DO", ExtraStatType.Eitr, 5f, ExtraSourceType.ItemDrop),
		new ExtraStatEntry("ArmorTotemcallerLegs_DO", ExtraStatType.Health, 5f, ExtraSourceType.ItemDrop),
		new ExtraStatEntry("ArmorDeathcallerHelmet_DO", ExtraStatType.Eitr, 10f, ExtraSourceType.ItemDrop),
		new ExtraStatEntry("ArmorFrostcallerChest_DO", ExtraStatType.Eitr, 15f, ExtraSourceType.ItemDrop),
		new ExtraStatEntry("ArmorFirecallerLegs_DO", ExtraStatType.Eitr, 20f, ExtraSourceType.ItemDrop),
		new ExtraStatEntry("ArmorStonecallerLegs_DO", ExtraStatType.Eitr, 20f, ExtraSourceType.ItemDrop),
		new ExtraStatEntry("ArmorWindcallerHelmet_DO", ExtraStatType.Eitr, 25f, ExtraSourceType.ItemDrop),
		new ExtraStatEntry("ArmorLightcallerHelmet_DO", ExtraStatType.Eitr, 25f, ExtraSourceType.ItemDrop),
		new ExtraStatEntry("ArmorStormcallerChest_DO", ExtraStatType.Eitr, 30f, ExtraSourceType.ItemDrop),
		new ExtraStatEntry("ArmorBloodcallerChest_DO", ExtraStatType.Health, 20f, ExtraSourceType.ItemDrop),
		new ExtraStatEntry("ArmorFrostcallerCape_DO", ExtraStatType.Eitr, 10f, ExtraSourceType.ItemDrop),
		new ExtraStatEntry("ArmorWindcallerCape_DO", ExtraStatType.Stamina, 20f, ExtraSourceType.ItemDrop),
		new ExtraStatEntry("ArmorBloodcallerCape_DO", ExtraStatType.Health, 50f, ExtraSourceType.ItemDrop),
		new ExtraStatEntry("SE_MushroomcallerTome_DO", ExtraStatType.Eitr, 10f, ExtraSourceType.StatusEffect),
		new ExtraStatEntry("SE_DeathcallerTome_DO", ExtraStatType.Eitr, 15f, ExtraSourceType.StatusEffect),
		new ExtraStatEntry("SE_FrostcallerTome_DO", ExtraStatType.Eitr, 15f, ExtraSourceType.StatusEffect),
		new ExtraStatEntry("SE_FirecallerTome_DO", ExtraStatType.Eitr, 20f, ExtraSourceType.StatusEffect),
		new ExtraStatEntry("SE_StonecallerTome_DO", ExtraStatType.Eitr, 20f, ExtraSourceType.StatusEffect),
		new ExtraStatEntry("SE_LightcallerTome_DO", ExtraStatType.Eitr, 20f, ExtraSourceType.StatusEffect),
		new ExtraStatEntry("SE_StormcallerTome_DO", ExtraStatType.Eitr, 25f, ExtraSourceType.StatusEffect),
		new ExtraStatEntry("SE_TotemcallerUtility_DO", ExtraStatType.Health, 10f, ExtraSourceType.StatusEffect),
		new ExtraStatEntry("SE_WindcallerUtility_DO", ExtraStatType.Stamina, 15f, ExtraSourceType.StatusEffect),
		new ExtraStatEntry("SE_BloodcallerBuff_DO", ExtraStatType.Health, 50f, ExtraSourceType.StatusEffect)
	};

	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 = "$health_DO";
		string text2 = "$stamina_DO";
		string text3 = "$eitr_DO";
		string text4 = "$attackspeed_DO";
		string text5 = "$immune_DO";
		string text6 = "$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");
		}
	}
}
[<5659c901-bae2-435e-a01b-19ba0d7edac2>Nullable(0)]
[<7ff4dd61-fbb9-4f30-85a4-9da04aa89218>NullableContext(1)]
[HarmonyPatch]
public static class LivingContainerSpawner
{
	[<7ff4dd61-fbb9-4f30-85a4-9da04aa89218>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;
	}

	[<5659c901-bae2-435e-a01b-19ba0d7edac2>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;
	}

	[<7ff4dd61-fbb9-4f30-85a4-9da04aa89218>NullableContext(0)]
	private struct ItemsCacheEntry
	{
		public int ItemsLen;

		public int QuickHash;

		public bool IsEmpty;

		public int DecodedCount;

		public float LastTouchTime;
	}

	[<7ff4dd61-fbb9-4f30-85a4-9da04aa89218>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;
		}
	}

	[<5659c901-bae2-435e-a01b-19ba0d7edac2>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
			{
			}
		}
	}

	[<7ff4dd61-fbb9-4f30-85a4-9da04aa89218>NullableContext(0)]
	private enum GroundFail
	{
		None,
		WorldGenNoHeight,
		RaycastNoHit,
		WrongBiome,
		InWater,
		WaterTooDeep,
		OceanDepth,
		Lava,
		Altitude,
		Overlap,
		MistlandsBlocked
	}

	[HarmonyPatch(typeof(InventoryGui), "Hide")]
	[<5659c901-bae2-435e-a01b-19ba0d7edac2>Nullable(0)]
	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);
			}
		}
	}

	[<5659c901-bae2-435e-a01b-19ba0d7edac2>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);
			}
		}
	}

	[<7ff4dd61-fbb9-4f30-85a4-9da04aa89218>NullableContext(0)]
	private class RikoSpawnStabilizer : MonoBehaviour
	{
		private bool _started;

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

		[<7ff4dd61-fbb9-4f30-85a4-9da04aa89218>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 = "EncounterCreatureRikoBlackforest_DO",
			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 = "PinRiko_DO",
			PinText = "",
			PinAnimate = false,
			PinDoubleSize = true
		},
		new LivingContainerDef
		{
			Prefab = "EncounterCreatureRikoSwamp_DO",
			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 = "PinRiko_DO",
			PinText = "",
			PinAnimate = false,
			PinDoubleSize = true
		},
		new LivingContainerDef
		{
			Prefab = "EncounterCreatureRikoMountain_DO",
			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 = "PinRiko_DO",
			PinText = "",
			PinAnimate = false,
			PinDoubleSize = true
		},
		new LivingContainerDef
		{
			Prefab = "EncounterCreatureRikoPlains_DO",
			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 = "PinRiko_DO",
			PinText = "",
			PinAnimate = false,
			PinDoubleSize = true
		},
		new LivingContainerDef
		{
			Prefab = "EncounterCreatureRikoMistlands_DO",
			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 = "PinRiko_DO",
			PinText = "",
			PinAnimate = false,
			PinDoubleSize = true
		},
		new LivingContainerDef
		{
			Prefab = "EncounterCreatureRikoAshlands_DO",
			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 = "PinRiko_DO",
			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>();
		}
	}

	[HarmonyPostfix]
	[HarmonyPatch(typeof(ZNet), "Awake")]
	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 && ZNetPeer_m_refPos_Field.GetValue(val2) is Vector3 val4)
					{
						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)Unsafe.As<ZDOID, ZDOID>(ref val5.m_uid)/*cast due to .constrained prefix*/).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_003b: 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) !=