Decompiled source of ValhalLoot v1.0.0

ValhalLoot.dll

Decompiled 3 weeks ago
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using ItemManager;
using JetBrains.Annotations;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using ServerSync;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
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("1.0.0")]
[assembly: Guid("E0E2F92E-557C-4A05-9D89-AA92A0BD75C4")]
[assembly: ComVisible(false)]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCopyright("Copyright ©  2022")]
[assembly: AssemblyProduct("ValhalLoot")]
[assembly: AssemblyCompany("ruijven")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyTitle("ValhalLoot")]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: CompilationRelaxations(8)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[<8f532b54-25c0-4aad-a53e-9dd3b78c8708>Embedded]
	internal sealed class <8f532b54-25c0-4aad-a53e-9dd3b78c8708>EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	[<8f532b54-25c0-4aad-a53e-9dd3b78c8708>Embedded]
	[CompilerGenerated]
	internal sealed class <6c1629e0-990f-46fb-933a-fb94e8696503>NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public <6c1629e0-990f-46fb-933a-fb94e8696503>NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public <6c1629e0-990f-46fb-933a-fb94e8696503>NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	[<8f532b54-25c0-4aad-a53e-9dd3b78c8708>Embedded]
	[CompilerGenerated]
	internal sealed class <022029f3-5fce-4252-8684-e6648986aff8>NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public <022029f3-5fce-4252-8684-e6648986aff8>NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
}
namespace ValhalLoot
{
	[BepInPlugin("ruijven.ValhalLoot", "ValhalLoot", "1.0.0")]
	[<022029f3-5fce-4252-8684-e6648986aff8>NullableContext(1)]
	[<6c1629e0-990f-46fb-933a-fb94e8696503>Nullable(0)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class ValhalLootPlugin : BaseUnityPlugin
	{
		[<022029f3-5fce-4252-8684-e6648986aff8>NullableContext(0)]
		public enum Toggle
		{
			On = 1,
			Off = 0
		}

		[HarmonyPatch(typeof(Player), "ConsumeItem")]
		[<022029f3-5fce-4252-8684-e6648986aff8>NullableContext(0)]
		private static class Player_ConsumeItem_Patch
		{
			[HarmonyPrefix]
			[<022029f3-5fce-4252-8684-e6648986aff8>NullableContext(1)]
			private static bool Prefix(Player __instance, ItemData item, ref bool __result)
			{
				try
				{
					if (item != null && (Object)(object)item.m_dropPrefab != (Object)null && ((Object)item.m_dropPrefab).name == "valhalloot_ru")
					{
						ValhalLootLogger.LogInfo((object)("Player " + __instance.GetPlayerName() + " is using ValhalLoot chest"));
						if ((Object)(object)ValhalLootManager.Instance != (Object)null)
						{
							ValhalLootManager.Instance.ProcessChestUse(__instance, item);
							__result = true;
							return false;
						}
					}
				}
				catch (Exception ex)
				{
					ValhalLootLogger.LogError((object)("Error in ConsumeItem patch: " + ex.Message));
				}
				return true;
			}
		}

		[<022029f3-5fce-4252-8684-e6648986aff8>NullableContext(0)]
		private class ConfigurationManagerAttributes
		{
			[UsedImplicitly]
			public int? Order = null;

			[UsedImplicitly]
			public bool? Browsable = null;

			[UsedImplicitly]
			[<6c1629e0-990f-46fb-933a-fb94e8696503>Nullable(2)]
			public string Category = null;

			[<6c1629e0-990f-46fb-933a-fb94e8696503>Nullable(new byte[] { 2, 1 })]
			[UsedImplicitly]
			public Action<ConfigEntryBase> CustomDrawer = null;
		}

		[<6c1629e0-990f-46fb-933a-fb94e8696503>Nullable(0)]
		private class AcceptableShortcuts : AcceptableValueBase
		{
			public AcceptableShortcuts()
				: base(typeof(KeyboardShortcut))
			{
			}

			public override object Clamp(object value)
			{
				return value;
			}

			public override bool IsValid(object value)
			{
				return true;
			}

			public override string ToDescriptionString()
			{
				return "# Acceptable values: " + string.Join(", ", UnityInput.Current.SupportedKeyCodes);
			}
		}

		internal const string ModName = "ValhalLoot";

		internal const string ModVersion = "1.0.0";

		internal const string Author = "ruijven";

		private const string ModGUID = "ruijven.ValhalLoot";

		private static string ConfigFileName = "ruijven.ValhalLoot.cfg";

		private static string ConfigFileFullPath;

		internal static string ConnectionError;

		private readonly Harmony _harmony = new Harmony("ruijven.ValhalLoot");

		public static readonly ManualLogSource ValhalLootLogger;

		private static readonly ConfigSync ConfigSync;

		[<6c1629e0-990f-46fb-933a-fb94e8696503>Nullable(2)]
		private static ValhalLootConfig _valhalLootConfig;

		[<6c1629e0-990f-46fb-933a-fb94e8696503>Nullable(2)]
		private static GameObject _valhalLootUIObject;

		[<6c1629e0-990f-46fb-933a-fb94e8696503>Nullable(2)]
		public Texture2D tex = null;

		private static ConfigEntry<Toggle> _serverConfigLocked;

		public void Awake()
		{
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Expected O, but got Unknown
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Expected O, but got Unknown
			RegisterTranslations();
			bool saveOnConfigSet = ((BaseUnityPlugin)this).Config.SaveOnConfigSet;
			((BaseUnityPlugin)this).Config.SaveOnConfigSet = false;
			_serverConfigLocked = config("1 - General", "Lock Configuration", Toggle.On, "If on, the configuration is locked and can be changed by server admins only.");
			ConfigSync.AddLockingConfigEntry<Toggle>(_serverConfigLocked);
			_valhalLootConfig = new ValhalLootConfig(ConfigSync, ((BaseUnityPlugin)this).Config);
			try
			{
				AssetBundle val = AssetUtils.LoadAssetBundleFromResources("lootbundle_ru", Assembly.GetExecutingAssembly());
				if ((Object)(object)val == (Object)null)
				{
					string text = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? "", "assets", "lootbundle_ru");
					val = AssetBundle.LoadFromFile(text);
				}
				if ((Object)(object)val == (Object)null)
				{
					ValhalLootLogger.LogError((object)"Failed to load lootbundle_ru asset bundle from resources or file path");
					ValhalLootLogger.LogInfo((object)"Creating placeholder chest without custom assets");
				}
				else
				{
					ValhalLootLogger.LogInfo((object)("Successfully loaded asset bundle: " + ((Object)val).name));
				}
			}
			catch (Exception ex)
			{
				ValhalLootLogger.LogError((object)("Error loading asset bundle: " + ex.Message));
			}
			GameObject val2 = new GameObject("ValhalLootManager");
			Object.DontDestroyOnLoad((Object)(object)val2);
			ValhalLootManager valhalLootManager = val2.AddComponent<ValhalLootManager>();
			_valhalLootUIObject = new GameObject("ValhalLootUI");
			Object.DontDestroyOnLoad((Object)(object)_valhalLootUIObject);
			ValhalLootUI valhalLootUI = _valhalLootUIObject.AddComponent<ValhalLootUI>();
			valhalLootManager.Initialize(_valhalLootConfig);
			valhalLootUI.Initialize();
			_harmony.PatchAll(typeof(ValhalLootPlugin));
			ValhalLootLogger.LogInfo((object)"ValhalLoot components created - initialization will complete when player enters world");
			ValhalLootLogger.LogInfo((object)"Harmony patches applied for item usage detection");
			Assembly executingAssembly = Assembly.GetExecutingAssembly();
			_harmony.PatchAll(executingAssembly);
			SetupWatcher();
			if (saveOnConfigSet)
			{
				((BaseUnityPlugin)this).Config.SaveOnConfigSet = saveOnConfigSet;
				((BaseUnityPlugin)this).Config.Save();
			}
		}

		private void RegisterTranslations()
		{
			Dictionary<string, string> dictionary = new Dictionary<string, string>
			{
				{ "valhalloot_chest_name", "Valhalla Chest" },
				{ "valhalloot_chest_description", "A chest containing treasures from Valhalla" },
				{ "valhalloot_ui_title", "Valhalla Loot" },
				{ "valhalloot_ui_select", "Select one item:" },
				{ "valhalloot_ui_close", "Close" }
			};
			CustomLocalization localization = LocalizationManager.Instance.GetLocalization();
			string text = "English";
			localization.AddTranslation(ref text, dictionary);
		}

		public void OnDestroy()
		{
			((BaseUnityPlugin)this).Config.Save();
			_harmony.UnpatchSelf();
		}

		private void SetupWatcher()
		{
			FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(Paths.ConfigPath, ConfigFileName);
			fileSystemWatcher.Changed += ReadConfigValues;
			fileSystemWatcher.Created += ReadConfigValues;
			fileSystemWatcher.Renamed += ReadConfigValues;
			fileSystemWatcher.IncludeSubdirectories = true;
			fileSystemWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject;
			fileSystemWatcher.EnableRaisingEvents = true;
		}

		private void ReadConfigValues(object sender, FileSystemEventArgs e)
		{
			if (!File.Exists(ConfigFileFullPath))
			{
				return;
			}
			try
			{
				ValhalLootLogger.LogDebug((object)"ReadConfigValues called");
				((BaseUnityPlugin)this).Config.Reload();
			}
			catch
			{
				ValhalLootLogger.LogError((object)("There was an issue loading your " + ConfigFileName));
				ValhalLootLogger.LogError((object)"Please check your config entries for spelling and format!");
			}
		}

		private ConfigEntry<T> config<[<6c1629e0-990f-46fb-933a-fb94e8696503>Nullable(2)] T>(string group, string name, T value, ConfigDescription description, bool synchronizedSetting = true)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			ConfigDescription val = new ConfigDescription(description.Description + (synchronizedSetting ? " [Synced with Server]" : " [Not Synced with Server]"), description.AcceptableValues, description.Tags);
			ConfigEntry<T> val2 = ((BaseUnityPlugin)this).Config.Bind<T>(group, name, value, val);
			SyncedConfigEntry<T> syncedConfigEntry = ConfigSync.AddConfigEntry<T>(val2);
			syncedConfigEntry.SynchronizedConfig = synchronizedSetting;
			return val2;
		}

		private ConfigEntry<T> config<[<6c1629e0-990f-46fb-933a-fb94e8696503>Nullable(2)] T>(string group, string name, T value, string description, bool synchronizedSetting = true)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			return config(group, name, value, new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty<object>()), synchronizedSetting);
		}

		static ValhalLootPlugin()
		{
			string configPath = Paths.ConfigPath;
			char directorySeparatorChar = Path.DirectorySeparatorChar;
			ConfigFileFullPath = configPath + directorySeparatorChar + ConfigFileName;
			ConnectionError = "";
			ValhalLootLogger = Logger.CreateLogSource("ValhalLoot");
			ConfigSync = new ConfigSync("ruijven.ValhalLoot")
			{
				DisplayName = "ValhalLoot",
				CurrentVersion = "1.0.0",
				MinimumRequiredVersion = "1.0.0"
			};
			_serverConfigLocked = null;
		}
	}
	[<6c1629e0-990f-46fb-933a-fb94e8696503>Nullable(0)]
	[<022029f3-5fce-4252-8684-e6648986aff8>NullableContext(1)]
	public class LootEntry
	{
		public string ItemName { get; set; } = string.Empty;


		public int MinQuality { get; set; }

		public int MaxQuality { get; set; }

		public float Weight { get; set; } = 1f;


		[<6c1629e0-990f-46fb-933a-fb94e8696503>Nullable(2)]
		[field: <6c1629e0-990f-46fb-933a-fb94e8696503>Nullable(2)]
		public Recipe Recipe
		{
			[<022029f3-5fce-4252-8684-e6648986aff8>NullableContext(2)]
			get;
			[<022029f3-5fce-4252-8684-e6648986aff8>NullableContext(2)]
			set;
		} = null;

	}
	[<022029f3-5fce-4252-8684-e6648986aff8>NullableContext(1)]
	[<6c1629e0-990f-46fb-933a-fb94e8696503>Nullable(0)]
	public class ValhalLootConfig
	{
		[<6c1629e0-990f-46fb-933a-fb94e8696503>Nullable(0)]
		public class YamlConfig
		{
			[<6c1629e0-990f-46fb-933a-fb94e8696503>Nullable(2)]
			[field: <6c1629e0-990f-46fb-933a-fb94e8696503>Nullable(2)]
			public YamlConfig Config
			{
				[<022029f3-5fce-4252-8684-e6648986aff8>NullableContext(2)]
				get;
				[<022029f3-5fce-4252-8684-e6648986aff8>NullableContext(2)]
				private set;
			}

			[<6c1629e0-990f-46fb-933a-fb94e8696503>Nullable(2)]
			[field: <6c1629e0-990f-46fb-933a-fb94e8696503>Nullable(2)]
			public Settings Settings
			{
				[<022029f3-5fce-4252-8684-e6648986aff8>NullableContext(2)]
				get;
				[<022029f3-5fce-4252-8684-e6648986aff8>NullableContext(2)]
				set;
			}

			[YamlMember(Alias = "LootChestTables")]
			public Dictionary<string, List<string>> ChestLoot { get; set; } = new Dictionary<string, List<string>>();


			[YamlMember(Alias = "EnemyChestTables")]
			public Dictionary<string, List<string>> ChestEnemyMap { get; set; } = new Dictionary<string, List<string>>();

		}

		[<6c1629e0-990f-46fb-933a-fb94e8696503>Nullable(0)]
		public class Settings
		{
			[YamlMember(Alias = "Minibosses")]
			public List<string> Minibosses { get; set; } = new List<string> { "Skeleton_Hildir", "Fenring_Cultist_Hildir", "GoblinBrute_Hildir", "Charred_Melee_Dyrnwyn" };

		}

		private static readonly string ConfigFileName = "ValhalLoot.yml";

		private static readonly string ConfigFilePath = Path.Combine(Paths.ConfigPath, ConfigFileName);

		private readonly ConfigSync _configSync;

		public ConfigEntry<float> CreatureDropChance { get; private set; }

		public ConfigEntry<float> BossDropChance { get; private set; }

		public ConfigEntry<float> MinibossDropChance { get; private set; }

		public Dictionary<string, List<LootEntry>> ChestLoot { get; private set; } = new Dictionary<string, List<LootEntry>>();


		public Dictionary<string, List<LootEntry>> BiomeLoot => ChestLoot;

		public Dictionary<string, List<string>> ChestEnemyMap { get; private set; } = new Dictionary<string, List<string>>();


		public Dictionary<string, List<string>> EnemyBiomeMap => ChestEnemyMap;

		public Dictionary<string, string> EnemyToChestMap { get; private set; } = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);


		public ValhalLootConfig(ConfigSync configSync, ConfigFile config)
		{
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Expected O, but got Unknown
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Expected O, but got Unknown
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Expected O, but got Unknown
			_configSync = configSync;
			CreatureDropChance = config.Bind<float>("Drop Chances", "RegularCreatures", 0.1f, new ConfigDescription("Chance for regular creatures to drop a ValhalLoot chest (0-1)", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			BossDropChance = config.Bind<float>("Drop Chances", "Bosses", 0.3f, new ConfigDescription("Chance for bosses to drop a ValhalLoot chest (0-1)", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			MinibossDropChance = config.Bind<float>("Drop Chances", "Minibosses", 0.5f, new ConfigDescription("Chance for minibosses to drop a ValhalLoot chest (0-1)", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			_configSync.AddConfigEntry<float>(CreatureDropChance);
			_configSync.AddConfigEntry<float>(BossDropChance);
			_configSync.AddConfigEntry<float>(MinibossDropChance);
			LoadYamlConfig();
		}

		public void LoadYamlConfig()
		{
			try
			{
				if (File.Exists(ConfigFilePath))
				{
					string input = File.ReadAllText(ConfigFilePath);
					IDeserializer deserializer = new DeserializerBuilder().WithNamingConvention(CamelCaseNamingConvention.Instance).Build();
					YamlConfig yamlConfig = deserializer.Deserialize<YamlConfig>(input);
					ConvertYamlConfig(yamlConfig);
					ValhalLootPlugin.ValhalLootLogger.LogInfo((object)"YAML configuration loaded successfully");
				}
				else
				{
					CreateDefaultYamlConfig();
					ValhalLootPlugin.ValhalLootLogger.LogInfo((object)"Default YAML configuration created");
				}
			}
			catch (Exception ex)
			{
				ValhalLootPlugin.ValhalLootLogger.LogError((object)("Error loading YAML configuration: " + ex.Message));
				CreateDefaultYamlConfig();
			}
		}

		private void ConvertYamlConfig(YamlConfig yamlConfig)
		{
			ChestLoot.Clear();
			ChestEnemyMap.Clear();
			EnemyToChestMap.Clear();
			if (yamlConfig.Settings != null)
			{
			}
			foreach (KeyValuePair<string, List<string>> item in yamlConfig.ChestLoot)
			{
				string key = item.Key;
				List<LootEntry> list = new List<LootEntry>();
				foreach (string item2 in item.Value)
				{
					LootEntry lootEntry = ParseLootEntry(item2);
					if (lootEntry != null)
					{
						list.Add(lootEntry);
					}
				}
				ChestLoot[key] = list;
				ValhalLootPlugin.ValhalLootLogger.LogInfo((object)$"Loaded {list.Count} loot entries for chest {key}");
			}
			foreach (KeyValuePair<string, List<string>> item3 in yamlConfig.ChestEnemyMap)
			{
				string key2 = item3.Key;
				List<string> list2 = new List<string>(item3.Value);
				ChestEnemyMap[key2] = list2;
				ValhalLootPlugin.ValhalLootLogger.LogInfo((object)$"Loaded {list2.Count} enemy mappings for chest {key2}");
				foreach (string item4 in list2)
				{
					EnemyToChestMap[item4] = key2;
					ValhalLootPlugin.ValhalLootLogger.LogDebug((object)("Mapped enemy " + item4 + " to chest " + key2));
				}
			}
		}

		private void CreateDefaultYamlConfig()
		{
			YamlConfig yamlConfig = new YamlConfig
			{
				Settings = new Settings(),
				ChestLoot = new Dictionary<string, List<string>>
				{
					{
						"meadowsloot_ru",
						new List<string>
						{
							"CapeDeerHide:2-4:1.0", "HelmetLeather:2-4:1.0", "ArmorLeatherChest:2-4:1.0", "ArmorLeatherLegs:2-4:1.0", "AxeStone:2-4:1.0", "AxeFlint:2-4:1.0", "Club:2-4:1.0", "ShieldWood:2-4:1.0", "ShieldWoodTower:2-4:1.0", "Bow:2-4:1.0",
							"KnifeFlint:2-4:1.0", "SpearFlint:2-4:1.0", "Hoe:2-4:1.0", "Hammer:2-4:1.0", "PickaxeAntler:2-4:0.5"
						}
					},
					{
						"blackforestloot_ru",
						new List<string>
						{
							"ArmorTrollLeatherChest:2-4:1.0", "ArmorTrollLeatherLegs:2-4:1.0", "HelmetTrollLeather:2-4:1.0", "CapeTrollHide:2-4:1.0", "ArmorBronzeChest:2-4:1.0", "ArmorBronzeLegs:2-4:1.0", "HelmetBronze:2-4:1.0", "MaceBronze:2-4:1.0", "SwordBronze:2-4:1.0", "AxeBronze:2-4:1.0",
							"KnifeCopper:2-4:1.0", "BowFineWood:2-4:1.0", "SpearBronze:2-4:1.0", "AtgeirBronze:2-4:1.0", "SledgeStagbreaker:2-4:1.0", "ShieldBoneTower:2-4:1.0", "ShieldBronzeBuckler:2-4:1.0", "Cultivator:2-4:1.0", "PickaxeBronze:2-4:1.0"
						}
					},
					{
						"swamploot_ru",
						new List<string>
						{
							"KnifeChitin:2-4:1.0", "SpearChitin:2-4:1.0", "ArmorRootChest:2-4:1.0", "ArmorRootLegs:2-4:1.0", "HelmetRoot:2-4:1.0", "ArmorIronChest:2-4:1.0", "ArmorIronLegs:2-4:1.0", "HelmetIron:2-4:1.0", "AxeIron:2-4:1.0", "Battleaxe:2-4:1.0",
							"BowHuntsman:2-4:1.0", "MaceIron:2-4:1.0", "SledgeIron:2-4:1.0", "ShieldBanded:2-4:1.0", "ShieldIronBuckler:2-4:1.0", "ShieldIronTower:2-4:1.0", "ShieldSerpentscale:2-4:1.0", "SpearElderbark:2-4:1.0", "SwordIron:2-4:1.0", "AtgeirIron:2-4:1.0",
							"PickaxeIron:2-4:1.0"
						}
					},
					{
						"mountainsloot_ru",
						new List<string>
						{
							"ArmorWolfChest:2-4:1.0", "ArmorWolfLegs:2-4:1.0", "HelmetDrake:2-4:1.0", "CapeWolf:2-4:1.0", "ArmorFenringChest:2-4:1.0", "ArmorFenringLegs:2-4:1.0", "HelmetFenring:2-4:1.0", "ShieldSilver:2-4:1.0", "BowDraugrFang:2-4:1.0", "SpearWolfFang:2-4:1.0",
							"SwordSilver:2-4:1.0", "KnifeSilver:2-4:1.0", "BattleaxeCrystal:2-4:1.0", "MaceSilver:2-4:1.0", "FistFenrirClaw:2-4:1.0"
						}
					},
					{
						"plainsloot_ru",
						new List<string>
						{
							"ArmorPaddedCuirass:2-4:1.0", "ArmorPaddedGreaves:2-4:1.0", "HelmetPadded:2-4:1.0", "CapeLinen:2-4:1.0", "AxeBlackMetal:2-4:1.0", "AtgeirBlackmetal:2-4:1.0", "KnifeBlackMetal:2-4:1.0", "MaceNeedle:2-4:1.0", "ShieldBlackmetal:2-4:1.0", "ShieldBlackmetalTower:2-4:1.0",
							"SwordBlackmetal:2-4:1.0"
						}
					},
					{
						"mistlandsloot_ru",
						new List<string>
						{
							"ArmorCarapaceChest:2-4:1.0", "ArmorCarapaceLegs:2-4:1.0", "HelmetCarapace:2-4:1.0", "HelmetMage:2-4:1.0", "ArmorMageChest:2-4:1.0", "ArmorMageLegs:2-4:1.0", "CapeFeather:2-4:1.0", "AxeJotunBane:2-4:1.0", "BowSpineSnap:2-4:1.0", "AtgeirHimminAfl:2-4:1.0",
							"KnifeSkollAndHati:2-4:1.0", "SledgeDemolisher:2-4:1.0", "SwordMistwalker:2-4:1.0", "THSwordKrom:2-4:1.0", "CrossbowArbalest:2-4:1.0", "ShieldCarapace:2-4:1.0", "ShieldCarapaceBuckler:2-4:1.0", "StaffFireball:2-4:1.0", "StaffIceShards:2-4:1.0", "StaffShield:2-4:1.0",
							"StaffSkeleton:2-4:1.0", "PickaxeBlackMetal:2-4:1.0"
						}
					},
					{
						"ashlandsloot_ru",
						new List<string>
						{
							"CapeAsksvin:2-4:1.0", "CapeAsh:2-4:1.0", "AxeBerzerkr:2-4:1.0", "MaceEldner:2-4:1.0", "SwordNiedhogg:2-4:1.0", "THSwordSlayer:2-4:1.0", "SpearSplitner:2-4:1.0", "ShieldFlametal:2-4:1.0", "ShieldFlametalTower:2-4:1.0", "BowAshlands:2-4:1.0",
							"CrossbowRipper:2-4:1.0", "StaffLightning:2-4:1.0", "StaffGreenRoots:2-4:1.0", "StaffClusterbomb:2-4:1.0", "StaffRedTroll:2-4:1.0", "ArmorMageChest_Ashlands:2-4:1.0", "ArmorMageLegs_Ashlands:2-4:1.0", "HelmetMage_Ashlands:2-4:1.0", "ArmorAshlandsMediumChest:2-4:1.0", "ArmorAshlandsMediumlegs:2-4:1.0",
							"HelmetAshlandsMediumHood:2-4:1.0", "HelmetFlametal:2-4:1.0", "ArmorFlametalChest:2-4:1.0", "ArmorFlametalLegs:2-4:1.0"
						}
					}
				},
				ChestEnemyMap = new Dictionary<string, List<string>>
				{
					{
						"meadowsloot_ru",
						new List<string> { "Greyling", "Boar", "Neck", "Deer" }
					},
					{
						"blackforestloot_ru",
						new List<string> { "Greydwarf", "Greydwarf_Elite", "Greydwarf_Shaman", "Skeleton_Hildir", "Troll", "Eikthyr", "Ghost" }
					},
					{
						"swamploot_ru",
						new List<string> { "Draugr", "Draugr_Elite", "Wraith", "Serpent", "gd_king", "Abomination" }
					},
					{
						"mountainsloot_ru",
						new List<string> { "Wolf", "Drake", "Fenring", "StoneGolem", "Bonemass", "Fenring_Cultist_Hildir", "Fenring_Cultist" }
					},
					{
						"plainsloot_ru",
						new List<string> { "Goblin", "GoblinBrute", "BlobTar", "GoblinShaman", "Deathsquito", "Dragon", "GoblinBrute_Hildir", "Lox" }
					},
					{
						"mistlandsloot_ru",
						new List<string> { "Gjall", "Seeker", "SeekerBrute", "GoblinKing", "Dverger" }
					},
					{
						"ashlandsloot_ru",
						new List<string>
						{
							"Charred_Archer", "Charred_Mage", "Charred_Melee", "Charred_Twitcher", "Morgen", "BonemawSerpent", "FallenValkyrie", "Volture", "piece_Charred_Balista", "SeekerQueen",
							"Fader", "Charred_Melee_Dyrnwyn", "Asksvin"
						}
					}
				}
			};
			ConvertYamlConfig(yamlConfig);
			SaveYamlConfig(yamlConfig);
		}

		private void SaveYamlConfig(YamlConfig config)
		{
			try
			{
				ISerializer serializer = new SerializerBuilder().WithNamingConvention(CamelCaseNamingConvention.Instance).Build();
				string contents = serializer.Serialize(config);
				File.WriteAllText(ConfigFilePath, contents);
				ValhalLootPlugin.ValhalLootLogger.LogInfo((object)"YAML configuration saved successfully");
			}
			catch (Exception ex)
			{
				ValhalLootPlugin.ValhalLootLogger.LogError((object)("Error saving YAML configuration: " + ex.Message));
			}
		}

		[return: <6c1629e0-990f-46fb-933a-fb94e8696503>Nullable(2)]
		private static LootEntry ParseLootEntry(string entryString)
		{
			try
			{
				string[] array = entryString.Trim().Split(new char[1] { ':' });
				string itemName = array[0];
				string[] array2 = array[1].Split(new char[1] { '-' });
				int num = int.Parse(array2[0]);
				int maxQuality = ((array2.Length > 1) ? int.Parse(array2[1]) : num);
				float weight = ((array.Length > 2) ? float.Parse(array[2]) : 1f);
				return new LootEntry
				{
					ItemName = itemName,
					MinQuality = num,
					MaxQuality = maxQuality,
					Weight = weight
				};
			}
			catch (Exception ex)
			{
				ValhalLootPlugin.ValhalLootLogger.LogError((object)("Error parsing loot entry '" + entryString + "': " + ex.Message));
				return null;
			}
		}
	}
	[<022029f3-5fce-4252-8684-e6648986aff8>NullableContext(1)]
	[<6c1629e0-990f-46fb-933a-fb94e8696503>Nullable(0)]
	public class ValhalLootManager : MonoBehaviour
	{
		[<6c1629e0-990f-46fb-933a-fb94e8696503>Nullable(0)]
		private class BiomeConfig
		{
			public string[] Resources { get; set; } = Array.Empty<string>();


			public string[] CraftingStations { get; set; } = Array.Empty<string>();

		}

		[CompilerGenerated]
		private sealed class <InitializeWhenReady>d__22 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			[<6c1629e0-990f-46fb-933a-fb94e8696503>Nullable(0)]
			private object <>2__current;

			[<6c1629e0-990f-46fb-933a-fb94e8696503>Nullable(0)]
			public ValhalLootManager <>4__this;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				[return: <6c1629e0-990f-46fb-933a-fb94e8696503>Nullable(0)]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				[return: <6c1629e0-990f-46fb-933a-fb94e8696503>Nullable(0)]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <InitializeWhenReady>d__22(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0050: Unknown result type (might be due to invalid IL or missing references)
				//IL_005a: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					ValhalLootPlugin.ValhalLootLogger.LogInfo((object)"Waiting for game systems to be ready before initializing ValhalLoot...");
					<>2__current = (object)new WaitUntil((Func<bool>)(() => (Object)(object)Player.m_localPlayer != (Object)null && (Object)(object)ObjectDB.instance != (Object)null && (Object)(object)ZNetScene.instance != (Object)null));
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					ValhalLootPlugin.ValhalLootLogger.LogInfo((object)"Game systems ready");
					if (Localization.instance != null && !Localization.instance.m_translations.ContainsKey("valhalloot_received"))
					{
						Localization.instance.AddWord("valhalloot_received", "You received a ValhalLoot chest!");
						Localization.instance.AddWord("valhalloot_dropped", "A ValhalLoot chest was dropped nearby (inventory full)");
					}
					<>4__this._isInitialized = true;
					ValhalLootPlugin.ValhalLootLogger.LogInfo((object)"ValhalLoot Manager fully initialized and ready");
					<>4__this.BuildDynamicChestLootFromObjectDB();
					return false;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <VerifyAndFixRegistration>d__31 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			[<6c1629e0-990f-46fb-933a-fb94e8696503>Nullable(0)]
			private object <>2__current;

			[<6c1629e0-990f-46fb-933a-fb94e8696503>Nullable(new byte[] { 0, 1, 1 })]
			public Dictionary<string, GameObject> loadedPrefabs;

			[<6c1629e0-990f-46fb-933a-fb94e8696503>Nullable(0)]
			public ValhalLootManager <>4__this;

			[<6c1629e0-990f-46fb-933a-fb94e8696503>Nullable(new byte[] { 0, 1, 1 })]
			private Dictionary<string, GameObject>.Enumerator <>s__1;

			[<6c1629e0-990f-46fb-933a-fb94e8696503>Nullable(new byte[] { 0, 1, 1 })]
			private KeyValuePair<string, GameObject> <kvp>5__2;

			[<6c1629e0-990f-46fb-933a-fb94e8696503>Nullable(0)]
			private string <prefabName>5__3;

			[<6c1629e0-990f-46fb-933a-fb94e8696503>Nullable(0)]
			private GameObject <prefab>5__4;

			[<6c1629e0-990f-46fb-933a-fb94e8696503>Nullable(0)]
			private GameObject <verifyPrefab>5__5;

			[<6c1629e0-990f-46fb-933a-fb94e8696503>Nullable(new byte[] { 0, 1, 1 })]
			private Dictionary<string, GameObject>.Enumerator <>s__6;

			[<6c1629e0-990f-46fb-933a-fb94e8696503>Nullable(new byte[] { 0, 1, 1 })]
			private KeyValuePair<string, GameObject> <kvp>5__7;

			[<6c1629e0-990f-46fb-933a-fb94e8696503>Nullable(0)]
			private string <prefabName>5__8;

			[<6c1629e0-990f-46fb-933a-fb94e8696503>Nullable(0)]
			private GameObject <verifyPrefab>5__9;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				[return: <6c1629e0-990f-46fb-933a-fb94e8696503>Nullable(0)]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				[return: <6c1629e0-990f-46fb-933a-fb94e8696503>Nullable(0)]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <VerifyAndFixRegistration>d__31(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>s__1 = default(Dictionary<string, GameObject>.Enumerator);
				<kvp>5__2 = default(KeyValuePair<string, GameObject>);
				<prefabName>5__3 = null;
				<prefab>5__4 = null;
				<verifyPrefab>5__5 = null;
				<>s__6 = default(Dictionary<string, GameObject>.Enumerator);
				<kvp>5__7 = default(KeyValuePair<string, GameObject>);
				<prefabName>5__8 = null;
				<verifyPrefab>5__9 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0026: Unknown result type (might be due to invalid IL or missing references)
				//IL_0030: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = (object)new WaitForSeconds(2f);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					ValhalLootPlugin.ValhalLootLogger.LogInfo((object)"Verifying prefab registration and applying fallback if needed");
					if ((Object)(object)ObjectDB.instance == (Object)null)
					{
						ValhalLootPlugin.ValhalLootLogger.LogError((object)"ObjectDB.instance is null during verification");
						return false;
					}
					<>s__1 = loadedPrefabs.GetEnumerator();
					try
					{
						while (<>s__1.MoveNext())
						{
							<kvp>5__2 = <>s__1.Current;
							<prefabName>5__3 = <kvp>5__2.Key;
							<prefab>5__4 = <kvp>5__2.Value;
							<verifyPrefab>5__5 = ObjectDB.instance.GetItemPrefab(<prefabName>5__3);
							if ((Object)(object)<verifyPrefab>5__5 != (Object)null)
							{
								ValhalLootPlugin.ValhalLootLogger.LogInfo((object)("SUCCESS: Verified " + <prefabName>5__3 + " exists in ObjectDB"));
							}
							else
							{
								ValhalLootPlugin.ValhalLootLogger.LogWarning((object)("FAILED: " + <prefabName>5__3 + " not found in ObjectDB after registration attempts"));
							}
							<prefabName>5__3 = null;
							<prefab>5__4 = null;
							<verifyPrefab>5__5 = null;
							<kvp>5__2 = default(KeyValuePair<string, GameObject>);
						}
					}
					finally
					{
						((IDisposable)<>s__1).Dispose();
					}
					<>s__1 = default(Dictionary<string, GameObject>.Enumerator);
					<>s__6 = loadedPrefabs.GetEnumerator();
					try
					{
						while (<>s__6.MoveNext())
						{
							<kvp>5__7 = <>s__6.Current;
							<prefabName>5__8 = <kvp>5__7.Key;
							<verifyPrefab>5__9 = ObjectDB.instance.GetItemPrefab(<prefabName>5__8);
							if ((Object)(object)<verifyPrefab>5__9 != (Object)null)
							{
								ValhalLootPlugin.ValhalLootLogger.LogInfo((object)("FINAL CHECK: " + <prefabName>5__8 + " exists in ObjectDB"));
							}
							else
							{
								ValhalLootPlugin.ValhalLootLogger.LogError((object)("FINAL CHECK FAILED: " + <prefabName>5__8 + " still not in ObjectDB!"));
							}
							<prefabName>5__8 = null;
							<verifyPrefab>5__9 = null;
							<kvp>5__7 = default(KeyValuePair<string, GameObject>);
						}
					}
					finally
					{
						((IDisposable)<>s__6).Dispose();
					}
					<>s__6 = default(Dictionary<string, GameObject>.Enumerator);
					return false;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[<6c1629e0-990f-46fb-933a-fb94e8696503>Nullable(2)]
		private static ValhalLootManager _instance;

		[<6c1629e0-990f-46fb-933a-fb94e8696503>Nullable(2)]
		private ValhalLootConfig _config = null;

		private bool _isInitialized = false;

		private Dictionary<string, GameObject> _biomePrefabs = new Dictionary<string, GameObject>();

		public Dictionary<string, string> _biomeToPrefabMap = new Dictionary<string, string>
		{
			{ "Meadows", "meadowsloot_ru" },
			{ "BlackForest", "blackforestloot_ru" },
			{ "Swamp", "swamploot_ru" },
			{ "Mountain", "mountainsloot_ru" },
			{ "Plains", "plainsloot_ru" },
			{ "Mistlands", "mistlandsloot_ru" },
			{ "Ashlands", "ashlandsloot_ru" }
		};

		private readonly Dictionary<string, string> _chestPrefabToBiome = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
		{
			{ "meadowsloot_ru", "Meadows" },
			{ "blackforestloot_ru", "BlackForest" },
			{ "swamploot_ru", "Swamp" },
			{ "mountainsloot_ru", "Mountain" },
			{ "plainsloot_ru", "Plains" },
			{ "mistlandsloot_ru", "Mistlands" },
			{ "ashlandsloot_ru", "Ashlands" }
		};

		private static readonly Dictionary<string, BiomeConfig> _biomeConfigs = new Dictionary<string, BiomeConfig>(StringComparer.OrdinalIgnoreCase)
		{
			{
				"Meadows",
				new BiomeConfig
				{
					Resources = new string[5] { "leather", "deer hide", "flint", "wood", "resin" },
					CraftingStations = new string[2] { "workbench", "$piece_workbench" }
				}
			},
			{
				"BlackForest",
				new BiomeConfig
				{
					Resources = new string[5] { "bronze", "copper", "tin", "core wood", "troll hide" },
					CraftingStations = new string[2] { "forge", "$piece_forge" }
				}
			},
			{
				"Swamp",
				new BiomeConfig
				{
					Resources = new string[5] { "iron", "ancient bark", "root", "guck", "chain" },
					CraftingStations = new string[2] { "forge", "$piece_forge" }
				}
			},
			{
				"Mountain",
				new BiomeConfig
				{
					Resources = new string[5] { "silver", "wolf pelt", "wolf fang", "obsidian", "dragon tear" },
					CraftingStations = new string[2] { "forge", "$piece_forge" }
				}
			},
			{
				"Plains",
				new BiomeConfig
				{
					Resources = new string[5] { "black metal", "linen thread", "needle", "lox pelt", "barley" },
					CraftingStations = new string[4] { "forge", "$piece_forge", "artisan table", "$piece_artisanstation" }
				}
			},
			{
				"Mistlands",
				new BiomeConfig
				{
					Resources = new string[6] { "carapace", "refined eitr", "yggdrasil wood", "scale hide", "bilebag", "mandible" },
					CraftingStations = new string[4] { "black forge", "$piece_blackforge", "galdr table", "$piece_galdrtable" }
				}
			},
			{
				"Ashlands",
				new BiomeConfig
				{
					Resources = new string[4] { "flametal", "asksvin hide", "primal lava", "charred bone" },
					CraftingStations = new string[2] { "black forge", "$piece_blackforge" }
				}
			}
		};

		private static readonly HashSet<string> _itemBlacklist = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "butcher knife", "deer" };

		public static ValhalLootManager Instance => _instance;

		public ValhalLootConfig Config
		{
			get
			{
				return _config;
			}
			set
			{
				_config = value;
			}
		}

		public void Awake()
		{
			if ((Object)(object)_instance == (Object)null)
			{
				_instance = this;
			}
			else if ((Object)(object)_instance != (Object)(object)this)
			{
				Object.Destroy((Object)(object)((Component)this).gameObject);
				return;
			}
			ValhalLootPlugin.ValhalLootLogger.LogInfo((object)"ValhalLoot Manager awakening");
			AddChestLocalizations();
			PrefabManager.OnVanillaPrefabsAvailable += OnVanillaPrefabsAvailable;
		}

		private void AddChestLocalizations()
		{
			ValhalLootPlugin.ValhalLootLogger.LogInfo((object)"Adding chest item localizations");
			Dictionary<string, string> dictionary = new Dictionary<string, string>
			{
				{ "item_meadowsloot_ru", "Meadows Treasure Chest" },
				{ "item_meadowsloot_ru_description", "A chest containing treasures from the Meadows. Right-click to open." },
				{ "item_blackforestloot_ru", "Black Forest Treasure Chest" },
				{ "item_blackforestloot_ru_description", "A chest containing treasures from the Black Forest. Right-click to open." },
				{ "item_swamploot_ru", "Swamp Treasure Chest" },
				{ "item_swamploot_ru_description", "A chest containing treasures from the Swamp. Right-click to open." },
				{ "item_mountainsloot_ru", "Mountain Treasure Chest" },
				{ "item_mountainsloot_ru_description", "A chest containing treasures from the Mountains. Right-click to open." },
				{ "item_plainsloot_ru", "Plains Treasure Chest" },
				{ "item_plainsloot_ru_description", "A chest containing treasures from the Plains. Right-click to open." },
				{ "item_mistlandsloot_ru", "Mistlands Treasure Chest" },
				{ "item_mistlandsloot_ru_description", "A chest containing treasures from the Mistlands. Right-click to open." },
				{ "item_ashlandsloot_ru", "Ashlands Treasure Chest" },
				{ "item_ashlandsloot_ru_description", "A chest containing treasures from the Ashlands. Right-click to open." }
			};
			try
			{
				CustomLocalization localization = LocalizationManager.Instance.GetLocalization();
				string text = "English";
				localization.AddTranslation(ref text, dictionary);
				ValhalLootPlugin.ValhalLootLogger.LogInfo((object)$"Added {dictionary.Count} chest localizations to Jotunn");
			}
			catch (Exception ex)
			{
				ValhalLootPlugin.ValhalLootLogger.LogWarning((object)("Could not add Jotunn localizations in Awake: " + ex.Message));
			}
		}

		private void OnVanillaPrefabsAvailable()
		{
			try
			{
				ValhalLootPlugin.ValhalLootLogger.LogInfo((object)"Registering chest items with Jotunn");
				AddLocalizationsToValheim();
				RegisterChestPrefabs();
			}
			catch (Exception ex)
			{
				ValhalLootPlugin.ValhalLootLogger.LogError((object)("Error in OnVanillaPrefabsAvailable: " + ex.Message));
			}
		}

		private void AddLocalizationsToValheim()
		{
			if (Localization.instance == null)
			{
				ValhalLootPlugin.ValhalLootLogger.LogWarning((object)"Localization.instance is null, cannot add chest localizations");
				return;
			}
			Dictionary<string, string> dictionary = new Dictionary<string, string>
			{
				{ "item_meadowsloot_ru", "Meadows Treasure Chest" },
				{ "item_meadowsloot_ru_description", "A chest containing treasures from the Meadows. Right-click to open." },
				{ "item_blackforestloot_ru", "Black Forest Treasure Chest" },
				{ "item_blackforestloot_ru_description", "A chest containing treasures from the Black Forest. Right-click to open." },
				{ "item_swamploot_ru", "Swamp Treasure Chest" },
				{ "item_swamploot_ru_description", "A chest containing treasures from the Swamp. Right-click to open." },
				{ "item_mountainsloot_ru", "Mountain Treasure Chest" },
				{ "item_mountainsloot_ru_description", "A chest containing treasures from the Mountains. Right-click to open." },
				{ "item_plainsloot_ru", "Plains Treasure Chest" },
				{ "item_plainsloot_ru_description", "A chest containing treasures from the Plains. Right-click to open." },
				{ "item_mistlandsloot_ru", "Mistlands Treasure Chest" },
				{ "item_mistlandsloot_ru_description", "A chest containing treasures from the Mistlands. Right-click to open." },
				{ "item_ashlandsloot_ru", "Ashlands Treasure Chest" },
				{ "item_ashlandsloot_ru_description", "A chest containing treasures from the Ashlands. Right-click to open." }
			};
			foreach (KeyValuePair<string, string> item in dictionary)
			{
				Localization.instance.AddWord("$" + item.Key, item.Value);
			}
			ValhalLootPlugin.ValhalLootLogger.LogInfo((object)$"Added {dictionary.Count} chest localizations to Valheim's Localization.instance");
		}

		private void RegisterChestPrefabs()
		{
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Expected O, but got Unknown
			//IL_00b8: 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_00f0: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				AssetBundle val = null;
				val = ((IEnumerable<AssetBundle>)Resources.FindObjectsOfTypeAll<AssetBundle>()).FirstOrDefault((Func<AssetBundle, bool>)([<022029f3-5fce-4252-8684-e6648986aff8>NullableContext(0)] (AssetBundle a) => ((Object)a).name == "lootbundle_ru"));
				if ((Object)(object)val == (Object)null)
				{
					ValhalLootPlugin.ValhalLootLogger.LogError((object)"Failed to load lootbundle_ru asset bundle");
					return;
				}
				ValhalLootPlugin.ValhalLootLogger.LogInfo((object)("Successfully loaded asset bundle: " + ((Object)val).name));
				Sprite val2 = val.LoadAsset<Sprite>("valhalloot_ru_icon");
				if ((Object)(object)val2 == (Object)null)
				{
					Sprite[] array = val.LoadAllAssets<Sprite>();
					if (array != null && array.Length != 0)
					{
						val2 = array[0];
					}
					else
					{
						Texture2D val3 = new Texture2D(1, 1);
						val3.SetPixel(0, 0, Color.white);
						val3.Apply();
						val2 = Sprite.Create(val3, new Rect(0f, 0f, 1f, 1f), new Vector2(0.5f, 0.5f));
					}
				}
				string[] array2 = new string[7] { "meadowsloot_ru", "blackforestloot_ru", "swamploot_ru", "mountainsloot_ru", "plainsloot_ru", "mistlandsloot_ru", "ashlandsloot_ru" };
				int num = 0;
				string[] array3 = array2;
				foreach (string text in array3)
				{
					try
					{
						string text2 = text;
						ValhalLootPlugin.ValhalLootLogger.LogInfo((object)("Loading prefab from asset bundle: " + text2));
						GameObject val4 = val.LoadAsset<GameObject>(text2);
						if ((Object)(object)val4 == (Object)null)
						{
							ValhalLootPlugin.ValhalLootLogger.LogWarning((object)("Could not find prefab " + text));
							continue;
						}
						ValhalLootPlugin.ValhalLootLogger.LogInfo((object)("Successfully loaded prefab for " + text));
						if (_chestPrefabToBiome.TryGetValue(text, out var value))
						{
							_biomePrefabs[value] = val4;
						}
						CreateJotunnCustomItem(val4, val2, text);
						num++;
					}
					catch (Exception ex)
					{
						ValhalLootPlugin.ValhalLootLogger.LogError((object)("Error registering prefab " + text + ": " + ex.Message));
					}
				}
				ValhalLootPlugin.ValhalLootLogger.LogInfo((object)$"Registered {num} chest prefabs");
			}
			catch (Exception ex2)
			{
				ValhalLootPlugin.ValhalLootLogger.LogError((object)("Error in RegisterChestPrefabs: " + ex2.Message + "\n" + ex2.StackTrace));
			}
		}

		public void ProcessChestUse(Player player, ItemData item)
		{
			if ((Object)(object)player == (Object)null || item == null)
			{
				ValhalLootPlugin.ValhalLootLogger.LogWarning((object)"ProcessChestUse called with null player or item");
				return;
			}
			ValhalLootPlugin.ValhalLootLogger.LogInfo((object)("Player " + player.GetPlayerName() + " used ValhalLoot chest"));
			if ((Object)(object)ValhalLootUI.Instance != (Object)null)
			{
				ValhalLootUI.Instance.ShowLootSelection(item);
				((Humanoid)player).GetInventory().RemoveItem(item, 1);
			}
		}

		public string GetChestPrefabName(ItemData chestItem)
		{
			if (chestItem == null)
			{
				ValhalLootPlugin.ValhalLootLogger.LogWarning((object)"Cannot get prefab name for null chest item");
				return "meadowsloot_ru";
			}
			GameObject dropPrefab = chestItem.m_dropPrefab;
			string text = ((dropPrefab != null) ? ((Object)dropPrefab).name : null) ?? "";
			if (string.IsNullOrEmpty(text))
			{
				ValhalLootPlugin.ValhalLootLogger.LogWarning((object)"Chest item has no prefab name");
				return "meadowsloot_ru";
			}
			return text;
		}

		public void Initialize(ValhalLootConfig config)
		{
			Config = config;
			((MonoBehaviour)this).StartCoroutine(InitializeWhenReady());
			ValhalLootPlugin.ValhalLootLogger.LogInfo((object)"ValhalLoot Manager initialization started");
		}

		[IteratorStateMachine(typeof(<InitializeWhenReady>d__22))]
		private IEnumerator InitializeWhenReady()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <InitializeWhenReady>d__22(0)
			{
				<>4__this = this
			};
		}

		private bool IsCombatItem(SharedData shared)
		{
			//IL_000f: 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_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Invalid comparison between Unknown and I4
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Invalid comparison between Unknown and I4
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Invalid comparison between Unknown and I4
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Invalid comparison between Unknown and I4
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Invalid comparison between Unknown and I4
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Invalid comparison between Unknown and I4
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Invalid comparison between Unknown and I4
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Invalid comparison between Unknown and I4
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Invalid comparison between Unknown and I4
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Invalid comparison between Unknown and I4
			if (shared == null)
			{
				return false;
			}
			ItemType itemType = shared.m_itemType;
			return (int)itemType == 3 || (int)itemType == 14 || (int)itemType == 22 || (int)itemType == 4 || (int)itemType == 5 || (int)itemType == 7 || (int)itemType == 11 || (int)itemType == 6 || (int)itemType == 17 || (int)itemType == 12;
		}

		private void BuildDynamicChestLootFromObjectDB()
		{
			try
			{
				if (Config == null)
				{
					ValhalLootPlugin.ValhalLootLogger.LogWarning((object)"[RECIPE LOOT] Cannot build dynamic loot: Config is null");
					return;
				}
				if ((Object)(object)ObjectDB.instance == (Object)null || ObjectDB.instance.m_recipes == null)
				{
					ValhalLootPlugin.ValhalLootLogger.LogWarning((object)"[RECIPE LOOT] Cannot build dynamic loot: ObjectDB.instance or recipes is null");
					return;
				}
				ValhalLootPlugin.ValhalLootLogger.LogInfo((object)$"[RECIPE LOOT] Starting Recipe-based loot generation. Found {ObjectDB.instance.m_recipes.Count} total recipes.");
				Config.ChestLoot.Clear();
				Dictionary<Recipe, string> dictionary = new Dictionary<Recipe, string>();
				string[] array = new string[7] { "Ashlands", "Mistlands", "Plains", "Mountain", "Swamp", "BlackForest", "Meadows" };
				int num = 0;
				int num2 = 0;
				int num3 = 0;
				int num4 = 0;
				string[] array2 = array;
				foreach (string text in array2)
				{
					if (!_biomeConfigs.TryGetValue(text, out var value))
					{
						continue;
					}
					if (!_biomeToPrefabMap.TryGetValue(text, out var value2))
					{
						ValhalLootPlugin.ValhalLootLogger.LogWarning((object)("[RECIPE LOOT] No chest prefab mapped for biome '" + text + "'"));
						continue;
					}
					List<LootEntry> list = new List<LootEntry>();
					foreach (Recipe recipe in ObjectDB.instance.m_recipes)
					{
						num++;
						if ((Object)(object)recipe == (Object)null || (Object)(object)recipe.m_item == (Object)null || !recipe.m_enabled || dictionary.ContainsKey(recipe))
						{
							continue;
						}
						ItemDrop item = recipe.m_item;
						if ((Object)(object)item == (Object)null || item.m_itemData == null || item.m_itemData.m_shared == null)
						{
							continue;
						}
						SharedData shared = item.m_itemData.m_shared;
						if (IsItemBlacklisted(((Object)((Component)recipe.m_item).gameObject).name, shared.m_name))
						{
							num3++;
							continue;
						}
						if (!IsCombatItem(shared))
						{
							num4++;
							continue;
						}
						bool flag = RecipeMatchesResources(recipe, value.Resources);
						bool flag2 = RecipeMatchesCraftingStation(recipe, value.CraftingStations);
						string text2 = ((Object)((Component)recipe.m_item).gameObject).name.ToLower();
						bool flag3 = text2.Contains("blackmetal") || text2.Contains("sledge") || text2.Contains("flametal") || text2.Contains("carapace");
						if (flag && flag2)
						{
							int num5 = Mathf.Max(1, shared.m_maxQuality);
							int minQuality = ((num5 < 2) ? 1 : 2);
							LootEntry item2 = new LootEntry
							{
								ItemName = ((Object)((Component)recipe.m_item).gameObject).name,
								MinQuality = minQuality,
								MaxQuality = num5,
								Weight = 1f,
								Recipe = recipe
							};
							list.Add(item2);
							dictionary[recipe] = value2;
							num2++;
						}
					}
					if (list.Count > 0)
					{
						Config.ChestLoot[value2] = list;
						ValhalLootPlugin.ValhalLootLogger.LogInfo((object)$"[RECIPE LOOT] Biome '{text}' (chest '{value2}'): {list.Count} recipes assigned");
					}
					else
					{
						ValhalLootPlugin.ValhalLootLogger.LogWarning((object)("[RECIPE LOOT] Biome '" + text + "' has no matching recipes!"));
					}
				}
				ValhalLootPlugin.ValhalLootLogger.LogInfo((object)"[RECIPE LOOT] Recipe-based loot generation complete:");
				ValhalLootPlugin.ValhalLootLogger.LogInfo((object)$"  Total recipes scanned: {num}");
				ValhalLootPlugin.ValhalLootLogger.LogInfo((object)$"  Recipes assigned to chests: {num2}");
				ValhalLootPlugin.ValhalLootLogger.LogInfo((object)$"  Skipped (blacklisted): {num3}");
				ValhalLootPlugin.ValhalLootLogger.LogInfo((object)$"  Skipped (non-combat): {num4}");
			}
			catch (Exception ex)
			{
				ValhalLootPlugin.ValhalLootLogger.LogError((object)("Error building Recipe-based chest loot tables: " + ex.Message + "\n" + ex.StackTrace));
			}
		}

		private bool RecipeMatchesResources(Recipe recipe, string[] biomeResources)
		{
			if (recipe.m_resources == null || recipe.m_resources.Length == 0)
			{
				return false;
			}
			Requirement[] resources = recipe.m_resources;
			foreach (Requirement val in resources)
			{
				if ((Object)(object)val.m_resItem == (Object)null)
				{
					continue;
				}
				string text = ((Object)val.m_resItem).name.ToLower();
				string text2 = Localization.instance.Localize(val.m_resItem.m_itemData.m_shared.m_name).ToLower();
				foreach (string text3 in biomeResources)
				{
					string text4 = text3.ToLower();
					bool flag = text == text4 || text2 == text4;
					bool flag2 = text.Contains(" " + text4 + " ") || text.StartsWith(text4 + " ") || text.EndsWith(" " + text4) || text2.Contains(" " + text4 + " ") || text2.StartsWith(text4 + " ") || text2.EndsWith(" " + text4);
					if (flag || flag2)
					{
						return true;
					}
				}
			}
			return false;
		}

		private bool RecipeMatchesCraftingStation(Recipe recipe, string[] biomeCraftingStations)
		{
			if ((Object)(object)recipe.m_craftingStation == (Object)null)
			{
				return false;
			}
			string text = ((Object)recipe.m_craftingStation).name.ToLower();
			string text2 = Localization.instance.Localize(recipe.m_craftingStation.m_name).ToLower();
			foreach (string text3 in biomeCraftingStations)
			{
				string value = text3.ToLower();
				if (text.Contains(value) || text2.Contains(value))
				{
					return true;
				}
			}
			return false;
		}

		private bool IsItemBlacklisted(string prefabName, string localizedName)
		{
			if (_itemBlacklist.Contains(prefabName.ToLower()))
			{
				return true;
			}
			string item = Localization.instance.Localize(localizedName).ToLower();
			if (_itemBlacklist.Contains(item))
			{
				return true;
			}
			return false;
		}

		private string NormalizeEnemyName(string name)
		{
			if (string.IsNullOrEmpty(name))
			{
				return string.Empty;
			}
			string text = name.Replace("(Clone)", "").Trim();
			return text.ToLowerInvariant();
		}

		public void RegisterRPCs(ZRoutedRpc rpc)
		{
			//IL_021f: 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_00ea: Expected O, but got Unknown
			//IL_00ee: 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_0126: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				AssetBundle val = null;
				val = ((IEnumerable<AssetBundle>)Resources.FindObjectsOfTypeAll<AssetBundle>()).FirstOrDefault((Func<AssetBundle, bool>)([<022029f3-5fce-4252-8684-e6648986aff8>NullableContext(0)] (AssetBundle a) => ((Object)a).name == "lootbundle_ru"));
				if ((Object)(object)val == (Object)null)
				{
					ValhalLootPlugin.ValhalLootLogger.LogError((object)"Failed to load lootbundle_ru asset bundle");
					return;
				}
				ValhalLootPlugin.ValhalLootLogger.LogInfo((object)"Loading chest icon sprite");
				Sprite val2 = val.LoadAsset<Sprite>("valhalloot_ru_icon");
				if ((Object)(object)val2 == (Object)null)
				{
					ValhalLootPlugin.ValhalLootLogger.LogWarning((object)"Could not find valhalloot_ru_icon, looking for any sprite in the bundle");
					Sprite[] array = val.LoadAllAssets<Sprite>();
					if (array != null && array.Length != 0)
					{
						ValhalLootPlugin.ValhalLootLogger.LogInfo((object)$"Found {array.Length} sprites in the bundle, using the first one");
						val2 = array[0];
					}
					else
					{
						ValhalLootPlugin.ValhalLootLogger.LogWarning((object)"No sprites found in bundle, creating placeholder sprite");
						Texture2D val3 = new Texture2D(1, 1);
						val3.SetPixel(0, 0, Color.white);
						val3.Apply();
						val2 = Sprite.Create(val3, new Rect(0f, 0f, 1f, 1f), new Vector2(0.5f, 0.5f));
					}
				}
				string[] array2 = new string[7] { "meadowsloot_ru", "blackforestloot_ru", "swamploot_ru", "mountainsloot_ru", "plainsloot_ru", "mistlandsloot_ru", "ashlandsloot_ru" };
				Dictionary<string, GameObject> dictionary = new Dictionary<string, GameObject>();
				string[] array3 = array2;
				foreach (string text in array3)
				{
					string text2 = "assets/ruijven/valhalloot/" + text + ".prefab";
					ValhalLootPlugin.ValhalLootLogger.LogInfo((object)("Loading prefab directly from asset bundle: " + text2));
					GameObject val4 = val.LoadAsset<GameObject>(text2);
					if ((Object)(object)val4 == (Object)null)
					{
						ValhalLootPlugin.ValhalLootLogger.LogError((object)("Failed to load prefab " + text2 + " from asset bundle"));
						continue;
					}
					ValhalLootPlugin.ValhalLootLogger.LogInfo((object)("Successfully loaded prefab for " + text));
					dictionary[text] = val4;
					try
					{
						EnsureItemDropComponent(val4);
						new Item(val4, false);
						ValhalLootPlugin.ValhalLootLogger.LogInfo((object)("Registered " + text + " with custom ItemManager"));
					}
					catch (Exception ex)
					{
						ValhalLootPlugin.ValhalLootLogger.LogError((object)("Error registering with custom ItemManager: " + ex.Message));
					}
					try
					{
						CreateJotunnCustomItem(val4, val2, text);
					}
					catch (Exception ex2)
					{
						ValhalLootPlugin.ValhalLootLogger.LogError((object)("Error registering with Jotunn: " + ex2.Message));
					}
				}
				ValhalLootPlugin.ValhalLootLogger.LogInfo((object)"Adding localization for chest items and UI elements");
				Dictionary<string, string> dictionary2 = new Dictionary<string, string>
				{
					{ "valhalloot_ui_title", "ValhalLoot Treasure" },
					{ "valhalloot_ui_description", "Select your reward" },
					{ "valhalloot_ui_select", "Claim" },
					{ "valhalloot_ui_close", "Close" },
					{ "valhalloot_drop_title", "Drop Loot Chest?" },
					{ "valhalloot_drop_message", "If you throw this Loot Chest away, you will not be able to reclaim it." },
					{ "valhalloot_drop_confirm", "Okay" },
					{ "valhalloot_drop_cancel", "Cancel" },
					{ "valhalloot_inventory_full", "Inventory full! Cannot receive loot chest." },
					{ "valhalloot_received", "Received a loot chest!" },
					{ "item_meadowsloot_ru", "Meadows Treasure Chest" },
					{ "item_meadowsloot_ru_description", "A chest containing treasures from the Meadows. Right-click to open." },
					{ "item_blackforestloot_ru", "Black Forest Treasure Chest" },
					{ "item_blackforestloot_ru_description", "A chest containing treasures from the Black Forest. Right-click to open." },
					{ "item_swamploot_ru", "Swamp Treasure Chest" },
					{ "item_swamploot_ru_description", "A chest containing treasures from the Swamp. Right-click to open." },
					{ "item_mountainsloot_ru", "Mountain Treasure Chest" },
					{ "item_mountainsloot_ru_description", "A chest containing treasures from the Mountains. Right-click to open." },
					{ "item_plainsloot_ru", "Plains Treasure Chest" },
					{ "item_plainsloot_ru_description", "A chest containing treasures from the Plains. Right-click to open." },
					{ "item_mistlandsloot_ru", "Mistlands Treasure Chest" },
					{ "item_mistlandsloot_ru_description", "A chest containing treasures from the Mistlands. Right-click to open." },
					{ "item_ashlandsloot_ru", "Ashlands Treasure Chest" },
					{ "item_ashlandsloot_ru_description", "A chest containing treasures from the Ashlands. Right-click to open." }
				};
				CustomLocalization localization = LocalizationManager.Instance.GetLocalization();
				string text3 = "English";
				localization.AddTranslation(ref text3, dictionary2);
				if (Localization.instance != null)
				{
					ValhalLootPlugin.ValhalLootLogger.LogInfo((object)"Adding translations to Valheim Localization system");
					foreach (KeyValuePair<string, string> item in dictionary2)
					{
						Localization.instance.AddWord("$" + item.Key, item.Value);
					}
				}
				else
				{
					ValhalLootPlugin.ValhalLootLogger.LogWarning((object)"Valheim Localization instance not available, translations may not work properly");
				}
				((MonoBehaviour)this).StartCoroutine(VerifyAndFixRegistration(dictionary));
				PrefabManager.OnVanillaPrefabsAvailable -= OnVanillaPrefabsAvailable;
			}
			catch (Exception ex3)
			{
				ValhalLootPlugin.ValhalLootLogger.LogError((object)("Error registering chest items: " + ex3.Message));
				ValhalLootPlugin.ValhalLootLogger.LogError((object)("Stack trace: " + ex3.StackTrace));
			}
		}

		private void CreateJotunnCustomItem(GameObject prefab, Sprite iconSprite, string chestPrefabName)
		{
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Expected O, but got Unknown
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Expected O, but got Unknown
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Expected O, but got Unknown
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Expected O, but got Unknown
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Expected O, but got Unknown
			//IL_026d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0274: Unknown result type (might be due to invalid IL or missing references)
			//IL_0288: Unknown result type (might be due to invalid IL or missing references)
			//IL_0292: Expected O, but got Unknown
			//IL_0293: Unknown result type (might be due to invalid IL or missing references)
			//IL_029d: Expected O, but got Unknown
			//IL_02a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02af: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0306: Expected O, but got Unknown
			//IL_030a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0333: Unknown result type (might be due to invalid IL or missing references)
			//IL_0342: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if ((Object)(object)prefab == (Object)null)
				{
					ValhalLootPlugin.ValhalLootLogger.LogError((object)("Cannot create CustomItem: prefab is null for " + chestPrefabName));
					return;
				}
				ValhalLootPlugin.ValhalLootLogger.LogInfo((object)("Creating Jotunn CustomItem for " + chestPrefabName));
				ItemDrop val = prefab.GetComponent<ItemDrop>();
				if ((Object)(object)val == (Object)null)
				{
					ValhalLootPlugin.ValhalLootLogger.LogInfo((object)("ItemDrop component missing on " + ((Object)prefab).name + ", adding it"));
					try
					{
						val = prefab.AddComponent<ItemDrop>();
						if ((Object)(object)val == (Object)null)
						{
							ValhalLootPlugin.ValhalLootLogger.LogError((object)("Failed to add ItemDrop component to " + ((Object)prefab).name));
							return;
						}
						val.m_itemData = new ItemData();
						val.m_itemData.m_shared = new SharedData();
					}
					catch (Exception ex)
					{
						ValhalLootPlugin.ValhalLootLogger.LogError((object)("Exception adding ItemDrop component: " + ex.Message + "\n" + ex.StackTrace));
						return;
					}
				}
				if (val.m_itemData == null)
				{
					ValhalLootPlugin.ValhalLootLogger.LogError((object)("ItemDrop.m_itemData is null on " + ((Object)prefab).name));
					val.m_itemData = new ItemData();
				}
				if (val.m_itemData.m_shared == null)
				{
					ValhalLootPlugin.ValhalLootLogger.LogError((object)("ItemDrop.m_itemData.m_shared is null on " + ((Object)prefab).name));
					val.m_itemData.m_shared = new SharedData();
				}
				CustomItem val2 = null;
				try
				{
					val2 = new CustomItem(prefab, true);
					ValhalLootPlugin.ValhalLootLogger.LogInfo((object)("CustomItem created successfully for " + ((Object)prefab).name));
				}
				catch (Exception ex2)
				{
					ValhalLootPlugin.ValhalLootLogger.LogError((object)("Failed to create CustomItem: " + ex2.Message + "\n" + ex2.StackTrace));
					return;
				}
				if (val2 == null || (Object)(object)val2.ItemDrop == (Object)null)
				{
					ValhalLootPlugin.ValhalLootLogger.LogError((object)("CustomItem or its ItemDrop is null for " + ((Object)prefab).name));
					return;
				}
				SharedData shared = val2.ItemDrop.m_itemData.m_shared;
				shared.m_name = "$item_" + ((Object)prefab).name;
				shared.m_description = "$item_" + ((Object)prefab).name + "_description";
				shared.m_maxQuality = 1;
				shared.m_maxStackSize = 20;
				shared.m_equipDuration = 0.2f;
				shared.m_variants = 1;
				shared.m_itemType = (ItemType)2;
				shared.m_animationState = (AnimationState)1;
				shared.m_questItem = true;
				shared.m_useDurability = false;
				shared.m_attack = new Attack();
				shared.m_secondaryAttack = new Attack();
				shared.m_damages = default(DamageTypes);
				shared.m_damagesPerLevel = default(DamageTypes);
				shared.m_damageModifiers = new List<DamageModPair>();
				if ((Object)(object)iconSprite != (Object)null)
				{
					shared.m_icons = (Sprite[])(object)new Sprite[1] { iconSprite };
				}
				else
				{
					ValhalLootPlugin.ValhalLootLogger.LogWarning((object)("No icon sprite provided for " + chestPrefabName + ", creating placeholder"));
					Texture2D val3 = new Texture2D(1, 1);
					val3.SetPixel(0, 0, Color.white);
					val3.Apply();
					Sprite val4 = Sprite.Create(val3, new Rect(0f, 0f, 1f, 1f), new Vector2(0.5f, 0.5f));
					shared.m_icons = (Sprite[])(object)new Sprite[1] { val4 };
				}
				if (val2.ItemDrop.m_itemData.m_customData == null)
				{
					val2.ItemDrop.m_itemData.m_customData = new Dictionary<string, string>();
				}
				string key = "CustomData_ValhalLoot";
				if (!val2.ItemDrop.m_itemData.m_customData.ContainsKey(key))
				{
					val2.ItemDrop.m_itemData.m_customData[key] = "{}";
				}
				val2.ItemDrop.m_itemData.m_customData["ChestID"] = Guid.NewGuid().ToString();
				val2.ItemDrop.m_itemData.m_customData["PrefabName"] = chestPrefabName;
				ItemManager.Instance.AddItem(val2);
				ValhalLootPlugin.ValhalLootLogger.LogInfo((object)("Successfully registered " + ((Object)prefab).name + " with Jotunn ItemManager"));
				if ((Object)(object)ObjectDB.instance != (Object)null)
				{
					GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(((Object)prefab).name);
					if (!((Object)(object)itemPrefab != (Object)null))
					{
						ValhalLootPlugin.ValhalLootLogger.LogError((object)("DEBUG: FAILED to find " + ((Object)prefab).name + " in ObjectDB after registration!"));
					}
				}
			}
			catch (Exception ex3)
			{
				ValhalLootPlugin.ValhalLootLogger.LogError((object)("Error creating Jotunn CustomItem: " + ex3.Message));
				ValhalLootPlugin.ValhalLootLogger.LogError((object)("Stack trace: " + ex3.StackTrace));
			}
		}

		[IteratorStateMachine(typeof(<VerifyAndFixRegistration>d__31))]
		private IEnumerator VerifyAndFixRegistration(Dictionary<string, GameObject> loadedPrefabs)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <VerifyAndFixRegistration>d__31(0)
			{
				<>4__this = this,
				loadedPrefabs = loadedPrefabs
			};
		}

		private void RegisterStatusEffect(StatusEffect statusEffect)
		{
			if ((Object)(object)statusEffect != (Object)null && (Object)(object)ObjectDB.instance != (Object)null && !Object.op_Implicit((Object)(object)ObjectDB.instance.GetStatusEffect(StringExtensionMethods.GetStableHashCode(((Object)statusEffect).name))))
			{
				ObjectDB.instance.m_StatusEffects.Add(statusEffect);
			}
		}

		private void EnsureItemDropComponent(GameObject prefab)
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Expected O, but got Unknown
			//IL_00dc: 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_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Expected O, but got Unknown
			ItemDrop val = prefab.GetComponent<ItemDrop>();
			if ((Object)(object)val == (Object)null)
			{
				ValhalLootPlugin.ValhalLootLogger.LogInfo((object)("ItemDrop component missing on " + ((Object)prefab).name + ", adding it"));
				val = prefab.AddComponent<ItemDrop>();
			}
			if (val.m_itemData == null)
			{
				val.m_itemData = new ItemData();
			}
			if (val.m_itemData.m_shared == null)
			{
				val.m_itemData.m_shared = new SharedData();
			}
			SharedData shared = val.m_itemData.m_shared;
			shared.m_name = "$item_" + ((Object)prefab).name;
			shared.m_description = "$item_" + ((Object)prefab).name + "_description";
			shared.m_maxQuality = 1;
			shared.m_maxStackSize = 20;
			shared.m_equipDuration = 0.2f;
			shared.m_variants = 1;
			shared.m_itemType = (ItemType)2;
			shared.m_animationState = (AnimationState)1;
			shared.m_questItem = true;
			shared.m_useDurability = false;
		}

		[return: <6c1629e0-990f-46fb-933a-fb94e8696503>Nullable(2)]
		private Player GetPlayerByID(string playerID)
		{
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			if (string.IsNullOrEmpty(playerID) || (Object)(object)ZNet.instance == (Object)null)
			{
				return null;
			}
			long result;
			bool flag = long.TryParse(playerID, out result);
			List<ZNetPeer> peers = ZNet.instance.GetPeers();
			foreach (ZNetPeer item in peers)
			{
				GameObject val = ZNetScene.instance.FindInstance(item.m_characterID);
				if ((Object)(object)val != (Object)null)
				{
					Player component = val.GetComponent<Player>();
					if ((Object)(object)component != (Object)null && ((flag && component.GetPlayerID() == result) || (!flag && component.GetPlayerID().ToString() == playerID)))
					{
						return component;
					}
				}
			}
			if ((Object)(object)Player.m_localPlayer != (Object)null && ((flag && Player.m_localPlayer.GetPlayerID() == result) || (!flag && Player.m_localPlayer.GetPlayerID().ToString() == playerID)))
			{
				return Player.m_localPlayer;
			}
			return null;
		}

		public bool ShouldDropChest(Character enemy, Player killer)
		{
			if ((Object)(object)enemy == (Object)null || (Object)(object)killer == (Object)null)
			{
				ValhalLootPlugin.ValhalLootLogger.LogWarning((object)"ShouldDropChest called with null enemy or killer");
				return false;
			}
			if (!_isInitialized)
			{
				ValhalLootPlugin.ValhalLootLogger.LogWarning((object)("ValhalLootManager not fully initialized when checking drop for " + enemy.m_name + ". Checking if we can proceed anyway."));
				if (Config == null)
				{
					ValhalLootPlugin.ValhalLootLogger.LogError((object)"Cannot proceed with drop check: Config is null");
					return false;
				}
			}
			string prefabName = Utils.GetPrefabName(((Component)enemy).gameObject);
			string text = NormalizeEnemyName(prefabName);
			ValhalLootPlugin.ValhalLootLogger.LogInfo((object)("Normalized enemy prefab name from " + prefabName + " to " + text));
			if (enemy.IsBoss())
			{
				ValhalLootPlugin.ValhalLootLogger.LogInfo((object)("Enemy " + text + " is a boss"));
				string enemyChestPrefab = GetEnemyChestPrefab(enemy);
				if (string.IsNullOrEmpty(enemyChestPrefab))
				{
					ValhalLootPlugin.ValhalLootLogger.LogInfo((object)("Boss " + text + " not found in any chest mapping, skipping drop"));
					return false;
				}
				float value = Config.BossDropChance.Value;
				float value2 = Random.value;
				bool flag = value2 <= value;
				string text2 = killer.GetPlayerID().ToString();
				string playerName = killer.GetPlayerName();
				ValhalLootPlugin.ValhalLootLogger.LogInfo((object)$"Boss drop roll for {text} (killed by {playerName}): {value2} vs chance {value}, shouldDrop: {flag}");
				return flag;
			}
			List<string> list = new List<string> { "Skeleton_Hildir", "Fenring_Cultist_Hildir", "GoblinBrute_Hildir", "Charred_Melee_Dyrnwyn" };
			if (list.Contains(text))
			{
				ValhalLootPlugin.ValhalLootLogger.LogInfo((object)("Enemy " + text + " is in miniboss list"));
				string enemyChestPrefab2 = GetEnemyChestPrefab(enemy);
				if (string.IsNullOrEmpty(enemyChestPrefab2))
				{
					ValhalLootPlugin.ValhalLootLogger.LogInfo((object)("Miniboss " + text + " not found in any chest mapping, skipping drop"));
					return false;
				}
				float value3 = Config.MinibossDropChance.Value;
				float value4 = Random.value;
				bool flag2 = value4 <= value3;
				string text3 = killer.GetPlayerID().ToString();
				string playerName2 = killer.GetPlayerName();
				ValhalLootPlugin.ValhalLootLogger.LogInfo((object)$"Miniboss drop roll for {text} (killed by {playerName2}): {value4} vs chance {value3}, shouldDrop: {flag2}");
				return flag2;
			}
			string enemyChestPrefab3 = GetEnemyChestPrefab(enemy);
			if (!string.IsNullOrEmpty(enemyChestPrefab3))
			{
				ValhalLootPlugin.ValhalLootLogger.LogInfo((object)("Enemy " + text + " is in chest-enemy mapping for " + enemyChestPrefab3));
				float value5 = Config.CreatureDropChance.Value;
				float value6 = Random.value;
				bool flag3 = value6 <= value5;
				string text4 = killer.GetPlayerID().ToString();
				string playerName3 = killer.GetPlayerName();
				ValhalLootPlugin.ValhalLootLogger.LogInfo((object)$"Regular creature drop roll for {text} (killed by {playerName3}): {value6} vs chance {value5}, shouldDrop: {flag3}");
				return flag3;
			}
			ValhalLootPlugin.ValhalLootLogger.LogInfo((object)("Enemy " + text + " is not in any chest mapping, skipping drop"));
			return false;
		}

		public string GetEnemyChestPrefab(Character enemy)
		{
			if ((Object)(object)enemy == (Object)null)
			{
				return string.Empty;
			}
			try
			{
				string prefabName = Utils.GetPrefabName(((Component)enemy).gameObject);
				string text = NormalizeEnemyName(prefabName);
				ValhalLootPlugin.ValhalLootLogger.LogInfo((object)("Mapping enemy: prefab=" + prefabName + ", normalized=" + text));
				if (Config.EnemyToChestMap.TryGetValue(text, out var value))
				{
					ValhalLootPlugin.ValhalLootLogger.LogInfo((object)("Enemy '" + text + "' directly mapped to chest '" + value + "'"));
					return value;
				}
				foreach (KeyValuePair<string, List<string>> item in Config.ChestEnemyMap)
				{
					string key = item.Key;
					List<string> value2 = item.Value;
					foreach (string item2 in value2)
					{
						if (text.Equals(item2, StringComparison.OrdinalIgnoreCase))
						{
							ValhalLootPlugin.ValhalLootLogger.LogInfo((object)("Enemy '" + text + "' mapped to chest '" + key + "' via ChestEnemyMap match with '" + item2 + "'"));
							return key;
						}
					}
				}
				ValhalLootPlugin.ValhalLootLogger.LogInfo((object)("Enemy '" + text + "' not found in any chest mapping, no chest will drop"));
				return string.Empty;
			}
			catch (Exception ex)
			{
				ValhalLootPlugin.ValhalLootLogger.LogError((object)("Error in GetEnemyChestPrefab: " + ex.Message));
				return string.Empty;
			}
		}

		public void GiveChestToPlayer(Player player, string chestName)
		{
			try
			{
				if ((Object)(object)player == (Object)null)
				{
					ValhalLootPlugin.ValhalLootLogger.LogError((object)"Cannot give chest to null player");
					return;
				}
				Inventory inventory = ((Humanoid)player).GetInventory();
				if (inventory == null)
				{
					ValhalLootPlugin.ValhalLootLogger.LogError((object)"Player inventory is null");
					return;
				}
				ValhalLootPlugin.ValhalLootLogger.LogInfo((object)("Requested chest: '" + chestName + "'"));
				if (string.IsNullOrEmpty(chestName) || (Object)(object)ObjectDB.instance == (Object)null)
				{
					ValhalLootPlugin.ValhalLootLogger.LogError((object)"Invalid chest name or ObjectDB not initialized");
					return;
				}
				GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(chestName);
				if ((Object)(object)itemPrefab == (Object)null)
				{
					ValhalLootPlugin.ValhalLootLogger.LogError((object)("Prefab for '" + chestName + "' not found in ObjectDB"));
					return;
				}
				ValhalLootPlugin.ValhalLootLogger.LogInfo((object)("Using chest prefab: " + ((Object)itemPrefab).name));
				ItemDrop component = itemPrefab.GetComponent<ItemDrop>();
				if ((Object)(object)component == (Object)null)
				{
					ValhalLootPlugin.ValhalLootLogger.LogError((object)("ItemDrop component not found on chest prefab " + ((Object)itemPrefab).name));
					return;
				}
				ItemData val;
				try
				{
					val = component.m_itemData.Clone();
					ValhalLootPlugin.ValhalLootLogger.LogInfo((object)"Successfully cloned ItemData");
					val.m_shared.m_maxStackSize = 50;
					val.m_shared.m_weight = 0f;
					val.m_stack = 1;
				}
				catch (Exception ex)
				{
					ValhalLootPlugin.ValhalLootLogger.LogError((object)("Error cloning ItemData: " + ex.Message + "\n" + ex.StackTrace));
					return;
				}
				if (!inventory.CanAddItem(val, -1))
				{
					((Character)player).Message((MessageType)2, "$valhalloot_inventory_full", 0, (Sprite)null);
					ValhalLootPlugin.ValhalLootLogger.LogInfo((object)("Could not give chest to player " + player.GetPlayerName() + ": Inventory full"));
					return;
				}
				ValhalLootPlugin.ValhalLootLogger.LogInfo((object)"Adding chest to player inventory");
				if (inventory.AddItem(val))
				{
					ValhalLootPlugin.ValhalLootLogger.LogInfo((object)"Chest added to player inventory successfully");
					((Character)player).Message((MessageType)2, "$valhalloot_received", 0, (Sprite)null);
				}
				else
				{
					ValhalLootPlugin.ValhalLootLogger.LogError((object)"Failed to add chest to inventory despite CanAddItem check");
					((Character)player).Message((MessageType)2, "$valhalloot_inventory_full", 0, (Sprite)null);
				}
			}
			catch (Exception ex2)
			{
				ValhalLootPlugin.ValhalLootLogger.LogError((object)("Error giving chest to player: " + ex2.Message));
				ValhalLootPlugin.ValhalLootLogger.LogError((object)("Stack trace: " + ex2.StackTrace));
			}
		}
	}
	[<6c1629e0-990f-46fb-933a-fb94e8696503>Nullable(0)]
	[<022029f3-5fce-4252-8684-e6648986aff8>NullableContext(1)]
	public class LootChestDropDialog : MonoBehaviour
	{
		[<6c1629e0-990f-46fb-933a-fb94e8696503>Nullable(2)]
		private static LootChestDropDialog _instance;

		private bool _isVisible = false;

		[<6c1629e0-990f-46fb-933a-fb94e8696503>Nullable(2)]
		private Player _player;

		[<6c1629e0-990f-46fb-933a-fb94e8696503>Nullable(2)]
		private ItemData _item;

		private Rect _windowRect = new Rect((float)(Screen.width / 2 - 250), (float)(Screen.height / 2 - 100), 500f, 200f);

		private int _windowId = 6789;

		private GUIStyle _titleStyle = new GUIStyle();

		private GUIStyle _textStyle = new GUIStyle();

		private GUIStyle _buttonStyle = new GUIStyle();

		private void Awake()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Expected O, but got Unknown
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Expected O, but got Unknown
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Expected O, but got Unknown
			_instance = this;
			Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
			_titleStyle = new GUIStyle();
			_titleStyle.fontSize = 18;
			_titleStyle.fontStyle = (FontStyle)1;
			_titleStyle.normal.textColor = Color.white;
			_titleStyle.alignment = (TextAnchor)4;
			_textStyle = new GUIStyle();
			_textStyle.fontSize = 14;
			_textStyle.normal.textColor = Color.white;
			_textStyle.alignment = (TextAnchor)4;
			_textStyle.wordWrap = true;
			_buttonStyle = new GUIStyle(GUI.skin.button);
			_buttonStyle.fontSize = 14;
			_buttonStyle.padding = new RectOffset(10, 10, 5, 5);
		}

		public static void ShowDropConfirmation(Player player, ItemData item)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected O, but got Unknown
			try
			{
				if ((Object)(object)_instance == (Object)null)
				{
					GameObject val = new GameObject("LootChestDropDialog");
					_instance = val.AddComponent<LootChestDropDialog>();
				}
				_instance._player = player;
				_instance._item = item;
				_instance._isVisible = true;
				ValhalLootPlugin.ValhalLootLogger.LogInfo((object)"Showing loot chest drop confirmation dialog");
			}
			catch (Exception ex)
			{
				ValhalLootPlugin.ValhalLootLogger.LogError((object)("Error showing drop confirmation dialog: " + ex.Message));
			}
		}

		private void OnGUI()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			if (_isVisible)
			{
				_windowRect = GUI.Window(_windowId, _windowRect, new WindowFunction(DrawWindow), "");
			}
		}

		private void DrawWindow(int windowId)
		{
			string text = Localization.instance.Localize("$valhalloot_drop_title");
			string text2 = Localization.instance.Localize("$valhalloot_drop_message");
			string text3 = Localization.instance.Localize("$valhalloot_drop_confirm");
			string text4 = Localization.instance.Localize("$valhalloot_drop_cancel");
			if (string.IsNullOrEmpty(text))
			{
				text = "Drop Loot Chest?";
			}
			if (string.IsNullOrEmpty(text2))
			{
				text2 = "If you throw this Loot Chest away, you will not be able to reclaim it.";
			}
			if (string.IsNullOrEmpty(text3))
			{
				text3 = "Okay";
			}
			if (string.IsNullOrEmpty(text4))
			{
				text4 = "Cancel";
			}
			GUILayout.Space(20f);
			GUILayout.Label(text, _titleStyle, Array.Empty<GUILayoutOption>());
			GUILayout.Space(20f);
			GUILayout.Label(text2, _textStyle, Array.Empty<GUILayoutOption>());
			GUILayout.Space(30f);
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.FlexibleSpace();
			if (GUILayout.Button(text3, _buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(100f) }))
			{
				if ((Object)(object)_player != (Object)null && _item != null)
				{
					PerformDrop(_player, _item);
				}
				else
				{
					ValhalLootPlugin.ValhalLootLogger.LogWarning((object)"Cannot drop item: player or item is null");
				}
				_isVisible = false;
			}
			GUILayout.Space(20f);
			if (GUILayout.Button(text4, _buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(100f) }))
			{
				_isVisible = false;
			}
			GUILayout.FlexibleSpace();
			GUILayout.EndHorizontal();
			GUI.DragWindow();
		}

		private static void PerformDrop(Player player, ItemData item)
		{
			//IL_0017: 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_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_003d: 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_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Inventory inventory = ((Humanoid)player).GetInventory();
				inventory.RemoveItem(item);
				Vector3 val = ((Component)player).transform.position + ((Component)player).transform.forward + ((Component)player).transform.up;
				Quaternion identity = Quaternion.identity;
				ItemDrop component = Object.Instantiate<GameObject>(item.m_dropPrefab, val, identity).GetComponent<ItemDrop>();
				component.m_itemData = item.Clone();
				Rigidbody componentInChildren = ((Component)component).GetComponentInChildren<Rigidbody>();
				if (Object.op_Implicit((Object)(object)componentInChildren))
				{
					componentInChildren.velocity = (((Component)player).transform.forward + Vector3.up) * 5f;
				}
				ValhalLootPlugin.ValhalLootLogger.LogInfo((object)("Player " + player.GetPlayerName() + " dropped loot chest after confirmation"));
			}
			catch (Exception ex)
			{
				ValhalLootPlugin.ValhalLootLogger.LogError((object)("Error dropping loot chest: " + ex.Message));
			}
		}
	}
	public static class ValhalLootPatches
	{
		[HarmonyPatch(typeof(Character), "OnDeath")]
		[<022029f3-5fce-4252-8684-e6648986aff8>NullableContext(1)]
		[<6c1629e0-990f-46fb-933a-fb94e8696503>Nullable(0)]
		public static class Character_OnDeath_Patch
		{
			private static readonly FieldInfo Character_m_nview_Field = typeof(Character).GetField("m_nview", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

			private static readonly FieldInfo Character_m_lastHit_Field = typeof(Character).GetField("m_lastHit", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

			private static void Postfix(Character __instance)
			{
				try
				{
					if ((Object)(object)__instance != (Object)null)
					{
						ValhalLootPlugin.ValhalLootLogger.LogInfo((object)("Character death detected: " + __instance.m_name));
						if (__instance.IsPlayer())
						{
							ValhalLootPlugin.ValhalLootLogger.LogInfo((object)"Skipping player death");
							return;
						}
						ZNetView characterNView = GetCharacterNView(__instance);
						if ((Object)(object)characterNView == (Object)null || !characterNView.IsValid())
						{
							ValhalLootPlugin.ValhalLootLogger.LogInfo((object)("Warning: " + __instance.m_name + " has invalid ZDO but continuing with drop check"));
						}
						else if (!characterNView.IsOwner())
						{
							ValhalLootPlugin.ValhalLootLogger.LogInfo((object)("Skipping " + __instance.m_name + " death: Not the owner"));
							return;
						}
						Player killingPlayer = GetKillingPlayer(__instance);
						if ((Object)(object)killingPlayer == (Object)null)
						{
							ValhalLootPlugin.ValhalLootLogger.LogInfo((object)("Skipping " + __instance.m_name + " death: No killer found"));
							return;
						}
						ValhalLootPlugin.ValhalLootLogger.LogInfo((object)(__instance.m_name + " was killed by player " + killingPlayer.GetPlayerName()));
						if ((Object)(object)ValhalLootManager.Instance == (Object)null)
						{
							ValhalLootPlugin.ValhalLootLogger.LogWarning((object)"ValhalLootManager not initialized when processing creature death");
							return;
						}
						ValhalLootPlugin.ValhalLootLogger.LogInfo((object)("Checking if " + __instance.m_name + " should drop a chest for " + killingPlayer.GetPlayerName()));
						if (ValhalLootManager.Instance.ShouldDropChest(__instance, killingPlayer))
						{
							string enemyChestPrefab = ValhalLootManager.Instance.GetEnemyChestPrefab(__instance);
							if (string.IsNullOrEmpty(enemyChestPrefab))
							{
								ValhalLootPlugin.ValhalLootLogger.LogWarning((object)("No chest prefab mapping found for " + __instance.m_name + ", skipping drop"));
								return;
							}
							ValhalLootPlugin.ValhalLootLogger.LogInfo((object)("Giving " + enemyChestPrefab + " chest to player " + killingPlayer.GetPlayerName() + " from " + __instance.m_name));
							ValhalLootManager.Instance.GiveChestToPlayer(killingPlayer, enemyChestPrefab);
						}
						else
						{
							ValhalLootPlugin.ValhalLootLogger.LogInfo((object)("No chest will be given to player " + killingPlayer.GetPlayerName() + " from " + __instance.m_name));
						}
					}
					else
					{
						ValhalLootPlugin.ValhalLootLogger.LogWarning((object)"Character death detected but instance is null");
					}
				}
				catch (Exception ex)
				{
					ValhalLootPlugin.ValhalLootLogger.LogError((object)("Error in Character.OnDeath patch: " + ex.Message));
					ValhalLootPlugin.ValhalLootLogger.LogError((object)("Stack trace: " + ex.StackTrace));
				}
			}

			private static Player GetKillingPlayer(Character character)
			{
				//IL_0093: Unknown result type (might be due to invalid IL or missing references)
				//IL_009f: Unknown result type (might be due to invalid IL or missing references)
				try
				{
					if ((Object)(object)character == (Object)null)
					{
						return null;
					}
					HitData characterLastHit = GetCharacterLastHit(character);
					if (characterLastHit != null)
					{
						Character attacker = characterLastHit.GetAttacker();
						if ((Object)(object)attacker != (Object)null && attacker.IsPlayer())
						{
							return (Player)(object)((attacker is Player) ? attacker : null);
						}
					}
					List<Player> allPlayers = Player.GetAllPlayers();
					Player result = null;
					float num = 50f;
					foreach (Player item in allPlayers)
					{
						if ((Object)(object)item != (Object)null)
						{
							float num2 = Vector3.Distance(((Component)character).transform.position, ((Component)item).transform.position);
							if (num2 < num)
							{
								result = item;
								num = num2;
							}
						}
					}
					return result;
				}
				catch (Exception ex)
				{
					ValhalLootPlugin.ValhalLootLogger.LogError((object)("Error determining killing player: " + ex.Message));
					return null;
				}
			}

			private static ZNetView GetCharacterNView(Character character)
			{
				if ((Object)(object)character == (Object)null || Character_m_nview_Field == null)
				{
					return null;
				}
				object? value = Character_m_nview_Field.GetValue(character);
				return (ZNetView)((value is ZNetView) ? value : null);
			}

			private static HitData GetCharacterLastHit(Character character)
			{
				if ((Object)(object)character == (Object)null || Character_m_lastHit_Field == null)
				{
					return null;
				}
				object? value = Character_m_lastHit_Field.GetValue(character);
				return (HitData)((value is HitData) ? value : null);
			}
		}

		[HarmonyPatch(typeof(ItemData), "IsEquipable")]
		public static class ItemData_IsEquipable_Patch
		{
			[<022029f3-5fce-4252-8684-e6648986aff8>NullableContext(1)]
			private static void Postfix(ItemData __instance, ref bool __result)
			{
				if (__instance != null && __instance.m_shared.m_name.Contains("valhalloot"))
				{
					__result = true;
				}
			}
		}

		[<6c1629e0-990f-46fb-933a-fb94e8696503>Nullable(0)]
		[<022029f3-5fce-4252-8684-e6648986aff8>NullableContext(1)]
		[HarmonyPatch(typeof(Humanoid), "UseItem")]
		public static class Humanoid_UseItem_Patch
		{
			private static bool Prefix(Humanoid __instance, ItemData item)
			{
				try
				{
					if (item != null)
					{
						Player val = (Player)(object)((__instance is Player) ? __instance : null);
						if (val != null)
						{
							string key = "CustomData_ValhalLoot";
							if (item.m_customData != null && item.m_customData.ContainsKey(key))
							{
								ValhalLootPlugin.ValhalLootLogger.LogInfo((object)"ValhalLoot chest used via Jotunn custom data");
								OnChestItemUsed(item, val);
								return false;
							}
							if (item.m_shared.m_name != null && (item.m_shared.m_name.Contains("valhalloot") || item.m_shared.m_name.Contains("loot_ru")))
							{
								ValhalLootPlugin.ValhalLootLogger.LogInfo((object)"ValhalLoot chest used via name detection");
								OnChestItemUsed(item, val);
								return false;
							}
						}
					}
					return true;
				}
				catch (Exception ex)
				{
					ValhalLootPlugin.ValhalLootLogger.LogError((object)("Error in Humanoid.UseItem patch: " + ex.Message));
					return true;
				}
			}

			private static void OnChestItemUsed(ItemData item, Player player)
			{
				try
				{
					ValhalLootPlugin.ValhalLootLogger.LogDebug((object)("ValhalLoot chest used by " + player.GetPlayerName()));
					if ((Object)(object)ValhalLootUI.Instance == (Object)null)
					{
						ValhalLootPlugin.ValhalLootLogger.LogWarning((object)"ValhalLootUI not initialized when using chest item");
					}
					else if ((Object)(object)ValhalLootManager.Instance != (Object)null)
					{
						ValhalLootManager.Instance.ProcessChestUse(player, item);
					}
					else
					{
						ValhalLootPlugin.ValhalLootLogger.LogWarning((object)"ValhalLootManager not initialized when using chest item");
					}
				}
				catch (Exception ex)
				{
					ValhalLootPlugin.ValhalLootLogger.LogError((object)("Error processing chest item use: " + ex.Message));
				}
			}
		}
	}
	[HarmonyPatch(typeof(Humanoid), "DropItem")]
	public static class Player_DropItem_Patch
	{
		[<022029f3-5fce-4252-8684-e6648986aff8>NullableContext(1)]
		private static bool Prefix(Humanoid __instance, Inventory inventory, ItemData item, int amount, ref bool __result)
		{
			try
			{
				if (item != null)
				{
					bool flag = false;
					string key = "CustomData_ValhalLoot";
					if (item.m_customData != null && item.m_customData.ContainsKey(key))
					{
						flag = true;
						ValhalLootPlugin.ValhalLootLogger.LogInfo((object)"Intercepted drop of loot chest item via Jotunn custom data");
					}
					else if (item.m_shared != null && item.m_shared.m_name != null && (item.m_shared.m_name.Contains("loot_ru") || item.m_shared.m_name.Contains("valhalloot")))
					{
						flag = true;
						ValhalLootPlugin.ValhalLootLogger.LogInfo((object)("Intercepted drop of loot chest item via name detection: " + item.m_shared.m_name));
					}
					if (flag)
					{
						Player val = (Player)(object)((__instance is Player) ? __instance : null);
						if (val != null)
						{
							LootChestDropDialog.ShowDropConfirmation(val, item);
							__result = true;
							return false;
						}
					}
				}
				return true;
			}
			catch (Exception ex)
			{
				ValhalLootPlugin.ValhalLootLogger.LogError((object)("Error in Player.DropItem patch: " + ex.Message));
				return true;
			}
		}
	}
	[<022029f3-5fce-4252-8684-e6648986aff8>NullableContext(1)]
	[<6c1629e0-990f-46fb-933a-fb94e8696503>Nullable(0)]
	public class ValhalLootUI : MonoBehaviour
	{
		[<6c1629e0-990f-46fb-933a-fb94e8696503>Nullable(0)]
		private class ItemSlot
		{
			public GameObject Container = null;

			public Image Background = null;

			public Image Icon = null;

			public Text NameText = null;

			public Text QualityText = null;

			public Button SelectButton = null;

			public EventTrigger EventTrigger = null;

			public int SlotIndex;
		}

		[CompilerGenerated]
		private sealed class <InitializeAndShowLoot>d__27 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			[<6c1629e0-990f-46fb-933a-fb94e8696503>Nullable(0)]
			private object <>2__current;

			[<6c1629e0-990f-46fb-933a-fb94e8696503>Nullable(0)]
			public ItemData chestItem;

			[<6c1629e0-990f-46fb-933a-fb94e8696503>Nullable(0)]
			public string prefabNameOverride;

			[<6c1629e0-990f-46fb-933a-fb94e8696503>Nullable(0)]
			public ValhalLootUI <>4__this;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				[return: <6c1629e0-990f-46fb-933a-fb94e8696503>Nullable(0)]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				[return: <6c1629e0-990f-46fb-933a-fb94e8696503>Nullable(0)]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <InitializeAndShowLoot>d__27(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					ValhalLootPlugin.ValhalLootLogger.LogInfo((object)"Starting UI initialization before showing loot");
					if (!<>4__this._isInitialized || (Object)(object)<>4__this._uiPanel == (Object)null)
					{
						<>4__this.CreateUI();
						<>4__this._isInitialized = true;
						ValhalLootPlugin.ValhalLootLogger.LogInfo((object)"Created UI in InitializeAndShowLoot");
					}
					<>4__this._chestItem = chestItem;
					<>4__this._currentChestPrefabName = <>4__this.GetChestPrefabNameWithFallbacks(chestItem, prefabNameOverride);
					<>4__this.GenerateLootOptions(<>4__this._currentChestPrefabName);
					<>2__current = null;
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					<>4__this.UpdateUIElements();
					if ((Object)(object)<>4__this._uiPanel != (Object)null)
					{
						<>4__this._uiPanel.SetActive(true);
						<>4__this._isVisible = true;
						GUIManager.BlockInput(true);
					}
					else
					{
						ValhalLootPlugin.ValhalLootLogger.LogError((object)"UI panel is null when trying to show it in InitializeAndShowLoot");
					}
					return false;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <InitializeWhenReady>d__21 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			[<6c1629e0-990f-46fb-933a-fb94e8696503>Nullable(0)]
			private object <>2__current;

			[<6c1629e0-990f-46fb-933a-fb94e8696503>Nullable(0)]
			public ValhalLootUI <>4__this;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				[return: <6c1629e0-990f-46fb-933a-fb94e8696503>Nullable(0)]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				[return: <6c1629e0-990f-46fb-933a-fb94e8696503>Nullable(0)]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <InitializeWhenReady>d__21(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_005e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0068: Expected O, but got Unknown
				//IL_0098: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a2: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					ValhalLootPlugin.ValhalLootLogger.LogInfo((object)"Waiting for dependencies to be ready");
					<>2__current = (object)new WaitUntil((Func<bool>)(() => (Object)(object)Player.m_localPlayer != (Object)null));
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					<>2__current = (object)new WaitUntil((Func<bool>)(() => GUIManager.Instance != null && (Object)(object)GUIManager.CustomGUIFront != (Object)null));
					<>1__state = 2;
					return true;
				case 2:
					<>1__state = -1;
					ValhalLootPlugin.ValhalLootLogger.LogInfo((object)"All dependencies ready, creating UI");
					<>4__this.CreateUI();
					<>4__this._isInitialized = true;
					ValhalLootPlugin.ValhalLootLogger.LogInfo((object)"ValhalLoot UI fully initialized");
					return false;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <RetryGenerateLootOptions>d__31 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			[<6c1629e0-990f-46fb-933a-fb94e8696503>Nullable(0)]
			private object <>2__current;

			[<6c1629e0-990f-46fb-933a-fb94e8696503>Nullable(0)]
			public string chestPrefabName;

			[<6c1629e0-990f-46fb-933a-fb94e8696503>Nullable(0)]
			public ValhalLootUI <>4__this;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				[return: <6c1629e0-990f-46fb-933a-fb94e8696503>Nullable(0)]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				[return: <6c1629e0-990f-46fb-933a-fb94e8696503>Nullable(0)]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <RetryGenerateLootOptions>d__31(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0036: Unknown result type (might be due to invalid IL or missing references)
				//IL_0040: Expected O, but got Unknow